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