openclonk/planet/Objects.ocd/Animals.ocd/Chippie.ocd/Script.c

386 lines
7.4 KiB
C

/**
Chippy
Small, lovely creatures.
*/
local Name = "$Name$";
local Description = "$Description$";
// Remember the attachee to be able to detach again.
local attach_object, attached_mesh;
// Remember the energy sucked to frequently spawn offsprings.
local energy_sucked;
public func Construction()
{
AddEffect("Activity", this, 1, 10, this);
SetAction("Walk");
energy_sucked = 0;
return true;
}
public func Destruction()
{
if (GetAction() == "Clawing")
StopClawing();
}
public func Death()
{
var particles =
{
Prototype = Particles_Material(RGB(50, 200, 50)),
OnCollision = PC_Bounce(),
DampingX = 900, DampingY = 900,
};
for (var particle_graphics in ["SmokeDirty", "Flash"])
{
CreateParticle(particle_graphics, PV_Random(-1, 1), PV_Random(-1, 1),
PV_Random(-20, 20), PV_Random(-20, 20),
PV_Random(20, 60), particles, 60);
}
Sound("Animals::Chippie::Chirp*", false, 50);
RemoveObject();
}
public func AttachTargetLost()
{
SetAction("Jump");
}
private func StartClawing()
{
AddEffect("Clawing", this, 1, 30, this);
}
private func StopClawing()
{
if (attach_object && attached_mesh != nil)
attach_object->DetachMesh(attached_mesh);
this.Visibility = VIS_All;
RemoveEffect("Clawing", this);
SetVertexXY(0, 0, -1);
}
private func FxClawingTimer(target, effect, time)
{
var e = GetActionTarget();
if(!e) return SetAction("Jump");
if((!e->GetAlive()) || GBackSemiSolid())
{
SetAction("Jump");
return;
}
if(!Random(3))
{
var damage = GetCon() * 10;
e->DoEnergy(-damage, true, FX_Call_EngGetPunched, GetOwner());
energy_sucked += damage;
if (energy_sucked > 10 * 1000)
{
LayEgg();
energy_sucked -= 10 * 1000;
}
// Grow and prosper.
if (GetCon() < 150 && !Random(10))
{
DoCon(1);
DoEnergy(5);
}
}
}
private func StartJump()
{
RotateGraphics(0, false);
if(!GetEffect("DmgShock", this) && !GetEffect("JumpCheck", this))
AddEffect("JumpCheck", this, 1, 4, this);
}
private func FxJumpCheckTimer(target, effect, time)
{
var e = FindObject(Find_AtPoint(), Find_OCF(OCF_Alive), Find_AnimalHostile(GetOwner()));
if(e)
{
ClawTo(e);
return -1;
}
}
private func ClawTo(object obj)
{
// Play the sound on the object, because the chippie turns invisible.
obj->Sound("Animals::Chippie::Bite*", false, 50);
energy_sucked += 5 * 1000;
obj->DoEnergy(-5, false, FX_Call_EngGetPunched, GetOwner());
// Woops, I broke it.
if (!obj || !obj->GetAlive()) return;
SetAction("Claw", obj);
SetVertexXY(0, obj->GetX() - GetX(), obj->GetY() - GetY());
// Special handling for the Clonk - attach directly to a random bone.
if (obj->~IsClonk())
{
var bone_name = ["skeleton_leg_upper.R", "skeleton_leg_upper.L",
"skeleton_arm_upper.R", "skeleton_arm_upper.L",
"pos_back2"][Random(5)];
attach_object = obj;
var scale = GetCon() * 1000 / 100;
attached_mesh = attach_object->AttachMesh(this, bone_name, "back",
Trans_Mul(Trans_Scale(scale, scale, scale), Trans_Rotate(Random(360), 0, 1, 0)));
// Hide the attached object.
this.Visibility = VIS_None;
}
else
{
this.MeshTransformation = Trans_Mul(Trans_Rotate(90, 0, 1, 0), Trans_Rotate(Random(360), 0, 0, 1));
}
}
private func EndJump()
{
RemoveEffect("JumpCheck", this);
}
private func StartWalk()
{
RotateGraphics(0, false);
}
private func StartScale()
{
RotateGraphics(90, false);
}
private func RotateGraphics(int r, bool mirror)
{
var transform = Trans_Rotate(r, 0, 0, 1);
if (mirror) transform = Trans_Mul(transform, Trans_Scale(-1000, 1000, 1000));
this.MeshTransformation = transform;
}
private func StartHangle()
{
RotateGraphics(180, true);
}
private func Jump()
{
SetAction("Jump");
SetSpeed(GetXDir(), -10 - GetXDir());
}
private func FxActivityTimer(target, effect, time)
{
if((GetAction() == "Jump") || (GetAction() == "Claw"))
{
return 1;
}
if(GetComDir() != COMD_Stop)
if(!Random(5)) Jump();
if(!GetEffect("DmgShock", this) && !GBackSemiSolid())
{
for(var enemy in FindObjects(Find_Distance(100), Find_OCF(OCF_Alive), Find_AnimalHostile(GetOwner()), Sort_Distance()))
{
if(!PathFree(GetX(), GetY(), enemy->GetX(), enemy->GetY())) continue;
if(enemy->GetX() < GetX())
SetComDir(COMD_Left);
else SetComDir(COMD_Right);
if(ObjectDistance(this, enemy) < 20)
{
SetAction("Jump");
var a = Angle(GetX(), GetY(), enemy->GetX(), enemy->GetY());
SetSpeed(Sin(a, 20), -Cos(a, 20) - 2);
}
return 1;
}
if(GetEffect("DoDance", this))
{
if(GetAction() == "Walk")
{
SetComDir(COMD_Stop);
Jump();
return 1;
}
}
else
if(!Random(20) && !GetEffect("DanceCooldown", this))
{
Sound("Animals::Chippie::Talk*");
var cnt = 0;
for(var obj in FindObjects(Find_Distance(100), Find_ID(GetID()), Find_Allied(GetOwner()), Sort_Distance()))
{
if(++cnt > 5) break;
obj->AddEffect("DoDance", obj, 1, 35*5, obj);
obj->AddEffect("DanceCooldown", obj, 1, 35*10, obj);
}
if(!GetEffect("EggCooldown", this))
{
if(!Random(10))
{
LayEgg();
}
}
}
}
if(!Random(5))
{
if(Random(2))
SetComDir(COMD_Right);
else SetComDir(COMD_Left);
} else SetComDir(COMD_Stop);
return 1;
}
private func FxActivityDamage(target, effect, dmg)
{
if(dmg > 0) return dmg;
AddEffect("DmgShock", this, 1, 35*5, this);
return dmg;
}
private func LayEgg()
{
if(GetEffect("DmgShock", this)) return;
var o = CreateObject(Chippie_Egg, 0, 0, GetOwner());
o->SetSpeed(-GetXDir(), -GetYDir());
o->SetCon(50);
o->StartGrowth(10);
AddEffect("EggCooldown", this, 1, 35*30, this);
}
local MaxEnergy = 10000;
local MaxBreath = 10000;
local NoBurnDecay = 1;
local ContactIncinerate = 15;
local CorrosionResist = 1;
local BorderBound = C4D_Border_Sides;
local ContactCalls = true;
local ActMap = {
Walk = {
Prototype = Action,
Name = "Walk",
Procedure = DFA_WALK,
Accel = 16,
Decel = 22,
Speed = 100,
Directions = 2,
FlipDir = 1,
Length = 20,
Delay = 1,
Animation = "Move",
StartCall = "StartWalk"
},
Swim = {
Prototype = Action,
Name = "Swim",
Procedure = DFA_SWIM,
Accel = 16,
Decel = 22,
Speed = 100,
Directions = 2,
FlipDir = 1,
Length = 20,
Delay = 1,
Animation = "Move",
StartCall = "StartWalk"
},
Scale = {
Prototype = Action,
Name = "Scale",
Procedure = DFA_SCALE,
Accel = 16,
Decel = 22,
Speed = 50,
Directions = 2,
FlipDir = 1,
Length = 20,
Delay = 2,
Animation = "Move",
StartCall = "StartScale"
},
Hangle = {
Prototype = Action,
Name = "Hangle",
Procedure = DFA_HANGLE,
Accel = 16,
Decel = 22,
Speed = 50,
Directions = 2,
FlipDir = 1,
Length = 20,
Delay = 2,
Animation = "Move",
StartCall = "StartHangle"
},
Kneel = {
Prototype = Action,
Name = "Kneel",
Procedure = DFA_KNEEL,
Directions = 2,
FlipDir = 1,
Length = 20,
Delay = 2,
Animation = "Move",
NextAction = "Walk",
},
Jump = {
Prototype = Action,
Name = "Jump",
Procedure = DFA_FLIGHT,
Speed = 200,
Accel = 14,
Directions = 2,
FlipDir = 1,
Length = 20,
Delay = 2,
Animation = "Move",
StartCall = "StartJump",
EndCall = "EndJump",
AbortCall = "EndJump"
},
Dead = {
Prototype = Action,
Name = "Dead",
Directions = 2,
FlipDir = 1,
Length = 10,
Delay = 3,
Animation = "Move",
NextAction = "Hold",
NoOtherAction = 1,
ObjectDisabled = 1,
},
Claw = {
Prototype = Action,
Name = "Claw",
Procedure = DFA_ATTACH,
Directions = 2,
FlipDir = 1,
Length = 1,
Delay = 0,
Animation = "Move",
NextAction = "Hold",
StartCall = "StartClawing",
EndCall = "StopClawing",
AbortCall = "StopClawing",
},
};