openclonk/planet/Objects.ocd/Libraries.ocd/CarryHeavy.ocd/Script.c

238 lines
6.6 KiB
C

/*--
Carry-Heavy Library
Author: Ringwaul
Special circumstances for when the clonk is carrying heavy objects
--*/
local liftheavy_carrier;
local liftheavy_mesh;
local liftheavy_anim;
public func IsCarryHeavy() { return true; }
public func IsInvInteract() { return true; }
public func Grabbed(object clonk, bool grab)
{
if(grab)
{
if(clonk->ContentsCount() <= clonk->MaxContentsCount() - 2 && !FindObject(Find_Container(clonk), Find_Func("IsCarryHeavy")))
this->Enter(clonk);
else
{
//Clonk's inventory is full and cannot switch an item to his backpack
//so as to pick up the heavy object with both hands
CustomMessage("$TxtHandsFull$", clonk, clonk->GetController(), 0, 0, 0xff0000);
//Let go of object
clonk->SetAction("Walk");
//Clear animation
clonk->SetCommand("None");
return false;
}
//If there is an object in the clonk's primary hand slot, put it into the rucksack
if(clonk->ContentsCount() > 1)
{
if(clonk.inventory[0])
clonk->Switch2Items(0,EmptyHandSlot(clonk, 0));
if(clonk.inventory[1])
EmptyHandSlot(clonk, 1);
}
liftheavy_carrier = clonk;
//AddEffect("IntLiftHeavy", liftheavy_carrier, 1, 1, this);
}
}
public func EmptyHandSlot(object clonk, int handslot)
{
//find an empty slot. Switches handslot with a rucksack slot
for(var sackslot = 2; clonk.inventory[sackslot] != nil; sackslot++);
clonk->Switch2Items(handslot, sackslot);
return sackslot;
}
static const lift_heavy_time = 60;
func FxIntLiftHeavyTimer(object clonk, proplist effect, int timer)
{
//Lift the object
if(timer == 1)
{
//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
liftheavy_mesh = clonk->AttachMesh(this->GetID(), "pos_tool1", "main", this->~GetCarryTransform(clonk));
//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");
//Play the animation of the clonk picking up the object
liftheavy_anim = clonk->PlayAnimation("CarryArmsPickup", 10, Anim_Linear(0,0,clonk->GetAnimationLength("CarryArmsPickup"), lift_heavy_time, ANIM_Remove), Anim_Const(1000));
}
//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)
{
UndoLift(clonk);
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
UndoLift(clonk);
return -1;
}
}
}
//When the clonk has finished lifting, remove movement-restrictions and add carry effect
if(timer >= lift_heavy_time)
{
clonk->SetTurnForced(-1);
clonk->SetHandAction(0);
clonk->SetAction("Walk");
//Detach the object's mesh since it is applied in the next animation ("CarryArms") by another script
clonk->DetachMesh(liftheavy_mesh);
liftheavy_mesh = nil;
AddEffect("IntCarryHeavy", clonk, 1, 1, this);
return -1;
}
}
func FxIntDropHeavyTimer(object clonk, proplist effect, int timer)
{
//Drop the object
if(timer == 1)
{
liftheavy_mesh = clonk->AttachMesh(this->GetID(), "pos_tool1", "main", this->~GetCarryTransform(clonk));
clonk->SetTurnForced(clonk->GetDir());
clonk->SetHandAction(1);
clonk->SetAction("Stand");
//Play the animation of the clonk setting down the object
liftheavy_anim = clonk->PlayAnimation("CarryArmsSetdown", 10, Anim_Linear(0,0,clonk->GetAnimationLength("CarryArmsSetdown"), lift_heavy_time, ANIM_Remove), Anim_Const(1000));
}
//Clonk was interrupted?
if(clonk->GetAction() != "Stand")
{
UndoLift(clonk);
return -1;
}
if(timer >= lift_heavy_time)
{
clonk->SetTurnForced(-1);
clonk->SetHandAction(0);
clonk->SetAction("Walk");
clonk->DetachMesh(liftheavy_mesh);
liftheavy_mesh = nil;
return -1;
}
}
func UndoLift(object clonk)
{
//allow the clonk to turn again
clonk->SetTurnForced(-1);
clonk->SetHandAction(0);
if(clonk->GetAction() == "Stand") clonk->SetAction("Walk");
clonk->DetachMesh(liftheavy_mesh);
//Stop the lifting animation
clonk->StopAnimation(liftheavy_anim);
this->Exit();
}
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 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)
{
//Is there more than one carry-heavy object in the clonk? Then exit one
if(clonk->GetItemPos(this) !=0 && ObjectCount(Find_Func("IsCarryHeavy"), Find_Container(clonk)) > 1)
this->Exit();
//If the carry-heavy object is not in the first hand slot, move it there
if(clonk->GetItemPos(this) != 0)
clonk->Switch2Items(0,clonk->GetItemPos(this));
//Is there an object in the second hand slot? If so, remove it.
if(clonk.inventory[1])
{
//exclude carry-heavy objects from the counting process. Only counts normal items
var contentscount = clonk->ContentsCount();
if(FindObject(Find_Container(clonk), Find_Func("IsCarryHeavy"))) contentscount--;
if(contentscount < clonk->MaxContentsCount())
{
this->EmptyHandSlot(clonk, 1);
//If the clonk had an object dropped into his inventory by other means than collection, drop it
if(clonk.inventory[1])
{
clonk.inventory[1]->Exit();
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;
}
//In case the object is added via script, add the carry heavy effect
func Entrance(object container)
{
if(container->~IsClonk() && !IsCarryingHeavy())
AddEffect("IntLiftHeavy", container, 1, 1, this);
}
func RejectCollect(id collectid, object collect)
{
if(collect->~IsCarryHeavy()) return true;
else
return false;
}