1 
2 #include "../stdai.h"
3 #include "pooh_black.fdh"
4 
5 #define FRAME_STAND			0
6 #define FRAME_DYING			1
7 #define FRAME_LANDED		2
8 #define FRAME_FLYING		3
9 
10 static int bubble_xmark = 0, bubble_ymark = 0;
11 
12 
INITFUNC(AIRoutines)13 INITFUNC(AIRoutines)
14 {
15 	ONTICK(OBJ_POOH_BLACK, ai_pooh_black);
16 	ONTICK(OBJ_POOH_BLACK_BUBBLE, ai_pooh_black_bubble);
17 
18 	ONTICK(OBJ_POOH_BLACK_DYING, ai_pooh_black_dying);
19 }
20 
21 /*
22 void c------------------------------() {}
23 */
24 
ai_pooh_black(Object * o)25 void ai_pooh_black(Object *o)
26 {
27 	// assume flying frame as it's the one used in most of the states
28 	o->frame = FRAME_FLYING;
29 
30 	//debugVline(o->CenterX(), 255,192,192);
31 	//debugVline(bubble_xmark, 0,0,255);
32 
33 	switch(o->state)
34 	{
35 		case 0:
36 		{
37 			FACEPLAYER;
38 			o->yinertia = 0xA00;
39 			o->flags |= FLAG_IGNORE_SOLID;
40 
41 			if (o->y >= (8 * TILE_H) << CSF)
42 			{
43 				o->flags &= ~FLAG_IGNORE_SOLID;
44 				o->state = 1;
45 			}
46 		}
47 		break;
48 
49 		case 1:
50 		{
51 			o->yinertia = 0xA00;
52 
53 			if (o->blockd)
54 			{
55 				SmokeSide(o, 8, DOWN);
56 				sound(SND_BIG_CRASH);
57 				quake(30);
58 
59 				KillObjectsOfType(OBJ_POOH_BLACK_BUBBLE);
60 				o->state = 2;
61 			}
62 
63 			// damage player if he falls on him
64 			o->damage = (o->y < player->y && player->blockd) ? 20 : 0;
65 		}
66 		break;
67 
68 		case 2:		// landed, showing landed frame
69 		{
70 			o->frame = FRAME_LANDED;
71 			o->damage = 0;
72 			if (++o->timer > 24)
73 			{
74 				o->state = 3;
75 				o->timer = 0;
76 			}
77 		}
78 		break;
79 
80 		case 3:		// standing, stare at player till he shoots us.
81 		{
82 			o->frame = FRAME_STAND;
83 			bubble_xmark = o->CenterX();
84 			bubble_ymark = o->CenterY();
85 
86 			// spawn bubbles when hit
87 			if (o->shaketime && (o->shaketime & 1))
88 			{
89 				int x = o->CenterX() + random(-12<<CSF, 12<<CSF);
90 				int y = o->CenterY() + random(-12<<CSF, 12<<CSF);
91 
92 				Object *bubble = CreateObject(x, y, OBJ_POOH_BLACK_BUBBLE);
93 
94 				bubble->xinertia = random(-0x600, 0x600);
95 				bubble->yinertia = random(-0x600, 0x600);
96 
97 				// fly away after hit enough times
98 				if (++o->timer > 30)
99 				{
100 					o->state = 4;
101 					o->timer = 0;
102 
103 					o->flags |= FLAG_IGNORE_SOLID;
104 					o->yinertia = -0xC00;
105 				}
106 			}
107 		}
108 		break;
109 
110 		case 4:		// flying away off-screen
111 		{
112 			o->timer++;
113 
114 			// bubbles shoot down past player just before
115 			// he falls.
116 			if (o->timer == 60)
117 			{
118 				bubble_xmark = player->CenterX();
119 				bubble_ymark = (10000 << CSF);
120 			}
121 			else if (o->timer < 60)
122 			{
123 				bubble_xmark = o->CenterX();
124 				bubble_ymark = o->CenterY();
125 			}
126 
127 			// fall on player
128 			if (o->timer >= 170)
129 			{
130 				o->x = player->CenterX() - (o->Width() / 2);
131 				o->y = 0;
132 				o->yinertia = 0x5ff;
133 
134 				o->state = 0;
135 				o->timer = 0;
136 			}
137 		}
138 		break;
139 	}
140 
141 	static const int frames[] = { 3, 3, 2, 0, 3 };
142 	o->frame = frames[o->state];
143 }
144 
145 
ai_pooh_black_bubble(Object * o)146 void ai_pooh_black_bubble(Object *o)
147 {
148 	if (o->hp < 100)
149 	{
150 		o->flags &= ~FLAG_SHOOTABLE;
151 		o->damage = 0;
152 		o->frame = 2;
153 	}
154 	else if (!random(0, 10))
155 	{
156 		o->frame = 0;
157 	}
158 	else
159 	{
160 		o->frame = 1;
161 	}
162 
163 	// adjust bubble target position so that they try to align
164 	// their centers with the mark instead of their upper-left corners.
165 	int xmark = bubble_xmark - ((sprites[SPR_POOH_BLACK_BUBBLE].w / 2) << CSF);
166 	int ymark = bubble_ymark - ((sprites[SPR_POOH_BLACK_BUBBLE].h / 2) << CSF);
167 
168 	o->xinertia += (o->x > xmark) ? -0x40 : 0x40;
169 	o->yinertia += (o->y > ymark) ? -0x40 : 0x40;
170 
171 	LIMITX(0x11FD);
172 	LIMITY(0x11FD);
173 }
174 
175 
ai_pooh_black_dying(Object * o)176 void ai_pooh_black_dying(Object *o)
177 {
178 	bubble_xmark = o->CenterX();
179 	bubble_ymark = -(10000 << CSF);
180 
181 	switch(o->state)
182 	{
183 		case 0:
184 		{
185 			o->frame = FRAME_DYING;
186 			FACEPLAYER;
187 
188 			sound(SND_BIG_CRASH);
189 			SmokeClouds(o, 10, 12, 12);
190 			KillObjectsOfType(OBJ_POOH_BLACK_BUBBLE);
191 
192 			o->state = 1;
193 		}
194 		break;
195 
196 		case 1:
197 		case 2:
198 		{
199 			game.quaketime = 2;
200 
201 			if (++o->timer > 200)
202 			{
203 				o->state = 2;
204 				o->timer2++;
205 
206 				o->clip_enable = true;
207 				o->clipy1 = (o->timer2 / 8);
208 				o->display_xoff = (o->timer2 & 1);
209 
210 				if ((o->timer2 % 4) == 2)
211 					sound(SND_BUBBLE);
212 
213 				if (o->clipy1 >= o->clipy2)
214 					o->Delete();
215 			}
216 		}
217 		break;
218 	}
219 
220 
221 	if (o->timer & 1)
222 	{
223 		int x = o->CenterX() + random(-12<<CSF, 12<<CSF);
224 		int y;
225 
226 		if (o->state == 2)
227 			y = o->y + (o->clipy1 << CSF) + random(-4<<CSF, 4<<CSF);
228 		else
229 			y = o->CenterY() + random(-12<<CSF, 12<<CSF);
230 
231 		Object *bubble = CreateObject(x, y, OBJ_POOH_BLACK_BUBBLE);
232 		bubble->xinertia = random(-0x200, 0x200);
233 		bubble->yinertia = -0x100;
234 	}
235 
236 }
237 
238 
239 
240 
241