Ticket #3919: UnitAIAnimal.js

File UnitAIAnimal.js, 6.3 KB (added by Palaxin, 8 years ago)

this is very WIP, but I would like some feedback if I'm on the right track since this is my first major JS programming task

Line 
1// function piggyback example
2// AnimalAI.protoype.SetNextState = UnitAI.prototype.SetNextState;
3
4function UnitAIAnimal() {}
5
6UnitAIAnimal.prototype.Schema =
7 "<element name='Behaviour' a:help='Behaviour of the animal'>" +
8 "<choice>" +
9 "<value a:help='Will actively attack any unit it encounters, even if not threatened'>violent</value>" +
10 "<value a:help='Will attack nearby units if it feels threatened (if they linger within LOS for too long)'>aggressive</value>" +
11 "<value a:help='Will attack nearby units if attacked'>defensive</value>" +
12 "<value a:help='Will never attack units but will attempt to flee when attacked'>passive</value>" +
13 "<value a:help='Will never attack units. Will typically attempt to flee for short distances when units approach'>skittish</value>" +
14 "<value a:help='Will never attack units and will not attempt to flee when attacked'>domestic</value>" +
15 "</choice>" +
16 "</element>" +
17 "<element name='RoamDistance'>" +
18 "<ref name='positiveDecimal'/>" +
19 "</element>" +
20 "<element name='RoamTimeMin'>" +
21 "<ref name='positiveDecimal'/>" +
22 "</element>" +
23 "<element name='RoamTimeMax'>" +
24 "<ref name='positiveDecimal'/>" +
25 "</element>" +
26 "<element name='FeedTimeMin'>" +
27 "<ref name='positiveDecimal'/>" +
28 "</element>" +
29 "<element name='FeedTimeMax'>" +
30 "<ref name='positiveDecimal'/>" +
31 "</element>";
32
33// See ../helpers/FSM.js for some documentation of this FSM specification syntax
34UnitAIAnimal.prototype.UnitFsmSpec = {
35
36 "ANIMAL": {
37 "Attacked": function(msg) {
38 if (this.template.Behaviour == "skittish" ||
39 this.template.Behaviour == "passive")
40 {
41 this.Flee(msg.data.attacker, false);
42 }
43 else if (this.IsDangerousAnimal() || this.template.Behaviour == "defensive")
44 {
45 if (this.CanAttack(msg.data.attacker))
46 this.Attack(msg.data.attacker, false);
47 }
48 else if (this.template.Behaviour == "domestic")
49 {
50 // Never flee, stop what we were doing
51 this.SetNextState("IDLE");
52 }
53 },
54
55 "Order.LeaveFoundation": function(msg) {
56 // Move a tile outside the building
57 var range = 4;
58 if (this.MoveToTargetRangeExplicit(msg.data.target, range, range))
59 {
60 // We've started walking to the given point
61 this.SetNextState("WALKING");
62 }
63 else
64 {
65 // We are already at the target, or can't move at all
66 this.FinishOrder();
67 }
68 },
69
70 "IDLE": {
71 // (We need an IDLE state so that FinishOrder works)
72
73 "enter": function() {
74 // Start feeding immediately
75 this.SetNextState("FEEDING");
76 return true;
77 },
78 },
79
80 "ROAMING": {
81 "enter": function() {
82 // Walk in a random direction
83 this.SelectAnimation("walk", false, this.GetWalkSpeed());
84 this.MoveRandomly(+this.template.RoamDistance);
85 // Set a random timer to switch to feeding state
86 this.StartTimer(RandomInt(+this.template.RoamTimeMin, +this.template.RoamTimeMax));
87 this.SetFacePointAfterMove(false);
88 },
89
90 "leave": function() {
91 this.StopTimer();
92 this.SetFacePointAfterMove(true);
93 },
94
95 "LosRangeUpdate": function(msg) {
96 if (this.template.Behaviour == "skittish")
97 {
98 if (msg.data.added.length > 0)
99 {
100 this.Flee(msg.data.added[0], false);
101 return;
102 }
103 }
104 // Start attacking one of the newly-seen enemy (if any)
105 else if (this.IsDangerousAnimal())
106 {
107 this.AttackVisibleEntity(msg.data.added);
108 }
109
110 // TODO: if two units enter our range together, we'll attack the
111 // first and then the second won't trigger another LosRangeUpdate
112 // so we won't notice it. Probably we should do something with
113 // ResetActiveQuery in ROAMING.enter/FEEDING.enter in order to
114 // find any units that are already in range.
115 },
116
117 "Timer": function(msg) {
118 this.SetNextState("FEEDING");
119 },
120
121 "MoveCompleted": function() {
122 this.MoveRandomly(+this.template.RoamDistance);
123 },
124 },
125
126 "FEEDING": {
127 "enter": function() {
128 // Stop and eat for a while
129 this.SelectAnimation("feeding");
130 this.StopMoving();
131 this.StartTimer(RandomInt(+this.template.FeedTimeMin, +this.template.FeedTimeMax));
132 },
133
134 "leave": function() {
135 this.StopTimer();
136 },
137
138 "LosRangeUpdate": function(msg) {
139 if (this.template.Behaviour == "skittish")
140 {
141 if (msg.data.added.length > 0)
142 {
143 this.Flee(msg.data.added[0], false);
144 return;
145 }
146 }
147 // Start attacking one of the newly-seen enemy (if any)
148 else if (this.template.Behaviour == "violent")
149 {
150 this.AttackVisibleEntity(msg.data.added);
151 }
152 },
153
154 "MoveCompleted": function() { },
155
156 "Timer": function(msg) {
157 this.SetNextState("ROAMING");
158 },
159 },
160
161 "FLEEING": "INDIVIDUAL.FLEEING", // reuse the same fleeing behaviour for animals
162
163 "COMBAT": "INDIVIDUAL.COMBAT", // reuse the same combat behaviour for animals
164
165 "WALKING": "INDIVIDUAL.WALKING", // reuse the same walking behaviour for animals
166 // only used for domestic animals
167 }
168}
169
170UnitAIAnimal.prototype.Init = UnitAI.prototype.Init;
171
172UnitAIAnimal.prototype.Flee = UnitAI.prototype.Flee;
173UnitAIAnimal.prototype.AddOrder = UnitAI.prototype.AddOrder;
174UnitAIAnimal.prototype.PushOrder = UnitAI.prototype.PushOrder;
175UnitAIAnimal.prototype.UnitFsm = UnitAI.prototype.UnitFsm;
176
177UnitAIAnimal.prototype.CanAttack = UnitAI.prototype.CanAttack;
178UnitAIAnimal.prototype.Attack = UnitAI.prototype.Attack;
179UnitAIAnimal.prototype.SetNextState = UnitAI.prototype.SetNextState;
180UnitAIAnimal.prototype.MoveToTargetRangeExplicit = UnitAI.prototype.MoveToTargetRangeExplicit;
181UnitAIAnimal.prototype.FinishOrder = UnitAI.prototype.FinishOrder;
182UnitAIAnimal.prototype.SelectAnimation = UnitAI.prototype.SelectAnimation;
183UnitAIAnimal.prototype.GetWalkSpeed = UnitAI.prototype.GetWalkSpeed;
184UnitAIAnimal.prototype.MoveRandomly = UnitAI.prototype.MoveRandomly;
185UnitAIAnimal.prototype.StartTimer = UnitAI.prototype.StartTimer;
186UnitAIAnimal.prototype.SetFacePointAfterMove = UnitAI.prototype.SetFacePointAfterMove;
187UnitAIAnimal.prototype.StopTimer = UnitAI.prototype.StopTimer;
188UnitAIAnimal.prototype.IsDangerousAnimal = UnitAI.prototype.IsDangerousAnimal;
189UnitAIAnimal.prototype.AttackVisibleEntity = UnitAI.prototype.AttackVisibleEntity;
190UnitAIAnimal.prototype.StopMoving = UnitAI.prototype.StopMoving;