forked from Mirrors/openclonk
310 lines
8.2 KiB
C
310 lines
8.2 KiB
C
/**
|
|
CarryHeavyControl
|
|
|
|
Handles the control of carry-heavy-objects as inventory objects.
|
|
Depends on Clonk Control and Inventory
|
|
*/
|
|
|
|
local lib_carryheavy_obj; // object beeing carried with carryheavy
|
|
|
|
public func GetCarryHeavy() { return lib_carryheavy_obj; }
|
|
public func IsCarryingHeavy() { return lib_carryheavy_obj != nil; }
|
|
|
|
|
|
// Helper function to create carry heavy contents without doing the pick up animation.
|
|
public func CreateCarryHeavyContents(id obj_id, int amount)
|
|
{
|
|
this.BlockCarryHeavyPickUpAnimation = true;
|
|
var res = CreateContents(obj_id, amount);
|
|
this.BlockCarryHeavyPickUpAnimation = false;
|
|
return res;
|
|
}
|
|
|
|
/* Overloads for Inventory */
|
|
|
|
// Check if we can carry a carry heavy object
|
|
protected func RejectCollect(id objid, object obj)
|
|
{
|
|
// Carry heavy only gets picked up if none held already
|
|
if(this.inventory.force_collection && obj->~IsCarryHeavy())
|
|
{
|
|
// Collection of that object magically disabled?
|
|
if(GetEffect("NoCollection", obj)) return true;
|
|
|
|
// Do callbacks to control effects to see if the effect blocks picking up a carry heavy object.
|
|
var block_carry_heavy = false;
|
|
var count = GetEffectCount("*Control*", this), control_effect;
|
|
while (count--)
|
|
{
|
|
control_effect = GetEffect("*Control*", this, count);
|
|
if (control_effect && EffectCall(this, control_effect, "RejectCarryHeavyPickUp", obj))
|
|
{
|
|
block_carry_heavy = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Don't pick up if already carrying a heavy object or if it is blocked.
|
|
if (IsCarryingHeavy() || block_carry_heavy)
|
|
{
|
|
CustomMessage("$TxtHandsFull$", this, this->GetController(), 0, 0, 0xff0000);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
return _inherited(objid,obj,...);
|
|
}
|
|
|
|
// Start visual effect when picking up carry heavy objects
|
|
public func Collection2(object obj)
|
|
{
|
|
if(obj->~IsCarryHeavy()) // we can assume that we don't have a carryheavy object yet. If we do, Scripters are to blame.
|
|
{
|
|
CarryHeavy(obj);
|
|
DoLiftCarryHeavy(obj);
|
|
return true;
|
|
}
|
|
return _inherited(obj,...);
|
|
}
|
|
|
|
public func GetHandItem(int i)
|
|
{
|
|
// carrying a carry heavy item always returns said item. (he holds it in both hands, after all!)
|
|
if (IsCarryingHeavy())
|
|
return GetCarryHeavy();
|
|
return _inherited(i, ...);
|
|
}
|
|
|
|
// Delete internal variables
|
|
public func Ejection(object obj)
|
|
{
|
|
// carry heavy special treatment
|
|
if(obj == GetCarryHeavy())
|
|
{
|
|
StopCarryHeavy();
|
|
return true;
|
|
}
|
|
return _inherited(obj,...);
|
|
}
|
|
|
|
// Delete internal variables
|
|
public func ContentsDestruction(object obj)
|
|
{
|
|
// check if it was carryheavy
|
|
if(obj == GetCarryHeavy())
|
|
{
|
|
StopCarryHeavy();
|
|
}
|
|
|
|
return _inherited(obj, ...);
|
|
}
|
|
|
|
/* Overloads for Clonk Control */
|
|
|
|
public func GetExtraInteractions()
|
|
{
|
|
var functions = _inherited(...);
|
|
|
|
// dropping carry heavy
|
|
if(IsCarryingHeavy() && GetAction() == "Walk")
|
|
{
|
|
var ch = GetCarryHeavy();
|
|
PushBack(functions, {Fn = "DropCarryHeavy", Description=ch->GetDropDescription(), Object=this, IconName="", IconID=Icon_LetGo, Priority=1});
|
|
}
|
|
return functions;
|
|
}
|
|
|
|
/* Carry heavy stuff */
|
|
|
|
/** Tells the clonk that he is carrying the given carry heavy object */
|
|
public func CarryHeavy(object target)
|
|
{
|
|
if(!target)
|
|
return;
|
|
// actually.. is it a carry heavy object?
|
|
if(!target->~IsCarryHeavy())
|
|
return;
|
|
// only if not carrying a heavy objcet already
|
|
if(IsCarryingHeavy())
|
|
return;
|
|
|
|
lib_carryheavy_obj = target;
|
|
|
|
if(target->Contained() != this)
|
|
target->Enter(this);
|
|
|
|
// Update attach stuff
|
|
this->~OnSlotFull();
|
|
|
|
// Do callbacks to control effects for this clonk that a carry heavy object has been picked up.
|
|
var count = GetEffectCount("*Control*", this), control_effect;
|
|
while (count--)
|
|
{
|
|
control_effect = GetEffect("*Control*", this, count);
|
|
if (control_effect)
|
|
EffectCall(this, control_effect, "OnCarryHeavyPickUp", target);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/** Drops the carried heavy object, if any */
|
|
public func DropCarryHeavy()
|
|
{
|
|
// only if actually possible
|
|
if(!IsCarryingHeavy())
|
|
return;
|
|
|
|
DoDropCarryHeavy(GetCarryHeavy());
|
|
StopCarryHeavy();
|
|
|
|
return true;
|
|
}
|
|
|
|
// Internal function to clear carryheavy-status
|
|
private func StopCarryHeavy()
|
|
{
|
|
if(!IsCarryingHeavy())
|
|
return;
|
|
|
|
lib_carryheavy_obj = nil;
|
|
this->~OnSlotEmpty();
|
|
}
|
|
|
|
/* Lifting / dropping effect */
|
|
|
|
local lib_carryheavy_lifttime = 45;
|
|
|
|
private func DoLiftCarryHeavy(object obj)
|
|
{
|
|
if (!obj || !obj->~IsCarryHeavy())
|
|
return;
|
|
if (obj->Contained() != this)
|
|
return;
|
|
// If inside something or not walking, skip the animation
|
|
if (Contained() || GetAction() != "Walk" || this.BlockCarryHeavyPickUpAnimation)
|
|
return;
|
|
AddEffect("IntLiftHeavy", this, 1, 1, this, nil, obj);
|
|
}
|
|
|
|
private func DoDropCarryHeavy(object obj)
|
|
{
|
|
if (!obj || !obj->~IsCarryHeavy())
|
|
return;
|
|
if (obj->Contained() != this)
|
|
return;
|
|
// If inside something or not walking, skip the animation
|
|
if (Contained() || GetAction() != "Walk")
|
|
return;
|
|
AddEffect("IntDropHeavy", this, 1, 1, this, nil, obj);
|
|
}
|
|
|
|
private func FxIntLiftHeavyStart(object me, proplist effect, bool tmp, object to_lift)
|
|
{
|
|
//Stop the clonk from moving, and tell the clonk's control library
|
|
//it now has a hand action
|
|
me->SetTurnForced(GetDir());
|
|
me->SetHandAction(1);
|
|
SetAction("Stand");
|
|
//Stop the clonk if he is moving
|
|
if(GetXDir() != 0) 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 = AttachMesh(to_lift, "pos_tool1", to_lift->GetCarryBone(), to_lift->~GetCarryTransform(this));
|
|
|
|
//Play the animation of the clonk picking up the object
|
|
effect.anim = PlayAnimation("CarryArmsPickup", CLONK_ANIM_SLOT_Arms, Anim_Linear(0,0, GetAnimationLength("CarryArmsPickup"), lib_carryheavy_lifttime, ANIM_Remove), Anim_Const(1000));
|
|
|
|
effect.obj = to_lift;
|
|
}
|
|
|
|
private func FxIntLiftHeavyTimer(object me, proplist effect, int time)
|
|
{
|
|
//If the clonk moves, he'll stop lifting and drop the object
|
|
if(time < lib_carryheavy_lifttime)
|
|
{
|
|
// first 2/3 of time, clonk will drop the object
|
|
if(time < lib_carryheavy_lifttime * 2 / 3)
|
|
{
|
|
if(GetAction() != "Stand" || me->IsJumping() || Abs(GetXDir()) > 0)
|
|
{
|
|
effect.fail = true;
|
|
return FX_Execute_Kill;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(GetAction() != "Stand")
|
|
return FX_Execute_Kill;
|
|
}
|
|
}
|
|
//When the clonk has finished lifting, remove movement-restrictions
|
|
if(time >= lib_carryheavy_lifttime)
|
|
return FX_Execute_Kill;
|
|
// Object got moved out during lifting
|
|
if(!effect.obj || effect.obj->Contained() != this)
|
|
return FX_Execute_Kill;
|
|
}
|
|
|
|
private func FxIntLiftHeavyStop(object me, proplist effect)
|
|
{
|
|
// If failed, drop the object
|
|
if(effect.fail && effect.obj && effect.obj->Contained() == this)
|
|
effect.obj->Exit(0,9);
|
|
|
|
DetachMesh(effect.mesh);
|
|
StopAnimation(effect.anim);
|
|
me->SetTurnForced(-1);
|
|
me->SetHandAction(0);
|
|
if(GetAction() == "Stand") SetAction("Walk");
|
|
}
|
|
|
|
private func FxIntDropHeavyStart(object me, proplist effect, bool tmp, object to_lift)
|
|
{
|
|
if(GetEffect("IntCarryHeavy"))
|
|
RemoveEffect("IntCarryHeavy", this, nil, true);
|
|
|
|
//Stop the clonk from moving, and tell the clonk's control library
|
|
//it now has a hand action
|
|
me->SetTurnForced(GetDir());
|
|
me->SetHandAction(1);
|
|
SetAction("Stand");
|
|
//Stop the clonk if he is moving
|
|
if(GetXDir() != 0) 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 = AttachMesh(to_lift, "pos_tool1", to_lift->GetCarryBone(), to_lift->~GetCarryTransform(this));
|
|
|
|
//Play the animation of the clonk setting down the object
|
|
effect.anim = PlayAnimation("CarryArmsPickup", CLONK_ANIM_SLOT_Arms, Anim_Linear(GetAnimationLength("CarryArmsPickup"), GetAnimationLength("CarryArmsPickup"), 0, lib_carryheavy_lifttime, ANIM_Remove), Anim_Const(1000));
|
|
|
|
effect.obj = to_lift;
|
|
}
|
|
|
|
private func FxIntDropHeavyTimer(object me, proplist effect, int time)
|
|
{
|
|
if (time >= lib_carryheavy_lifttime)
|
|
return FX_Execute_Kill;
|
|
if (GetAction() != "Stand")
|
|
return FX_Execute_Kill;
|
|
if (!effect.obj)
|
|
return FX_Execute_Kill;
|
|
if (effect.obj->Contained() != this)
|
|
return FX_Execute_Kill;
|
|
}
|
|
|
|
private func FxIntDropHeavyStop(object me, proplist effect)
|
|
{
|
|
// Drop the object
|
|
if(effect.obj && effect.obj->Contained() == this)
|
|
effect.obj->Exit(0,9);
|
|
|
|
DetachMesh(effect.mesh);
|
|
StopAnimation(effect.anim);
|
|
me->SetTurnForced(-1);
|
|
me->SetHandAction(0);
|
|
if(GetAction() == "Stand") SetAction("Walk");
|
|
} |