1
2 #include "../stdai.h"
3 #include "../balrog_common.h"
4 #include "balrog_boss_missiles.fdh"
5
6 #define STATE_CHARGE 10
7 #define STATE_JUMP_FIRE 20
8 #define STATE_PAUSE 30
9 #define STATE_CAUGHT_PLAYER 40
10
11
INITFUNC(AIRoutines)12 INITFUNC(AIRoutines)
13 {
14 ONTICK(OBJ_BALROG_BOSS_MISSILES, ai_balrog_boss_missiles);
15 ONDEATH(OBJ_BALROG_BOSS_MISSILES, ondeath_balrog_boss_missiles);
16
17 ONTICK(OBJ_BALROG_MISSILE, ai_balrog_missile);
18 }
19
20 /*
21 void c------------------------------() {}
22 */
23
ai_balrog_boss_missiles(Object * o)24 void ai_balrog_boss_missiles(Object *o)
25 {
26 // try to catch player
27 switch(o->state)
28 {
29 case STATE_CHARGE+1:
30 case STATE_JUMP_FIRE+1:
31 {
32 if (pdistlx(12<<CSF) && pdistly2(12<<CSF, 8<<CSF))
33 {
34 balrog_grab_player(o);
35 hurtplayer(5);
36 o->state = STATE_CAUGHT_PLAYER;
37 }
38 }
39 break;
40 }
41
42 // main state engine
43 switch(o->state)
44 {
45 case 0:
46 {
47 o->nxflags |= NXFLAG_FOLLOW_SLOPE;
48 FACEPLAYER;
49
50 o->state = 1;
51 o->frame = 0;
52 o->timer = 0;
53 }
54 case 1:
55 {
56 if (++o->timer > 30)
57 {
58 o->state = STATE_CHARGE;
59 o->timer2 ^= 1; // affects how we react if we miss the player
60 }
61 }
62 break;
63
64 // charge the player
65 case STATE_CHARGE:
66 {
67 o->timer = 0;
68 o->frame = 9;
69 o->animtimer = 0;
70 o->state++;
71 }
72 case STATE_CHARGE+1:
73 {
74 XACCEL(0x20);
75 walking_animation(o);
76
77 // stuck against the wall?
78 if ((o->dir == LEFT && o->blockl) || \
79 (o->dir == RIGHT && o->blockr))
80 {
81 if (++o->timer3 > 5)
82 o->state = STATE_JUMP_FIRE;
83 }
84 else
85 {
86 o->timer3 = 0;
87 }
88
89 // he behaves differently after every other time he pauses
90 if (o->timer2)
91 {
92 if (++o->timer > 75)
93 {
94 o->frame = 0;
95 o->state = STATE_PAUSE;
96 }
97 }
98 else
99 {
100 if (++o->timer > 24)
101 o->state = STATE_JUMP_FIRE;
102 }
103 }
104 break;
105
106 // jump and fire missiles
107 case STATE_JUMP_FIRE:
108 {
109 o->state++;
110 o->timer = 0;
111 o->frame = 3;
112 o->yinertia = -0x5ff;
113 }
114 case STATE_JUMP_FIRE+1:
115 {
116 FACEPLAYER;
117
118 // fire missiles
119 if (++o->timer < 30)
120 {
121 if ((o->timer % 6) == 1)
122 {
123 sound(SND_EM_FIRE);
124
125 Object *shot = SpawnObjectAtActionPoint(o, OBJ_BALROG_MISSILE);
126 shot->dir = o->dir;
127 shot->xinertia = 0x100;
128 }
129 }
130
131 // landed?
132 if (o->blockd && o->yinertia >= 0)
133 {
134 o->frame = 2;
135 o->state = STATE_PAUSE;
136 quake(30);
137 }
138 }
139 break;
140
141 // stop for a moment
142 case STATE_PAUSE:
143 {
144 o->xinertia *= 4;
145 o->xinertia /= 5;
146 if (o->xinertia != 0) break;
147
148 o->state = 0;
149 }
150 break;
151
152 case STATE_CAUGHT_PLAYER: // caught player
153 {
154 if (balrog_toss_player_away(o))
155 o->state = 0;
156 }
157 break;
158 }
159
160 o->yinertia += 0x20;
161 LIMITX(0x300);
162 LIMITY(0x5ff);
163 }
164
ondeath_balrog_boss_missiles(Object * o)165 void ondeath_balrog_boss_missiles(Object *o)
166 {
167 o->xinertia = 0;
168 }
169
walking_animation(Object * o)170 static void walking_animation(Object *o)
171 {
172 if (++o->animtimer > 3)
173 {
174 o->animtimer = 0;
175 o->frame++;
176
177 if (o->frame == 12)
178 {
179 sound(SND_THUD);
180 }
181 else if (o->frame > 12)
182 {
183 o->frame = 9;
184 }
185 }
186 }
187
188
189 /*
190 void c------------------------------() {}
191 */
192
ai_balrog_missile(Object * o)193 void ai_balrog_missile(Object *o)
194 {
195 if ((o->dir == RIGHT && o->blockr) || \
196 (o->dir == LEFT && o->blockl))
197 {
198 SmokeClouds(o, 3, 0, 0);
199 effect(o->CenterX(), o->CenterY(), EFFECT_BOOMFLASH);
200 sound(SND_MISSILE_HIT);
201
202 o->Delete();
203 return;
204 }
205
206 if (o->state == 0)
207 {
208 // recoil in oppisite direction
209 o->xinertia = random(-2, -1) << CSF;
210 if (o->dir == LEFT) o->xinertia = -o->xinertia;
211
212 o->yinertia = random(-2, 0) << CSF;
213
214 o->state = 1;
215 }
216
217 XACCEL(0x20);
218
219 if ((++o->timer2 % 4) == 1)
220 {
221 effect(o->CenterX() - o->xinertia, o->CenterY(), EFFECT_SMOKETRAIL_SLOW);
222 }
223
224 // heat-seeking at start, then level out straight
225 if (o->timer2 < 50)
226 {
227 if (o->y < player->y)
228 o->yinertia += 0x20;
229 else
230 o->yinertia -= 0x20;
231 }
232 else
233 {
234 o->yinertia = 0;
235 }
236
237 // flash
238 o->frame ^= 1;
239
240 if (o->xinertia < -0x400)
241 o->xinertia = -0x600;
242
243 if (o->xinertia > 0x400)
244 o->xinertia = 0x600;
245 }
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268