added worldarea -> will be responsible for world map rendering
[dboe.git] / specials.c
blobdadc91c8f826ca026ae3e847e0ecf8ccdc8cdf25
3 #include <Windows.h>
4 #include "stdio.h"
5 #include "string.h"
7 #include "global.h"
8 #include "party.h"
9 #include "town.h"
10 #include "text.h"
11 #include "infodlgs.h"
12 #include "items.h"
13 #include "itemdata.h"
14 #include "combat.h"
15 #include "monster.h"
16 #include "locutils.h"
17 #include "fields.h"
18 #include "exlsound.h"
19 #include "townspec.h"
20 #include "graphics.h"
21 #include "fileio.h"
22 #include "specials.h"
23 #include "newgraph.h"
24 #include "dlgutils.h"
26 extern HWND mainPtr;
27 extern short overall_mode;
28 extern party_record_type far party;
29 extern piles_of_stuff_dumping_type *data_store;
30 extern piles_of_stuff_dumping_type2 *data_store2;
31 extern talking_record_type far talking;
32 extern scenario_data_type far scenario;
34 extern current_town_type far c_town;
35 extern unsigned char far out[96][96];
36 extern unsigned char far out_e[96][96];
37 extern unsigned char far combat_terrain[64][64];
38 extern unsigned char far sfx[64][64];
39 extern short which_combat_type,current_pc,stat_window;
40 extern outdoor_record_type far outdoors[2][2];
41 extern location pc_pos[6],center;
42 extern Boolean in_scen_debug,belt_present,registered,processing_fields,monsters_going,suppress_stat_screen,boom_anim_active;
43 extern big_tr_type far t_d;
44 extern pc_record_type far adven[6];
45 extern effect_pat_type current_pat;
46 extern town_item_list far t_i;
47 extern out_wandering_type store_wandering_special;
48 extern short pc_marked_damage[6];
49 extern short monst_marked_damage[T_M];
50 extern HWND modeless_dialogs[18];
51 extern Boolean fast_bang,end_scenario;
52 extern short town_size[3];
53 extern short town_type;
54 extern piles_of_stuff_dumping_type5 *data_store5;
55 extern char far scen_strs2[110][256];
57 Boolean can_draw_pcs = TRUE;
58 short store_item_spell_level = 10;
59 Boolean special_in_progress = FALSE;
61 item_record_type null_item = {0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0, 0,0, {0,0},"", "",0,0,0,0};
62 short spec_str_offset[3] = {160,10,20};
63 short current_pc_picked_in_spec_enc = -1; // pc that's been selected, -1 if none
64 location store_special_loc;
65 short boom_gr[8] = {3,0,2,1,1,4,3,3};
66 short skill_max[20] = {20,20,20,20,20,20,20,20,20,7,
67 7,20,20,10,20,20,20,20,20};
69 // 0 - everywhere 1 - combat only 2 - town only 3 - town & combat only 4 - can't use 5 - outdoor
70 // + 10 - mag. inept can use
71 short abil_chart[200] = {4,4,4,4,4,4,4,4,4,4,
72 4,4,4,4,4,4,4,4,4,4,
73 4,4,4,4,4,4,4,4,4,4,
74 4,4,4,4,4,4,4,4,4,4,
75 4,4,4,4,4,4,4,4,4,4,
76 4,4,4,4,4,4,4,4,4,4, // 50
77 4,4,4,4,4,4,4,4,4,4,
78 13,0,0,0,3, 3,3,0,3,3,
79 3,3,3,3,3, 0,0,0,0,3,
80 13,3,3,5,0, 0,0,0,0,0,
81 4,4,4,4,4,4,4,4,4,4, // 100
82 1,1,1,1,1, 1,1,1,1,3,
83 3,1,1,1,1, 1,1,1,1,3,
84 1,2,2,1,1, 1,4,4,4,4,
85 4,4,4,4,4,4,4,4,4,4,
86 4,4,4,4,4,4,4,4,4,4, // 150
87 4,4,4,4,4,4,4,4,4,4,
88 4,4,4,4,4,4,4,4,4,4,
89 4,4,4,4,4,4,4,4,4,4,
90 4,4,4,4,4,4,4,4,4,4};
92 Boolean town_specials(short which,short t_num)
93 //short which; // number, 0 - 39, of special
95 Boolean can_enter = TRUE;
96 short choice,spec_id,str_resource;
97 location l;
100 l = c_town.town.special_locs[which];
101 spec_id = c_town.town.spec_id[which];
102 if (spec_id < 0)
103 return TRUE;
105 // call special
107 erase_specials();
109 return can_enter;
112 Boolean handle_wandering_specials (short which,short mode)
113 //short mode; // 0 - pre 1 - end by victory 2 - end by flight
114 // wanderin spec 99 -> generic spec
117 short choice,i,j;
118 short s1 = 0,s2 = 0,s3 = 0;
119 location null_loc = {0,0};
121 if ((mode == 0) && (store_wandering_special.spec_on_meet >= 0)) { // When encountering
122 run_special(13,1,store_wandering_special.spec_on_meet,null_loc,&s1,&s2,&s3);
123 if (s1 > 0)
124 return FALSE;
127 if ((mode == 1) && (store_wandering_special.spec_on_win >= 0)) {// After defeating
128 run_special(15,1,store_wandering_special.spec_on_win,null_loc,&s1,&s2,&s3);
130 if ((mode == 2) && (store_wandering_special.spec_on_flee >= 0)) {// After fleeing like a buncha girly men
131 run_special(14,1,store_wandering_special.spec_on_flee,null_loc,&s1,&s2,&s3);
133 return TRUE;
137 Boolean check_special_terrain(location where_check,short mode,short which_pc,short *spec_num,
138 Boolean *forced)
139 //short mode; // 0 - out 1 - town 2 - combat
141 unsigned char ter;
142 short r1,i,choice,door_pc,x,ter_special,ter_flag1,ter_flag2,dam_type = 0,pic_type = 0,ter_pic = 0;
143 Boolean can_enter = TRUE;
144 location out_where,from_loc,to_loc;
145 short s1 = 0,s2 = 0,s3 = 0;
147 *spec_num = -1;
148 *forced = FALSE;
150 switch (mode) {
151 case 0:
152 ter = out[where_check.x][where_check.y];
153 from_loc = party.p_loc;
154 break;
155 case 1:
156 ter = t_d.terrain[where_check.x][where_check.y];
157 from_loc = c_town.p_loc;
158 break;
159 case 2:
160 ter = combat_terrain[where_check.x][where_check.y];
161 from_loc = pc_pos[current_pc];
162 break;
164 ter_special = scenario.ter_types[ter].special;
165 ter_flag1 = scenario.ter_types[ter].flag1;
166 ter_flag2 = scenario.ter_types[ter].flag2;
167 ter_pic = scenario.ter_types[ter].picture;
169 if ((mode > 0) && (ter_special >= 16) &&
170 (ter_special <= 19)) {
171 if (
172 ((ter_special == 16) && (where_check.y > from_loc.y)) ||
173 ((ter_special == 17) && (where_check.x < from_loc.x)) ||
174 ((ter_special == 18) && (where_check.y < from_loc.y)) ||
175 ((ter_special == 19) && (where_check.x > from_loc.x)) ) {
176 ASB("The moving floor prevents you.");
177 return FALSE;
181 if (mode == 0) {
182 out_where = global_to_local(where_check);
184 for (i = 0; i < 18; i++)
185 if (same_point(out_where,outdoors[party.i_w_c.x][party.i_w_c.y].special_locs[i]) == TRUE) {
186 *spec_num = outdoors[party.i_w_c.x][party.i_w_c.y].special_id[i];
187 if ((*spec_num >= 0) &&
188 (outdoors[party.i_w_c.x][party.i_w_c.y].specials[*spec_num].type == 4))
189 *forced = TRUE;
190 // call special
191 run_special(mode,1,outdoors[party.i_w_c.x][party.i_w_c.y].special_id[i],out_where,&s1,&s2,&s3);
192 if (s1 > 0)
193 can_enter = FALSE;
194 erase_out_specials();
195 put_pc_screen();
196 put_item_screen(stat_window,0);
200 if ((is_combat()) && (((ter_pic <= 207) && (ter_pic >= 212)) || (ter_pic == 406))) {
201 ASB("Move: Can't trigger this special in combat.");
202 return FALSE;
205 if (((mode == 1) || ((mode == 2) && (which_combat_type == 1)))
206 && (special(where_check.x,where_check.y))) {
207 if (is_force_barrier(where_check.x,where_check.y)) {
208 add_string_to_buf(" Magic barrier! ");
209 return FALSE;
211 for (i = 0; i < 50; i++)
212 if ((same_point(where_check,c_town.town.special_locs[i]) == TRUE) &&
213 (c_town.town.spec_id[i] >= 0)) {
214 if (c_town.town.specials[c_town.town.spec_id[i]].type == 4) {
215 *forced = TRUE;
217 *spec_num = c_town.town.spec_id[i];
218 if ((is_blocked(where_check) == FALSE) || (ter_special == 1)
219 || (ter_special == 12) || (ter_special == 13)) {
220 give_help(54,0,0);
221 run_special(mode,2,c_town.town.spec_id[i],where_check,&s1,&s2,&s3);
222 if (s1 > 0)
223 can_enter = FALSE;
226 put_pc_screen();
227 put_item_screen(stat_window,0);
230 if (can_enter == FALSE)
231 return FALSE;
233 if ((!is_out()) && (overall_mode < 20)) {
234 check_fields(where_check,mode,which_pc);
236 if (is_web(where_check.x,where_check.y)) {
237 add_string_to_buf(" Webs! ");
238 if (mode < 2) {
239 suppress_stat_screen = TRUE;
240 for (i = 0; i < 6; i++) {
241 r1 = get_ran(1,2,3);
242 web_pc(i,r1);
244 suppress_stat_screen = TRUE;
245 put_pc_screen();
247 else web_pc(current_pc,get_ran(1,2,3));
248 take_web(where_check.x,where_check.y);
250 if (is_force_barrier(where_check.x,where_check.y)) {
251 add_string_to_buf(" Magic barrier! ");
252 can_enter = FALSE;
254 if (is_crate(where_check.x,where_check.y)) {
255 add_string_to_buf(" You push the crate.");
256 to_loc = push_loc(from_loc,where_check);
257 take_crate((short) where_check.x,(short) where_check.y);
258 if (to_loc.x > 0)
259 make_crate((short) to_loc.x,(short) to_loc.y);
260 for (i = 0; i < NUM_TOWN_ITEMS; i++)
261 if ((t_i.items[i].variety > 0) && (same_point(t_i.items[i].item_loc,where_check))
262 && (is_contained(t_i.items[i]) == TRUE))
263 t_i.items[i].item_loc = to_loc;
265 if (is_barrel(where_check.x,where_check.y)) {
266 add_string_to_buf(" You push the barrel.");
267 to_loc = push_loc(from_loc,where_check);
268 take_barrel((short) where_check.x,(short) where_check.y);
269 if (to_loc.x > 0)
270 make_barrel((short) to_loc.x,(short) to_loc.y);
271 for (i = 0; i < NUM_TOWN_ITEMS; i++)
272 if ((t_i.items[i].variety > 0) && (same_point(t_i.items[i].item_loc,where_check))
273 && (is_contained(t_i.items[i]) == TRUE))
274 t_i.items[i].item_loc = to_loc;
279 switch (ter_special) {
280 case 1:
281 alter_space(where_check.x,where_check.y,ter_flag1);
282 if (ter_flag2 < 200) {
283 play_sound(-1 * ter_flag2);
285 give_help(47,65,0);
286 if (scenario.ter_types[ter].blockage > 2)
287 can_enter = FALSE;
288 break;
289 case 2: case 3:case 4:
290 if (flying())
291 break;
292 if (ter_special == 2) {
293 add_string_to_buf(" It's hot!");
294 dam_type = 1; pic_type = 0;
295 if (party.stuff_done[305][3] > 0) {
296 add_string_to_buf(" It doesn't affect you.");
297 break;
300 if (ter_special == 3) {
301 add_string_to_buf(" You feel cold!");
302 dam_type = 5; pic_type = 4;
304 if (ter_special == 4) {
305 add_string_to_buf(" Something shocks you!");
306 dam_type = 3; pic_type = 1;
308 r1 = get_ran(ter_flag2,dam_type,ter_flag1);
309 if (mode < 2)
310 hit_party(r1,1);
311 fast_bang = 1;
312 if (mode == 2)
313 damage_pc(which_pc,r1,dam_type,-1);
314 if (overall_mode < 10)
315 boom_space(party.p_loc,overall_mode,pic_type,r1,12);
316 fast_bang = 0;
317 break;
318 case 5: case 6:
319 if (flying())
320 break;
321 if (party.in_boat >= 0)
322 return TRUE;
323 one_sound(17);
324 if (mode < 2) {
325 for (i = 0; i < 6; i++)
326 if (adven[i].main_status == 1)
328 if (get_ran(1,1,100) <= ter_flag2) {
329 if (ter_special == 5)
330 poison_pc(i,ter_flag1);
331 else disease_pc(i,ter_flag1);
335 //print_nums(1,which_pc,current_pc);
336 if (mode == 2) {
337 if (get_ran(1,1,100) <= ter_flag2){
338 if (ter_special == 5)
339 poison_pc(which_pc,ter_flag1);
340 else disease_pc(which_pc,ter_flag1);
343 break;
344 case 12: // local special
345 run_special(mode,2,ter_flag1,where_check,&s1,&s2,&s3);
346 if (s1 > 0)
347 can_enter = FALSE;
348 break;
349 case 13: // global special
350 run_special(mode,0,ter_flag1,where_check,&s1,&s2,&s3);
351 if (s1 > 0)
352 can_enter = FALSE;
353 break;
356 // Locked doors
357 case 9: case 10:
358 if (is_combat()) { // No lockpicking in combat
359 add_string_to_buf(" Can't enter: It's locked.");
360 break;
363 // See what party wants to do.
364 choice = fancy_choice_dialog(993,0);
366 can_enter = FALSE;
367 if (choice == 1)
368 break;
369 if ((door_pc = select_pc(1,0)) < 6) {
370 if (choice == 2)
371 pick_lock(where_check,door_pc);
372 else bash_door(where_check,door_pc);
374 break;
379 // Action may change terrain, so update what's been seen
380 if (is_town())
381 update_explored(c_town.p_loc);
382 if (is_combat())
383 update_explored(pc_pos[current_pc]);
385 return can_enter;
388 // This procedure find the effects of fields that would affect a PC who moves into
389 // a space or waited in that same space
390 void check_fields(location where_check,short mode,short which_pc)
391 //mode; // 0 - out 1 - town 2 - combat
393 short r1,i,choice,door_pc;
395 if (is_out())
396 return;
397 if (is_town())
398 fast_bang = 1;
399 if (is_fire_wall(where_check.x,where_check.y)) {
400 add_string_to_buf(" Fire wall! ");
401 r1 = get_ran(1,1,6) + 1;
402 // if (mode < 2)
403 // hit_party(r1,1);
404 if (mode == 2)
405 damage_pc(which_pc,r1,1,-1);
406 if (overall_mode < 10)
407 boom_space(party.p_loc,overall_mode,0,r1,5);
409 if (is_force_wall(where_check.x,where_check.y)) {
410 add_string_to_buf(" Force wall! ");
411 r1 = get_ran(2,1,6);
412 // if (mode < 2)
413 // hit_party(r1,3);
414 if (mode == 2)
415 damage_pc(which_pc,r1,3,-1);
416 if (overall_mode < 10)
417 boom_space(party.p_loc,overall_mode,1,r1,12);
419 if (is_ice_wall(where_check.x,where_check.y)) {
420 add_string_to_buf(" Ice wall! ");
421 r1 = get_ran(2,1,6);
422 // if (mode < 2)
423 // hit_party(r1,5);
424 if (mode == 2)
425 damage_pc(which_pc,r1,5,-1);
426 if (overall_mode < 10)
427 boom_space(party.p_loc,overall_mode,4,r1,7);
429 if (is_blade_wall(where_check.x,where_check.y)) {
430 add_string_to_buf(" Blade wall! ");
431 r1 = get_ran(4,1,8);
432 // if (mode < 2)
433 // hit_party(r1,0);
434 if (mode == 2)
435 damage_pc(which_pc,r1,0,-1);
436 if (overall_mode < 10)
437 boom_space(party.p_loc,overall_mode,3,r1,2);
439 if (is_quickfire(where_check.x,where_check.y)) {
440 add_string_to_buf(" Quickfire! ");
441 r1 = get_ran(2,1,8);
442 // if (mode < 2)
443 // hit_party(r1,1);
444 if (mode == 2)
445 damage_pc(which_pc,r1,1,-1);
446 if (overall_mode < 10)
447 boom_space(party.p_loc,overall_mode,0,r1,5);
449 if (is_scloud(where_check.x,where_check.y)) {
450 add_string_to_buf(" Stinking cloud! ");
451 if (mode < 2) {
452 suppress_stat_screen = TRUE;
453 for (i = 0; i < 6; i++) {
454 r1 = get_ran(1,2,3);
455 curse_pc(i,r1);
457 suppress_stat_screen = FALSE;
458 put_pc_screen();
460 else curse_pc(current_pc,get_ran(1,2,3));
462 if (is_sleep_cloud(where_check.x,where_check.y)) {
463 add_string_to_buf(" Sleep cloud! ");
464 if (mode < 2) {
465 suppress_stat_screen = TRUE;
466 for (i = 0; i < 6; i++) {
467 sleep_pc(i,3,11,0);
469 suppress_stat_screen = FALSE;
470 put_pc_screen();
472 else sleep_pc(current_pc,3,11,0);
474 if (is_fire_barrier(where_check.x,where_check.y)) {
475 add_string_to_buf(" Magic barrier! ");
476 r1 = get_ran(2,1,10);
477 if (mode < 2)
478 hit_party(r1,3);
479 if (mode == 2)
480 damage_pc(which_pc,r1,3,-1);
481 if (overall_mode < 10)
482 boom_space(party.p_loc,overall_mode,1,r1,12);
484 fast_bang = 0;
486 void use_item(short pc,short item)
488 Boolean take_charge = TRUE,inept_ok = FALSE;
489 short abil,level,i,j,item_use_code,store,str,type,amt,which_stat,r1;
490 char to_draw[60];
491 location user_loc;
492 creature_data_type *which_m;
493 effect_pat_type s = {{{0,0,0,0,0,0,0,0,0},
494 {0,0,0,0,0,0,0,0,0},
495 {0,0,0,0,0,0,0,0,0},
496 {0,0,0,0,0,0,0,0,0},
497 {0,0,0,0,1,0,0,0,0},
498 {0,0,0,0,0,0,0,0,0},
499 {0,0,0,0,0,0,0,0,0},
500 {0,0,0,0,0,0,0,0,0},
501 {0,0,0,0,0,0,0,0,0}}};
502 abil = adven[pc].items[item].ability;
503 level = adven[pc].items[item].item_level;
505 item_use_code = abil_chart[abil];
506 if (item_use_code >= 10) {
507 item_use_code -= 10;
508 inept_ok = TRUE;
511 if (is_out())
512 user_loc = party.p_loc;
513 if (is_town())
514 user_loc = c_town.p_loc;
515 if (is_combat())
516 user_loc = pc_pos[current_pc];
518 if (item_use_code == 4) {
519 add_string_to_buf("Use: Can't use this item. ");
520 take_charge = FALSE;
522 if ((adven[pc].traits[11] == TRUE) && (inept_ok == FALSE)){
523 add_string_to_buf("Use: Can't - magically inept. ");
524 take_charge = FALSE;
527 if (take_charge == TRUE) {
528 if ((overall_mode == 0) && (item_use_code > 0) && (item_use_code != 5)) {
529 add_string_to_buf("Use: Not while outdoors. ");
530 take_charge = FALSE;
532 if ((overall_mode == 1) && (item_use_code == 1)) {
533 add_string_to_buf("Use: Not while in town. ");
534 take_charge = FALSE;
536 if ((overall_mode == 10) && (item_use_code == 2)) {
537 add_string_to_buf("Use: Not in combat. ");
538 take_charge = FALSE;
540 if ((overall_mode != 0) && (item_use_code == 5)){
541 add_string_to_buf("Use: Only outdoors. ");
542 take_charge = FALSE;
545 if (take_charge == TRUE) {
546 if (is_ident(adven[pc].items[item]) == FALSE)
547 sprintf((char *) to_draw, "Use: %s",adven[pc].items[item].name);
548 else sprintf((char *) to_draw, "Use: %s",adven[pc].items[item].full_name);
549 add_string_to_buf((char *) to_draw);
551 if ((adven[pc].items[item].variety == 7) &&
552 (adven[pc].items[item].graphic_num >= 50) && (adven[pc].items[item].graphic_num <= 52))
553 play_sound(56);
555 str = adven[pc].items[item].ability_strength;
556 store_item_spell_level = str * 2 + 1;
557 type = adven[pc].items[item].magic_use_type;
559 switch (abil) {
560 case 70: // poison weapon
561 take_charge = poison_weapon(pc,str,0);
562 break;
563 case 71: case 73: case 74: case 75: case 76:
564 switch (abil) {
565 case 71:
566 play_sound(4);
567 which_stat = 1;
568 if (type % 2 == 1) {
569 ASB(" You feel awkward."); str = str * -1;}
570 else ASB(" You feel blessed.");
571 break;
572 case 73:
573 play_sound(75);
574 which_stat = 3;
575 if (type % 2 == 1) {
576 ASB(" You feel sluggish."); str = str * -1;}
577 else ASB(" You feel speedy.");
578 break;
579 case 74:
580 play_sound(68);
581 which_stat = 4;
582 if (type % 2 == 1) {
583 ASB(" You feel odd."); str = str * -1;}
584 else ASB(" You feel protected.");
585 break;
586 case 75:
587 play_sound(51);
588 which_stat = 5;
589 if (type % 2 == 1) {
590 ASB(" You feel odd."); str = str * -1;}
591 else ASB(" You feel protected.");
592 break;
593 case 76:
594 which_stat = 6;
595 if (type % 2 == 1)
596 ASB(" You feel sticky.");
597 else {
598 ASB(" Your skin tingles."); str = str * -1;}
599 break;
600 case 78:
601 play_sound(43);
602 which_stat = 8;
603 if (type % 2 == 1) {
604 ASB(" You feel exposed."); str = str * -1;}
605 else ASB(" You feel obscure.");
606 break;
607 case 80:
608 play_sound(43);
609 which_stat = 10;
610 if (type % 2 == 1) {
611 ASB(" You feel dull."); str = str * -1;}
612 else ASB(" You start to glow slightly.");
613 break;
615 if (type > 1)
616 affect_party(which_stat,str);
617 else affect_pc(pc,which_stat,str);
618 break;
619 case 72:
620 switch (type) {
621 case 0: ASB(" You feel better."); cure_pc(pc,str); break;
622 case 1: ASB(" You feel ill."); poison_pc(pc,str); break;
623 case 2: ASB(" You all feel better."); cure_party(str); break;
624 case 3: ASB(" You all feel ill."); poison_party(str); break;
626 break;
627 case 77:
628 switch (type) {
629 case 0: ASB(" You feel healthy."); affect_pc(pc,7,-1 * str); break;
630 case 1: ASB(" You feel sick."); disease_pc(pc,str); break;
631 case 2: ASB(" You all feel healthy."); affect_party(7,-1 * str); break;
632 case 3: ASB(" You all feel sick."); for (i = 0; i < 6; i++) disease_pc(i,str); break;
634 break;
635 case 79:
636 switch (type) {
637 case 0: ASB(" You feel clear headed."); affect_pc(pc,9,-1 * str); break;
638 case 1: ASB(" You feel confused."); dumbfound_pc(pc,str); break;
639 case 2: ASB(" You all feel clear headed."); affect_party(9,-1 * str); break;
640 case 3: ASB(" You all feel confused."); for (i = 0; i < 6; i++) dumbfound_pc(i,str); break;
642 break;
643 case 81:
644 switch (type) {
645 case 0: ASB(" You feel alert."); affect_pc(pc,11,-1 * str); break;
646 case 1: ASB(" You feel very tired."); sleep_pc(pc,str + 1,11,200); break;
647 case 2: ASB(" You all feel alert."); affect_party(11,-1 * str); break;
648 case 3: ASB(" You all feel very tired."); for (i = 0; i < 6; i++) sleep_pc(i,str + 1,11,200); break;
650 break;
651 case 82:
652 switch (type) {
653 case 0: ASB(" You find it easier to move."); affect_pc(pc,12,-1 * str * 100); break;
654 case 1: ASB(" You feel very stiff."); sleep_pc(pc,str * 20 + 10,12,200); break;
655 case 2: ASB(" You all find it easier to move."); affect_party(12,-1 * str * 100); break;
656 case 3: ASB(" You all feel very stiff."); for (i = 0; i < 6; i++) sleep_pc(i,str * 20 + 10,12,200); break;
658 break;
659 case 83:
660 switch (type) {
661 case 0: ASB(" Your skin tingles pleasantly."); affect_pc(pc,13,-1 * str); break;
662 case 1: ASB(" Your skin burns!"); acid_pc(pc,str); break;
663 case 2: ASB(" You all tingle pleasantly."); affect_party(13,-1 * str); break;
664 case 3: ASB(" Everyone's skin burns!"); for (i = 0; i < 6; i++) acid_pc(i,str); break;
666 break;
667 case 84:
668 switch (type) {
669 case 0:
670 case 1: ASB(" You feel wonderful!"); heal_pc(pc,str * 20); affect_pc(pc,1,str); break;
671 case 2:
672 case 3: ASB(" Everyone feels wonderful!"); for (i = 0; i < 6; i++) {
673 heal_pc(i,str * 20); affect_pc(i,1,str); } break;
675 break;
676 case 85:
677 switch (type) {
678 case 0: ASB(" You feel much smarter."); award_xp(pc,str * 5); break;
679 case 1: ASB(" You feel forgetful."); drain_pc(pc,str * 5); break;
680 case 2: ASB(" You all feel much smarter."); award_party_xp(str * 5); break;
681 case 3: ASB(" You all feel forgetful."); for (i = 0; i < 6; i++) drain_pc(i,str * 5); break;
683 break;
684 case 86:
685 play_sound(68);
686 switch (type) {
687 case 0: ASB(" You feel much smarter."); adven[pc].skill_pts += str; break;
688 case 1: ASB(" You feel forgetful."); adven[pc].skill_pts = max(0,adven[pc].skill_pts - str); break;
689 case 2: ASB(" You all feel much smarter."); for (i = 0; i < 6; i++) adven[i].skill_pts += str; break;
690 case 3: ASB(" You all feel forgetful."); for (i = 0; i < 6; i++) adven[i].skill_pts = max(0,adven[i].skill_pts - str); break;
692 break;
693 case 87:
694 switch (type) {
695 case 0: ASB(" You feel better."); heal_pc(pc,str * 20); break;
696 case 1: ASB(" You feel sick."); damage_pc(pc,20 * str,4,0); break;
697 case 2: ASB(" You all feel better."); heal_party(str * 20); break;
698 case 3: ASB(" You all feel sick."); hit_party(20 * str,4); break;
700 break;
701 case 88:
702 switch (type) {
703 case 0: ASB(" You feel energized."); restore_sp_pc(pc,str * 5); break;
704 case 1: ASB(" You feel drained."); adven[pc].cur_sp = max(0,adven[pc].cur_sp - str * 5); break;
705 case 2: ASB(" You all feel energized."); restore_sp_party(str * 5); break;
706 case 3: ASB(" You all feel drained."); for (i = 0; i < 6; i++) adven[i].cur_sp = max(0,adven[i].cur_sp - str * 5); break;
708 break;
709 case 89:
710 switch (type) {
711 case 0:
712 case 1: ASB(" You feel terrible."); drain_pc(pc,str * 5); damage_pc(pc,20 * str,4,0); disease_pc(pc,2 * str); dumbfound_pc(pc,2 * str); break;
713 case 2:
714 case 3: ASB(" You all feel terrible."); for (i = 0; i < 6; i++) {
715 drain_pc(i,str * 5); damage_pc(i,20 * str,4,0); disease_pc(i,2 * str); dumbfound_pc(i,2 * str);} break;
717 break;
718 case 90:
719 ASB(" You have more light."); increase_light(50 * str);
720 break;
721 case 91:
722 ASB(" Your footsteps become quieter."); party.stuff_done[305][0] += 5 * str;
723 break;
724 case 92:
725 ASB(" You feel chilly."); party.stuff_done[305][3] += 2 * str;
726 break;
727 case 93:
728 if (party.stuff_done[305][1] > 0) {
729 add_string_to_buf(" Not while already flying. ");
730 break;
732 if (party.in_boat >= 0)
733 add_string_to_buf(" Leave boat first. ");
734 else if (party.in_horse >= 0)////
735 add_string_to_buf(" Leave horse first. ");
736 else {
737 ASB(" You rise into the air!"); party.stuff_done[305][1] += str;
739 break;
740 case 94:
741 switch (type) {
742 case 0:
743 case 1: ASB(" You feel wonderful."); heal_pc(pc,200); cure_pc(pc,8); break;
744 case 2:
745 case 3: ASB(" You all feel wonderful."); heal_party(200); cure_party(8); break;
747 break;
749 // spell effects
750 case 110:
751 add_string_to_buf(" It fires a bolt of flame.");
752 start_spell_targeting(1011);
753 break;
754 case 111:
755 add_string_to_buf(" It shoots a fireball. ");
756 start_spell_targeting(1022);
757 break;
758 case 112:
759 add_string_to_buf(" It shoots a huge fireball. ");
760 start_spell_targeting(1040);
761 break;
762 case 113:
763 add_string_to_buf(" It shoots a black ray. ");
764 start_spell_targeting(1048);
765 break;
766 case 114:
767 add_string_to_buf(" It fires a ball of ice. ");
768 start_spell_targeting(1031);
769 break;
770 case 115:
771 add_string_to_buf(" It fires a purple ray. ");
772 start_spell_targeting(1012);
773 break;
774 case 116:
775 add_string_to_buf(" The ground shakes! ");
776 do_shockwave(pc_pos[current_pc]);
777 break;
778 case 117:
779 add_string_to_buf(" It shoots a white ray. ");
780 start_spell_targeting(1132);
781 break;
782 case 118:
783 add_string_to_buf(" It shoots a golden ray. ");
784 start_spell_targeting(1155);
785 break;
786 case 119:
787 if (summon_monster(str,user_loc,50,2) == FALSE)
788 add_string_to_buf(" Summon failed.");
789 break;
790 case 120:
791 r1 = get_ran(6,1,4);
792 for (i = 0; i < get_ran(1,3,5); i++)
793 if (summon_monster(str,user_loc,r1,2) == FALSE)
794 add_string_to_buf(" Summon failed.");
795 break;
796 case 121:
797 add_string_to_buf(" Acid sprays from the tip! ");
798 start_spell_targeting(1068);
799 break;
800 case 122:
801 add_string_to_buf(" It creates a cloud of gas. ");
802 start_spell_targeting(1066);
803 break;
804 case 123:
805 add_string_to_buf(" It creates a shimmering cloud. ");
806 start_spell_targeting(1019);
807 break;
808 case 124:
809 add_string_to_buf(" A green ray emerges. ");
810 start_spell_targeting(1030);
811 break;
812 case 125:
813 add_string_to_buf(" Sparks fly.");
814 start_spell_targeting(1044);
815 break;
816 case 126:
817 add_string_to_buf(" It shoots a silvery beam. ");
818 start_spell_targeting(1069);
819 break;
820 case 127:
821 add_string_to_buf(" It explodes!");
822 start_spell_targeting(1065);
823 break;
824 case 128:
825 add_string_to_buf(" It shoots a fiery red ray. ");
826 start_spell_targeting(1062);
827 break;
828 case 129:
829 add_string_to_buf("Fire pours out!");
830 make_quickfire(user_loc.x,user_loc.y);
831 break;
832 case 130:
833 ASB("It throbs, and emits odd rays.");
834 for (i = 0; i < T_M; i++) {
835 if ((c_town.monst.dudes[i].active != 0) && (c_town.monst.dudes[i].attitude % 2 == 1)
836 && (dist(pc_pos[current_pc],c_town.monst.dudes[i].m_loc) <= 8)
837 && (can_see(pc_pos[current_pc],c_town.monst.dudes[i].m_loc,0) < 5)) {
838 which_m = &c_town.monst.dudes[i];
839 charm_monst(which_m,0,0,8);
842 break;
843 case 131:
844 if (c_town.town.specials2 % 10 == 1) {
845 add_string_to_buf(" It doesn't work.");
846 break;
848 add_string_to_buf(" You have a vision. ");
849 for (i = 0; i < town_size[town_type]; i++)
850 for (j = 0; j < town_size[town_type]; j++)
851 make_explored(i,j);
852 clear_map();
853 break;
854 case 132:
855 add_string_to_buf(" It fires a blinding ray.");
856 add_string_to_buf(" Target spell. ");
857 overall_mode = 3;
858 current_pat = s;
859 set_town_spell(1041,current_pc);
860 break;
861 case 133:
862 add_string_to_buf(" It shoots a blue sphere. ");
863 start_spell_targeting(1064);
864 break;
865 case 134:
866 add_string_to_buf(" It fires a lovely, sparkling beam.");
867 start_spell_targeting(1117);
868 break;
869 case 135:
870 add_string_to_buf(" Your hair stands on end. ");
871 start_spell_targeting(1051);
872 break;
874 // Special spells:
875 // 62 - Carrunos
876 // 63 - Summon Rat
877 // 64 - Ice Wall Balls
878 // 65 - Goo Bomb
879 // 66 - Foul Vapors
880 // 67 - Sleep cloud
881 // 68 - spray acid
882 // 69 - paralyze
883 // 70 - mass sleep
886 put_pc_screen();
887 if ((take_charge == TRUE) && (adven[pc].items[item].charges > 0))
888 remove_charge(pc,item);
889 if (take_charge == FALSE) {
890 draw_terrain(0);
891 put_item_screen(stat_window,0);
895 // Returns TRUE if an action is actually carried out. This can only be reached in town.
896 Boolean use_space(location where)
898 unsigned char ter;
899 char debug[60];
900 short r1,i,choice,door_pc,spec_num;
901 Boolean can_enter = TRUE;
902 location out_where,from_loc,to_loc;
905 ter = t_d.terrain[where.x][where.y];
906 from_loc = c_town.p_loc;
908 add_string_to_buf("Use...");
910 if (is_web(where.x,where.y)) {
911 add_string_to_buf(" You clear the webs.");
912 take_web(where.x,where.y);
913 return TRUE;
915 if (is_crate(where.x,where.y)) {
916 to_loc = push_loc(from_loc,where);
917 if (same_point(from_loc,to_loc) == TRUE) {
918 add_string_to_buf(" Can't push crate.");
919 return FALSE;
921 add_string_to_buf(" You push the crate.");
922 take_crate((short) where.x,(short) where.y);
923 make_crate((short) to_loc.x,(short) to_loc.y);
924 for (i = 0; i < NUM_TOWN_ITEMS; i++)
925 if ((t_i.items[i].variety > 0) && (same_point(t_i.items[i].item_loc,where))
926 && (is_contained(t_i.items[i]) == TRUE))
927 t_i.items[i].item_loc = to_loc;
929 if (is_barrel(where.x,where.y)) {
930 to_loc = push_loc(from_loc,where);
931 if (same_point(from_loc,to_loc) == TRUE) {
932 add_string_to_buf(" Can't push barrel.");
933 return FALSE;
935 add_string_to_buf(" You push the barrel.");
936 take_barrel((short) where.x,(short) where.y);
937 make_barrel((short) to_loc.x,(short) to_loc.y);
938 for (i = 0; i < NUM_TOWN_ITEMS; i++)
939 if ((t_i.items[i].variety > 0) && (same_point(t_i.items[i].item_loc,where))
940 && (is_contained(t_i.items[i]) == TRUE))
941 t_i.items[i].item_loc = to_loc;
944 switch (scenario.ter_types[ter].special) {
945 case 22:
946 if (same_point(where,from_loc) == TRUE) {
947 add_string_to_buf(" Not while on space.");
948 return FALSE;
950 add_string_to_buf(" OK.");
951 alter_space(where.x,where.y,scenario.ter_types[ter].flag1);
952 play_sound(scenario.ter_types[ter].flag2);
953 return TRUE;
954 break;
955 case 23: // call special
956 run_special(17,0,scenario.ter_types[ter].flag1,where,&i,&i,&i);
957 break;
959 add_string_to_buf(" Nothing to use.");
961 return FALSE;
964 // Note ... if this is a container, the code must first process any specials. If
965 //specials return FALSE, can't get items inside. If TRUE, can get items inside.
966 // Can't get items out in combat.
967 Boolean adj_town_look(location where)
969 char terrain;
970 Boolean can_open = TRUE,item_there = FALSE,got_special = FALSE;
971 short i = 0,trap_pc,s1 = 0, s2 = 0, s3 = 0;
973 for (i = 0; i < NUM_TOWN_ITEMS; i++)
974 if ((t_i.items[i].variety > 0) && (is_contained(t_i.items[i]) == TRUE) &&
975 (same_point(where,t_i.items[i].item_loc) == TRUE))
976 item_there = TRUE;
978 terrain = t_d.terrain[where.x][where.y];
979 if (special(where.x,where.y)) {// && (get_blockage(terrain) > 0)) {
980 if (adjacent(c_town.p_loc,where) == FALSE)
981 add_string_to_buf(" Not close enough to search.");
982 else {
983 for (i = 0; i < 50; i++)
984 if (same_point(where,c_town.town.special_locs[i]) == TRUE) {
985 if (get_blockage(t_d.terrain[where.x][where.y]) > 0) {
986 // tell party you find something, if looking at a space they can't step in
987 //if (c_town.town.special_id[i] >= 10)
988 // add_string_to_buf(" Search: You find something! ");
989 // else if (party.stuff_done[c_town.town_num][c_town.town.special_id[i]] < 20)
990 // add_string_to_buf(" Search: You find something! ");
992 //call special can_open = town_specials(i,c_town.town_num);
994 run_special(4,2,c_town.town.spec_id[i],where,&s1,&s2,&s3);
995 if (s1 > 0)
996 can_open = FALSE;
997 got_special = TRUE;
999 put_item_screen(stat_window,0);
1002 if ((is_container(where)) && (item_there == TRUE) && (can_open == TRUE)) {
1003 get_item(where,6,TRUE);
1005 else switch (terrain) {
1006 case 22: case 23:
1007 add_string_to_buf(" (Use this space to do something");
1008 add_string_to_buf(" with it.)");
1009 break;
1011 default:
1012 if (got_special == FALSE)
1013 add_string_to_buf(" Search: You don't find anything. ");
1014 return FALSE;
1016 return FALSE;
1019 // PSOE - place_special_outdoor_encounter
1020 void PSOE(short str1a,short str1b,short str2a,short str2b,
1021 short which_special,unsigned char *stuff_done_val,short where_put)
1022 // if always, stuff_done_val is NULL
1024 short i,j,graphic_num = 0;
1026 if (stuff_done_val != NULL) {
1027 if (*stuff_done_val > 0)
1028 return;
1029 else *stuff_done_val = 20;
1031 for (i = 0; i < 18; i++)
1032 if (outdoors[party.i_w_c.x][party.i_w_c.y].special_id[i] == where_put) {
1033 for (j = 0; j < 7; j++)
1034 if (outdoors[party.i_w_c.x][party.i_w_c.y].special_enc[which_special].monst[j] > 0) {
1035 graphic_num = 400 + get_monst_picnum(outdoors[party.i_w_c.x][party.i_w_c.y].special_enc[which_special].monst[j]);
1036 j = 7;
1038 //display_strings( str1a, str1b, str2a, str2b,
1039 //// "Encounter!",57, graphic_num, 0);
1040 draw_terrain(0);
1041 pause(15);
1042 //if (outdoors[party.i_w_c.x][party.i_w_c.y].special_enc[which_special].spec_code == 0)
1043 // outdoors[party.i_w_c.x][party.i_w_c.y].special_enc[which_special].spec_code = 1;
1044 //place_outd_wand_monst(outdoors[party.i_w_c.x][party.i_w_c.y].special_locs[i],
1045 // outdoors[party.i_w_c.x][party.i_w_c.y].special_enc[which_special]);
1047 i = 18;
1049 draw_terrain(0);
1050 play_sound(61);
1051 //play_sound(0);
1054 void out_move_party(char x,char y)
1056 location l;
1058 l.x = x;l.y = y;
1059 l = local_to_global(l);
1060 party.p_loc = l;
1061 center = l;
1062 update_explored(l);
1065 void teleport_party(short x,short y,short mode)
1066 // mode - 0 full teleport flash 1 no teleport flash 2 only fade flash
1068 short i;
1069 location l;
1071 if (is_combat())
1072 mode = 1;
1074 l = c_town.p_loc;
1075 update_explored(l);
1077 if (mode != 1) {
1078 start_missile_anim();
1079 for (i = 0; i < 9; i++)
1080 add_explosion(l,-1,1,1,0,0);
1081 do_explosion_anim(5,1);
1083 if (mode != 1)
1084 can_draw_pcs = FALSE;
1085 if (mode != 1) {
1086 do_explosion_anim(5,2);
1087 end_missile_anim();
1089 center.x = x; center.y = y;
1090 if (is_combat()) {
1091 pc_pos[current_pc].x = x;pc_pos[current_pc].y = y;
1093 l.x = x; l.y = y;
1094 c_town.p_loc.x = x;
1095 c_town.p_loc.y = y;
1096 update_explored(l);
1097 draw_terrain(0);
1099 if (mode == 0) {
1100 start_missile_anim();
1101 for (i = 0; i < 14; i++)
1102 add_explosion(center,-1,1,1,0,0);
1103 do_explosion_anim(5,1);
1105 can_draw_pcs = TRUE;
1106 if (mode == 0) {
1107 do_explosion_anim(5,2);
1108 end_missile_anim();
1110 draw_map(modeless_dialogs[5],5);
1113 void fade_party()
1115 short i;
1116 location l;
1118 l = c_town.p_loc;
1119 start_missile_anim();
1120 for (i = 0; i < 14; i++)
1121 add_explosion(l,-1,1,1,0,0);
1122 do_explosion_anim(5,1);
1123 c_town.p_loc.x = 100;
1124 c_town.p_loc.y = 100;
1125 do_explosion_anim(5,2);
1126 end_missile_anim();
1129 void change_level(short town_num,short x,short y)
1131 location l;
1133 if ((town_num < 0) || (town_num >= scenario.num_towns)) {
1134 give_error("The scenario special encounter tried to put you into a town that doesn't exist.","",0);
1135 return;
1138 l.x = x; l.y = y;
1140 force_town_enter(town_num,l);
1141 end_town_mode(1,l);
1142 start_town_mode(town_num,9);
1146 // Damaging and killing monsters needs to be here because several have specials attached to them.
1147 Boolean damage_monst(short which_m, short who_hit, short how_much, short how_much_spec, short dam_type)
1148 //short which_m, who_hit, how_much, how_much_spec; // 6 for who_hit means dist. xp evenly 7 for no xp
1149 //short dam_type; // 0 - weapon 1 - fire 2 - poison 3 - general magic 4 - unblockable 5 - cold
1150 // 6 - demon 7 - undead
1151 // 9 - marked damage, from during anim mode
1152 //+10 = no_print
1153 // 100s digit - damage sound for boom space
1155 creature_data_type *victim;
1156 short r1,which_spot,sound_type;
1157 location where_put;
1159 Boolean do_print = TRUE;
1160 char resist;
1162 //print_num(which_m,(short)c_town.monst.dudes[which_m].m_loc.x,(short)c_town.monst.dudes[which_m].m_loc.y);
1164 if (c_town.monst.dudes[which_m].active == 0) return FALSE;
1166 sound_type = dam_type / 100;
1167 dam_type = dam_type % 100;
1169 if (dam_type >= 10) {
1170 do_print = FALSE;
1171 dam_type -= 10;
1174 if (sound_type == 0) {
1175 if ((dam_type == 1) || (dam_type == 4) )
1176 sound_type = 5;
1177 if (dam_type == 5)
1178 sound_type = 7;
1179 if (dam_type == 3)
1180 sound_type = 12;
1181 if (dam_type == 2)
1182 sound_type = 11;
1186 victim = &c_town.monst.dudes[which_m];
1187 resist = victim->m_d.immunities;
1189 if (dam_type == 3) {
1190 if (resist & 1)
1191 how_much = how_much / 2;
1192 if (resist & 2)
1193 how_much = 0;
1195 if (dam_type == 1) {
1196 if (resist & 4)
1197 how_much = how_much / 2;
1198 if (resist & 8)
1199 how_much = 0;
1201 if (dam_type == 5) {
1202 if (resist & 16)
1203 how_much = how_much / 2;
1204 if (resist & 32)
1205 how_much = 0;
1207 if (dam_type == 2) {
1208 if (resist & 64)
1209 how_much = how_much / 2;
1210 if (resist & 128)
1211 how_much = 0;
1214 // Absorb damage?
1215 if (((dam_type == 1) || (dam_type == 3) || (dam_type == 5))
1216 && (victim->m_d.spec_skill == 26)) {
1217 victim->m_d.health += how_much;
1218 ASB(" Magic absorbed.");
1219 return FALSE;
1222 // Saving throw
1223 if (((dam_type == 1) || (dam_type == 5)) && (get_ran(1,0,20) <= victim->m_d.level))
1224 how_much = how_much / 2;
1225 if ((dam_type == 3) && (get_ran(1,0,24) <= victim->m_d.level))
1226 how_much = how_much / 2;
1228 // Rentar-Ihrno?
1229 if (victim->m_d.spec_skill == 36)
1230 how_much = how_much / 10;
1233 r1 = get_ran(1,0,(victim->m_d.armor * 5) / 4);
1234 r1 += victim->m_d.level / 4;
1235 if (dam_type == 0)
1236 how_much -= r1;
1238 if (boom_anim_active == TRUE) {
1239 if (how_much < 0)
1240 how_much = 0;
1241 monst_marked_damage[which_m] += how_much;
1242 add_explosion(victim->m_loc,how_much,0,(dam_type > 2) ? 2 : 0,14 * (victim->m_d.x_width - 1),18 * (victim->m_d.y_width - 1));
1243 if (how_much == 0)
1244 return FALSE;
1245 else return TRUE;
1248 if (how_much <= 0) {
1249 if (is_combat())
1250 monst_spell_note(victim->number,7);
1251 if ((how_much <= 0) && ((dam_type == 0) || (dam_type == 6) || (dam_type == 7))) {
1252 draw_terrain(2);
1253 play_sound(2);
1255 // sprintf ((char *) create_line, " No damage. ");
1256 // add_string_to_buf((char *) create_line);
1257 return FALSE;
1260 if (do_print == TRUE)
1261 monst_damaged_mes(which_m,how_much,how_much_spec);
1262 victim->m_d.health = victim->m_d.health - how_much - how_much_spec;
1264 if (in_scen_debug == TRUE)
1265 victim->m_d.health = -1;
1266 // splitting monsters
1267 if ((victim->m_d.spec_skill == 12) && (victim->m_d.health > 0)){
1268 where_put = find_clear_spot(victim->m_loc,1);
1269 if (where_put.x > 0)
1270 if ((which_spot = place_monster(victim->number,where_put)) < 90) {
1271 c_town.monst.dudes[which_spot].m_d.health = victim->m_d.health;
1272 c_town.monst.dudes[which_spot].monst_start = victim->monst_start;
1273 monst_spell_note(victim->number,27);
1276 if (who_hit < 7)
1277 party.total_dam_done += how_much + how_much_spec;
1279 // Monster damages. Make it hostile.
1280 victim->active = 2;
1283 if (dam_type != 9) { // note special damage only gamed in hand-to-hand, not during animation
1284 if (party_can_see_monst(which_m) == TRUE) {
1285 pre_boom_space(victim->m_loc,100,boom_gr[dam_type],how_much,sound_type);
1286 if (how_much_spec > 0)
1287 boom_space(victim->m_loc,100,51,how_much_spec,5);
1289 else {
1290 pre_boom_space(victim->m_loc,overall_mode, boom_gr[dam_type],how_much,sound_type);
1291 if (how_much_spec > 0)
1292 boom_space(victim->m_loc,overall_mode,51,how_much_spec,5);
1296 if (victim->m_d.health < 0) {
1297 monst_killed_mes(which_m);
1298 kill_monst(victim,who_hit);
1300 else {
1301 if (how_much > 0)
1302 victim->m_d.morale = victim->m_d.morale - 1;
1303 if (how_much > 5)
1304 victim->m_d.morale = victim->m_d.morale - 1;
1305 if (how_much > 10)
1306 victim->m_d.morale = victim->m_d.morale - 1;
1307 if (how_much > 20)
1308 victim->m_d.morale = victim->m_d.morale - 2;
1311 if ((victim->attitude % 2 != 1) && (who_hit < 7) &&
1312 (processing_fields == FALSE) && (monsters_going == FALSE)) {
1313 add_string_to_buf("Damaged an innocent. ");
1314 victim->attitude = 1;
1315 make_town_hostile();
1317 if ((victim->attitude % 2 != 1) && (who_hit < 7) &&
1318 ((processing_fields == TRUE) && (party.stuff_done[305][9] == 0))) {
1319 add_string_to_buf("Damaged an innocent.");
1320 victim->attitude = 1;
1321 make_town_hostile();
1324 return TRUE;
1327 void kill_monst(creature_data_type *which_m,short who_killed)
1329 short xp,i,j,num_brooch = 0,s1,s2,s3;
1330 location false_loc = {20,20},l;
1331 /* item_record_type items[4] = {
1332 {8,0,0,0,0,0,0,33,69,0,0,0,1,0,0,{0,0},"Nephilim Map","Scroll"},
1333 {13,7,3,0,0,0,0,16,0,0,0,150,0,0,0,{0,0},"Bronze Breastplate","Breastplate"},
1334 {7,3,0,0,0,1,1,30,3,0,0,350,0,0,1,{0,0},"Strong Healing P.","Potion"},
1335 {8,0,0,0,0,0,0,33,106,0,0,0,1,0,0,{0,0},"Empire orders","Scroll"}
1336 }; */
1338 // play_sound(29 + get_ran(1,0,2));
1339 // play kill noise
1340 switch (which_m->m_d.m_type) {
1341 case 0: case 3: case 4: case 5: case 6:
1342 if (( which_m->number == 38) ||
1343 ( which_m->number == 39))
1344 i = 4;
1345 else if ( which_m->number == 45)
1346 i = 0;
1347 else i = get_ran(1,0,1);
1348 play_sound(29 + i); break;
1349 case 9: play_sound(29); break;
1350 case 1: case 2: case 7: case 8: case 11:
1351 i = get_ran(1,0,1); play_sound(31 + i); break;
1352 default: play_sound(33); break;
1355 // Special killing effects
1356 if (sd_legit(which_m->monst_start.spec1,which_m->monst_start.spec2) == TRUE)
1357 party.stuff_done[which_m->monst_start.spec1][which_m->monst_start.spec2] = 1;
1359 run_special(12,2,which_m->monst_start.special_on_kill,which_m->m_loc,&s1,&s2,&s3);
1360 if (which_m->m_d.radiate_1 == 15)
1361 run_special(12,0,which_m->m_d.radiate_2,which_m->m_loc,&s1,&s2,&s3);
1363 if ((in_scen_debug == FALSE) && ((which_m->summoned >= 100) || (which_m->summoned == 0))) { // no xp for party-summoned monsters
1364 xp = which_m->m_d.level * 2;
1365 if (who_killed < 6)
1366 award_xp(who_killed,xp);
1367 else if (who_killed == 6)
1368 award_party_xp(xp / 6 + 1);
1369 if (who_killed < 7) {
1370 i = max((xp / 6),1);
1371 award_party_xp(i);
1373 l = which_m->m_loc;
1374 place_glands(l,which_m->number);
1377 if ((in_scen_debug == FALSE) && (which_m->summoned == 0))
1378 place_treasure(which_m->m_loc, which_m->m_d.level / 2, which_m->m_d.treasure, 0);
1380 i = which_m->m_loc.x;
1381 j = which_m->m_loc.y;
1382 switch (which_m->m_d.m_type) {
1383 case 7: make_sfx(i,j,6); break;
1384 case 8: if (which_m->number <= 59) make_sfx(i,j,7); break;
1385 case 10: case 12: make_sfx(i,j,4); break;
1386 case 11: make_sfx(i,j,8); break;
1387 default: make_sfx(i,j,1); break;
1392 if (((is_town()) || (which_combat_type == 1)) && (which_m->summoned == 0)) {
1393 party.m_killed[c_town.town_num]++;
1396 party.total_m_killed++;
1398 which_m->monst_start.spec1 = 0; // make sure, if this is a spec. activated monster, it won't come back
1400 which_m->active = 0;
1403 // Pushes party and monsters around by moving walls and conveyor belts.
1404 //This is very fragils, and only hands a few cases.
1405 void push_things()
1407 Boolean redraw = FALSE;
1408 short i,k;
1409 unsigned char ter;
1410 location l;
1412 if (is_out())
1413 return;
1414 if (belt_present == FALSE)
1415 return;
1417 for (i = 0; i < T_M; i++)
1418 if (c_town.monst.dudes[i].active > 0) {
1419 l = c_town.monst.dudes[i].m_loc;
1420 ter = t_d.terrain[l.x][l.y];
1421 switch (scenario.ter_types[ter].special) {
1422 case 16: l.y--; break;
1423 case 17: l.x++; break;
1424 case 18: l.y++; break;
1425 case 19: l.x--; break;
1427 if (same_point(l,c_town.monst.dudes[i].m_loc) == FALSE) {
1428 c_town.monst.dudes[i].m_loc = l;
1429 if ((point_onscreen(center,c_town.monst.dudes[i].m_loc) == TRUE) ||
1430 (point_onscreen(center,l) == TRUE))
1431 redraw = TRUE;
1434 for (i = 0; i < NUM_TOWN_ITEMS; i++)
1435 if (t_i.items[i].variety > 0) {
1436 l = t_i.items[i].item_loc;
1437 ter = t_d.terrain[l.x][l.y];
1438 switch (scenario.ter_types[ter].special) {
1439 case 16: l.y--; break;
1440 case 17: l.x++; break;
1441 case 18: l.y++; break;
1442 case 19: l.x--; break;
1444 if (same_point(l,t_i.items[i].item_loc) == FALSE) {
1445 t_i.items[i].item_loc = l;
1446 if ((point_onscreen(center,t_i.items[i].item_loc) == TRUE) ||
1447 (point_onscreen(center,l) == TRUE))
1448 redraw = TRUE;
1452 if (is_town()) {
1453 ter = t_d.terrain[c_town.p_loc.x][c_town.p_loc.y];
1454 l = c_town.p_loc;
1455 switch (scenario.ter_types[ter].special) {
1456 case 16: l.y--; break;
1457 case 17: l.x++; break;
1458 case 18: l.y++; break;
1459 case 19: l.x--; break;
1461 if (same_point(l,c_town.p_loc) == FALSE) {
1462 ASB("You get pushed.");
1463 if (scenario.ter_types[ter].special >= 16)
1464 draw_terrain(0);
1465 center = l;
1466 c_town.p_loc = l;
1467 update_explored(l);
1468 ter = t_d.terrain[c_town.p_loc.x][c_town.p_loc.y];
1469 draw_map(modeless_dialogs[5],5);
1470 if (is_barrel(c_town.p_loc.x,c_town.p_loc.y)) {
1471 take_barrel(c_town.p_loc.x,c_town.p_loc.y);
1472 ASB("You smash the barrel.");
1474 if (is_crate(c_town.p_loc.x,c_town.p_loc.y)) {
1475 take_crate(c_town.p_loc.x,c_town.p_loc.y);
1476 ASB("You smash the crate.");
1478 for (k = 0; k < NUM_TOWN_ITEMS; k++)
1479 if ((t_i.items[k].variety > 0) && (is_contained(t_i.items[k]) == TRUE)
1480 && (same_point(t_i.items[k].item_loc,c_town.p_loc) == TRUE))
1481 t_i.items[k].item_properties = t_i.items[k].item_properties & 247;
1482 redraw = TRUE;
1485 if (is_combat()) {
1486 for (i = 0; i < 6; i++)
1487 if (adven[i].main_status == 1) {
1488 ter = t_d.terrain[pc_pos[i].x][pc_pos[i].y];
1489 l = pc_pos[i];
1490 switch (scenario.ter_types[ter].special) {
1491 case 16: l.y--; break;
1492 case 17: l.x++; break;
1493 case 18: l.y++; break;
1494 case 19: l.x--; break;
1496 if (same_point(l, pc_pos[i]) == FALSE) {
1497 ASB("Someone gets pushed.");
1498 ter = t_d.terrain[l.x][l.y];
1499 if (scenario.ter_types[ter].special >= 16)
1500 draw_terrain(0);
1501 pc_pos[i] = l;
1502 update_explored(l);
1503 draw_map(modeless_dialogs[5],5);
1504 if (is_barrel(pc_pos[i].x,pc_pos[i].y)) {
1505 take_barrel(pc_pos[i].x,pc_pos[i].y);
1506 ASB("You smash the barrel.");
1508 if (is_crate(pc_pos[i].x,pc_pos[i].y)) {
1509 take_crate(pc_pos[i].x,pc_pos[i].y);
1510 ASB("You smash the crate.");
1512 for (k = 0; k < NUM_TOWN_ITEMS; k++)
1513 if ((t_i.items[k].variety > 0) && (is_contained(t_i.items[k]) == TRUE)
1514 && (same_point(t_i.items[k].item_loc,pc_pos[i]) == TRUE))
1515 t_i.items[k].item_properties = t_i.items[k].item_properties & 247;
1516 redraw = TRUE;
1520 if (redraw == TRUE) {
1521 print_buf();
1522 draw_terrain(0);
1526 void special_increase_age()
1528 short i,s1,s2,s3;
1529 Boolean redraw = FALSE,stat_area = FALSE;
1530 location null_loc = {0,0};
1532 for (i = 0; i < 8; i++)
1533 if ((c_town.town.timer_spec_times[i] > 0) && (party.age % c_town.town.timer_spec_times[i] == 0)
1534 && ((is_town() == TRUE) || ((is_combat() == TRUE) && (which_combat_type == 1)))) {
1535 run_special(9,2,c_town.town.timer_specs[i],null_loc,&s1,&s2,&s3);
1536 stat_area = TRUE;
1537 if (s3 > 0)
1538 redraw = TRUE;
1540 for (i = 0; i < 20; i++)
1541 if ((scenario.scenario_timer_times[i] > 0) && (party.age % scenario.scenario_timer_times[i] == 0)) {
1542 run_special(10,0,scenario.scenario_timer_specs[i],null_loc,&s1,&s2,&s3);
1543 stat_area = TRUE;
1544 if (s3 > 0)
1545 redraw = TRUE;
1547 for (i = 0; i < 30; i++)
1548 if (party.party_event_timers[i] > 0) {
1549 if (party.party_event_timers[i] == 1) {
1550 if (party.global_or_town[i] == 0)
1551 run_special(11,0,party.node_to_call[i],null_loc,&s1,&s2,&s3);
1552 else run_special(11,2,party.node_to_call[i],null_loc,&s1,&s2,&s3);
1553 party.party_event_timers[i] = 0;
1554 stat_area = TRUE;
1555 if (s3 > 0)
1556 redraw = TRUE;
1558 else party.party_event_timers[i]--;
1560 if (stat_area == TRUE) {
1561 put_pc_screen();
1562 put_item_screen(stat_window,0);
1564 if (redraw == TRUE)
1565 draw_terrain(0);
1569 // This is the big painful one, the main special engine
1570 // which_mode - says when it was called
1571 // 0 - out moving (a - 1 if blocked)
1572 // 1 - town moving (a - 1 if blocked)
1573 // 2 - combat moving (a - 1 if blocked)
1574 // 3 - out looking (a - 1 if don't get items inside) NOT USED!!!
1575 // 4 - town looking (a - 1 if don't get items inside)
1576 // 5 - entering town
1577 // 6 - leaving town
1578 // 7 - talking (a,b - numbers of strings to respond)
1579 // 8 - using a special item
1580 // 9 - town timer
1581 // 10 - scen timer
1582 // 11 - party countdown timer
1583 // 12 - killed a monst
1584 // 13 - encountering outdoor enc (a - 1 if no fight)
1585 // 14 - winning outdoor enc
1586 // 15 - fleeing outdoor enc
1587 // 16 - ritual of sanct
1588 // 17 - using space
1589 // which_type - 0 - scen 1 - out 2 - town
1590 // start spec - the number of the first spec to call
1591 // a,b - 2 values that can be returned
1592 // redraw - 1 if now need redraw
1593 void run_special(short which_mode,short which_type,short start_spec,location spec_loc,short *a,short *b,short *redraw)
1595 short cur_spec,cur_spec_type,next_spec,next_spec_type;
1596 special_node_type cur_node;
1597 short num_nodes = 0;
1599 if (special_in_progress == TRUE) {
1600 give_error("The scenario called a special node while processing another special encounter. The second special will be ignored.","",0);
1601 return;
1603 special_in_progress = TRUE;
1604 next_spec = start_spec;
1605 next_spec_type = which_type;
1606 current_pc_picked_in_spec_enc = -1;
1607 store_special_loc = spec_loc;
1608 if (end_scenario == TRUE) {
1609 special_in_progress = FALSE;
1610 return;
1613 while (next_spec >= 0) {
1615 cur_spec = next_spec;
1616 cur_spec_type = next_spec_type;
1617 next_spec = -1;
1618 cur_node = get_node(cur_spec,cur_spec_type);
1620 //print_nums(1111,cur_spec_type,cur_node.type);
1622 if (cur_node.type == -1) { /// got an error
1623 special_in_progress = FALSE;
1624 return;
1626 if ((cur_node.type >= 0) && (cur_node.type <= 27)) {
1627 general_spec(which_mode,cur_node,cur_spec_type,&next_spec,&next_spec_type,a,b,redraw);
1629 if ((cur_node.type >= 50) && (cur_node.type <= 63)) {
1630 oneshot_spec(which_mode,cur_node,cur_spec_type,&next_spec,&next_spec_type,a,b,redraw);
1632 if ((cur_node.type >= 80) && (cur_node.type <= 106)) {
1633 affect_spec(which_mode,cur_node,cur_spec_type,&next_spec,&next_spec_type,a,b,redraw);
1635 if ((cur_node.type >= 130) && (cur_node.type <= 155)) {
1636 ifthen_spec(which_mode,cur_node,cur_spec_type,&next_spec,&next_spec_type,a,b,redraw);
1638 if ((cur_node.type >= 170) && (cur_node.type <= 195)) {
1639 townmode_spec(which_mode,cur_node,cur_spec_type,&next_spec,&next_spec_type,a,b,redraw);
1641 if ((cur_node.type >= 200) && (cur_node.type <= 218)) {
1642 rect_spec(which_mode,cur_node,cur_spec_type,&next_spec,&next_spec_type,a,b,redraw);
1644 if ((cur_node.type >= 225) && (cur_node.type <= 229)) {
1645 outdoor_spec(which_mode,cur_node,cur_spec_type,&next_spec,&next_spec_type,a,b,redraw);
1648 num_nodes++;
1649 if (num_nodes >= 50) {
1650 give_error("A special encounter can be at most 50 nodes long. The 50th node was just processed. The encounter will now end.","",0);
1651 next_spec = -1;
1654 if (is_out())
1655 erase_out_specials();
1656 else erase_specials();
1657 special_in_progress = FALSE;
1660 special_node_type get_node(short cur_spec,short cur_spec_type)
1662 special_node_type dummy_node;
1664 dummy_node = scenario.scen_specials[0];
1665 dummy_node.type = -1;
1666 if (cur_spec_type == 0) {
1667 if (cur_spec != minmax(0,255,cur_spec)) {
1668 give_error("The scenario called a scenario special node out of range.","",0);
1669 return dummy_node;
1671 return scenario.scen_specials[cur_spec];
1673 if (cur_spec_type == 1) {
1674 if (cur_spec != minmax(0,59,cur_spec)) {
1675 give_error("The scenario called an outdoor special node out of range.","",0);
1676 return dummy_node;
1678 return outdoors[party.i_w_c.x][party.i_w_c.y].specials[cur_spec];
1680 if (cur_spec_type == 2) {
1681 if (cur_spec != minmax(0,99,cur_spec)) {
1682 give_error("The scenario called a town special node out of range.","",0);
1683 return dummy_node;
1685 return c_town.town.specials[cur_spec];
1687 return dummy_node;
1690 void general_spec(short which_mode,special_node_type cur_node,short cur_spec_type,
1691 short *next_spec,short *next_spec_type,short *a,short *b,short *redraw)
1693 Boolean check_mess = FALSE;
1694 char str1[256] = "",str2[256] = "";
1695 short store_val = 0,i,j;
1696 special_node_type spec;
1697 short mess_adj[3] = {160,10,20};
1699 spec = cur_node;
1700 *next_spec = cur_node.jumpto;
1702 switch (cur_node.type) {
1703 case 0: break; // null spec
1704 case 1:
1705 check_mess = TRUE; setsd(cur_node.sd1,cur_node.sd2,cur_node.ex1a);
1706 break;
1707 case 2:
1708 check_mess = TRUE;
1709 setsd(cur_node.sd1,cur_node.sd2,
1710 PSD[cur_node.sd1][cur_node.sd2] + ((cur_node.ex1b == 0) ? 1 : -1) * cur_node.ex1a);
1711 break;
1712 case 3:
1713 check_mess = TRUE;break;
1714 case 5:
1715 get_strs((char *) str1,(char *) str2, cur_spec_type,cur_node.m1 + mess_adj[cur_spec_type],
1716 cur_node.m2 + mess_adj[cur_spec_type]);
1717 if (cur_node.m1 >= 0)
1718 ASB((char *) str1);
1719 if (cur_node.m2 >= 0)
1720 ASB((char *) str2);
1721 break;
1722 case 6:
1723 setsd(cur_node.sd1,cur_node.sd2,
1724 ((PSD[cur_node.sd1][cur_node.sd2] == 0) ? 1 : 0) );
1725 check_mess = TRUE;break;
1726 case 7:
1727 if (is_out()) *next_spec = -1;
1728 if ((is_out()) && (spec.ex1a != 0) && (which_mode == 0)) {
1729 ASB("Can't go here while outdoors.");
1730 *a = 1;
1732 break;
1733 case 8:
1734 if (is_town()) *next_spec = -1;
1735 if ((is_town()) && (spec.ex1a != 0) && (which_mode == 1)) {
1736 ASB("Can't go here while in town mode.");
1737 *a = 1;
1739 break;
1740 case 9:
1741 if (is_combat()) *next_spec = -1;
1742 if ((is_combat()) && (spec.ex1a != 0) && (which_mode == 2)) {
1743 ASB("Can't go here during combat.");
1744 *a = 1;
1746 break;
1747 case 10:
1748 if ((which_mode == 3) || (which_mode == 4)) *next_spec = -1;
1749 break;
1750 case 11:
1751 check_mess = TRUE;
1752 if (which_mode < 3) {
1753 if (spec.ex1a != 0)
1754 *a = 1;
1755 else *a = 0;
1757 break;
1758 case 12:
1759 check_mess = TRUE; party.age += spec.ex1a;
1760 break;
1761 case 13:
1762 check_mess = TRUE;
1763 for (i = 0; i < 30; i++)
1764 if (party.party_event_timers[i] == 0) {
1765 party.party_event_timers[i] = spec.ex1a;
1766 party.node_to_call[i] = spec.ex1b;
1767 party.global_or_town[i] = 0;
1768 i = 30;
1770 break;
1771 case 14:
1772 play_sound(1000 + spec.ex1a);
1773 break;
1774 case 15:
1775 check_mess = TRUE;
1776 if (spec.ex1a != minmax(0,29,spec.ex1a))
1777 give_error("Horse out of range.","",0);
1778 else party.horses[spec.ex1a].property = (spec.ex2a == 0) ? 1 : 0;
1779 break;
1780 case 16:
1781 check_mess = TRUE;
1782 if (spec.ex1a != minmax(0,29,spec.ex1a))
1783 give_error("Boat out of range.","",0);
1784 else party.boats[spec.ex1a].property = (spec.ex2a == 0) ? 1 : 0;
1785 break;
1786 case 17:
1787 check_mess = TRUE;
1788 if (spec.ex1a != minmax(0,scenario.num_towns - 1,spec.ex1a))
1789 give_error("Town out of range.","",0);
1790 else party.can_find_town[spec.ex1a] = (spec.ex2a == 0) ? 0 : 1;
1791 *redraw = TRUE;
1792 break;
1793 case 18:
1794 check_mess = TRUE;
1795 if (spec.ex1a != minmax(1,10,spec.ex1a))
1796 give_error("Event code out of range.","",0);
1797 else if (party.key_times[spec.ex1a] == 30000)
1798 party.key_times[spec.ex1a] = calc_day();
1799 break;
1800 case 19:
1801 check_mess = TRUE;
1802 if ((forced_give(spec.ex1a,0) == FALSE) && ( spec.ex1b >= 0))
1803 *next_spec = spec.ex1b;
1804 break;
1805 case 20:
1806 for (i = 0; i < 144; i++)
1807 if (party_check_class(spec.ex1a,0) == TRUE)
1808 store_val++;
1809 if (store_val == 0) {
1810 if ( spec.ex1b >= 0)
1811 *next_spec = spec.ex1b;
1813 else {
1814 check_mess = TRUE;
1815 give_gold(store_val * spec.ex2a,TRUE);
1817 break;
1818 case 21:
1819 *next_spec_type = 0;
1820 break;
1821 case 22:
1822 if (spec.sd1 != minmax(0,299,spec.sd1))
1823 give_error("Stuff Done flag out of range.","",0);
1824 else for (i = 0; i < 10; i++) PSD[spec.sd1][i] = spec.ex1a;
1825 break;
1826 case 23:
1827 if ((sd_legit(spec.sd1,spec.sd2) == FALSE) || (sd_legit(spec.ex1a,spec.ex1b) == FALSE))
1828 give_error("Stuff Done flag out of range.","",0);
1829 else PSD[spec.sd1][spec.sd2] = PSD[spec.ex1a][spec.ex1b];
1830 break;
1831 case 24:
1832 if (which_mode != 16)
1833 *next_spec = spec.ex1b;
1834 break;
1835 case 25:
1836 check_mess = TRUE;
1837 party.age += spec.ex1a;
1838 heal_party(spec.ex1b); restore_sp_party(spec.ex1b);
1839 break;
1840 case 26:
1841 if (which_mode != 13)
1842 break;
1843 *a = (spec.ex1a == 0) ? 1 : 0;
1844 break;
1845 case 27:
1846 end_scenario = TRUE;
1847 break;
1849 if (check_mess == TRUE) {
1850 handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b);
1855 void general_spec(short which_mode,special_node_type cur_node,short cur_spec_type,
1856 short *next_spec,short *next_spec_type,short *a,short *b,short *redraw)
1858 Boolean check_mess = FALSE;
1859 Str255 str1 = "",str2 = "";
1860 short store_val = 0,i,j;
1861 special_node_type spec;
1863 spec = cur_node;
1864 *next_spec = cur_node.jumpto;
1866 switch (cur_node.type) {
1867 case :
1868 break;
1870 if (check_mess == TRUE) {
1871 handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b);
1876 void oneshot_spec(short which_mode,special_node_type cur_node,short cur_spec_type,
1877 short *next_spec,short *next_spec_type,short *a,short *b,short *redraw)
1879 Boolean check_mess = TRUE,set_sd = TRUE;
1880 char str1[256] = "",str2[256] = "";
1881 char strs[6][256] = {"","","","","",""};
1882 short store_val = 0,i,j,buttons[3] = {-1,-1,-1};
1883 special_node_type spec;
1884 item_record_type store_i;
1885 location l;
1887 spec = cur_node;
1888 *next_spec = cur_node.jumpto;
1889 if ((sd_legit(spec.sd1,spec.sd2) == TRUE) && (PSD[spec.sd1][spec.sd2] == 250)) {
1890 *next_spec = -1;
1891 return;
1893 switch (cur_node.type) {
1894 case 50:
1895 if (forced_give(spec.ex1a,0) == FALSE) {
1896 set_sd = FALSE;
1897 if ( spec.ex2b >= 0)
1898 *next_spec = spec.ex2b;
1900 else {
1901 give_gold(spec.ex1b,TRUE);
1902 give_food(spec.ex2a,TRUE);
1904 break;
1905 case 51:
1906 if (spec.ex1a != minmax(0,49,spec.ex1a)) {
1907 give_error("Special item is out of range.","",0);
1908 set_sd = FALSE;
1910 else {
1911 party.spec_items[spec.ex1a] = (spec.ex1b == 0) ? 1 : 0;
1913 if (stat_window == 6)
1914 set_stat_window(6);
1915 *redraw = 1;
1916 break;
1917 case 52:
1918 set_sd = FALSE;
1919 check_mess = FALSE;
1920 break;
1921 case 53:
1922 check_mess = FALSE;
1923 break;
1924 case 55: case 56: case 57:
1925 check_mess = FALSE;
1926 if (spec.m1 < 0)
1927 break;
1928 for (i = 0; i < 3; i++)
1929 get_strs((char *) strs[i * 2],(char *) strs[i * 2 + 1],cur_spec_type,
1930 spec.m1 + i * 2 + spec_str_offset[cur_spec_type],spec.m1 + i * 2 + 1 + spec_str_offset[cur_spec_type]);
1931 if (spec.m2 > 0)
1932 {buttons[0] = 1; buttons[1] = spec.ex1a; buttons[2] = spec.ex2a;
1933 if ((spec.ex1a >= 0) || (spec.ex2a >= 0)) buttons[0] = 20; }
1934 if (spec.m2 <= 0) {buttons[0] = spec.ex1a;buttons[1] = spec.ex2a;}
1935 if ((buttons[0] < 0) && (buttons[1] < 0)) {
1936 give_error("Dialog box ended up with no buttons.","",0);
1937 break;
1939 switch (cur_node.type) {
1940 case 55: if (spec.pic >= 1000) i = custom_choice_dialog((char *) strs,(spec.pic % 1000) + 2400,buttons) ;
1941 else i = custom_choice_dialog((char *) strs,spec.pic ,buttons) ; break;
1942 case 56: if (spec.pic >= 1000) i = custom_choice_dialog((char *) strs,(spec.pic % 1000) + 2000,buttons) ;
1943 else i = custom_choice_dialog((char *) strs,spec.pic,buttons) ; break;
1944 case 57: if (spec.pic >= 1000) i = custom_choice_dialog((char *) strs,(spec.pic % 1000) + 2000,buttons) ;
1945 else i = custom_choice_dialog((char *) strs,spec.pic ,buttons) ; break;
1947 if (spec.m2 > 0) {
1948 if (i == 1) {
1949 if ((spec.ex1a >= 0) || (spec.ex2a >= 0)) {
1950 set_sd = FALSE;
1953 if (i == 2) *next_spec = spec.ex1b;
1954 if (i == 3) *next_spec = spec.ex2b;
1956 else {
1957 if (i == 1) *next_spec = spec.ex1b;
1958 if (i == 2) *next_spec = spec.ex2b;
1960 break;
1961 case 58: case 59: case 60:
1962 check_mess = FALSE;
1963 if (spec.m1 < 0)
1964 break;
1965 for (i = 0; i < 3; i++)
1966 get_strs((char *) strs[i * 2],(char *) strs[i * 2 + 1],cur_spec_type,
1967 spec.m1 + i * 2 + spec_str_offset[cur_spec_type],spec.m1 + i * 2 + 1 + spec_str_offset[cur_spec_type]);
1968 buttons[0] = 20; buttons[1] = 19;
1969 //i = custom_choice_dialog(strs,spec.pic,buttons) ;
1970 switch (cur_node.type) {
1971 case 58: if (spec.pic >= 1000) i = custom_choice_dialog((char *) strs,(spec.pic % 1000) + 2400,buttons) ;
1972 else i = custom_choice_dialog((char *) strs,spec.pic,buttons) ; break;
1973 case 59: if (spec.pic >= 1000) i = custom_choice_dialog((char *) strs,(spec.pic % 1000) + 2000,buttons) ;
1974 else i = custom_choice_dialog((char *) strs,spec.pic,buttons) ; break;
1975 case 60: if (spec.pic >= 1000) i = custom_choice_dialog((char *) strs,(spec.pic % 1000) + 2000,buttons) ;
1976 else i = custom_choice_dialog((char *) strs,spec.pic,buttons) ; break;
1978 if (i == 1) {set_sd = FALSE; *next_spec = -1;}
1979 else {
1980 store_i = get_stored_item(spec.ex1a);
1981 if ((spec.ex1a >= 0) && (give_to_party(store_i,TRUE) == FALSE)) {
1982 set_sd = FALSE; *next_spec = -1;
1984 else {
1985 give_gold(spec.ex1b,TRUE);
1986 give_food(spec.ex2a,TRUE);
1987 if ((spec.m2 >= 0) && (spec.m2 < 50)) {
1988 if (party.spec_items[spec.m2] == 0)
1989 ASB("You get a special item.");
1990 party.spec_items[spec.m2] = 1;
1991 *redraw = TRUE;
1992 if (stat_window == 6)
1993 set_stat_window(6);
1995 if (spec.ex2b >= 0) *next_spec = spec.ex2b;
1998 break;
1999 case 61:
2000 if (spec.ex1a != minmax(0,3,spec.ex1a)) {
2001 give_error("Special outdoor enc. is out of range. Must be 0-3.","",0);
2002 set_sd = FALSE;
2004 else {
2005 l = global_to_local(party.p_loc);
2006 place_outd_wand_monst(l,
2007 outdoors[party.i_w_c.x][party.i_w_c.y].special_enc[spec.ex1a],TRUE);
2009 break;
2010 case 62:
2011 activate_monsters(spec.ex1a,0);
2012 break;
2013 case 63:
2014 check_mess = FALSE;
2015 if ((spec.m1 >= 0) || (spec.m2 >= 0)) {
2016 get_strs((char *) strs[0],(char *) strs[1],
2017 cur_spec_type,
2018 spec.m1 + ((spec.m1 >= 0) ? spec_str_offset[cur_spec_type] : 0),
2019 spec.m2 + ((spec.m2 >= 0) ? spec_str_offset[cur_spec_type] : 0));
2020 buttons[0] = 3; buttons[1] = 2;
2021 i = custom_choice_dialog((char *) strs,727,buttons);
2023 else i = FCD(872,0);
2024 if (i == 1) {set_sd = FALSE; *next_spec = -1; *a = 1;}
2025 else {
2026 if (is_combat() == TRUE)
2027 j = run_trap(current_pc,spec.ex1a,spec.ex1b,spec.ex2a);
2028 else j = run_trap(7,spec.ex1a,spec.ex1b,spec.ex2a);
2029 if (j == 0) {
2030 *a = 1; set_sd = FALSE;
2033 break;
2035 if (check_mess == TRUE) {
2036 handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b);
2038 if ((set_sd == TRUE) && (sd_legit(spec.sd1,spec.sd2) == TRUE))
2039 PSD[spec.sd1][spec.sd2] = 250;
2043 void affect_spec(short which_mode,special_node_type cur_node,short cur_spec_type,
2044 short *next_spec,short *next_spec_type,short *a,short *b,short *redraw)
2046 Boolean check_mess = TRUE;
2047 char str1[256] = "",str2[256] = "";
2048 short store_val = 0,i,j,pc,r1;
2049 special_node_type spec;
2051 spec = cur_node;
2052 *next_spec = cur_node.jumpto;
2053 pc = current_pc_picked_in_spec_enc;
2056 if ((check_mess == TRUE) && (cur_node.type != 80)) {
2057 handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b);
2061 switch (cur_node.type) {
2062 case 80:
2063 if (spec.ex1a == 2)
2064 current_pc_picked_in_spec_enc = -1;
2065 else if (spec.ex1a == 1) {
2066 i = select_pc(0,0);
2067 if (i != 6)
2068 current_pc_picked_in_spec_enc = i;
2070 else if (spec.ex1a == 0) {
2071 i = select_pc(1,0);
2072 if (i != 6)
2073 current_pc_picked_in_spec_enc = i;
2075 if (i == 6)// && (spec.ex1b >= 0))
2076 *next_spec = spec.ex1b;
2077 break;
2078 case 81:
2079 r1 = get_ran(spec.ex1a,1,spec.ex1b) + spec.ex2a;
2080 if (pc < 0) {
2081 hit_party(r1,spec.ex2b);
2083 else damage_pc(pc,r1,spec.ex2b,0);
2084 break;
2085 case 82:
2086 for (i = 0; i < 6; i++)
2087 if ((pc < 0) || (pc == i))
2088 adven[i].cur_health = minmax(0, adven[i].max_health,
2089 adven[i].cur_health + spec.ex1a * ((spec.ex1b != 0) ? -1: 1));
2090 break;
2091 case 83:
2092 for (i = 0; i < 6; i++)
2093 if ((pc < 0) || (pc == i))
2094 adven[i].cur_sp = minmax(0, adven[i].max_sp,
2095 adven[i].cur_sp + spec.ex1a * ((spec.ex1b != 0) ? -1: 1));
2096 break;
2097 case 84:
2098 for (i = 0; i < 6; i++)
2099 if ((pc < 0) || (pc == i)) {
2100 if (spec.ex1b == 0) award_xp(i,spec.ex1a); else drain_pc(i,spec.ex1a);
2102 break;
2103 case 85:
2104 for (i = 0; i < 6; i++)
2105 if ((pc < 0) || (pc == i))
2106 adven[i].skill_pts = minmax(0, 100,
2107 adven[i].skill_pts + spec.ex1a * ((spec.ex1b != 0) ? -1: 1));
2108 break;
2109 case 86:
2110 for (i = 0; i < 6; i++)
2111 if ((pc < 0) || (pc == i)) {
2112 if (spec.ex1b == 0) {
2113 if ((adven[i].main_status > 0) && (adven[i].main_status < 10))
2114 adven[i].main_status = 1;
2116 else kill_pc(i,spec.ex1a + 2 + 10);
2118 *redraw = 1;
2119 break;
2120 case 87:
2121 for (i = 0; i < 6; i++)
2122 if ((pc < 0) || (pc == i)) {
2123 if (spec.ex1b == 0) {
2124 cure_pc(i,spec.ex1a);
2126 else poison_pc(i,spec.ex1a);
2128 break;
2129 case 88:
2130 for (i = 0; i < 6; i++)
2131 if ((pc < 0) || (pc == i)) {
2132 if (spec.ex1b == 0) {
2133 slow_pc(i,-1 * spec.ex1a);
2135 else slow_pc(i,spec.ex1a);
2137 break;
2138 case 89:
2139 for (i = 0; i < 6; i++)
2140 if ((pc < 0) || (pc == i))
2141 affect_pc(i,4,spec.ex1a * ((spec.ex1b != 0) ? -1: 1));
2142 break;
2143 case 90:
2144 for (i = 0; i < 6; i++)
2145 if ((pc < 0) || (pc == i))
2146 affect_pc(i,5,spec.ex1a * ((spec.ex1b != 0) ? -1: 1));
2147 break;
2148 case 91:
2149 for (i = 0; i < 6; i++)
2150 if ((pc < 0) || (pc == i))
2151 affect_pc(i,6,spec.ex1a * ((spec.ex1b != 0) ? -1: 1));
2152 break;
2153 case 92:
2154 for (i = 0; i < 6; i++)
2155 if ((pc < 0) || (pc == i))
2156 affect_pc(i,7,spec.ex1a * ((spec.ex1b != 0) ? 1: -1));
2157 break;
2158 case 93:
2159 for (i = 0; i < 6; i++)
2160 if ((pc < 0) || (pc == i))
2161 affect_pc(i,8,spec.ex1a * ((spec.ex1b != 0) ? -1: 1));
2162 break;
2163 case 94:
2164 for (i = 0; i < 6; i++)
2165 if ((pc < 0) || (pc == i))
2166 affect_pc(i,1,spec.ex1a * ((spec.ex1b != 0) ? -1: 1));
2167 break;
2168 case 95:
2169 for (i = 0; i < 6; i++)
2170 if ((pc < 0) || (pc == i))
2171 affect_pc(i,9,spec.ex1a * ((spec.ex1b == 0) ? -1: 1));
2172 break;
2173 case 96:
2174 for (i = 0; i < 6; i++)
2175 if ((pc < 0) || (pc == i)) {
2176 if (spec.ex1b == 0) {
2177 affect_pc(i,11,-1 * spec.ex1a);
2179 else sleep_pc(i,spec.ex1a,11,10);
2181 break;
2182 case 97:
2183 for (i = 0; i < 6; i++)
2184 if ((pc < 0) || (pc == i)) {
2185 if (spec.ex1b == 0) {
2186 affect_pc(i,12,-1 * spec.ex1a);
2188 else sleep_pc(i,spec.ex1a,12,10);
2190 break;
2191 case 98:
2192 if (spec.ex2a != minmax(0,18,spec.ex2a)) {
2193 give_error("Skill is out of range.","",0);
2194 break;
2196 for (i = 0; i < 6; i++)
2197 if (((pc < 0) || (pc == i)) && (get_ran(1,0,100) < spec.pic))
2198 adven[i].skills[spec.ex2a] = minmax(0, skill_max[spec.ex2a],
2199 adven[i].skills[spec.ex2a] + spec.ex1a * ((spec.ex1b != 0) ? -1: 1));
2200 break;
2201 case 99:
2202 if (spec.ex1a != minmax(0,31,spec.ex1a)) {
2203 give_error("Mage spell is out of range (0 - 31). See docs.","",0);
2204 break;
2206 for (i = 0; i < 6; i++)
2207 if ((pc < 0) || (pc == i))
2208 adven[i].mage_spells[spec.ex1a + 30] = TRUE;
2209 break;
2210 case 100:
2211 if (spec.ex1a != minmax(0,31,spec.ex1a)) {
2212 give_error("Priest spell is out of range (0 - 31). See docs.","",0);
2213 break;
2215 for (i = 0; i < 6; i++)
2216 if ((pc < 0) || (pc == i))
2217 adven[i].priest_spells[spec.ex1a + 30] = TRUE;
2218 break;
2219 case 101:
2220 if (spec.ex1b == 0)
2221 give_gold(spec.ex1a,TRUE);
2222 else if (party.gold < spec.ex1a)
2223 party.gold = 0;
2224 else take_gold(spec.ex1a,FALSE);
2225 break;
2226 case 102:
2227 if (spec.ex1b == 0)
2228 give_food(spec.ex1a,TRUE);
2229 else if (party.food < spec.ex1a)
2230 party.food = 0;
2231 else take_food(spec.ex1a,FALSE);
2232 break;
2233 case 103:
2234 if (spec.ex1a != minmax(0,19,spec.ex1a)) {
2235 give_error("Alchemy is out of range.","",0);
2236 break;
2238 party.alchemy[spec.ex1a] = TRUE;
2239 break;
2240 case 104:
2241 r1 = (short) party.stuff_done[305][0];
2242 r1 = minmax(0,250,r1 + spec.ex1a);
2243 party.stuff_done[305][0] = r1;
2244 break;
2245 case 105:
2246 r1 = (short) party.stuff_done[305][3];
2247 r1 = minmax(0,250,r1 + spec.ex1a);
2248 party.stuff_done[305][3] = r1;
2249 break;
2250 case 106:
2251 if (party.in_boat >= 0)
2252 add_string_to_buf(" Can't fly when on a boat. ");
2253 else if (party.in_horse >= 0)////
2254 add_string_to_buf(" Can't fly when on a horse. ");
2255 else {
2256 r1 = (short) party.stuff_done[305][1];
2257 r1 = minmax(0,250,r1 + spec.ex1a);
2258 party.stuff_done[305][1] = r1;
2260 break;
2264 void ifthen_spec(short which_mode,special_node_type cur_node,short cur_spec_type,
2265 short *next_spec,short *next_spec_type,short *a,short *b,short *redraw)
2267 Boolean check_mess = FALSE;
2268 char str1[256] = "",str2[256] = "",str3[256] = "";
2269 short store_val = 0,i,j,k;
2270 special_node_type spec;
2271 location l;
2273 spec = cur_node;
2274 *next_spec = cur_node.jumpto;
2276 switch (cur_node.type) {
2277 case 130:
2278 if (sd_legit(spec.sd1,spec.sd2) == TRUE) {
2279 if ((spec.ex1a >= 0) && (PSD[spec.sd1][spec.sd2] >= spec.ex1a))
2280 *next_spec = spec.ex1b;
2281 else if ((spec.ex2a >= 0) && (PSD[spec.sd1][spec.sd2] < spec.ex2a))
2282 *next_spec = spec.ex2b;
2284 break;
2285 case 131:
2286 if (((is_town()) || (is_combat())) && (c_town.town_num == spec.ex1a))
2287 *next_spec = spec.ex1b;
2288 break;
2289 case 132:
2290 if (get_ran(1,1,100) < spec.ex1a)
2291 *next_spec = spec.ex1b;
2292 break;
2293 case 133:
2294 if (spec.ex1a != minmax(0,49,spec.ex1a)) {
2295 give_error("Special item is out of range.","",0);
2297 else if (party.spec_items[spec.ex1a] > 0)
2298 *next_spec = spec.ex1b;
2299 break;
2300 case 134:
2301 if ((sd_legit(spec.sd1,spec.sd2) == TRUE) && (sd_legit(spec.ex1a,spec.ex1b) == TRUE)) {
2302 if (PSD[spec.ex1a][spec.ex1b] < PSD[spec.sd1][spec.sd2])
2303 *next_spec = spec.ex2b;
2305 else give_error("A Stuff Done flag is out of range.","",0);
2306 break;
2307 case 135:
2308 if (((is_town()) || (is_combat())) && (t_d.terrain[spec.ex1a][spec.ex1b] == spec.ex2a))
2309 *next_spec = spec.ex2b;
2310 break;
2311 case 136:
2312 l.x = spec.ex1a; l.y = spec.ex1b;
2313 l = local_to_global(l);
2314 if ((is_out()) && (out[l.x][l.y] == spec.ex2a))
2315 *next_spec = spec.ex2b;
2316 break;
2317 case 137:
2318 if (party.gold >= spec.ex1a)
2319 *next_spec = spec.ex1b;
2320 break;
2321 case 138:
2322 if (party.food >= spec.ex1a)
2323 *next_spec = spec.ex1b;
2324 break;
2325 case 139:
2326 if (is_out())
2327 break;
2328 l.x = spec.ex1a; l.y = spec.ex1b;
2329 for (i = 0; i < NUM_TOWN_ITEMS; i++)
2330 if ((t_i.items[i].variety > 0) && (t_i.items[i].special_class == spec.ex2a)
2331 && (same_point(l,t_i.items[i].item_loc) == TRUE))
2332 *next_spec = spec.ex2b;
2333 break;
2334 case 140:
2335 if (party_check_class(spec.ex1a,1) == TRUE)
2336 *next_spec = spec.ex1b;
2337 break;
2338 case 141:
2339 for (i = 0; i < 6; i++)
2340 if (adven[i].main_status == 1)
2341 for (j = 0; j < 24; j++)
2342 if ((adven[i].items[j].variety > 0) && (adven[i].items[j].special_class == spec.ex1a)
2343 && (adven[i].equip[j] == TRUE))
2344 *next_spec = spec.ex1b;
2345 break;
2346 case 142:
2347 if (party.gold >= spec.ex1a) {
2348 take_gold(spec.ex1a,TRUE);
2349 *next_spec = spec.ex1b;
2351 break;
2352 case 143:
2353 if (party.food >= spec.ex1a) {
2354 take_food(spec.ex1a,TRUE);
2355 *next_spec = spec.ex1b;
2357 break;
2358 case 144:
2359 if (is_out())
2360 break;
2361 l.x = spec.ex1a; l.y = spec.ex1b;
2362 for (i = 0; i < NUM_TOWN_ITEMS; i++)
2363 if ((t_i.items[i].variety > 0) && (t_i.items[i].special_class == spec.ex2a)
2364 && (same_point(l,t_i.items[i].item_loc) == TRUE)) {
2365 *next_spec = spec.ex2b;
2366 *redraw = 1;
2367 t_i.items[i].variety = 0;
2369 break;
2370 case 145:
2371 if (party_check_class(spec.ex1a,0) == TRUE)
2372 *next_spec = spec.ex1b;
2373 break;
2374 case 146:
2375 for (i = 0; i < 6; i++)
2376 if (adven[i].main_status == 1)
2377 for (j = 0; j < 24; j++)
2378 if ((adven[i].items[j].variety > 0) && (adven[i].items[j].special_class == spec.ex1a)
2379 && (adven[i].equip[j] == TRUE)) {
2380 *next_spec = spec.ex1b;
2381 *redraw = 1;
2382 take_item(i,j);
2384 break;
2385 case 147:
2386 if (calc_day() >= spec.ex1a)
2387 *next_spec = spec.ex1b;
2388 break;
2389 case 148:
2390 for (j = 0; j < town_size[town_type]; j++)
2391 for (k = 0; k < town_size[town_type]; k++)
2392 if (is_barrel(j,k))
2393 *next_spec = spec.ex1b;
2394 break;
2395 case 149:
2396 for (j = 0; j < town_size[town_type]; j++)
2397 for (k = 0; k < town_size[town_type]; k++)
2398 if (is_crate(j,k))
2399 *next_spec = spec.ex1b;
2400 break;
2401 case 150:
2402 if (day_reached(spec.ex1a,spec.ex1b) == TRUE)
2403 *next_spec = spec.ex2b;
2404 break;
2405 case 151:
2406 for (i = 0; i < 6; i++)
2407 if ((adven[i].main_status == 1) && (adven[i].traits[4] > 0))
2408 *next_spec = spec.ex1b;
2409 break;
2410 case 152:
2411 for (i = 0; i < 6; i++)
2412 if ((adven[i].main_status == 1) && (adven[i].traits[5] > 0))
2413 *next_spec = spec.ex1b;
2414 break;
2415 case 153:
2416 if (mage_lore_total() >= spec.ex1a)
2417 *next_spec = spec.ex1b;
2418 break;
2419 case 154: // text response
2420 check_mess = FALSE;
2421 get_text_response(873,str3,0);
2422 j = 1; k = 1;
2423 spec.pic = minmax(0,8,spec.pic);
2424 get_strs((char *) str1,(char *) str2,0,spec.ex1a,spec.ex2a);
2425 for (i = 0; i < spec.pic;i++) {
2426 if ((spec.ex1a < 0) || (str3[i] != str1[i]))
2427 j = 0;
2428 if ((spec.ex2a < 0) || (str3[i] != str2[i]))
2429 k = 0;
2431 if (j == 1)
2432 *next_spec = spec.ex1b;
2433 else if (k == 1)
2434 *next_spec = spec.ex2b;
2435 break;
2436 case 155:
2437 if (sd_legit(spec.sd1,spec.sd2) == TRUE) {
2438 if (PSD[spec.sd1][spec.sd2] == spec.ex1a)
2439 *next_spec = spec.ex1b;
2441 break;
2443 if (check_mess == TRUE) {
2444 handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b);
2448 void townmode_spec(short which_mode,special_node_type cur_node,short cur_spec_type,
2449 short *next_spec,short *next_spec_type,short *a,short *b,short *redraw)
2451 Boolean check_mess = TRUE;
2452 char str1[256] = "",str2[256] = "",strs[6][256] = {"","","","","",""};
2453 short store_val = 0,i,j,buttons[3] = {-1,-1,-1},r1;
2454 special_node_type spec;
2455 location l;
2456 unsigned char ter;
2457 item_record_type store_i;
2459 spec = cur_node;
2460 *next_spec = cur_node.jumpto;
2462 l.x = spec.ex1a; l.y = spec.ex1b;
2464 if (is_out())
2465 return;
2466 switch (cur_node.type) {
2467 case 170:
2468 make_town_hostile();
2469 break;
2470 case 171:
2471 set_terrain(l,spec.ex2a);
2472 *redraw = TRUE;
2473 break;
2474 case 172:
2475 if (coord_to_ter(spec.ex1a,spec.ex1b) == spec.ex2a)
2476 set_terrain(l,spec.ex2b);
2477 else if (coord_to_ter(spec.ex1a,spec.ex1b) == spec.ex2b)
2478 set_terrain(l,spec.ex2a);
2479 *redraw = 1;
2480 break;
2481 case 173:
2482 ter = coord_to_ter(spec.ex1a,spec.ex1b);
2483 set_terrain(l,scenario.ter_types[ter].trans_to_what);
2484 *redraw = 1;
2485 break;
2486 case 174:
2487 if (is_combat()) {
2488 ASB("Not while in combat.");
2489 if (which_mode < 3)
2490 *a = 1;
2491 *next_spec = -1;
2492 check_mess = FALSE;
2494 else { // 1 no
2495 *a = 1;
2496 if ((which_mode == 7) || (spec.ex2a == 0))
2497 teleport_party(spec.ex1a,spec.ex1b,1);
2498 else teleport_party(spec.ex1a,spec.ex1b,0);
2500 *redraw = 1;
2501 break;
2502 case 175:
2503 if (which_mode == 7)
2504 break;
2505 hit_space(l,spec.ex2a,spec.ex2b,1,1);
2506 *redraw = 1;
2507 break;
2508 case 176:
2509 if (which_mode == 7)
2510 break;
2511 radius_damage(l,spec.pic, spec.ex2a, spec.ex2b);
2512 *redraw = 1;
2513 break;
2514 case 177:
2515 ter = coord_to_ter(spec.ex1a,spec.ex1b);
2516 if (scenario.ter_types[ter].special == 8)
2517 set_terrain(l,scenario.ter_types[ter].flag1);
2518 *redraw = 1;
2519 break;
2520 case 178:
2521 ter = coord_to_ter(spec.ex1a,spec.ex1b);
2522 if ((scenario.ter_types[ter].special == 9) || (scenario.ter_types[ter].special == 10))
2523 set_terrain(l,scenario.ter_types[ter].flag1);
2524 *redraw = 1;
2525 break;
2526 case 179:
2527 if (which_mode == 7)
2528 break;
2529 run_a_boom(l,spec.ex2a,0,0);
2530 break;
2531 case 180:
2532 create_wand_monst();
2533 *redraw = 1;
2534 break;
2535 case 181:
2536 if (spec.ex2a > 0)
2537 forced_place_monster(spec.ex2a,l);
2538 else place_monster(spec.ex2a,l);
2539 *redraw = 1;
2540 break;
2541 case 182:
2542 for (i = 0; i < T_M; i++)
2543 if (c_town.monst.dudes[i].number == spec.ex1a) {
2544 c_town.monst.dudes[i].active = 0;
2546 *redraw = 1;
2547 break;
2548 case 183:
2549 for (i = 0; i < T_M; i++)
2550 if ((c_town.monst.dudes[i].active > 0) &&
2551 (((spec.ex1a == 0) && (1 == 1)) ||
2552 ((spec.ex1a == 1) && (c_town.monst.dudes[i].attitude % 2 == 0)) ||
2553 ((spec.ex1a == 2) && (c_town.monst.dudes[i].attitude % 2 == 1)))){
2554 c_town.monst.dudes[i].active = 0;
2556 *redraw = 1;
2557 break;
2558 case 184:
2559 if (which_mode > 4) {
2560 ASB("Can't use lever now.");
2561 check_mess = FALSE;
2562 *next_spec = -1;
2564 else {
2565 if (handle_lever(store_special_loc) > 0)
2566 *next_spec = spec.ex1b;
2568 break;
2569 case 185:
2570 if (is_combat()) {
2571 ASB("Not while in combat.");
2572 if (which_mode < 3)
2573 *a = 1;
2574 *next_spec = -1;
2575 check_mess = FALSE;
2577 else if ((which_mode != 1) && (which_mode != 4)) {
2578 ASB("Can't teleport now.");
2579 if (which_mode < 3)
2580 *a = 1;
2581 *next_spec = -1;
2582 check_mess = FALSE;
2584 else if (FCD(870,0) == 2) {
2585 *a = 1;
2586 if ((which_mode == 7) || (spec.ex2a == 0))
2587 teleport_party(spec.ex1a,spec.ex1b,1);
2588 else teleport_party(spec.ex1a,spec.ex1b,0);
2590 break;
2591 case 186:
2592 if (FCD(871,0) == 2)
2593 *next_spec = spec.ex1b;
2594 break;
2595 case 187:
2596 if (is_combat()) {
2597 ASB("Can't change level in combat.");
2598 if (which_mode < 3)
2599 *a = 1;
2600 *next_spec = -1;
2601 check_mess = FALSE;
2603 else if (which_mode != 1) {
2604 ASB("Can't change level now.");
2605 if (which_mode < 3)
2606 *a = 1;
2607 *next_spec = -1;
2608 check_mess = FALSE;
2610 else {
2611 *a = 1;
2612 if (spec.ex2b < 0) spec.ex2b = 0;
2613 if ((spec.ex2b >= 8) || (FCD(880 + spec.ex2b,0) == 2))
2614 change_level(spec.ex2a,l.x,l.y);
2616 break;
2617 case 188:
2618 check_mess = FALSE;
2619 if (spec.m1 < 0)
2620 break;
2621 if (which_mode > 4) {
2622 ASB("Can't use lever now.");
2623 check_mess = FALSE;
2624 *next_spec = -1;
2626 else {
2627 for (i = 0; i < 3; i++)
2628 get_strs((char *) strs[i * 2],(char *) strs[i * 2 + 1],cur_spec_type,
2629 spec.m1 + i * 2 + spec_str_offset[cur_spec_type],spec.m1 + i * 2 + 1 + spec_str_offset[cur_spec_type]);
2630 buttons[0] = 9; buttons[1] = 35;
2631 i = custom_choice_dialog((char *) strs,spec.pic,buttons);
2632 if (i == 1) {*next_spec = -1;}
2633 else {
2634 ter = coord_to_ter(store_special_loc.x,store_special_loc.y);
2635 set_terrain(store_special_loc,scenario.ter_types[ter].trans_to_what);
2636 *next_spec = spec.ex1b;
2639 break;
2640 case 189:
2641 check_mess = FALSE;
2642 if (spec.m1 < 0)
2643 break;
2644 if (is_combat()) {
2645 ASB("Not while in combat.");
2646 if (which_mode < 3)
2647 *a = 1;
2648 *next_spec = -1;
2649 check_mess = FALSE;
2651 else if ((which_mode != 1) && (which_mode != 4)) {
2652 ASB("Can't teleport now.");
2653 if (which_mode < 3)
2654 *a = 1;
2655 *next_spec = -1;
2656 check_mess = FALSE;
2658 else {
2659 for (i = 0; i < 3; i++)
2660 get_strs((char *) strs[i * 2],(char *) strs[i * 2 + 1]
2661 ,cur_spec_type,spec.m1 + i * 2 + spec_str_offset[cur_spec_type],spec.m1 + i * 2 + 1 + spec_str_offset[cur_spec_type]);
2662 buttons[0] = 9; buttons[1] = 8;
2663 i = custom_choice_dialog((char *) strs,722,buttons);
2664 if (i == 1) { *next_spec = -1; if (which_mode < 3) *a = 1;}
2665 else {
2666 *a = 1;
2667 if (which_mode == 7)
2668 teleport_party(spec.ex1a,spec.ex1b,1);
2669 else teleport_party(spec.ex1a,spec.ex1b,0);
2672 break;
2673 case 190:
2674 check_mess = FALSE;
2675 if ((spec.m1 < 0) && (spec.ex2b != 1))
2676 break;
2677 if (is_combat()) {
2678 ASB("Can't change level in combat.");
2679 if (which_mode < 3)
2680 *a = 1;
2681 *next_spec = -1;
2682 check_mess = FALSE;
2684 else if (which_mode != 1) {
2685 ASB("Can't change level now.");
2686 if (which_mode < 3)
2687 *a = 1;
2688 *next_spec = -1;
2689 check_mess = FALSE;
2691 else {
2692 if (spec.m1 >= 0) {
2693 for (i = 0; i < 3; i++)
2694 get_strs((char *) strs[i * 2],(char *) strs[i * 2 + 1],cur_spec_type,
2695 spec.m1 + i * 2 + spec_str_offset[cur_spec_type],spec.m1 + i * 2 + 1 + spec_str_offset[cur_spec_type]);
2696 buttons[0] = 20; buttons[1] = 24;
2698 if (spec.ex2b == 1)
2699 i = 2;
2700 else i = custom_choice_dialog((char *) strs,719,buttons) ;
2701 *a = 1;
2702 if (i == 1) { *next_spec = -1;}
2703 else {
2704 *a = 1;
2705 change_level(spec.ex2a,l.x,l.y);
2708 break;
2709 case 191:
2710 position_party(spec.ex1a,spec.ex1b,spec.ex2a,spec.ex2b);
2711 break;
2712 case 192:
2713 store_i = get_stored_item(spec.ex2a);
2714 place_item(store_i,l,TRUE);
2715 break;
2716 case 193:
2717 if (which_mode == 7)
2718 break;
2719 if (is_combat()) {
2720 ASB("Not while in combat.");
2721 if (which_mode < 3)
2722 *a = 1;
2723 *next_spec = -1;
2724 check_mess = FALSE;
2726 if (party.stuff_done[304][0] > 0) {
2727 ASB("Party is already split.");
2728 if (which_mode < 3)
2729 *a = 1;
2730 *next_spec = -1;
2731 check_mess = FALSE;
2733 r1 = char_select_pc(1,0,"Which character goes?");
2734 if (which_mode < 3)
2735 *a = 1;
2736 if (r1 != 6) {
2737 party.stuff_done[304][3] = r1;
2738 *next_spec = -1;
2739 start_split(spec.ex1a,spec.ex1b,spec.ex2a);
2741 else check_mess = FALSE;
2742 break;
2743 case 194:
2744 if (is_combat()) {
2745 ASB("Not while in combat.");
2746 break;
2748 if (which_mode < 3)
2749 *a = 1;
2750 *next_spec = -1;
2751 check_mess = FALSE;
2752 end_split(spec.ex1a);
2753 break;
2754 case 195:
2755 for (i = 0; i < 30; i++)
2756 if (party.party_event_timers[i] == 0) {
2757 party.party_event_timers[i] = spec.ex1a;
2758 party.node_to_call[i] = spec.ex1b;
2759 party.global_or_town[i] = 1;
2760 i = 30;
2762 break;
2764 if (check_mess == TRUE) {
2765 handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b);
2769 void rect_spec(short which_mode,special_node_type cur_node,short cur_spec_type,
2770 short *next_spec,short *next_spec_type,short *a,short *b,short *redraw)
2772 Boolean check_mess = TRUE;
2773 char str1[256] = "",str2[256] = "";
2774 short store_val = 0,i,j,k;
2775 special_node_type spec;
2776 location l;
2777 unsigned char ter;
2779 spec = cur_node;
2780 *next_spec = cur_node.jumpto;
2782 if (is_out())
2783 return;
2785 *redraw = 1;
2786 for (i = spec.ex1b;i <= spec.ex2b;i++)
2787 for (j = spec.ex1a; j <= spec.ex2a; j++) {
2789 l.x = i; l.y = j;
2790 switch (cur_node.type) {
2791 case 200: if (get_ran(1,0,100) <= spec.sd1 ) make_fire_wall(i,j); break;
2792 case 201: if (get_ran(1,0,100) <= spec.sd1 ) make_force_wall(i,j); break;
2793 case 202: if (get_ran(1,0,100) <= spec.sd1 ) make_ice_wall(i,j); break;
2794 case 203: if (get_ran(1,0,100) <= spec.sd1 ) make_blade_wall(i,j); break;
2795 case 204: if (get_ran(1,0,100) <= spec.sd1 ) make_scloud(i,j); break;
2796 case 205: if (get_ran(1,0,100) <= spec.sd1 ) make_sleep_cloud(i,j); break;
2797 case 206: if (get_ran(1,0,100) <= spec.sd1 ) make_quickfire(i,j); break;
2798 case 207: if (get_ran(1,0,100) <= spec.sd1 ) make_fire_barrier(i,j); break;
2799 case 208: if (get_ran(1,0,100) <= spec.sd1 ) make_force_barrier(i,j); break;
2800 case 209: if (spec.sd1 == 0) dispel_fields(i,j,1); else dispel_fields(i,j,2);break;
2801 case 210: if (get_ran(1,0,100) <= spec.sd1 ) make_sfx(i,j,spec.sd2 + 1); break;
2802 case 211: if (get_ran(1,0,100) <= spec.sd1 ) {
2803 if (spec.sd2 == 0) make_web(i,j);
2804 if (spec.sd2 == 1) make_barrel(i,j);
2805 if (spec.sd2 == 2) make_crate(i,j);
2806 } break;
2807 case 212:
2808 for (i = 0; i < NUM_TOWN_ITEMS; i++)
2809 if ((t_i.items[i].variety > 0) && (same_point(t_i.items[i].item_loc,l) == TRUE)) {
2810 t_i.items[i].item_loc.x = spec.sd1;
2811 t_i.items[i].item_loc.y = spec.sd2;
2813 break;
2814 case 213:
2815 for (i = 0; i < NUM_TOWN_ITEMS; i++)
2816 if ((t_i.items[i].variety > 0) && (same_point(t_i.items[i].item_loc,l) == TRUE)) {
2817 t_i.items[i].variety = 0;
2819 break;
2820 case 214:
2821 if (get_ran(1,0,100) <= spec.sd2) set_terrain(l,spec.sd1);
2822 break;
2823 case 215:
2824 if (coord_to_ter(i,j) == spec.sd1) set_terrain(l,spec.sd2);
2825 else if (coord_to_ter(i,j) == spec.sd2) set_terrain(l,spec.sd1);
2826 break;
2827 case 216:
2828 ter = coord_to_ter(i,j);
2829 set_terrain(l,scenario.ter_types[ter].trans_to_what);
2830 break;
2831 case 217:
2832 ter = coord_to_ter(i,j);
2833 if (scenario.ter_types[ter].special == 8)
2834 set_terrain(l,scenario.ter_types[ter].flag1);
2835 break;
2836 case 218:
2837 ter = coord_to_ter(i,j);
2838 if ((scenario.ter_types[ter].special == 9) || (scenario.ter_types[ter].special == 10))
2839 set_terrain(l,scenario.ter_types[ter].flag1);
2840 break;
2844 if (check_mess == TRUE) {
2845 handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b);
2849 void outdoor_spec(short which_mode,special_node_type cur_node,short cur_spec_type,
2850 short *next_spec,short *next_spec_type,short *a,short *b,short *redraw)
2852 Boolean check_mess = FALSE;
2853 char str1[256] = "",str2[256] = "";
2854 short store_val = 0,i,j;
2855 special_node_type spec;
2856 location l;
2858 spec = cur_node;
2859 *next_spec = cur_node.jumpto;
2861 if (is_out() == FALSE) return;
2863 switch (cur_node.type) {
2864 case 225: create_wand_monst();
2865 *redraw = 1;
2866 break;
2867 case 226:
2868 outdoors[party.i_w_c.x][party.i_w_c.y].terrain[spec.ex1a][spec.ex1b] = spec.ex2a;
2869 l.x = spec.ex1a;
2870 l.y = spec.ex1b;
2871 l = local_to_global(l);
2872 out[l.x][l.y] = spec.ex2a;
2873 *redraw = 1;
2874 check_mess = TRUE;
2875 break;
2876 case 227:
2877 if (spec.ex1a != minmax(0,3,spec.ex1a)) {
2878 give_error("Special outdoor enc. is out of range. Must be 0-3.","",0);
2879 //set_sd = FALSE;
2881 else {
2882 l = global_to_local(party.p_loc);
2883 place_outd_wand_monst(l,
2884 outdoors[party.i_w_c.x][party.i_w_c.y].special_enc[spec.ex1a],TRUE);
2885 check_mess = TRUE;
2887 break;
2888 case 228:
2889 check_mess = TRUE;
2890 out_move_party(spec.ex1a,spec.ex1b);
2891 *redraw = 1;
2892 *a = 1;
2893 break;
2894 case 229:
2895 get_strs((char *) str1,(char *) str2,1,spec.m1 + 10,-1);
2896 if (spec.ex2a >= 40)
2897 spec.ex2a = 39;
2898 if (spec.ex2a < 1)
2899 spec.ex2a = 1;
2900 spec.ex2b = minmax(0,6,spec.ex2b);
2901 switch (spec.ex1b) {
2902 case 0: start_shop_mode(0,spec.ex1a,spec.ex1a + spec.ex2a - 1,spec.ex2b,(char *) str1); break;
2903 case 1: start_shop_mode(10,spec.ex1a,spec.ex1a + spec.ex2a - 1,spec.ex2b,(char *) str1); break;
2904 case 2: start_shop_mode(11,spec.ex1a,spec.ex1a + spec.ex2a - 1 ,spec.ex2b,(char *) str1); break;
2905 case 3: start_shop_mode(12,spec.ex1a,spec.ex1a + spec.ex2a - 1,spec.ex2b,(char *) str1); break;
2906 case 4: start_shop_mode(3,spec.ex1a,spec.ex1a + spec.ex2a - 1,spec.ex2b,(char *) str1); break;
2908 *next_spec = -1;
2909 break;
2912 if (check_mess == TRUE) {
2913 handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b);
2917 void setsd(short a,short b,short val)
2919 if (sd_legit(a,b) == FALSE) {
2920 give_error("The scenario attempted to change an out of range Stuff Done flag.","",0);
2921 return;
2923 PSD[a][b] = val;
2926 void handle_message(short which_mode,short cur_type,short mess1,short mess2,short *a,short *b)
2928 char str1[256] = "",str2[256] = "";
2929 short label1 = -1,label2 = -1,label1b = -1,label2b = -1;
2930 short mess_adj[3] = {160,10,20};
2932 if ((mess1 < 0) && (mess2 < 0))
2933 return;
2934 if (which_mode == 7) { // talking
2935 *a = mess1 + ((mess1 >= 0) ? mess_adj[cur_type] : 0);
2936 *b = mess2 + ((mess2 >= 0) ? mess_adj[cur_type] : 0);
2937 return;
2939 get_strs((char *) str1,(char *) str2, cur_type, mess1 + ((mess1 >= 0) ? mess_adj[cur_type] : 0),
2940 mess2 + ((mess2 >= 0) ? mess_adj[cur_type] : 0)) ;
2941 if (mess1 >= 0) {
2942 label1 = 1000 * cur_type + mess1 + mess_adj[cur_type];
2943 label1b = (is_out()) ? (party.outdoor_corner.x + party.i_w_c.x) +
2944 scenario.out_width * (party.outdoor_corner.y + party.i_w_c.y) : c_town.town_num;
2946 if (mess2 >= 0) {
2947 label2 = 1000 * cur_type + mess2 + mess_adj[cur_type];
2948 label2b = (is_out()) ? (party.outdoor_corner.x + party.i_w_c.x) +
2949 scenario.out_width * (party.outdoor_corner.y + party.i_w_c.y) : c_town.town_num;
2951 display_strings((char *) str1, (char *) str2,label1,label2, label1b,label2b,
2952 "",57,1600 + scenario.intro_pic,0);
2955 void get_strs(char *str1,char *str2,short cur_type,short which_str1,short which_str2)
2957 short num_strs[3] = {260,108,135};
2959 if (((which_str1 >= 0) && (which_str1 != minmax(0,num_strs[cur_type],which_str1))) ||
2960 ((which_str2 >= 0) && (which_str2 != minmax(0,num_strs[cur_type],which_str2)))) {
2961 give_error("The scenario attempted to access a message out of range.","",0);
2962 return;
2964 switch (cur_type) {
2965 case 0:
2966 if (which_str1 >= 0) {
2967 if (which_str1 < 160)
2968 strcpy((char *) str1,data_store5->scen_strs[which_str1]);
2969 else strcpy((char *) str1,scen_strs2[which_str1 - 160]);
2972 if (which_str2 >= 0){
2973 if (which_str2 < 160)
2974 strcpy((char *) str2,data_store5->scen_strs[which_str2]);
2975 else strcpy((char *) str2,scen_strs2[which_str2 - 160]);
2977 break;
2978 case 1:
2979 if (which_str1 >= 0)
2980 load_outdoors(party.outdoor_corner.x + party.i_w_c.x,
2981 party.outdoor_corner.y + party.i_w_c.y, party.i_w_c.x, party.i_w_c.y,
2982 1,which_str1,(char *) str1);
2983 if (which_str2 >= 0)
2984 load_outdoors(party.outdoor_corner.x + party.i_w_c.x,
2985 party.outdoor_corner.y + party.i_w_c.y, party.i_w_c.x, party.i_w_c.y,
2986 1,which_str2,(char *) str2);
2987 break;
2988 case 2:
2989 if (which_str1 >= 0)
2990 strcpy((char *) str1,data_store->town_strs[which_str1]);
2991 if (which_str2 >= 0)
2992 strcpy((char *) str2,data_store->town_strs[which_str2]);
2993 break;
2999 void use_spec_item(short item)
3001 short i,j,k;
3002 location null_loc = {0,0};
3004 run_special(8,0,scenario.special_item_special[item],null_loc,&i,&j,&k);