openclonk/planet/Objects.ocd/Items.ocd/Tools.ocd/TeleGlove.ocd/Script.c

275 lines
6.4 KiB
C

/*--
TeleGlove
Author: Ringwaul
Move objects remotely.
--*/
local reach;
local radius; //actual effect radius to grab objects
local radiusparticle; //radius of particles around object
local aiming;
local anim_spin;
local iAngle;
local aim_anim;
local carry_bone;
local target_object;
protected func Initialize()
{
reach = 150;
radius = 60;
radiusparticle = 60;
}
public func GetCarryMode() { return CARRY_HandBack; }
public func GetCarrySpecial(clonk) { return carry_bone; }
public func GetCarryBone() { return "main"; }
public func GetCarryTransform()
{
//Left hand's bone is different? I don't know, but this is a work-around.
if(carry_bone == "pos_hand1") return Trans_Rotate(180,0,0,1);
return Trans_Rotate(-90,0,0,1);
}
protected func HoldingEnabled() { return true; }
protected func ControlUseStart(object clonk, ix, iy)
{
// if the clonk doesn't have an action where he can use it's hands do nothing
if(!clonk->HasHandAction() || (!clonk->IsWalking() && !clonk->IsJumping()))
return true;
else
{
StartUsage(clonk);
UpdateGloveAngle(clonk, ix, iy);
}
return 1;
}
private func StartUsage(object clonk)
{
var hand;
// which animation to use? (which hand)
if(clonk->GetHandPosByItemPos(clonk->GetItemPos(this)) == 0)
{
carry_bone = "pos_hand2";
hand = "AimArmsGeneric.R";
}
else
{
carry_bone = "pos_hand1";
hand = "AimArmsGeneric.L";
}
aiming = 1;
aim_anim = clonk->PlayAnimation(hand, 10, Anim_Const(clonk->GetAnimationLength(hand)/2), Anim_Const(1000));
clonk->UpdateAttach();
//Animations and effects for TeleGlove
Sound("Electrical",nil,nil,nil,+1);
PlayAnimation("Opening", -5, Anim_Linear(0,0,GetAnimationLength("Opening"), 10, ANIM_Hold), Anim_Const(1000));
anim_spin = PlayAnimation("Spin",5, Anim_Linear(0,0,GetAnimationLength("Spin"), 40, ANIM_Loop), Anim_Const(1000));
}
private func EndUsage(object clonk)
{
carry_bone = nil;
aim_anim = nil;
iAngle = 0;
clonk->StopAnimation(clonk->GetRootAnimation(10));
clonk->UpdateAttach();
}
// Update the glove aim angle
private func UpdateGloveAngle(object clonk, num x, num y)
{
var angle=Normalize(Angle(0,0, x,y),-180);
angle=BoundBy(angle,-150,150);
if(clonk->GetDir() == DIR_Left)
{
if(angle > 0) return;
}
else
{
if(angle < 0) return;
}
iAngle=angle;
// var weight = 0;
// if( Abs(iAngle) > 90) weight = 1000*( Abs(iAngle)-60 )/90;
clonk->SetAnimationPosition(aim_anim, Anim_Const(Abs(iAngle) * 11111/1000));
}
public func ControlUseHolding(object clonk, ix, iy)
{
if(!clonk->HasHandAction() || !aiming || (!clonk->IsWalking() && !clonk->IsJumping()))
{
CancelUse(clonk);
return 1;
}
UpdateGloveAngle(clonk, ix, iy);
//effects
var xs = Sin(Random(359),radiusparticle/2);
var ys = -Cos(Random(359),radiusparticle/2);
var anglep = Angle(0,0,ix,iy);
var distp = Distance(0,0,ix,iy);
if(distp < reach)
{
//Particles moving towards object
for(var i; i < 2; i++)
{
CreateParticle("Spark1", ix + xs, iy + ys, -xs/3, -ys/3, RandomX(30,90), RGB(185,250,250));
CreateParticle("Spark2", ix + xs, iy + ys, -xs/3, -ys/3, RandomX(30,90), RGB(185,250,250));
}
//Particles emitting from clonk
var wp = 1;
if(Random(2)) wp = -1;
var xp = anglep - 90 + (Angle(0,0,distp,radiusparticle/2 * wp));
var yp = anglep - 90 + (Angle(0,0,distp,radiusparticle/2 * wp));
CreateParticle("Spark1", Sin(xp, Random(distp)), -Cos(yp, Random(distp)), Sin(xp, 10), -Cos(yp, 10), RandomX(30,90), RGB(185,250,250));
}
var target;
if(target_object)
{
radiusparticle = 30;
if(Distance(target_object->GetX(), target_object->GetY(), clonk->GetX() + ix, clonk->GetY() + iy) > radius ||
Distance(target_object->GetX(), target_object->GetY(), clonk->GetX(), clonk->GetY()) > reach)
{
LostTargetObject(target);
target_object = nil;
}
}
if(!target_object)
{
radiusparticle = 60;
target = FindObject(Find_Exclude(this),
Find_NoContainer(),
Find_Category(C4D_Object),
Find_And(Find_Distance(radius, ix, iy),
Find_Distance(reach - 15)),
Sort_Distance(ix,iy));
if(target)
{
GainedTargetObject(target);
target_object = target;
}
}
//Has the object recently been thrown by another player?
var e = GetEffect("TeleGloveReleased", target_object);
var old_controller; if(e) old_controller = e.controller;
if(target_object
&& !target_object->Stuck()
&& (!e || old_controller == Contained()->GetOwner()))
{
var angle = Angle(target_object->GetX(), target_object->GetY(), clonk->GetX() + ix, clonk->GetY() + iy);
var dist = Distance(target_object->GetX(), target_object->GetY(), clonk->GetX() + ix, clonk->GetY() + iy);
var speed = dist;
//Set speed
target_object->SetSpeed(Sin(angle, speed), -Cos(angle, speed));
//Particles emitting from object
target_object->CreateParticle("Spark1", 0, 0, xs/10, ys/10, RandomX(20,40), RGB(185,250,250));
}
else
LostTargetObject(target_object);
return 1;
}
public func GainedTargetObject(object target)
{
if(!GetEffect("TeleGloveWeight", target))
{
//Who holds the object? For killtracing
target->SetController(Contained()->GetController());
AddEffect("TeleGloveWeight", target, 1, 0, target);
return 1;
}
else
return 0;
}
public func LostTargetObject(object target)
{
RemoveEffect("TeleGloveWeight", target);
var effect = AddEffect("TeleGloveReleased", target, 1, 35*5);
effect.controller = Contained()->GetController();
}
global func FxTeleGloveReleasedStart(object target, effect)
{
return;
}
global func FxTeleGloveWeightStart(object target, int num)
{
target->SetMass(target->GetMass()/2);
}
global func FxTeleGloveWeightStop(object target, int num, int reason, bool temp)
{
target->SetMass(target->GetDefCoreVal("Mass", "DefCore"));
}
protected func ControlUseStop(object clonk, ix, iy)
{
CancelUse(clonk);
return 1;
}
protected func ControlUseCancel(object clonk, num ix, num iy)
{
CancelUse(clonk);
}
protected func CancelUse(object clonk)
{
EndUsage(clonk);
Sound("Electrical",nil,nil,nil,-1);
if(aiming = 1) PlayAnimation("Closing", -5, Anim_Linear(0,0,GetAnimationLength("Closing"), 10, ANIM_Hold), Anim_Const(1000));
StopAnimation(anim_spin);
aiming = 0;
if(target_object) LostTargetObject(target_object);
target_object = nil;
radiusparticle = 60;
return 1;
}
func Hit()
{
Sound("GeneralHit?");
}
func IsInventorProduct() { return true; }
func Definition(def) {
SetProperty("PictureTransformation",Trans_Rotate(-60,1,0,1),def);
}
local Name = "$Name$";
local UsageHelp = "$UsageHelp$";
local Description = "$Description$";
local Collectible = 1;
local Rebuy = true;