1 /**
2 	Mooq
3 	Author: jok
4 */
5 
6 // Animations
7 local turn_angle;
8 // Color
9 local color;
10 // The closest enemy that has been found.
11 local enemy;
12 // Closest food that has been found.
13 local food;
14 
Place(int amount,proplist rectangle,proplist settings)15 public func Place(int amount, proplist rectangle, proplist settings)
16 {
17 	var max_tries = 3 * amount;
18 	var loc_area = nil;
19 	if (rectangle) loc_area = Loc_InArea(rectangle);
20 	var animal;
21 
22 	while ((amount > 0) && (--max_tries > 0))
23 	{
24 		// Try to find walkable ground near lava.
25 		var lava_spot = FindLocation(Loc_Material("DuroLava"));
26 		var ground_spot = nil;
27 		if (lava_spot)
28 		{
29 			var lava_rectangle = Shape->Rectangle(lava_spot.x - 200, lava_spot.y - 200, 400, 400);
30 			// Make sure the position is inside the required target rectangle.
31 			lava_rectangle = Shape->Intersect(lava_rectangle, rectangle)->GetBoundingRectangle();
32 			ground_spot = FindLocation(Loc_Wall(CNAT_Bottom), Loc_Or(Loc_Sky(), Loc_Tunnel()), Loc_Space(20, CNAT_Top), Loc_InArea(lava_rectangle));
33 		}
34 
35 		// If no hip and cool spot found, just get some generic spot.
36 		if (!ground_spot) ground_spot = FindLocation(Loc_Wall(CNAT_Bottom), Loc_Or(Loc_Sky(), Loc_Tunnel()), Loc_Space(20, CNAT_Top), loc_area);
37 		if (!ground_spot) continue;
38 
39 		animal = CreateObjectAbove(this, ground_spot.x, ground_spot.y, NO_OWNER);
40 		if (!animal) continue;
41 
42 		if (animal->Stuck())
43 		{
44 			animal->RemoveObject();
45 			continue;
46 		}
47 		--amount;
48 	}
49 	return animal;
50 }
51 
IsAnimal()52 public func IsAnimal() { return true; }
53 
Construction()54 func Construction()
55 {
56 	turn_angle = -60;
57 	color = 255;
58 
59 	AddEffect("IntActivity", this, 1, 10, this);
60 	AddTimer("UpdateEnemy", 30);
61 	AddTimer("UpdateFood", 60);
62 
63 	Stop();
64 	CheckTurn(GetDir());
65 
66 	SetTailOnFire();
67 }
68 
Death()69 func Death()
70 {
71 	RemoveTimer("UpdateEnemy");
72 	RemoveTimer("UpdateFood");
73 	RemoveEffect("IntActivity", this);
74 
75 	Sound("Animals::Mooq::Die*");
76 }
77 
CatchBlow(int damage,object from)78 func CatchBlow(int damage, object from)
79 {
80 	Schedule(this, "Sound(\"Animals::Mooq::Hurt*\")", RandomX(5, 20));
81 }
82 
83 /* Action Callbacks */
84 
CheckStuck()85 func CheckStuck()
86 {
87 	// Prevents getting stuck on middle vertex
88 	if(!GetXDir())
89 		if(Abs(GetYDir()) < 5)
90 			if(GBackSolid(0, 3))
91 				SetPosition(GetX(), GetY() - 1);
92 }
93 
ClearActivity()94 func ClearActivity()
95 {
96 	this.Activity = nil;
97 }
98 
StartSwim()99 func StartSwim()
100 {
101 	this.Activity = this.ActivitySwimming;
102 }
103 
StartWalk()104 func StartWalk()
105 {
106 	SetTailOnFire();
107 	this.Activity = this.ActivityWalking;
108 }
109 
SpitPhase()110 func SpitPhase()
111 {
112 	if(GetActTime() > 45 && GetActTime() < 65)
113 	{
114 		if(!Random(4))
115 		{
116 			var iX, iY;
117 			iX = 5;
118 			if (!GetDir()) iX = -iX;
119 			iY = -4;
120 			Smoke(iX,iY,5);
121 		}
122 	}
123 	if(GetActTime() == 58)
124 	{
125 		var iX, iY, iXDir, iYDir;
126 		iX = 10;
127 		if (!GetDir()) iX = -iX;
128 		iY = -4;
129 		iXDir = 300;
130 		if (!GetDir()) iXDir = -iXDir;
131 		iYDir = -300;
132 
133 		Sound("Animals::Mooq::Spit*");
134 
135 		var obj = CreateContents(Mooq_Firebomb);
136 		obj->Exit(iX, iY);
137 		obj->SetXDir(iXDir,100);
138 		obj->SetYDir(iYDir,100);
139 	}
140 }
141 
EatPhase()142 func EatPhase()
143 {
144 	var actt = GetActTime();
145 
146 	if(actt > 13 && actt < 25)
147 	{
148 		if(!Random(4))
149 		{
150 			var iX, iY;
151 			iX = 5;
152 			if (!GetDir()) iX = -iX;
153 			iY = 4;
154 			Smoke(iX,iY,5);
155 		}
156 	}
157 	if(actt == 22)
158 	{
159 		if (!food) return;
160 
161 		Sound("Animals::Mooq::Munch*");
162 		DoEnergy(food->GetMass());
163 		food->RemoveObject();
164 	}
165 	if(actt > 43 && actt < 55)
166 	{
167 		if(!Random(4))
168 		{
169 			var iX, iY;
170 			iX = 5;
171 			if (!GetDir()) iX = -iX;
172 			iY = 1;
173 			Smoke(iX,iY,5);
174 		}
175 	}
176 }
177 
178 /* Activity */
179 
ActivitySwimming()180 func ActivitySwimming()
181 {
182 	CheckBreathe();
183 	if(GetMaterial() == Material("Water"))
184 		CheckFossilize();
185 
186 	// Stuck?
187 	if (GetComDir() && !GetXDir() && !GetYDir())
188 	{
189 		DoJump(true);
190 		return Swim(Random(2));
191 	}
192 
193 	// Fossilizing?
194 	if(GetEffect("IntFossilizing", this))
195 	{
196 		var lava_spot = FindLava();
197 		if (lava_spot)
198 			return TaskSwimTo(lava_spot);
199 	}
200 
201 	if (enemy && Random(2)) return TaskSwimTo(enemy);
202 
203 	if (!enemy && food) return TaskSwimTo(food);
204 
205 	if (!Random(6)) return Swim(Random(2));
206 
207 	if (!Random(6)) return DoJump(true);
208 }
209 
ActivityWalking()210 func ActivityWalking()
211 {
212 	// Stuck?
213 	if (GetComDir() && !GetXDir() && !GetYDir())
214 	{
215 		if(GetDir())
216 			Walk(0);
217 		else
218 			Walk(1);
219 		return DoJump();
220 	}
221 
222 	// Fossilizing?
223 	if(GetEffect("IntFossilizing", this))
224 	{
225 		var lava_spot = FindLava();
226 		if (lava_spot) return TaskWalkTo(lava_spot);
227 	}
228 
229 	// If enemy, hopefully attack!
230 	if (enemy)
231 	{
232 		var distance = ObjectDistance(this, enemy);
233 
234 		if (distance < 50 && Random(2)) return TaskHeadbutt(distance);
235 
236 		if (Inside(distance, 85, 145) && !Random(5)) return TaskSpit();
237 	}
238 
239 	// If no enemy, go to food and eat.
240 	if (!enemy && food) return TaskFood();
241 
242 	// If not walking, randomly idle.
243 	if (GetAction() == "Stand")
244 	{
245 		if (!enemy && !food)
246 		{
247 			// Idle?
248 			if (!Random(15)) return TaskIdle();
249 		}
250 
251 		if (!Random(5)) return Walk(Random(2));
252 
253 		return;
254 	}
255 
256 	if (!Random(5)) return Stop();
257 
258 	if (!Random(5)) return Walk(Random(2));
259 
260 	if (GetAction() == "Walk")
261 	{
262 		if (!Random(5)) return DoJump();
263 	}
264 
265 	// Anticipate holes in the landscape while walking.
266 
267 }
268 
FxIntActivityTimer(target,effect,time)269 func FxIntActivityTimer(target, effect, time)
270 {
271 	if (this.Activity) this->Activity();
272 	if (!GetAlive()) return -1;
273 	return 1;
274 }
275 
FxIntActivityDamage(target,effect,dmg)276 func FxIntActivityDamage(target, effect, dmg)
277 {
278 	if (dmg > 0) return dmg;
279 	return dmg;
280 }
281 
282 /* Tasks */
283 
TaskIdle()284 func TaskIdle()
285 {
286 	Sound("Animals::Mooq::Snorting*");
287 
288 	if (!Random(3)) return SetAction("IdleSit");
289 	if (!Random(2)) return SetAction("IdleStand");
290 
291 	return SetAction("IdleTailwave");
292 }
293 
TaskFood()294 func TaskFood()
295 {
296 	var distance = ObjectDistance(this, food);
297 	if (distance < 11) return Eat();
298 
299 	return TaskWalkTo(food);
300 }
301 
TaskHeadbutt(distance)302 func TaskHeadbutt(distance)
303 {
304 	if (distance < 11) return Headbutt();
305 
306 	return TaskWalkTo(enemy);
307 }
308 
TaskSpit()309 func TaskSpit()
310 {
311 	var eX = enemy->GetX();
312 	var iX = GetX();
313 
314 	if (iX < eX)
315 	{
316 		if (GetDir() != DIR_Right) return Turn(DIR_Right);
317 		Stop();
318 		return Spit();
319 	} else {
320 		if (GetDir() != DIR_Left) return Turn(DIR_Left);
321 		Stop();
322 		return Spit();
323 	}
324 }
325 
TaskWalkTo(spot)326 func TaskWalkTo(spot)
327 {
328 	var iX = GetX();
329 	var iY = GetY();
330 
331 	if (GetType(spot) == C4V_C4Object)
332 	{
333 		var sX = spot->GetX();
334 		var sY = spot->GetY();
335 	}
336 	else if (GetType(spot) == C4V_PropList)
337 	{
338 		var sX = spot.x;
339 		var sY = spot.y;
340 	}
341 	else return;
342 
343 	if (iX < sX)
344 	{
345 		if (GetDir() == DIR_Right)
346 			if (iY > sY + 6)
347 				if (Random(2)) if(DoJump())
348 					return true;
349 
350 		return Walk(DIR_Right);
351 	} else {
352 		if (GetDir() == DIR_Left)
353 			if(iY > sY + 6)
354 				if(Random(2)) if(DoJump())
355 					return true;
356 		return Walk(DIR_Left);
357 	}
358 }
359 
TaskSwimTo(spot)360 func TaskSwimTo(spot)
361 {
362 	var iX = GetX();
363 	var iY = GetY();
364 
365 	if (GetType(spot) == C4V_C4Object)
366 	{
367 		var sX = spot->GetX();
368 		var sY = spot->GetY();
369 	}
370 	else if (GetType(spot) == C4V_PropList)
371 	{
372 		var sX = spot.x;
373 		var sY = spot.y;
374 	}
375 	else return;
376 
377 	if (iX < sX)
378 	{
379 		if (GetDir() == DIR_Right)
380 			if(iY > sY)
381 				if(DoJump(true))
382 					return true;
383 
384 		return Swim(DIR_Right);
385 	} else {
386 		if (GetDir() == DIR_Left)
387 			if(iY > sY)
388 				if(DoJump(true))
389 					return true;
390 		return Swim(DIR_Left);
391 	}
392 }
393 
394 /* Actions */
395 
Stop()396 func Stop()
397 {
398 	SetComDir(COMD_Stop);
399 	SetXDir(0);
400 	return SetAction("Stand");
401 }
402 
Turn(int dir,bool move)403 func Turn(int dir, bool move)
404 {
405 	if (dir == nil)
406 	{
407 		if (GetDir() == DIR_Left)
408 			dir = DIR_Right;
409 		else
410 			dir = DIR_Left;
411 	}
412 
413 	if(GetDir() == dir) return;
414 
415 	return CheckTurn(dir, move);
416 }
417 
Walk(int dir)418 func Walk(int dir)
419 {
420 	if (GetAction() != "Stand" && GetAction() != "Walk") return;
421 
422 	if (GetDir() == dir)
423 	{
424 		SetAction("Walk");
425 		if (GetDir())
426 			return SetComDir(COMD_Right);
427 		else
428 			return SetComDir(COMD_Left);
429 	}
430 
431 	return Turn(dir, true);
432 }
433 
Swim(int dir)434 func Swim(int dir)
435 {
436 	if (GetAction() != "Swim") return;
437 
438 	if (GetDir() == dir)
439 	{
440 		SetAction("Swim");
441 		if (GetDir())
442 			return SetComDir(COMD_UpRight);
443 		else
444 			return SetComDir(COMD_UpLeft);
445 	}
446 
447 	return Turn(dir, true);
448 }
449 
DoJump(bool swimming)450 func DoJump(bool swimming)
451 {
452 	if (GetAction() != "Walk" && GetAction() != "Stand" && GetAction() != "Swim") return;
453 
454 	if (swimming)
455 	{
456 		if (GBackSky(0, -2))
457 			SetPosition(GetX(), GetY() - 2);
458 		else
459 			return;
460 
461 		var iX, iY, iXDir, iYDir;
462 		iX = 10;
463 		if (!GetDir()) iX = -iX;
464 		iY = -4;
465 		iXDir = 200;
466 		if (!GetDir()) iXDir = -iXDir;
467 		iYDir = -200;
468 
469 		if (Random(2)) Sound("Animals::Mooq::Snort*");
470 
471 		SetSpeed(iXDir + GetXDir(100), iYDir + GetYDir(100), 100);
472 		return true;
473 	}
474 
475 	if (Random(2)) Sound("Animals::Mooq::Snort*");
476 	return Jump();
477 }
478 
Spit()479 func Spit()
480 {
481 	if (GetAction() == "Stand") return SetAction("Spit");
482 }
483 
Eat(object food)484 func Eat(object food)
485 {
486 	Stop();
487 	if (GetAction() == "Stand") return SetAction("Eat");
488 }
489 
Headbutt()490 func Headbutt()
491 {
492 	if (GetAction() != "Walk") return;
493 
494 	Punch(enemy, 10);
495 	return SetAction("Headbutt");
496 }
497 
498 /* FindEnemy */
499 
UpdateEnemy()500 func UpdateEnemy()
501 {
502 	// Already disposed of the last one?
503 	if (enemy && !enemy->GetAlive()) enemy = nil;
504 	// Last one too far away now?
505 	if (enemy && ObjectDistance(this, enemy) > 250) enemy = nil;
506 	// Slid in water?
507 	if (enemy && enemy->GBackLiquid()) enemy = nil;
508 
509 	var x = GetX();
510 	var y = GetY();
511 	for (var obj in FindObjects(Find_Distance(200), Find_OCF(OCF_Alive), Find_AnimalHostile(GetOwner()), Sort_Distance()))
512 	{
513 		if (!PathFree(x, y, obj->GetX(), obj->GetY())) continue;
514 		if (obj->GBackLiquid()) continue;
515 		enemy = obj;
516 		return;
517 	}
518 }
519 
520 /* FindFood */
521 
UpdateFood()522 func UpdateFood()
523 {
524 	// Need food?
525 	if (GetEnergy() >= MaxEnergy/1000) return food = nil;
526 	// Last one too far away now?
527 	if (food && ObjectDistance(this, food) > 150) food = nil;
528 	// Slid in water?
529 	if (food && food->GBackLiquid()) food = nil;
530 
531 	var x = GetX();
532 	var y = GetY();
533 	var Find_FoodIDs = Find_Or(Find_ID(Rock), Find_ID(Coal), Find_ID(Ore));
534 	for (var obj in FindObjects(Find_Distance(100), Find_FoodIDs, Sort_Distance()))
535 	{
536 		if (!PathFree(x, y, obj->GetX(), obj->GetY())) continue;
537 		if (obj->GBackLiquid()) continue;
538 		food = obj;
539 		return;
540 	}
541 }
542 
543 /* FindLava */
544 
FindLava()545 func FindLava()
546 {
547 	var lava_spot = FindLocation(Loc_Material("DuroLava"), Loc_Space(20));
548 	if (lava_spot) return lava_spot;
549 
550 	var lava_spot = FindLocation(Loc_Material("Lava"), Loc_Space(20));
551 	if (lava_spot) return lava_spot;
552 
553 	return;
554 }
555 
556 /* Turning */
557 
CheckTurn(int dir,bool move)558 func CheckTurn(int dir, bool move)
559 {
560 	if (!GetEffect("IntTurning", this))
561 	{
562 		SetDir(dir);
563 		AddEffect("IntTurning", this, 1, 1, this, nil, move);
564 		return true;
565 	}
566 	return false;
567 }
568 
FxIntTurningStart(object target,effect fx,temp,move)569 func FxIntTurningStart(object target, effect fx, temp, move)
570 {
571 	fx.mvmn = move;
572 
573 	if (!InLiquid())
574 	{
575 		Stop();
576 		SetAction("Turn");
577 	} else {
578 		SetComDir(COMD_Stop);
579 		SetXDir(0);
580 		SetAction("SwimTurn");
581 	}
582 
583 	if (temp) return true;
584 }
585 
FxIntTurningTimer(object target,effect fx,int time)586 func FxIntTurningTimer(object target, effect fx, int time)
587 {
588 	if (GetDir() == DIR_Left)
589 		turn_angle += 15;
590 	else
591 		turn_angle -= 15;
592 
593 	if (turn_angle < -60 || turn_angle > 180)
594 	{
595 		turn_angle = BoundBy(turn_angle, -60, 180);
596 		this.MeshTransformation = Trans_Rotate(turn_angle + 180 + 30,0,1,0);
597 		return -1;
598 	}
599 	this.MeshTransformation = Trans_Rotate(turn_angle + 180 + 30,0,1,0);
600 	return 1;
601 }
602 
FxIntTurningStop(object target,effect fx,temp)603 func FxIntTurningStop(object target, effect fx, temp)
604 {
605 	if (fx.mvmn)
606 	{
607 		if (!InLiquid())
608 		{
609 			if (GetDir()) SetComDir(COMD_Right);
610 			else SetComDir(COMD_Left);
611 			return SetAction("Walk");
612 		}
613 
614 		if (GetDir()) SetComDir(COMD_UpRight);
615 		else SetComDir(COMD_UpLeft);
616 		return SetAction("Swim");
617 	}
618 }
619 
620 /* Breathing */
621 
CheckBreathe()622 func CheckBreathe()
623 {
624 	if (!GetEffect("IntBreathing", this)) AddEffect("IntBreathing", this, 1, 1, this, nil);
625 }
626 
FxIntBreathingStart(object target,effect fx,temp)627 func FxIntBreathingStart(object target, effect fx, temp)
628 {
629 	if (temp) return true;
630 }
631 
FxIntBreathingTimer(object target,effect fx,int time)632 func FxIntBreathingTimer(object target, effect fx, int time)
633 {
634 	DoBreath(MaxBreath - GetBreath());
635 	if (!InLiquid()) return -1;
636 
637 	return 1;
638 }
639 
640 /* Fossilizing */
641 
CheckFossilize()642 func CheckFossilize()
643 {
644 	if (!GetEffect("IntFossilizing", this))
645 		// Ca. 60 seconds till death without lava
646 		AddEffect("IntFossilizing", this, 1, 11, this, nil);
647 }
648 
FxIntFossilizingStart(object target,effect fx,temp)649 func FxIntFossilizingStart(object target, effect fx, temp)
650 {
651 	if (temp) return true;
652 }
653 
FxIntFossilizingTimer(object target,effect fx,int time)654 func FxIntFossilizingTimer(object target, effect fx, int time)
655 {
656 	if (GetMaterial() == Material("DuroLava") || GetMaterial() == Material("Lava"))
657 	{
658 		color++;
659 		if (Speed < MaxSpeed) Speed += Random(2);
660 		if (JumpSpeed < MaxJumpSpeed)
661 		{
662 			JumpSpeed += Random(3);
663 			if(JumpSpeed > MaxJumpSpeed) JumpSpeed = MaxJumpSpeed;
664 		}
665 	} else {
666 		color--;
667 		if (Speed > 0) Speed -= Random(2);
668 		if (JumpSpeed > 0)
669 		{
670 			JumpSpeed -= Random(3);
671 			if(JumpSpeed < 0) JumpSpeed = 0;
672 		}
673 	}
674 	if (color < 45 || color > 255)
675 	{
676 		color = BoundBy(color, 45, 255);
677 		SetClrModulation(RGBa(color, color, color, 255));
678 		return -1;
679 	}
680 	SetClrModulation(RGBa(color, color, color, 255));
681 
682 	return 1;
683 }
684 
FxIntFossilizingStop(object target,effect fx,temp)685 func FxIntFossilizingStop(object target, effect fx, temp)
686 {
687 	if (GetMaterial() == Material("DuroLava") || GetMaterial() == Material("Lava")) return SetAction("Swim");
688 	else return Kill();
689 }
690 
691 /* Burning Tail */
692 
SetTailOnFire()693 func SetTailOnFire()
694 {
695 	if (!GetEffect("IntTailBurning", this))
696 		AddEffect("IntTailBurning", this, 1, 2, this, nil);
697 }
698 
FxIntTailBurningStart(object target,effect fx,temp)699 func FxIntTailBurningStart(object target, effect fx, temp)
700 {
701 	fx.fire = {
702 		R = 200 + Random(55),
703 		G = 200 + Random(55),
704 		B = 200 + Random(55),
705 		Alpha = PV_Linear(255, 0),
706 		Size = 4,
707 		Phase = PV_Linear(0, 9),
708 		DampingX = 1000,
709 		DampingY = 1000,
710 		Attach = ATTACH_MoveRelative
711 	};
712 
713 	if (temp) return true;
714 }
715 
FxIntTailBurningTimer(object target,effect fx,int time)716 func FxIntTailBurningTimer(object target, effect fx, int time)
717 {
718 	if (!GetAlive() || InLiquid())
719 	{
720 		var level;
721 		level = 5 ?? 10;
722 		var particles = Particles_Smoke();
723 		particles.Size = PV_Linear(PV_Random(level/2, level), PV_Random(2 * level, 3 * level));
724 		var pos = [3, -1, 0];
725 		var dir = [PV_Random(-level/3, level/3), PV_Random(-level/2, -level/3), 0];
726 		CreateParticleAtBone("Smoke", "tail_3", pos, dir, PV_Random(level * 2, level * 10), particles, BoundBy(level/5, 3, 20));
727 		return -1;
728 	}
729 
730 	var pos = [3, -1, 0];
731 	var dir = [0, 0, 0];
732 	CreateParticleAtBone("Fire", "tail_3", pos, dir, 5, fx.fire, 1);
733 	return 1;
734 }
735 
736 /* ActMap */
737 
738 local ActMap = {
739 
740 Walk = {
741 	Prototype = Action,
742 	Name = "Walk",
743 	Procedure = DFA_WALK,
744 	Speed = Speed,
745 	Accel = 4,
746 	Decel = 22,
747 	Directions = 2,
748 	FlipDir = 0,
749 	Length = 12,
750 	Delay = 1,
751 	Animation = "Walk",
752 	StartCall = "StartWalk",
753 	InLiquidAction = "Swim",
754 },
755 Swim = {
756 	Prototype = Action,
757 	Name = "Swim",
758 	Procedure = DFA_SWIM,
759 	Speed = Speed,
760 	Accel = 16,
761 	Decel = 22,
762 	Directions = 2,
763 	FlipDir = 0,
764 	Length = 12,
765 	Delay = 1,
766 	Animation = "Swim",
767 	StartCall = "StartSwim",
768 },
769 Jump = {
770 	Prototype = Action,
771 	Name = "Jump",
772 	Procedure = DFA_FLIGHT,
773 	Speed = 200,
774 	Accel = 14,
775 	Directions = 2,
776 	FlipDir = 0,
777 	Length = 20,
778 	Delay = 1,
779 	Animation = "Jump",
780 	NextAction = "Hold",
781 	PhaseCall = "CheckStuck",
782     StartCall = "ClearActivity",
783 	InLiquidAction = "Swim",
784 },
785 Dead = {
786 	Prototype = Action,
787 	Name = "Dead",
788 	Directions = 2,
789 	FlipDir = 0,
790 	Length = 30,
791 	Delay = 1,
792 	Animation = "Death",
793 	NextAction = "Hold",
794 	StartCall = "ClearActivity",
795 	NoOtherAction = 1,
796 	ObjectDisabled = 1,
797 },
798 Stand = {
799 	Prototype = Action,
800 	Name = "Stand",
801 	Procedure = DFA_WALK, //DFA_THROW
802 	Directions = 2,
803 	FlipDir = 0,
804 	Length = 90,
805 	Delay = 1,
806 	Animation = "Stand",
807 	NextAction = "Stand",
808 	StartCall = "StartWalk",
809 	InLiquidAction = "Swim",
810 },
811 Turn = {
812     Prototype = Action,
813 	Name = "Turn",
814 	Procedure = DFA_THROW,
815 	Directions = 2,
816 	FlipDir = 0,
817 	Length = 16,
818 	Delay = 1,
819 	Animation = "Walk",
820 	NextAction = "Stand",
821 	StartCall = "ClearActivity",
822 },
823 SwimTurn = {
824     Prototype = Action,
825 	Name = "SwimTurn",
826 	Procedure = DFA_THROW,
827 	Directions = 2,
828 	FlipDir = 0,
829 	Length = 16,
830 	Delay = 1,
831 	Animation = "Swim",
832 	NextAction = "Swim",
833 	StartCall = "ClearActivity",
834 },
835 Spit = {
836     Prototype = Action,
837 	Name = "Spit",
838 	Procedure = DFA_THROW,
839 	Directions = 2,
840 	FlipDir = 0,
841 	Length = 90,
842 	Delay = 1,
843 	Animation = "SitMouthOpen",
844 	NextAction = "Stand",
845 	PhaseCall = "SpitPhase",
846 	StartCall = "ClearActivity",
847 	InLiquidAction = "Swim",
848 },
849 Eat = {
850 	Prototype = Action,
851 	Name = "Eat",
852 	Procedure = DFA_NONE,
853 	Directions = 2,
854 	Length = 60,
855 	Delay = 1,
856 	Animation = "Eat",
857 	PhaseCall = "EatPhase",
858 	StartCall = "ClearActivity",
859 	NextAction = "Stand",
860 	InLiquidAction = "Swim",
861 	Attach=CNAT_Bottom,
862 },
863 Headbutt = {
864 	Prototype = Action,
865 	Name = "Headbutt",
866 	Procedure = DFA_THROW,
867 	Directions = 2,
868 	FlipDir = 0,
869 	Length = 12,
870 	Delay = 1,
871 	Animation = "Headbutt",
872 	StartCall = "ClearActivity",
873 	NextAction = "Stand",
874 	InLiquidAction = "Swim",
875 },
876 IdleStand = {
877 	Prototype = Action,
878 	Name = "IdleStand",
879 	Procedure = DFA_THROW,
880 	Directions = 2,
881 	FlipDir = 0,
882 	Length = 32,
883 	Delay = 1,
884 	Animation = "IdleStand",
885 	NextAction = "Stand",
886 	InLiquidAction = "Swim",
887 	StartCall = "ClearActivity",
888 },
889 IdleSit = {
890 	Prototype = Action,
891 	Name = "IdleSit",
892 	Procedure = DFA_THROW,
893 	Directions = 2,
894 	FlipDir = 0,
895 	Length = 64,
896 	Delay = 1,
897 	Animation = "IdleSit",
898 	NextAction = "Stand",
899 	InLiquidAction = "Swim",
900 	StartCall = "ClearActivity",
901 },
902 IdleTailwave = {
903 	Prototype = Action,
904 	Name = "IdleTailwave",
905 	Procedure = DFA_THROW,
906 	Directions = 2,
907 	FlipDir = 0,
908 	Length = 16,
909 	Delay = 1,
910 	Animation = "IdleTailwave",
911 	NextAction = "Stand",
912 	InLiquidAction = "Swim",
913 	StartCall = "ClearActivity",
914 },
915 };
916 
917 local Name = "$Name$";
918 local Description = "$Description$";
919 local MaxEnergy = 250000;
920 local MaxBreath = 720; // Mooq can breathe for 20 seconds under water. // But it haz special effects ignoring MaxBreath.
921 local MaxSpeed = 100;
922 local Speed = MaxSpeed;
923 local MaxJumpSpeed = 300;
924 local JumpSpeed = MaxJumpSpeed;
925 local NoBurnDecay = true;
926 local BorderBound = C4D_Border_Sides;
927 local ContactCalls = true;
928 
Definition(proplist def)929 public func Definition(proplist def)
930 {
931 	def.PictureTransformation = Trans_Mul(Trans_Translate(2000, 3000, 0), Trans_Scale(1400), Trans_Rotate(20, 1, 0, 0), Trans_Rotate(60, 0, 1, 0));
932 }