1 /* Copyright (C) 1995-2002 FSGames. Ported by Sean Ford and Yan Shosh
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17 //
18 // treasure; a derived class of walker
19 //
20
21 //#include "graph.h"
22 #include <math.h>
23 #include "obmap.h"
24 #include "loader.h"
25 #include "screen.h"
26 #include "treasure.h"
27 #include "text.h"
28 #include "stats.h"
29 #include "guy.h"
30
31 // Zardus: this is the func to get events
32 void get_input_events(bool);
33
34 // Zardus: from video.cpp for retreat crash ugly hack fix
35 extern bool retreat;
36
treasure(unsigned char * data,screen * myscreen)37 treasure::treasure(unsigned char *data, screen *myscreen) : walker(data, myscreen)
38 {
39 ignore =(char) 0;
40 dead = (char) 0;
41 }
42
~treasure()43 treasure::~treasure()
44 {
45 //bufffers: PORT: cannot call destructor w/o obj: walker::~walker();
46 }
47
act()48 short treasure::act()
49 {
50 // Abort all later code for now ..
51 return 1;
52 }
53
eat_me(walker * eater)54 short treasure::eat_me(walker * eater)
55 {
56 short guys_here;
57 oblink *here;
58 static text eattext(screenp);
59 char message[80];
60 char * eatkeys;
61 long distance;
62 walker *target, *flash;
63 static char exitname[40];
64 long leftside, rightside;
65
66 switch (family)
67 {
68 case FAMILY_DRUMSTICK:
69 if (eater->stats->hitpoints >= eater->stats->max_hitpoints)
70 return 1;
71 else
72 {
73 eater->stats->hitpoints += (short) ((10*stats->level) + (short) random((short) 10*stats->level));
74 if (eater->stats->hitpoints > eater->stats->max_hitpoints)
75 eater->stats->hitpoints = eater->stats->max_hitpoints;
76 dead = 1;
77 if (on_screen())
78 screenp->soundp->play_sound(SOUND_EAT);
79 return 1;
80 }
81 case FAMILY_GOLD_BAR:
82 if (eater->team_num == 0 || eater->myguy)
83 {
84 myscreen->m_score[eater->team_num] += (200*stats->level);
85 dead = 1;
86 if (on_screen())
87 screenp->soundp->play_sound(SOUND_MONEY);
88 }
89 return 1;
90 case FAMILY_SILVER_BAR:
91 if (eater->team_num == 0 || eater->myguy)
92 {
93 myscreen->m_score[eater->team_num] += (50*stats->level);
94 dead = 1;
95 if (on_screen())
96 screenp->soundp->play_sound(SOUND_MONEY);
97 }
98 return 1;
99 case FAMILY_FLIGHT_POTION:
100 if (!eater->stats->query_bit_flags(BIT_FLYING) )
101 {
102 eater->flight_left += (150*stats->level);
103 if (eater->user != -1)
104 {
105 sprintf(message, "Potion of Flight(%d)!", stats->level);
106 screenp->do_notify(message, eater);
107 }
108 dead = 1;
109 }
110 return 1;
111 case FAMILY_MAGIC_POTION:
112 if (eater->stats->magicpoints < eater->stats->max_magicpoints)
113 eater->stats->magicpoints = eater->stats->max_magicpoints;
114 eater->stats->magicpoints += (50*stats->level);
115 dead = 1;
116 if (eater->user != -1)
117 {
118 sprintf(message, "Potion of Mana(%d)!", stats->level);
119 screenp->do_notify(message, eater);
120 }
121 return 1;
122 case FAMILY_INVULNERABLE_POTION:
123 if (!eater->stats->query_bit_flags(BIT_INVINCIBLE) )
124 {
125 eater->invulnerable_left += (150*stats->level);
126 dead = 1;
127 if (eater->user != -1)
128 {
129 sprintf(message, "Potion of Invulnerability(%d)!", stats->level);
130 screenp->do_notify(message, eater);
131 }
132 }
133 return 1;
134 case FAMILY_INVIS_POTION:
135 eater->invisibility_left += (150*stats->level);
136 if (eater->user != -1)
137 {
138 sprintf(message, "Potion of Invisibility(%d)!", stats->level);
139 screenp->do_notify(message, eater);
140 }
141 dead = 1;
142 return 1;
143 case FAMILY_SPEED_POTION:
144 eater->speed_bonus_left += 50*stats->level;
145 eater->speed_bonus = stats->level;
146 if (eater->user != -1)
147 {
148 sprintf(message, "Potion of Speed(%d)!", stats->level);
149 screenp->do_notify(message, eater);
150 }
151 dead = 1;
152 return 1;
153 case FAMILY_EXIT: // go to another level, possibly
154 if (eater->in_act) return 1;
155 if (eater->query_act_type()!= ACT_CONTROL || (eater->skip_exit > 1))
156 return 1;
157 eater->skip_exit = 10;
158 // See if there are any enemies left ...
159 if (screenp->level_done == 0)
160 guys_here = 1;
161 else
162 guys_here = 0;
163 // Get the name of our exit..
164 sprintf(message, "scen%d", stats->level);
165 strcpy(exitname, myscreen->get_scen_title(message, myscreen) );
166
167 //buffers: PORT: using strcmp instead of stricmp
168 if (!strcmp(exitname, "none"))
169 sprintf(exitname, "Level %d", stats->level);
170
171 leftside = 160 - ( (strlen(exitname) + 18) * 3);
172 rightside = 160 + ( (strlen(exitname) + 18) * 3);
173 // First check to see if we're withdrawing into
174 // somewhere we've been, in which case we abort
175 // this level, and set our current level to
176 // that pointed to by the exit ...
177 if ( (screenp->levelstatus[stats->level] == 1)
178 && (screenp->levelstatus[screenp->scen_num] == 0)
179 && (guys_here != 0)
180 ) // okay to leave
181 {
182 leftside -= 12;
183 rightside += 12;
184 screenp->draw_dialog(leftside, 20, rightside, 54, "Exit Field");
185 sprintf(message, "Withdraw to %s? (Y/N)", exitname);
186 eattext.write_y(42, message, DARK_BLUE, 1);
187 screenp->buffer_to_screen(0, 0, 320, 200);
188 eatkeys = query_keyboard();
189 clear_keyboard();
190 while (!eatkeys[SDLK_y] && !eatkeys[SDLK_n])
191 get_input_events(WAIT);
192 // Redraw screen ..
193 screenp->redrawme = 1;
194
195 if (eatkeys[SDLK_y]) // accepted level change
196 {
197 clear_keyboard();
198 screenp->levelstatus[screenp->scen_num] = 0; // NOT done
199 // Delete all of our current information and abort ..
200 here = myscreen->oblist;
201 while (here)
202 {
203 if (here->ob && here->ob->query_order() == ORDER_LIVING)
204 {
205 //myscreen->remove_ob(here->ob);
206 here->ob->dead = 1;
207 myscreen->myobmap->remove
208 (here->ob);
209 //myscreen->remove_obmap(here->ob);
210 }
211 here = here->next;
212 }
213 //here = myscreen->fxlist;
214 //while (here)
215 //{
216 // if (here->ob)
217 // myscreen->remove_fx_ob(here->ob);
218 // here = here->next;
219 //}
220 // Now load the game as it was ...
221 load_saved_game("save0", myscreen);
222 myscreen->scen_num = (short) (stats->level-1);
223 myscreen->end = 1;
224 save_game("save0", myscreen);
225 retreat = 1;
226
227 return screenp->endgame(1, stats->level); // retreat
228 } // end of accepted withdraw to new level ..
229 clear_keyboard();
230 } // end of checking for withdrawal to completed level
231
232 if (!guys_here) // nobody evil left, so okay to exit level ..
233 {
234 screenp->draw_dialog(30, 20, 290, 54, "Exit Field");
235 sprintf(message, "Exit to %s? (Y/N)", exitname);
236 eattext.write_y(42, message, DARK_BLUE, 1);
237 screenp->buffer_to_screen(0, 0, 320, 200);
238 eatkeys = query_keyboard();
239 clear_keyboard();
240 // Zardus: FIX: get_input_events instead of freezing and counting :-)
241 while (!eatkeys[SDLK_y] && !eatkeys[SDLK_n])
242 get_input_events(WAIT);
243 // Redraw screen ..
244 screenp->redrawme = 1;
245
246 if (eatkeys[SDLK_y]) // accepted level change
247 {
248 clear_keyboard();
249 //screenp->levelstatus[screenp->scen_num] = 1;
250 return screenp->endgame(0, stats->level);
251 }
252 clear_keyboard();
253 return 1;
254 }
255 return 1;
256 case FAMILY_TELEPORTER:
257 if (eater->skip_exit > 1)
258 return 1;
259 distance = distance_to_ob_center(eater); // how away?
260 if (distance > 21)
261 return 1;
262 if (distance < 4 && eater->skip_exit)
263 {
264 //eater->skip_exit++;
265 eater->skip_exit = 8;
266 return 1;
267 }
268 // If we're close enough, teleport ..
269 eater->skip_exit += 20;
270 if (!leader)
271 target = find_teleport_target();
272 else
273 target = leader;
274 if (!target)
275 return 1;
276 leader = target;
277 eater->center_on(target);
278 if (!screenp->query_passable(eater->xpos, eater->ypos, eater))
279 {
280 eater->center_on(this);
281 return 1;
282 }
283 // Now do special effects
284 flash = screenp->add_ob(ORDER_FX, FAMILY_FLASH);
285 flash->ani_type = ANI_EXPAND_8;
286 flash->center_on(this);
287 return 1;
288 case FAMILY_LIFE_GEM: // get back some of lost man's xp ..
289 if (eater->team_num != team_num) // only our team can get these
290 return 1;
291 myscreen->m_score[eater->team_num] += stats->hitpoints;
292 flash = screenp->add_ob(ORDER_FX, FAMILY_FLASH);
293 flash->ani_type = ANI_EXPAND_8;
294 flash->center_on(this);
295 dead = 1;
296 death();
297 return 1;
298 case FAMILY_KEY: // get the key to this door ..
299 if (!(eater->keys & (long)(pow((double) 2, stats->level)) )) // just got it?
300 {
301 eater->keys |= (long) (pow((double)2, stats->level)); // ie, 2, 4, 8, 16...
302 if (eater->myguy)
303 sprintf(message, "%s picks up key %d", eater->myguy->name,
304 stats->level);
305 else
306 sprintf(message, "%s picks up key %d", eater->stats->name, stats->level);
307 if (eater->team_num == 0) // only show players picking up keys
308 {
309 myscreen->do_notify(message, eater);
310 if (eater->on_screen())
311 myscreen->soundp->play_sound(SOUND_MONEY);
312 }
313 }
314 return 1;
315 default:
316 return 1;
317 } // end of treasure-check
318 }
319
set_direct_frame(short whatframe)320 void treasure::set_direct_frame(short whatframe)
321 {
322 unsigned char * data;
323 frame = whatframe;
324
325 data = screenp->myloader->graphics[PIX(order, family)];
326 bmp = (unsigned char *) (data+3 + frame*size);
327
328 }
329
find_teleport_target()330 walker * treasure::find_teleport_target()
331 {
332 walker *target = NULL;
333 oblink *here = screenp->fxlist;
334 short keep_looking = 1;
335 short number = 0;
336
337 // First find where we are in the list ...
338 while (here && keep_looking)
339 {
340 if (here->ob && here->ob == this) // found us
341 keep_looking = 0;
342 else
343 {
344 here = here->next;
345 number++;
346 }
347 }
348
349 if (keep_looking) // didn't find us?
350 return NULL;
351
352 //printf("Teleporting from #%d ..", number);
353
354 // Now search the rest of the loop ..
355 keep_looking = 1;
356 here = here->next;
357 number++;
358 while (here && keep_looking)
359 {
360 if (here->ob && !here->ob->dead)
361 {
362 if (here->ob->query_order() == ORDER_TREASURE &&
363 here->ob->query_family() == FAMILY_TELEPORTER &&
364 here->ob->stats->level == stats->level)
365 {
366 target = here->ob;
367 keep_looking = 0;
368 //printf(" to target %d\n", number);
369 return target;
370 }
371 }
372 here = here->next;
373 number++;
374 }
375
376 // Hit the end of the list, look from top down now ..
377 here = screenp->fxlist;
378 number = 0;
379 while (here)
380 {
381 if (here->ob && !here->ob->dead)
382 {
383 if (here->ob->query_order() == ORDER_TREASURE &&
384 here->ob->query_family() == FAMILY_TELEPORTER &&
385 here->ob->stats->level == stats->level)
386 {
387 target = here->ob;
388 //printf(" to looped target %d\n", number);
389 return target;
390 }
391 }
392 here = here->next;
393 number++;
394 }
395
396 return target;
397 }
398
399