forked from Mirrors/openclonk
306 lines
7.7 KiB
C
306 lines
7.7 KiB
C
/*--
|
|
Carry-Heavy Library
|
|
Author: Ringwaul
|
|
|
|
Special circumstances for when the clonk is carrying heavy objects
|
|
--*/
|
|
|
|
local liftheavy_carrier;
|
|
local liftheavy_effect;
|
|
|
|
public func IsCarryHeavy() { return true; }
|
|
public func IsInvInteract() { return true; }
|
|
|
|
public func GetCarryMode(clonk) { return CARRY_BothHands; }
|
|
public func GetCarrySpecial(clonk)
|
|
{
|
|
var action = clonk->~GetAction();
|
|
if(action == "Scale" || action == "Hangle" || action == "Push")
|
|
return "skeleton_body";
|
|
}
|
|
|
|
public func GetDropDescription() { return Format("$TxtPutDown$", GetName()); }
|
|
|
|
public func Grabbed(object clonk, bool grab)
|
|
{
|
|
if(grab)
|
|
{
|
|
// clonk already carries something. Don't pick up
|
|
if(clonk->~IsCarryingHeavy())
|
|
{
|
|
CustomMessage("$TxtHandsFull$", clonk, clonk->GetController(), 0, 0, 0xff0000);
|
|
//Let go of object
|
|
clonk->SetAction("Walk");
|
|
//Clear animation
|
|
clonk->SetCommand("None");
|
|
|
|
return false;
|
|
}
|
|
|
|
// do pickup stuff enter stuff whatever
|
|
liftheavy_carrier = clonk;
|
|
|
|
Enter(liftheavy_carrier);
|
|
DoLift();
|
|
}
|
|
}
|
|
|
|
|
|
private func DoLift(bool forceEnter)
|
|
{
|
|
if(!liftheavy_carrier)
|
|
return;
|
|
if(!IsCarryingHeavy(liftheavy_carrier))
|
|
AddEffect("IntLiftHeavy", liftheavy_carrier, 1, 1, this, nil, forceEnter);
|
|
}
|
|
|
|
// ------------------
|
|
// Lifting the object
|
|
// ------------------
|
|
static const lift_heavy_time = 60;
|
|
func FxIntLiftHeavyStart(object clonk, proplist effect, bool tmp, bool forceEnter)
|
|
{
|
|
if(tmp) return;
|
|
if(!clonk) return -1;
|
|
if(Contained() != clonk) return -1;
|
|
|
|
// if the clonk is inside, we can skip the animation
|
|
if(clonk->Contained())
|
|
{
|
|
AddEffect("IntCarryHeavy", clonk, 1, 1, this);
|
|
return -1;
|
|
}
|
|
|
|
//Stop the clonk from moving, and tell the clonk's control library
|
|
//it now has a hand action
|
|
clonk->SetTurnForced(clonk->GetDir());
|
|
clonk->SetHandAction(1);
|
|
clonk->SetAction("Stand");
|
|
|
|
//Attach the mesh of the object. It is not displayed normally because the
|
|
//hands are told they have an action in the next few lines
|
|
effect.mesh = clonk->AttachMesh(this->GetID(), "pos_tool1", "main", this->~GetCarryTransform(clonk));
|
|
|
|
//Play the animation of the clonk picking up the object
|
|
effect.anim = clonk->PlayAnimation("CarryArmsPickup", 10, Anim_Linear(0,0,clonk->GetAnimationLength("CarryArmsPickup"), lift_heavy_time, ANIM_Remove), Anim_Const(1000));
|
|
|
|
effect.doExit = !forceEnter; // default: true
|
|
}
|
|
|
|
func FxIntLiftHeavyTimer(object clonk, proplist effect, int timer)
|
|
{
|
|
//If the clonk moves, he'll stop lifting and drop the object
|
|
if(timer < lift_heavy_time)
|
|
{
|
|
//from 0 to 40, the clonk will drop the object if he moves
|
|
if(timer < lift_heavy_time - 20)
|
|
{
|
|
if(clonk->GetAction() != "Stand" || clonk->IsJumping() || Abs(clonk->GetXDir()) > 0)
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
//There is a small over-shot at the end the player may mistake for finished lifting
|
|
//So stop the clonk from moving during 40-60
|
|
else
|
|
{
|
|
if(clonk->GetAction() != "Stand")
|
|
{
|
|
//If the clonk moved when he was disabled from doing so (or jumped), cancel lifting
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
//When the clonk has finished lifting, remove movement-restrictions and add carry effect
|
|
if(timer >= lift_heavy_time)
|
|
{
|
|
liftheavy_effect = AddEffect("IntCarryHeavy", clonk, 1, 1, this);
|
|
// don't exit the object
|
|
effect.doExit = false;
|
|
return -1;
|
|
}
|
|
|
|
// we got moved out during lifting
|
|
if(Contained() != clonk)
|
|
return -1;
|
|
}
|
|
|
|
func FxIntLiftHeavyStop(object clonk, proplist effect, int reason, bool tmp)
|
|
{
|
|
if(tmp) return;
|
|
|
|
// drop the object
|
|
if(effect.doExit && Contained()==clonk) // only if still in the clonk
|
|
Exit();
|
|
|
|
clonk->DetachMesh(effect.mesh);
|
|
clonk->StopAnimation(effect.anim);
|
|
|
|
UndoLift(clonk);
|
|
}
|
|
|
|
// -------------------
|
|
// Carrying the object
|
|
// -------------------
|
|
func FxIntCarryHeavyStart(object clonk, proplist effect, int temp)
|
|
{
|
|
if (temp) return;
|
|
clonk->DisableScale();
|
|
clonk->DisableHangle();
|
|
var throw = clonk.ThrowSpeed;
|
|
if (throw < 150) return; // I know this may be bad in some situations and result in normal throwing speed
|
|
// If so, see it as an easter egg exploit!
|
|
clonk.ThrowSpeed -= 150;
|
|
effect.throw = throw - clonk.ThrowSpeed;
|
|
}
|
|
|
|
func FxIntCarryHeavyTimer(object clonk, proplist effect, int timer)
|
|
{
|
|
if (!this) return -1;
|
|
//Delete this effect if not contained in the clonk anymore
|
|
if(Contained() != clonk) return -1;
|
|
}
|
|
|
|
func FxIntCarryHeavyStop(object clonk, proplist effect, int reason, bool temp)
|
|
{
|
|
if (temp) return;
|
|
clonk->EnableScale();
|
|
clonk->EnableHangle();
|
|
clonk.ThrowSpeed += effect.throw;
|
|
effect.throw = 0; // Failsafe
|
|
liftheavy_effect = nil;
|
|
}
|
|
|
|
// ------------------
|
|
// Dropping the object
|
|
// ------------------
|
|
func FxIntDropHeavyStart(object clonk, proplist effect, bool tmp)
|
|
{
|
|
if(tmp) return;
|
|
if(!clonk) return -1;
|
|
if(Contained() != clonk) return -1;
|
|
|
|
if(clonk->GetEffect("IntCarryHeavy"))
|
|
clonk->RemoveEffect("IntCarryHeavy");
|
|
|
|
// if the clonk is inside, we don't play the animation
|
|
if(clonk->Contained())
|
|
return -1;
|
|
|
|
clonk->SetTurnForced(clonk->GetDir());
|
|
clonk->SetHandAction(1);
|
|
clonk->SetAction("Stand");
|
|
|
|
//Stop the clonk if he is moving
|
|
if(clonk->GetXDir() != 0) clonk->SetXDir();
|
|
|
|
//Attach the mesh of the object. It is not displayed normally because the
|
|
//hands are told they have an action in the next few lines
|
|
effect.mesh = clonk->AttachMesh(this->GetID(), "pos_tool1", "main", this->~GetCarryTransform(clonk));
|
|
|
|
//Play the animation of the clonk setting down the object
|
|
effect.anim = clonk->PlayAnimation("CarryArmsPickup", 10, Anim_Linear(clonk->GetAnimationLength("CarryArmsPickup"),clonk->GetAnimationLength("CarryArmsPickup"),0, lift_heavy_time, ANIM_Remove), Anim_Const(1000));
|
|
//liftheavy_anim = clonk->PlayAnimation("CarryArmsSetdown", 10, Anim_Linear(0,0,clonk->GetAnimationLength("CarryArmsSetdown"), lift_heavy_time, ANIM_Remove), Anim_Const(1000));
|
|
}
|
|
|
|
func FxIntDropHeavyTimer(object clonk, proplist effect, int timer)
|
|
{
|
|
//Clonk was interrupted?
|
|
if(clonk->GetAction() != "Stand")
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
// animation finished?
|
|
if(timer >= lift_heavy_time)
|
|
return -1;
|
|
|
|
// we got moved out during lifting
|
|
if(Contained() != clonk)
|
|
return -1;
|
|
}
|
|
|
|
func FxIntDropHeavyStop(object clonk, proplist effect, int reason, bool tmp)
|
|
{
|
|
if(tmp) return;
|
|
|
|
clonk->DetachMesh(effect.mesh);
|
|
clonk->StopAnimation(effect.anim);
|
|
|
|
if(clonk->GetAction() != "Stand")
|
|
Exit();
|
|
else
|
|
{
|
|
var dir = 1;
|
|
if(clonk->GetDir() == DIR_Left)
|
|
dir = -1;
|
|
// Set down at barrel position
|
|
Exit(6*dir, 9);
|
|
}
|
|
|
|
UndoLift(clonk);
|
|
}
|
|
|
|
func Drop()
|
|
{
|
|
if(liftheavy_carrier == nil)
|
|
return;
|
|
if(!IsCarryingHeavy(liftheavy_carrier))
|
|
return;
|
|
|
|
AddEffect("IntDropHeavy", liftheavy_carrier, 1, 1, this);
|
|
}
|
|
|
|
func UndoLift(object clonk)
|
|
{
|
|
//allow the clonk to turn again
|
|
clonk->SetTurnForced(-1);
|
|
clonk->SetHandAction(0);
|
|
if(clonk->GetAction() == "Stand") clonk->SetAction("Walk");
|
|
}
|
|
|
|
func IsCarryingHeavy(object clonk)
|
|
{
|
|
//Is the clonk in the process of lifting or carrying a heavy object?
|
|
if(GetEffect("IntLiftHeavy", clonk)) return 1;
|
|
if(GetEffect("IntCarryHeavy", clonk)) return 2;
|
|
if(GetEffect("IntDropHeavy", clonk)) return 3;
|
|
return false;
|
|
}
|
|
|
|
func Entrance(object obj)
|
|
{
|
|
// tell the carrier to carryheavy if it got moved into it by script
|
|
if(!liftheavy_carrier)
|
|
if(obj->~GetCarryHeavy() == this)
|
|
{
|
|
liftheavy_carrier = obj;
|
|
if(obj->GetAction() == "Walk" && !obj->Contained())
|
|
DoLift(true);
|
|
else
|
|
AddEffect("IntCarryHeavy",obj, 1, 1, this);
|
|
}
|
|
}
|
|
|
|
func Departure(object obj)
|
|
{
|
|
if(!liftheavy_carrier)
|
|
return;
|
|
|
|
if (GetEffect("IntCarryHeavy", obj)) RemoveEffect("IntCarryHeavy", obj);
|
|
liftheavy_carrier = nil;
|
|
}
|
|
|
|
func Destruction()
|
|
{
|
|
if (liftheavy_effect) RemoveEffect(nil,nil, liftheavy_effect);
|
|
}
|
|
|
|
// Cannot pickup other carryheavy objects (is that really what you intended, Ringwaul?)
|
|
func RejectCollect(id collectid, object collect)
|
|
{
|
|
if(collect->~IsCarryHeavy()) return true;
|
|
else
|
|
return false;
|
|
} |