forked from Mirrors/openclonk
925 lines
17 KiB
C
925 lines
17 KiB
C
/**
|
|
Mooq
|
|
Author: jok
|
|
*/
|
|
|
|
// Animations
|
|
local turn_angle;
|
|
// Color
|
|
local color;
|
|
// The closest enemy that has been found.
|
|
local enemy;
|
|
// Closest food that has been found.
|
|
local food;
|
|
|
|
public func Place(int amount, proplist rectangle, proplist settings)
|
|
{
|
|
var max_tries = 3 * amount;
|
|
var loc_area = nil;
|
|
if (rectangle) loc_area = Loc_InArea(rectangle);
|
|
var animal;
|
|
|
|
while ((amount > 0) && (--max_tries > 0))
|
|
{
|
|
// Try to find walkable ground near lava.
|
|
var lava_spot = FindLocation(Loc_Material("DuroLava"));
|
|
var ground_spot = nil;
|
|
if (lava_spot)
|
|
{
|
|
var lava_rectangle = Shape->Rectangle(lava_spot.x - 200, lava_spot.y - 200, 400, 400);
|
|
// Make sure the position is inside the required target rectangle.
|
|
lava_rectangle = Shape->Intersect(lava_rectangle, rectangle)->GetBoundingRectangle();
|
|
ground_spot = FindLocation(Loc_Wall(CNAT_Bottom), Loc_Or(Loc_Sky(), Loc_Tunnel()), Loc_Space(20, CNAT_Top), Loc_InArea(lava_rectangle));
|
|
}
|
|
|
|
// If no hip and cool spot found, just get some generic spot.
|
|
if (!ground_spot) ground_spot = FindLocation(Loc_Wall(CNAT_Bottom), Loc_Or(Loc_Sky(), Loc_Tunnel()), Loc_Space(20, CNAT_Top), loc_area);
|
|
if (!ground_spot) continue;
|
|
|
|
animal = CreateObjectAbove(this, ground_spot.x, ground_spot.y, NO_OWNER);
|
|
if (!animal) continue;
|
|
|
|
if (animal->Stuck())
|
|
{
|
|
animal->RemoveObject();
|
|
continue;
|
|
}
|
|
--amount;
|
|
}
|
|
return animal;
|
|
}
|
|
|
|
func Construction()
|
|
{
|
|
turn_angle = -60;
|
|
color = 255;
|
|
|
|
AddEffect("IntActivity", this, 1, 10, this);
|
|
AddTimer("UpdateEnemy", 30);
|
|
AddTimer("UpdateFood", 60);
|
|
|
|
Stop();
|
|
CheckTurn(GetDir());
|
|
|
|
SetTailOnFire();
|
|
}
|
|
|
|
func Death()
|
|
{
|
|
RemoveTimer("UpdateEnemy");
|
|
RemoveTimer("UpdateFood");
|
|
RemoveEffect("IntActivity", this);
|
|
|
|
Sound("Animals::Mooq::Die*");
|
|
}
|
|
|
|
func CatchBlow(int damage, object from)
|
|
{
|
|
Schedule(this, "Sound(\"Animals::Mooq::Hurt*\")", RandomX(5, 20));
|
|
}
|
|
|
|
/* Action Callbacks */
|
|
|
|
func CheckStuck()
|
|
{
|
|
// Prevents getting stuck on middle vertex
|
|
if(!GetXDir())
|
|
if(Abs(GetYDir()) < 5)
|
|
if(GBackSolid(0, 3))
|
|
SetPosition(GetX(), GetY() - 1);
|
|
}
|
|
|
|
func ClearActivity()
|
|
{
|
|
this.Activity = nil;
|
|
}
|
|
|
|
func StartSwim()
|
|
{
|
|
this.Activity = this.ActivitySwimming;
|
|
}
|
|
|
|
func StartWalk()
|
|
{
|
|
SetTailOnFire();
|
|
this.Activity = this.ActivityWalking;
|
|
}
|
|
|
|
func SpitPhase()
|
|
{
|
|
if(GetActTime() > 45 && GetActTime() < 65)
|
|
{
|
|
if(!Random(4))
|
|
{
|
|
var iX, iY;
|
|
iX = 5;
|
|
if (!GetDir()) iX = -iX;
|
|
iY = -4;
|
|
Smoke(iX,iY,5);
|
|
}
|
|
}
|
|
if(GetActTime() == 58)
|
|
{
|
|
var iX, iY, iXDir, iYDir;
|
|
iX = 10;
|
|
if (!GetDir()) iX = -iX;
|
|
iY = -4;
|
|
iXDir = 300;
|
|
if (!GetDir()) iXDir = -iXDir;
|
|
iYDir = -300;
|
|
|
|
Sound("Animals::Mooq::Spit*");
|
|
|
|
var obj = CreateContents(Mooq_Firebomb);
|
|
obj->Exit(iX, iY);
|
|
obj->SetXDir(iXDir,100);
|
|
obj->SetYDir(iYDir,100);
|
|
}
|
|
}
|
|
|
|
func EatPhase()
|
|
{
|
|
var actt = GetActTime();
|
|
|
|
if(actt > 13 && actt < 25)
|
|
{
|
|
if(!Random(4))
|
|
{
|
|
var iX, iY;
|
|
iX = 5;
|
|
if (!GetDir()) iX = -iX;
|
|
iY = 4;
|
|
Smoke(iX,iY,5);
|
|
}
|
|
}
|
|
if(actt == 22)
|
|
{
|
|
if (!food) return;
|
|
|
|
Sound("Animals::Mooq::Munch*");
|
|
DoEnergy(food->GetMass());
|
|
food->RemoveObject();
|
|
}
|
|
if(actt > 43 && actt < 55)
|
|
{
|
|
if(!Random(4))
|
|
{
|
|
var iX, iY;
|
|
iX = 5;
|
|
if (!GetDir()) iX = -iX;
|
|
iY = 1;
|
|
Smoke(iX,iY,5);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Activity */
|
|
|
|
func ActivitySwimming()
|
|
{
|
|
CheckBreathe();
|
|
if(GetMaterial() == Material("Water"))
|
|
CheckFossilize();
|
|
|
|
// Stuck?
|
|
if (GetComDir() && !GetXDir() && !GetYDir())
|
|
{
|
|
DoJump(true);
|
|
return Swim(Random(2));
|
|
}
|
|
|
|
// Fossilizing?
|
|
if(GetEffect("IntFossilizing", this))
|
|
{
|
|
var lava_spot = FindLava();
|
|
if (lava_spot)
|
|
return TaskSwimTo(lava_spot);
|
|
}
|
|
|
|
if (enemy && Random(2)) return TaskSwimTo(enemy);
|
|
|
|
if (!enemy && food) return TaskSwimTo(food);
|
|
|
|
if (!Random(6)) return Swim(Random(2));
|
|
|
|
if (!Random(6)) return DoJump(true);
|
|
}
|
|
|
|
func ActivityWalking()
|
|
{
|
|
// Stuck?
|
|
if (GetComDir() && !GetXDir() && !GetYDir())
|
|
{
|
|
if(GetDir())
|
|
Walk(0);
|
|
else
|
|
Walk(1);
|
|
return DoJump();
|
|
}
|
|
|
|
// Fossilizing?
|
|
if(GetEffect("IntFossilizing", this))
|
|
{
|
|
var lava_spot = FindLava();
|
|
if (lava_spot) return TaskWalkTo(lava_spot);
|
|
}
|
|
|
|
// If enemy, hopefully attack!
|
|
if (enemy)
|
|
{
|
|
var distance = ObjectDistance(this, enemy);
|
|
|
|
if (distance < 50 && Random(2)) return TaskHeadbutt(distance);
|
|
|
|
if (Inside(distance, 85, 145) && !Random(5)) return TaskSpit();
|
|
}
|
|
|
|
// If no enemy, go to food and eat.
|
|
if (!enemy && food) return TaskFood();
|
|
|
|
// If not walking, randomly idle.
|
|
if (GetAction() == "Stand")
|
|
{
|
|
if (!enemy && !food)
|
|
{
|
|
// Idle?
|
|
if (!Random(15)) return TaskIdle();
|
|
}
|
|
|
|
if (!Random(5)) return Walk(Random(2));
|
|
|
|
return;
|
|
}
|
|
|
|
if (!Random(5)) return Stop();
|
|
|
|
if (!Random(5)) return Walk(Random(2));
|
|
|
|
if (GetAction() == "Walk")
|
|
{
|
|
if (!Random(5)) return DoJump();
|
|
}
|
|
|
|
// Anticipate holes in the landscape while walking.
|
|
|
|
}
|
|
|
|
func FxIntActivityTimer(target, effect, time)
|
|
{
|
|
if (this.Activity) this->Activity();
|
|
if (!GetAlive()) return -1;
|
|
return 1;
|
|
}
|
|
|
|
func FxIntActivityDamage(target, effect, dmg)
|
|
{
|
|
if (dmg > 0) return dmg;
|
|
return dmg;
|
|
}
|
|
|
|
/* Tasks */
|
|
|
|
func TaskIdle()
|
|
{
|
|
Sound("Animals::Mooq::Snorting*");
|
|
|
|
if (!Random(3)) return SetAction("IdleSit");
|
|
if (!Random(2)) return SetAction("IdleStand");
|
|
|
|
return SetAction("IdleTailwave");
|
|
}
|
|
|
|
func TaskFood()
|
|
{
|
|
var distance = ObjectDistance(this, food);
|
|
if (distance < 11) return Eat();
|
|
|
|
return TaskWalkTo(food);
|
|
}
|
|
|
|
func TaskHeadbutt(distance)
|
|
{
|
|
if (distance < 11) return Headbutt();
|
|
|
|
return TaskWalkTo(enemy);
|
|
}
|
|
|
|
func TaskSpit()
|
|
{
|
|
var eX = enemy->GetX();
|
|
var iX = GetX();
|
|
|
|
if (iX < eX)
|
|
{
|
|
if (GetDir() != DIR_Right) return Turn(DIR_Right);
|
|
Stop();
|
|
return Spit();
|
|
} else {
|
|
if (GetDir() != DIR_Left) return Turn(DIR_Left);
|
|
Stop();
|
|
return Spit();
|
|
}
|
|
}
|
|
|
|
func TaskWalkTo(spot)
|
|
{
|
|
var iX = GetX();
|
|
var iY = GetY();
|
|
|
|
if (GetType(spot) == C4V_C4Object)
|
|
{
|
|
var sX = spot->GetX();
|
|
var sY = spot->GetY();
|
|
}
|
|
else if (GetType(spot) == C4V_PropList)
|
|
{
|
|
var sX = spot.x;
|
|
var sY = spot.y;
|
|
}
|
|
else return;
|
|
|
|
if (iX < sX)
|
|
{
|
|
if (GetDir() == DIR_Right)
|
|
if (iY > sY + 6)
|
|
if (Random(2)) if(DoJump())
|
|
return true;
|
|
|
|
return Walk(DIR_Right);
|
|
} else {
|
|
if (GetDir() == DIR_Left)
|
|
if(iY > sY + 6)
|
|
if(Random(2)) if(DoJump())
|
|
return true;
|
|
return Walk(DIR_Left);
|
|
}
|
|
}
|
|
|
|
func TaskSwimTo(spot)
|
|
{
|
|
var iX = GetX();
|
|
var iY = GetY();
|
|
|
|
if (GetType(spot) == C4V_C4Object)
|
|
{
|
|
var sX = spot->GetX();
|
|
var sY = spot->GetY();
|
|
}
|
|
else if (GetType(spot) == C4V_PropList)
|
|
{
|
|
var sX = spot.x;
|
|
var sY = spot.y;
|
|
}
|
|
else return;
|
|
|
|
if (iX < sX)
|
|
{
|
|
if (GetDir() == DIR_Right)
|
|
if(iY > sY)
|
|
if(DoJump(true))
|
|
return true;
|
|
|
|
return Swim(DIR_Right);
|
|
} else {
|
|
if (GetDir() == DIR_Left)
|
|
if(iY > sY)
|
|
if(DoJump(true))
|
|
return true;
|
|
return Swim(DIR_Left);
|
|
}
|
|
}
|
|
|
|
/* Actions */
|
|
|
|
func Stop()
|
|
{
|
|
SetComDir(COMD_Stop);
|
|
SetXDir(0);
|
|
return SetAction("Stand");
|
|
}
|
|
|
|
func Turn(int dir, bool move)
|
|
{
|
|
if (dir == nil)
|
|
{
|
|
if (GetDir() == DIR_Left)
|
|
dir = DIR_Right;
|
|
else
|
|
dir = DIR_Left;
|
|
}
|
|
|
|
if(GetDir() == dir) return;
|
|
|
|
return CheckTurn(dir, move);
|
|
}
|
|
|
|
func Walk(int dir)
|
|
{
|
|
if (GetAction() != "Stand" && GetAction() != "Walk") return;
|
|
|
|
if (GetDir() == dir)
|
|
{
|
|
SetAction("Walk");
|
|
if (GetDir())
|
|
return SetComDir(COMD_Right);
|
|
else
|
|
return SetComDir(COMD_Left);
|
|
}
|
|
|
|
return Turn(dir, true);
|
|
}
|
|
|
|
func Swim(int dir)
|
|
{
|
|
if (GetAction() != "Swim") return;
|
|
|
|
if (GetDir() == dir)
|
|
{
|
|
SetAction("Swim");
|
|
if (GetDir())
|
|
return SetComDir(COMD_UpRight);
|
|
else
|
|
return SetComDir(COMD_UpLeft);
|
|
}
|
|
|
|
return Turn(dir, true);
|
|
}
|
|
|
|
func DoJump(bool swimming)
|
|
{
|
|
if (GetAction() != "Walk" && GetAction() != "Stand" && GetAction() != "Swim") return;
|
|
|
|
if (swimming)
|
|
{
|
|
if (GBackSky(0, -2))
|
|
SetPosition(GetX(), GetY() - 2);
|
|
else
|
|
return;
|
|
|
|
var iX, iY, iXDir, iYDir;
|
|
iX = 10;
|
|
if (!GetDir()) iX = -iX;
|
|
iY = -4;
|
|
iXDir = 200;
|
|
if (!GetDir()) iXDir = -iXDir;
|
|
iYDir = -200;
|
|
|
|
if (Random(2)) Sound("Animals::Mooq::Snort*");
|
|
|
|
SetSpeed(iXDir + GetXDir(100), iYDir + GetYDir(100), 100);
|
|
return true;
|
|
}
|
|
|
|
if (Random(2)) Sound("Animals::Mooq::Snort*");
|
|
return Jump();
|
|
}
|
|
|
|
func Spit()
|
|
{
|
|
if (GetAction() == "Stand") return SetAction("Spit");
|
|
}
|
|
|
|
func Eat(object food)
|
|
{
|
|
Stop();
|
|
if (GetAction() == "Stand") return SetAction("Eat");
|
|
}
|
|
|
|
func Headbutt()
|
|
{
|
|
if (GetAction() != "Walk") return;
|
|
|
|
Punch(enemy, 10);
|
|
return SetAction("Headbutt");
|
|
}
|
|
|
|
/* FindEnemy */
|
|
|
|
func UpdateEnemy()
|
|
{
|
|
// Already disposed of the last one?
|
|
if (enemy && !enemy->GetAlive()) enemy = nil;
|
|
// Last one too far away now?
|
|
if (enemy && ObjectDistance(this, enemy) > 250) enemy = nil;
|
|
// Slid in water?
|
|
if (enemy && enemy->GBackLiquid()) enemy = nil;
|
|
|
|
var x = GetX();
|
|
var y = GetY();
|
|
for (var obj in FindObjects(Find_Distance(200), Find_OCF(OCF_Alive), Find_AnimalHostile(GetOwner()), Sort_Distance()))
|
|
{
|
|
if (!PathFree(x, y, obj->GetX(), obj->GetY())) continue;
|
|
if (obj->GBackLiquid()) continue;
|
|
enemy = obj;
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* FindFood */
|
|
|
|
func UpdateFood()
|
|
{
|
|
// Need food?
|
|
if (GetEnergy() >= MaxEnergy/1000) return food = nil;
|
|
// Last one too far away now?
|
|
if (food && ObjectDistance(this, food) > 150) food = nil;
|
|
// Slid in water?
|
|
if (food && food->GBackLiquid()) food = nil;
|
|
|
|
var x = GetX();
|
|
var y = GetY();
|
|
var Find_FoodIDs = Find_Or(Find_ID(Rock), Find_ID(Coal), Find_ID(Ore));
|
|
for (var obj in FindObjects(Find_Distance(100), Find_FoodIDs, Sort_Distance()))
|
|
{
|
|
if (!PathFree(x, y, obj->GetX(), obj->GetY())) continue;
|
|
if (obj->GBackLiquid()) continue;
|
|
food = obj;
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* FindLava */
|
|
|
|
func FindLava()
|
|
{
|
|
var lava_spot = FindLocation(Loc_Material("DuroLava"), Loc_Space(20));
|
|
if (lava_spot) return lava_spot;
|
|
|
|
var lava_spot = FindLocation(Loc_Material("Lava"), Loc_Space(20));
|
|
if (lava_spot) return lava_spot;
|
|
|
|
return;
|
|
}
|
|
|
|
/* Turning */
|
|
|
|
func CheckTurn(int dir, bool move)
|
|
{
|
|
if (!GetEffect("IntTurning", this))
|
|
{
|
|
SetDir(dir);
|
|
AddEffect("IntTurning", this, 1, 1, this, nil, move);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
func FxIntTurningStart(object target, effect fx, temp, move)
|
|
{
|
|
fx.mvmn = move;
|
|
|
|
if (!InLiquid())
|
|
{
|
|
Stop();
|
|
SetAction("Turn");
|
|
} else {
|
|
SetComDir(COMD_Stop);
|
|
SetXDir(0);
|
|
SetAction("SwimTurn");
|
|
}
|
|
|
|
if (temp) return true;
|
|
}
|
|
|
|
func FxIntTurningTimer(object target, effect fx, int time)
|
|
{
|
|
if (GetDir() == DIR_Left)
|
|
turn_angle += 15;
|
|
else
|
|
turn_angle -= 15;
|
|
|
|
if (turn_angle < -60 || turn_angle > 180)
|
|
{
|
|
turn_angle = BoundBy(turn_angle, -60, 180);
|
|
this.MeshTransformation = Trans_Rotate(turn_angle + 180 + 30,0,1,0);
|
|
return -1;
|
|
}
|
|
this.MeshTransformation = Trans_Rotate(turn_angle + 180 + 30,0,1,0);
|
|
return 1;
|
|
}
|
|
|
|
func FxIntTurningStop(object target, effect fx, temp)
|
|
{
|
|
if (fx.mvmn)
|
|
{
|
|
if (!InLiquid())
|
|
{
|
|
if (GetDir()) SetComDir(COMD_Right);
|
|
else SetComDir(COMD_Left);
|
|
return SetAction("Walk");
|
|
}
|
|
|
|
if (GetDir()) SetComDir(COMD_UpRight);
|
|
else SetComDir(COMD_UpLeft);
|
|
return SetAction("Swim");
|
|
}
|
|
}
|
|
|
|
/* Breathing */
|
|
|
|
func CheckBreathe()
|
|
{
|
|
if (!GetEffect("IntBreathing", this)) AddEffect("IntBreathing", this, 1, 1, this, nil);
|
|
}
|
|
|
|
func FxIntBreathingStart(object target, effect fx, temp)
|
|
{
|
|
if (temp) return true;
|
|
}
|
|
|
|
func FxIntBreathingTimer(object target, effect fx, int time)
|
|
{
|
|
DoBreath(MaxBreath - GetBreath());
|
|
if (!InLiquid()) return -1;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* Fossilizing */
|
|
|
|
func CheckFossilize()
|
|
{
|
|
if (!GetEffect("IntFossilizing", this))
|
|
// Ca. 60 seconds till death without lava
|
|
AddEffect("IntFossilizing", this, 1, 11, this, nil);
|
|
}
|
|
|
|
func FxIntFossilizingStart(object target, effect fx, temp)
|
|
{
|
|
if (temp) return true;
|
|
}
|
|
|
|
func FxIntFossilizingTimer(object target, effect fx, int time)
|
|
{
|
|
if (GetMaterial() == Material("DuroLava") || GetMaterial() == Material("Lava"))
|
|
{
|
|
color++;
|
|
if (Speed < MaxSpeed) Speed += Random(2);
|
|
if (JumpSpeed < MaxJumpSpeed)
|
|
{
|
|
JumpSpeed += Random(3);
|
|
if(JumpSpeed > MaxJumpSpeed) JumpSpeed = MaxJumpSpeed;
|
|
}
|
|
} else {
|
|
color--;
|
|
if (Speed > 0) Speed -= Random(2);
|
|
if (JumpSpeed > 0)
|
|
{
|
|
JumpSpeed -= Random(3);
|
|
if(JumpSpeed < 0) JumpSpeed = 0;
|
|
}
|
|
}
|
|
if (color < 45 || color > 255)
|
|
{
|
|
color = BoundBy(color, 45, 255);
|
|
SetClrModulation(RGBa(color, color, color, 255));
|
|
return -1;
|
|
}
|
|
SetClrModulation(RGBa(color, color, color, 255));
|
|
|
|
return 1;
|
|
}
|
|
|
|
func FxIntFossilizingStop(object target, effect fx, temp)
|
|
{
|
|
if (GetMaterial() == Material("DuroLava") || GetMaterial() == Material("Lava")) return SetAction("Swim");
|
|
else return Kill();
|
|
}
|
|
|
|
/* Burning Tail */
|
|
|
|
func SetTailOnFire()
|
|
{
|
|
if (!GetEffect("IntTailBurning", this))
|
|
AddEffect("IntTailBurning", this, 1, 2, this, nil);
|
|
}
|
|
|
|
func FxIntTailBurningStart(object target, effect fx, temp)
|
|
{
|
|
fx.fire = {
|
|
R = 200 + Random(55),
|
|
G = 200 + Random(55),
|
|
B = 200 + Random(55),
|
|
Alpha = PV_Linear(255, 0),
|
|
Size = 4,
|
|
Phase = PV_Linear(0, 9),
|
|
DampingX = 1000,
|
|
DampingY = 1000,
|
|
Attach = ATTACH_MoveRelative
|
|
};
|
|
|
|
if (temp) return true;
|
|
}
|
|
|
|
func FxIntTailBurningTimer(object target, effect fx, int time)
|
|
{
|
|
if (!GetAlive() || InLiquid())
|
|
{
|
|
var level;
|
|
level = 5 ?? 10;
|
|
var particles = Particles_Smoke();
|
|
particles.Size = PV_Linear(PV_Random(level/2, level), PV_Random(2 * level, 3 * level));
|
|
var pos = [3, -1, 0];
|
|
var dir = [PV_Random(-level/3, level/3), PV_Random(-level/2, -level/3), 0];
|
|
CreateParticleAtBone("Smoke", "tail_3", pos, dir, PV_Random(level * 2, level * 10), particles, BoundBy(level/5, 3, 20));
|
|
return -1;
|
|
}
|
|
|
|
var pos = [3, -1, 0];
|
|
var dir = [0, 0, 0];
|
|
CreateParticleAtBone("Fire", "tail_3", pos, dir, 5, fx.fire, 1);
|
|
return 1;
|
|
}
|
|
|
|
/* ActMap */
|
|
|
|
local ActMap = {
|
|
|
|
Walk = {
|
|
Prototype = Action,
|
|
Name = "Walk",
|
|
Procedure = DFA_WALK,
|
|
Speed = Speed,
|
|
Accel = 4,
|
|
Decel = 22,
|
|
Directions = 2,
|
|
FlipDir = 0,
|
|
Length = 12,
|
|
Delay = 1,
|
|
Animation = "Walk",
|
|
StartCall = "StartWalk",
|
|
InLiquidAction = "Swim",
|
|
},
|
|
Swim = {
|
|
Prototype = Action,
|
|
Name = "Swim",
|
|
Procedure = DFA_SWIM,
|
|
Speed = Speed,
|
|
Accel = 16,
|
|
Decel = 22,
|
|
Directions = 2,
|
|
FlipDir = 0,
|
|
Length = 12,
|
|
Delay = 1,
|
|
Animation = "Swim",
|
|
StartCall = "StartSwim",
|
|
},
|
|
Jump = {
|
|
Prototype = Action,
|
|
Name = "Jump",
|
|
Procedure = DFA_FLIGHT,
|
|
Speed = 200,
|
|
Accel = 14,
|
|
Directions = 2,
|
|
FlipDir = 0,
|
|
Length = 20,
|
|
Delay = 1,
|
|
Animation = "Jump",
|
|
NextAction = "Hold",
|
|
PhaseCall = "CheckStuck",
|
|
StartCall = "ClearActivity",
|
|
InLiquidAction = "Swim",
|
|
},
|
|
Dead = {
|
|
Prototype = Action,
|
|
Name = "Dead",
|
|
Directions = 2,
|
|
FlipDir = 0,
|
|
Length = 30,
|
|
Delay = 1,
|
|
Animation = "Death",
|
|
NextAction = "Hold",
|
|
StartCall = "ClearActivity",
|
|
NoOtherAction = 1,
|
|
ObjectDisabled = 1,
|
|
},
|
|
Stand = {
|
|
Prototype = Action,
|
|
Name = "Stand",
|
|
Procedure = DFA_WALK, //DFA_THROW
|
|
Directions = 2,
|
|
FlipDir = 0,
|
|
Length = 90,
|
|
Delay = 1,
|
|
Animation = "Stand",
|
|
NextAction = "Stand",
|
|
StartCall = "StartWalk",
|
|
InLiquidAction = "Swim",
|
|
},
|
|
Turn = {
|
|
Prototype = Action,
|
|
Name = "Turn",
|
|
Procedure = DFA_THROW,
|
|
Directions = 2,
|
|
FlipDir = 0,
|
|
Length = 16,
|
|
Delay = 1,
|
|
Animation = "Walk",
|
|
NextAction = "Stand",
|
|
StartCall = "ClearActivity",
|
|
},
|
|
SwimTurn = {
|
|
Prototype = Action,
|
|
Name = "SwimTurn",
|
|
Procedure = DFA_THROW,
|
|
Directions = 2,
|
|
FlipDir = 0,
|
|
Length = 16,
|
|
Delay = 1,
|
|
Animation = "Swim",
|
|
NextAction = "Swim",
|
|
StartCall = "ClearActivity",
|
|
},
|
|
Spit = {
|
|
Prototype = Action,
|
|
Name = "Spit",
|
|
Procedure = DFA_THROW,
|
|
Directions = 2,
|
|
FlipDir = 0,
|
|
Length = 90,
|
|
Delay = 1,
|
|
Animation = "SitMouthOpen",
|
|
NextAction = "Stand",
|
|
PhaseCall = "SpitPhase",
|
|
StartCall = "ClearActivity",
|
|
InLiquidAction = "Swim",
|
|
},
|
|
Eat = {
|
|
Prototype = Action,
|
|
Name = "Eat",
|
|
Procedure = DFA_NONE,
|
|
Directions = 2,
|
|
Length = 60,
|
|
Delay = 1,
|
|
Animation = "Eat",
|
|
PhaseCall = "EatPhase",
|
|
StartCall = "ClearActivity",
|
|
NextAction = "Stand",
|
|
InLiquidAction = "Swim",
|
|
Attach=CNAT_Bottom,
|
|
},
|
|
Headbutt = {
|
|
Prototype = Action,
|
|
Name = "Headbutt",
|
|
Procedure = DFA_THROW,
|
|
Directions = 2,
|
|
FlipDir = 0,
|
|
Length = 12,
|
|
Delay = 1,
|
|
Animation = "Headbutt",
|
|
StartCall = "ClearActivity",
|
|
NextAction = "Stand",
|
|
InLiquidAction = "Swim",
|
|
},
|
|
IdleStand = {
|
|
Prototype = Action,
|
|
Name = "IdleStand",
|
|
Procedure = DFA_THROW,
|
|
Directions = 2,
|
|
FlipDir = 0,
|
|
Length = 32,
|
|
Delay = 1,
|
|
Animation = "IdleStand",
|
|
NextAction = "Stand",
|
|
InLiquidAction = "Swim",
|
|
StartCall = "ClearActivity",
|
|
},
|
|
IdleSit = {
|
|
Prototype = Action,
|
|
Name = "IdleSit",
|
|
Procedure = DFA_THROW,
|
|
Directions = 2,
|
|
FlipDir = 0,
|
|
Length = 64,
|
|
Delay = 1,
|
|
Animation = "IdleSit",
|
|
NextAction = "Stand",
|
|
InLiquidAction = "Swim",
|
|
StartCall = "ClearActivity",
|
|
},
|
|
IdleTailwave = {
|
|
Prototype = Action,
|
|
Name = "IdleTailwave",
|
|
Procedure = DFA_THROW,
|
|
Directions = 2,
|
|
FlipDir = 0,
|
|
Length = 16,
|
|
Delay = 1,
|
|
Animation = "IdleTailwave",
|
|
NextAction = "Stand",
|
|
InLiquidAction = "Swim",
|
|
StartCall = "ClearActivity",
|
|
},
|
|
};
|
|
|
|
local Name = "$Name$";
|
|
local Description = "$Description$";
|
|
local MaxEnergy = 250000;
|
|
local MaxBreath = 720; // Mooq can breathe for 20 seconds under water. // But it haz special effects ignoring MaxBreath.
|
|
local MaxSpeed = 100;
|
|
local Speed = MaxSpeed;
|
|
local MaxJumpSpeed = 300;
|
|
local JumpSpeed = MaxJumpSpeed;
|
|
local NoBurnDecay = 1;
|
|
local BorderBound = C4D_Border_Sides;
|
|
local ContactCalls = true; |