openclonk/planet/Objects.ocd/Libraries.ocd/CarryHeavyControl.ocd/Script.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 object 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");
}