added worldarea -> will be responsible for world map rendering
[dboe.git] / combat.c
bloba72c24eb291e82d885a7bc32161e40ddd0a225e7
1 #include <Windows.h>
2 #include "stdio.h"
3 #include "global.h"
4 #include "monster.h"
5 #include "graphics.h"
6 #include "locutils.h"
7 #include "newgraph.h"
8 #include "infodlgs.h"
9 #include "fields.h"
10 #include "text.h"
11 #include "items.h"
12 #include "party.h"
13 #include "combat.h"
14 #include "exlsound.h"
15 #include "town.h"
16 #include "specials.h"
17 #include "gutils.h"
19 extern party_record_type far party;
20 extern piles_of_stuff_dumping_type *data_store;
21 extern piles_of_stuff_dumping_type2 *data_store2;
22 extern talking_record_type far talking;
23 extern scenario_data_type far scenario;
25 extern pc_record_type far adven[6];
26 extern current_town_type far c_town;
27 extern big_tr_type far t_d;
28 extern town_item_list far t_i;
29 extern short overall_mode,store_item_spell_level;
30 extern short which_combat_type;
31 extern short stat_window;
32 extern location center;
33 extern unsigned char far combat_terrain[64][64];
34 extern location pc_pos[6];
35 extern short current_pc;
36 extern short pc_last_cast[2][6];
37 extern short combat_active_pc;
38 extern Boolean monsters_going,spell_forced,in_scen_debug;
39 extern HWND mainPtr;
40 extern short store_mage, store_priest;
41 extern short store_mage_lev, store_priest_lev;
42 extern short store_spell_target,pc_casting,current_spell_range;
43 extern effect_pat_type current_pat;
44 extern short town_size[3];
45 extern short town_type;
46 extern short monst_target[T_M]; // 0-5 target that pc 6 - no target 100 + x - target monster x
47 extern short num_targets_left;
48 extern location spell_targets[8];
49 extern Boolean web,crate,barrel,fire_barrier,force_barrier,quickfire,force_wall,fire_wall,antimagic,scloud,ice_wall,blade_wall;
50 extern Boolean sleep_field;
51 extern Boolean fast_bang;
52 extern unsigned char far misc_i[64][64],sfx[64][64];
53 extern short store_current_pc;
54 extern short refer_mage[62],refer_priest[62];
55 extern location monster_targs[T_M];
56 extern short combat_posing_monster , current_working_monster ; // 0-5 PC 100 + x - monster x
58 extern short spell_caster, missile_firer,current_monst_tactic;
59 char create_line[60];
60 short spell_being_cast;
61 short missile_inv_slot, ammo_inv_slot;
62 short force_wall_position = 10; // 10 -> no force wall
63 Boolean processing_fields = TRUE;
64 short futzing;
65 unsigned char store_sum_monst;
66 short store_sum_monst_cost;
69 location out_start_loc = {20,23};
70 short far hit_chance[51] = {20,30,40,45,50,55,60,65,69,73,
71 77,81,84,87,90,92,94,96,97,98,99
72 ,99,99,99,99,99,99,99,99,99,99
73 ,99,99,99,99,99,99,99,99,99,99,
74 99,99,99,99,99,99,99,99,99,99};
75 short far abil_range[40] = {0,6,8,8,10, 10,10,8,6,8, 6,0,0,0,6, 0,0,0,0,4, 10,0,0,0,0,
76 0,0,0,0,0, 0,0,8,6,9, 0,0,0,0,0};
77 short far abil_odds[40] = {0,5,7,6,6, 5,5,6,6,6, 6,0,0,0,4, 0,0,0,0,4, 8,0,0,0,0,
78 0,0,0,0,0, 0,0,7,5,6, 0,0,0,0,0};
81 //short s_cost[2][62] = {{1,1,1,1,1,2,15,2,1,3, 2,2,2,2,2,2,4,6,2,2, 3,3,4,3,3,5,5,4,6,4,/
82 // 4,4,4,4,30,-1,8,5, 5,8,7,5,8,10,5,7, 6,6,7,7,12,10,-1,20, 12,8,20,8,14,10,50,10},
83 // {1,1,1,2,1,2,2,5,50,1, 2,2,2,2,2,6,8,7,4,3, 3,4,3,3,3,10,6,3,3,7,
84 // 4,5,5,15,8,6,4,4, 5,5,25,8,12,12,10,5, 7,6,6,8,14,20,7,6, 8,7,20,12,8,12,30,8}};
85 short far s_cost[2][62] = {{1,1,1,1,1,2,50,2,1,3, 2,3,2,2,2,2,4,4,2,6, 3,3,5,3,3,5,6,4,6,4,
86 4,5,4,8,30,-1,8,6, 5,8,8,6,9,10,6,6, 7,6,8,7,12,10,12,20, 12,8,20,10,14,10,50,10},
87 {1,1,1,2,1,1,3,5,50,1, 2,2,2,2,3,5,8,6,4,2, 3,4,3,3,3,10,5,3,4,6,
88 5,5,5,15,6,5,5,8, 6,7,25,8,10,12,12,6, 8,7,8,8,14,17,8,7, 10,10,35,10,12,12,30,10}};
90 short far mage_range[80] = {0,6,0,0,7,7,0,14,8,0, 6,8,7,10,0,8,3,8,10,6, 0,0,12,0,10,12,4,10,8,0,
91 8,12,12,0,10,4,8,8, 0,0,14,0,2,4,10,12, 8,12,6,8,5,8,4,0, 0,0,8,0,4,2,4,6
92 ,10,8,8,12,8,10,10,10, 10,10,10,10,10,10,10,10,10,10};
93 short far priest_range[62] = {0,0,0,8,0,0,0,0,0,10, 0,0,10,0,6,4,0,6,6,8, 0,0,8,0,10,0,8,0,0,8,
94 0,10,8,0,6,0,0,0, 0,0,0,9,0,4,0,8, 0,0,10,0,4,8,0,8, 0,4,0,12,0,10,0,0};
95 short far monst_mage_spell[55] = {1,1,1,1,1,1,2,2,2,2,
96 2,2,3,3,3,3,3,4,4,4,
97 4,4,4,5,5,5,5,5,4,4,
98 6,6,6,6,7,7,7,7,7,8,
99 8,8,8,8,9,9,9,10,10,10,
100 11,11,11,12,12};
101 short far monst_cleric_spell[55] = {1,1,1,1,1,1,1,1,2,2,
102 2,2,2,3,3,3,11,11,11,4,
103 4,4,4,5,5,5,11,11,6,6,
104 6,6,6,6,7,7,7,7,7,7,
105 8,8,8,8,8,7,7,7,7,7,
106 7,9,9,10,10};
107 short monst_mage_cost[27] = {1,1,1,1,2, 2,2,2,2,4, 2,4,4,3,4, 4,4,5,5,5, 5,6,6,6,7, 7,7};
108 short monst_mage_area_effect[27] = {0,0,0,0,0, 0,0,0,1,0, 1,1,0,1,0, 0,0,0,1,0, 1,0,0,0,0, 0,0};
109 short monst_priest_cost[26] = {1,1,1,1,2, 2,2,4,2,3, 3,3,4,4,4, 5,5,5,10,6, 6,10,8,8,8, 8};
110 short monst_priest_area_effect[26] = {0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 1};
112 extern short boom_gr[8];
114 char *d_string[] = {"North", "NorthEast", "East", "SouthEast", "South", "SouthWest", "West", "NorthWest"};
116 short pc_marked_damage[6];
117 short monst_marked_damage[T_M];
119 location hor_vert_place[14] = {{0,0},{-1,1},{1,1},{-2,2},{0,2},
120 {2,2},{0,1},{-1,2},{1,2},{-1,3},
121 {1,3},{0,3},{0,4},{0,5}};
122 location diag_place[14] = {{0,0},{-1,0},{0,1},{-1,1},{-2,0},
123 {0,2},{-2,1},{-1,2},{-2,2},{-3,2},
124 {-2,3},{-3,3},{-4,3},{-3,4}};
126 unsigned char beasts[5] = {82,115,78,99,78};
127 unsigned char m1[20] = {38,40,58,60,72, 75,79,80,40,118, 174,40,58,60,72, 75,79,80,58,120};
128 unsigned char m2[16] = {39,41,45,47,62, 63,73,74,88,100, 116,130,134,39,41,45};
129 unsigned char m3[16] = {48,49,50,65,66, 67,73,74,76,84, 84,103,121,127,74, 129};
131 short far mage_caster_array[7][18] = {{1,1,1,2,2, 2,1,3,4,4, 1,1,1,2,2, 2,3,4},
132 {5,5,5,6,7, 8,9,10,11,11, 2,2,2,5,7, 10,10,5},
133 {5,5,2,9,11, 12,12,12,14,13, 13,12,12,2,2, 2,2,2},
134 {15,15,16,17,17, 5,12,12,13,13, 17,17,16,17,16, 2,2,2},
135 {15,18,19,19,20, 20,21,21,16,17, 18,18,18,18,19, 19,19,20},
136 {23,23,22,22,21, 21,20,24,19,18, 18,18,18,18,18, 23,23,19},
137 {23,23,24,25,26, 27,19,22,19,18, 18,18,18,18,26, 24,24,23}};
138 short far mage_emer_spells[7][4] = {{2,0,0,5},
139 {2,10,11,7},
140 {2,13,12,13},
141 {2,13,12,13},
142 {18,20,19,18},
143 {18,24,19,24},
144 {18,26,19,27}};
145 short far priest_caster_array[7][10] = {{1,1,1,1,3,3,3,4,4,4},
146 {5,5,6,6,7,7,8,8,8,9},
147 {9,6,6,8,11,12,12,5,5,12},
148 {12,12,13,13,14,9,9,14,14,15},
149 {19,18,13,19,15,18,18,19,16,18},
150 {22,18,16,19,18,18,21,22,23,23},
151 {26,26,25,24,26,22,24,22,26,25}};
152 short far priest_emer_spells[7][4] = {{0,1,0,2},
153 {0,8,0,2},
154 {0,8,0,10},
155 {0,14,0,10},
156 {0,19,18,17},
157 {0,19,18,20},
158 {25,25,26,24}};
159 effect_pat_type far null_pat = {{{0,0,0,0,0,0,0,0,0},
160 {0,0,0,0,0,0,0,0,0},
161 {0,0,0,0,0,0,0,0,0},
162 {0,0,0,0,0,0,0,0,0},
163 {0,0,0,0,0,0,0,0,0},
164 {0,0,0,0,0,0,0,0,0},
165 {0,0,0,0,0,0,0,0,0},
166 {0,0,0,0,0,0,0,0,0},
167 {0,0,0,0,0,0,0,0,0}}};
168 effect_pat_type far single = {{{0,0,0,0,0,0,0,0,0},
169 {0,0,0,0,0,0,0,0,0},
170 {0,0,0,0,0,0,0,0,0},
171 {0,0,0,0,0,0,0,0,0},
172 {0,0,0,0,1,0,0,0,0},
173 {0,0,0,0,0,0,0,0,0},
174 {0,0,0,0,0,0,0,0,0},
175 {0,0,0,0,0,0,0,0,0},
176 {0,0,0,0,0,0,0,0,0}}};
177 effect_pat_type far t = {{{0,0,0,0,0,0,0,0,0},
178 {0,0,0,0,0,0,0,0,0},
179 {0,0,0,0,0,0,0,0,0},
180 {0,0,0,0,1,0,0,0,0},
181 {0,0,0,1,1,1,0,0,0},
182 {0,0,0,0,1,0,0,0,0},
183 {0,0,0,0,0,0,0,0,0},
184 {0,0,0,0,0,0,0,0,0},
185 {0,0,0,0,0,0,0,0,0}}};
186 effect_pat_type far small_square = {{{0,0,0,0,0,0,0,0,0},
187 {0,0,0,0,0,0,0,0,0},
188 {0,0,0,0,0,0,0,0,0},
189 {0,0,0,0,0,0,0,0,0},
190 {0,0,0,0,1,1,0,0,0},
191 {0,0,0,0,1,1,0,0,0},
192 {0,0,0,0,0,0,0,0,0},
193 {0,0,0,0,0,0,0,0,0},
194 {0,0,0,0,0,0,0,0,0}}};
195 effect_pat_type far square = {{{0,0,0,0,0,0,0,0,0},
196 {0,0,0,0,0,0,0,0,0},
197 {0,0,0,0,0,0,0,0,0},
198 {0,0,0,1,1,1,0,0,0},
199 {0,0,0,1,1,1,0,0,0},
200 {0,0,0,1,1,1,0,0,0},
201 {0,0,0,0,0,0,0,0,0},
202 {0,0,0,0,0,0,0,0,0},
203 {0,0,0,0,0,0,0,0,0}}};
204 effect_pat_type far open_square = {{{0,0,0,0,0,0,0,0,0},
205 {0,0,0,0,0,0,0,0,0},
206 {0,0,0,0,0,0,0,0,0},
207 {0,0,0,1,1,1,0,0,0},
208 {0,0,0,1,0,1,0,0,0},
209 {0,0,0,1,1,1,0,0,0},
210 {0,0,0,0,0,0,0,0,0},
211 {0,0,0,0,0,0,0,0,0},
212 {0,0,0,0,0,0,0,0,0}}};
213 effect_pat_type far rad2 = {{{0,0,0,0,0,0,0,0,0},
214 {0,0,0,0,0,0,0,0,0},
215 {0,0,0,1,1,1,0,0,0},
216 {0,0,1,1,1,1,1,0,0},
217 {0,0,1,1,1,1,1,0,0},
218 {0,0,1,1,1,1,1,0,0},
219 {0,0,0,1,1,1,0,0,0},
220 {0,0,0,0,0,0,0,0,0},
221 {0,0,0,0,0,0,0,0,0}}};
222 effect_pat_type far rad3 = {{{0,0,0,0,0,0,0,0,0},
223 {0,0,0,1,1,1,0,0,0},
224 {0,0,1,1,1,1,1,0,0},
225 {0,1,1,1,1,1,1,1,0},
226 {0,1,1,1,1,1,1,1,0},
227 {0,1,1,1,1,1,1,1,0},
228 {0,0,1,1,1,1,1,0,0},
229 {0,0,0,1,1,1,0,0,0},
230 {0,0,0,0,0,0,0,0,0}}};
231 effect_pat_type far field[8] = {{{{0,0,0,0,1,1,0,0,0},
232 {0,0,0,0,1,1,0,0,0},
233 {0,0,0,0,1,1,0,0,0},
234 {0,0,0,0,1,1,0,0,0},
235 {0,0,0,0,1,1,0,0,0},
236 {0,0,0,0,1,1,0,0,0},
237 {0,0,0,0,1,1,0,0,0},
238 {0,0,0,0,1,1,0,0,0},
239 {0,0,0,0,1,1,0,0,0}}},
241 {{{0,0,0,0,0,0,0,0,1},
242 {0,0,0,0,0,0,0,1,1},
243 {0,0,0,0,0,0,1,1,0},
244 {0,0,0,0,0,1,1,0,0},
245 {0,0,0,0,1,1,0,0,0},
246 {0,0,0,1,1,0,0,0,0},
247 {0,0,1,1,0,0,0,0,0},
248 {0,1,1,0,0,0,0,0,0},
249 {1,1,0,0,0,0,0,0,0}}},
251 {{{0,0,0,0,0,0,0,0,0},
252 {0,0,0,0,0,0,0,0,0},
253 {0,0,0,0,0,0,0,0,0},
254 {0,0,0,0,0,0,0,0,0},
255 {1,1,1,1,1,1,1,1,1},
256 {1,1,1,1,1,1,1,1,1},
257 {0,0,0,0,0,0,0,0,0},
258 {0,0,0,0,0,0,0,0,0},
259 {0,0,0,0,0,0,0,0,0}}},
261 {{{1,0,0,0,0,0,0,0,0},
262 {1,1,0,0,0,0,0,0,0},
263 {0,1,1,0,0,0,0,0,0},
264 {0,0,1,1,0,0,0,0,0},
265 {0,0,0,1,1,0,0,0,0},
266 {0,0,0,0,1,1,0,0,0},
267 {0,0,0,0,0,1,1,0,0},
268 {0,0,0,0,0,0,1,1,0},
269 {0,0,0,0,0,0,0,1,1}}},
271 {{{0,0,0,1,1,0,0,0,0},
272 {0,0,0,1,1,0,0,0,0},
273 {0,0,0,1,1,0,0,0,0},
274 {0,0,0,1,1,0,0,0,0},
275 {0,0,0,1,1,0,0,0,0},
276 {0,0,0,1,1,0,0,0,0},
277 {0,0,0,1,1,0,0,0,0},
278 {0,0,0,1,1,0,0,0,0},
279 {0,0,0,1,1,0,0,0,0}}},
281 {{{0,0,0,0,0,0,0,1,1},
282 {0,0,0,0,0,0,1,1,0},
283 {0,0,0,0,0,1,1,0,0},
284 {0,0,0,0,1,1,0,0,0},
285 {0,0,0,1,1,0,0,0,0},
286 {0,0,1,1,0,0,0,0,0},
287 {0,1,1,0,0,0,0,0,0},
288 {1,1,0,0,0,0,0,0,0},
289 {1,0,0,0,0,0,0,0,0}}},
291 {{{0,0,0,0,0,0,0,0,0},
292 {0,0,0,0,0,0,0,0,0},
293 {0,0,0,0,0,0,0,0,0},
294 {1,1,1,1,1,1,1,1,1},
295 {1,1,1,1,1,1,1,1,1},
296 {0,0,0,0,0,0,0,0,0},
297 {0,0,0,0,0,0,0,0,0},
298 {0,0,0,0,0,0,0,0,0},
299 {0,0,0,0,0,0,0,0,0}}},
301 {{{1,1,0,0,0,0,0,0,0},
302 {0,1,1,0,0,0,0,0,0},
303 {0,0,1,1,0,0,0,0,0},
304 {0,0,0,1,1,0,0,0,0},
305 {0,0,0,0,1,1,0,0,0},
306 {0,0,0,0,0,1,1,0,0},
307 {0,0,0,0,0,0,1,1,0},
308 {0,0,0,0,0,0,0,1,1},
309 {0,0,0,0,0,0,0,0,1}}}};
311 short last_attacked[6],pc_dir[6],pc_parry[6],pc_moves[6];
312 Boolean center_on_monst;
318 void start_outdoor_combat(outdoor_creature_type encounter,unsigned char in_which_terrain,short num_walls)
320 short i,j,r1,r2,how_many,num_tries = 0;
321 short low[10] = {15,7,3,3,1,1,1,7,2,1};
322 short high[10] = {30,10,5,5,3,2,1,10,4,1};
323 RECT town_rect = {0,0,47,47};
324 short nums[10];
326 for (i = 0; i < 7; i++)
327 nums[i] = get_ran(1,low[i],high[i]);
328 for (i = 0; i < 3; i++)
329 nums[i + 7] = get_ran(1,low[i + 7],high[i + 7]);
330 notify_out_combat_began(encounter.what_monst,nums);
331 print_buf();
332 play_sound(23);
334 which_combat_type = 0;
335 town_type = 1;
336 overall_mode = 10;
338 // Basically, in outdoor combat, we create kind of a 48x48 town for
339 // the combat to take place in
340 for (i = 0; i < 48; i++)
341 for (j = 0; j < 48; j++) {
342 c_town.explored[i][j] = 0;
343 misc_i[i][j] = 0;
344 sfx[i][j] = 0;
346 c_town.town.in_town_rect = town_rect;
348 create_out_combat_terrain((short) in_which_terrain,num_walls,0);////
350 for (i = 0; i < T_M; i++) {
351 c_town.monst.dudes[i].number = 0;
352 c_town.monst.dudes[i].active = 0;
354 for (i = 0; i < 7; i++) {
355 how_many = nums[i];
356 if (encounter.what_monst.monst[i] != 0)
357 for (j = 0; j < how_many; j++)
358 set_up_monst(0,encounter.what_monst.monst[i]);
360 for (i = 0; i < 3; i++) {
361 how_many = nums[i + 7];
362 if (encounter.what_monst.friendly[i] != 0)
363 for (j = 0; j < how_many; j++)
364 set_up_monst(1,encounter.what_monst.friendly[i]);
367 // place PCs
368 pc_pos[0] = out_start_loc;
369 update_explored(pc_pos[0]);
370 if (get_blockage(combat_terrain[pc_pos[0].x][pc_pos[0].y]) > 0)
371 combat_terrain[pc_pos[0].x][pc_pos[0].y] = combat_terrain[0][0];
372 for (i = 1; i < 6; i++) {
373 pc_pos[i] = pc_pos[0];
374 pc_pos[i].x = pc_pos[i].x + hor_vert_place[i].x;
375 pc_pos[i].y = pc_pos[i].y + hor_vert_place[i].y;
376 if (get_blockage(combat_terrain[pc_pos[i].x][pc_pos[i].y]) > 0)
377 combat_terrain[pc_pos[i].x][pc_pos[i].y] = combat_terrain[0][0];
378 update_explored(pc_pos[i]);
380 for (j = 0; j < 6; j++)
381 if (j != 2)
382 adven[i].status[j] = 0;
385 // place monsters, w. friendly monsts landing near PCs
386 for (i = 0; i < T_M; i++)
387 if (c_town.monst.dudes[i].active > 0) {
388 monst_target[i] = 6;
390 c_town.monst.dudes[i].m_loc.x = get_ran(1,15,25);
391 c_town.monst.dudes[i].m_loc.y = get_ran(1,14,18);
392 if (c_town.monst.dudes[i].attitude == 2)
393 c_town.monst.dudes[i].m_loc.y += 9;
394 else if ((c_town.monst.dudes[i].m_d.mu > 0) || (c_town.monst.dudes[i].m_d.cl > 0))
395 c_town.monst.dudes[i].m_loc.y = c_town.monst.dudes[i].m_loc.y - 4;//max(12,c_town.monst.dudes[i].m_loc.y - 4);
396 num_tries = 0;
397 while (((monst_can_be_there(c_town.monst.dudes[i].m_loc,i) == FALSE) ||
398 (combat_terrain[c_town.monst.dudes[i].m_loc.x][c_town.monst.dudes[i].m_loc.y] == 180) ||
399 (pc_there(c_town.monst.dudes[i].m_loc) < 6)) &&
400 (num_tries++ < 50)) {
401 c_town.monst.dudes[i].m_loc.x = get_ran(1,15,25);
402 c_town.monst.dudes[i].m_loc.y = get_ran(1,14,18);
403 if (c_town.monst.dudes[i].attitude == 2)
404 c_town.monst.dudes[i].m_loc.y += 9;
405 else if ((c_town.monst.dudes[i].m_d.mu > 0) || (c_town.monst.dudes[i].m_d.cl > 0))
406 c_town.monst.dudes[i].m_loc.y = c_town.monst.dudes[i].m_loc.y - 4;//max(12,c_town.monst.dudes[i].m_loc.y - 4);
408 if (get_blockage(combat_terrain[c_town.monst.dudes[i].m_loc.x][c_town.monst.dudes[i].m_loc.y]) > 0)
409 combat_terrain[c_town.monst.dudes[i].m_loc.x][c_town.monst.dudes[i].m_loc.y] = combat_terrain[0][0];
413 combat_active_pc = 6;
414 spell_caster = 6; missile_firer = 6;
415 for (i = 0; i < T_M; i++)
416 monst_target[i] = 6;
418 for (i = 0; i < 6; i++) {
419 pc_parry[i] = 0;
420 last_attacked[i] = T_M + 10;
423 for (i = 0; i < NUM_TOWN_ITEMS; i++)
424 t_i.items[i].variety = 0;
425 store_current_pc = current_pc;
426 current_pc = 0;
427 set_pc_moves();
428 pick_next_pc();
429 center = pc_pos[current_pc];
430 load_area_graphics();
431 draw_buttons(0);
432 put_pc_screen();
433 set_stat_window(current_pc);
435 adjust_spell_menus();
437 //clear_map();
438 give_help(48,49,0);
442 Boolean pc_combat_move(location destination)
444 short dir,monst_hit,s1,s2,i,monst_exist,switch_pc;
445 Boolean keep_going = TRUE,forced = FALSE,check_f;
446 location monst_loc,store_loc;
447 short spec_num;
449 if (monst_there(destination) > T_M)
450 keep_going = check_special_terrain(destination,2,current_pc,&spec_num,&check_f);
451 if (check_f == TRUE)
452 forced = TRUE;
454 if (spec_num == 50)
455 forced = TRUE;
457 if (keep_going == TRUE) {
459 dir = set_direction(pc_pos[current_pc], destination);
461 if ((loc_off_act_area(destination) == TRUE) && (which_combat_type == 1)) {
462 add_string_to_buf("Move: Can't leave town during combat.");
463 print_buf();
464 return TRUE;
466 else if ((combat_terrain[destination.x][destination.y] == 90) && (which_combat_type == 0)) {
467 if (get_ran(1,1,10) < 3) {
468 adven[current_pc].main_status = 5;
469 if (combat_active_pc == current_pc)
470 combat_active_pc = 6;
471 sprintf ((char *) create_line, "Moved: Fled. ");
472 pc_moves[current_pc] = 0;
474 else {
475 take_ap(1);
476 sprintf ((char *) create_line, "Moved: Couldn't flee. ");
478 add_string_to_buf((char *) create_line);
479 return TRUE;
481 else if ((monst_hit = monst_there(destination)) <= T_M) {
482 s1 = c_town.monst.dudes[monst_hit].attitude;
483 s2 = (s1 % 2 == 1) ? 2 : fancy_choice_dialog(1045,0);
484 if ((s2 == 2) && (s1 % 2 != 1))
485 make_town_hostile();
486 if (s2 == 2) {
487 last_attacked[current_pc] = monst_hit;
488 pc_attack(current_pc,monst_hit);
489 return TRUE;
492 else if ((switch_pc = pc_there(destination)) < 6) {
493 if (pc_moves[switch_pc] == 0) {
494 add_string_to_buf("Move: Can't switch places.");
495 add_string_to_buf(" (other PC has no APs) ");
496 return FALSE;
498 else pc_moves[switch_pc]--;
499 add_string_to_buf("Move: Switch places.");
500 store_loc = pc_pos[current_pc];
501 pc_pos[current_pc] = destination;
502 pc_pos[switch_pc] = store_loc;
503 adven[current_pc].direction = dir;
504 take_ap(1);
505 check_special_terrain(store_loc,2,switch_pc,&spec_num,&check_f);
506 move_sound(combat_terrain[destination.x][destination.y],pc_moves[current_pc]);
507 return TRUE;
509 else if ((forced == TRUE)
510 || ((impassable(combat_terrain[destination.x][destination.y]) == FALSE) && (pc_there(destination) == 6))) {
512 // monsters get back-shots
513 for (i = 0; i < T_M; i++) {
514 monst_loc = c_town.monst.dudes[i].m_loc;
515 monst_exist = c_town.monst.dudes[i].active;
517 s1 = current_pc;
518 if ((monst_exist > 0) && (monst_adjacent(pc_pos[current_pc],i) == TRUE)
519 && (monst_adjacent(destination,i) == FALSE) &&
520 (c_town.monst.dudes[i].attitude % 2 == 1) &&
521 (c_town.monst.dudes[i].m_d.status[11] <= 0) &&
522 (c_town.monst.dudes[i].m_d.status[12] <= 0)) {
523 combat_posing_monster = current_working_monster = 100 + i;
524 monster_attack_pc(i,current_pc);
525 combat_posing_monster = current_working_monster = -1;
526 draw_terrain(0);
528 if (s1 != current_pc)
529 return FALSE;
532 // move if still alive
533 if (adven[current_pc].main_status == 1) {
534 pc_dir[current_pc] = set_direction(pc_pos[current_pc],destination);
535 pc_pos[current_pc] = destination;
536 adven[current_pc].direction = dir;
537 take_ap(1);
538 //sprintf ((char *) create_line, "Moved: %s ",d_string[dir]);
539 //add_string_to_buf((char *) create_line);
540 move_sound(combat_terrain[destination.x][destination.y],pc_moves[current_pc]);
543 else return FALSE;
544 return TRUE;
546 else {
547 sprintf ((char *) create_line, "Blocked: %s ",d_string[dir]);
548 add_string_to_buf((char *) create_line);
549 return FALSE;
552 return FALSE;
555 void char_parry()
557 pc_parry[current_pc] = (pc_moves[current_pc] / 4) *
558 (2 + stat_adj(current_pc,1) + adven[current_pc].skills[8]);
559 pc_moves[current_pc] = 0;
562 void char_stand_ready()
564 pc_parry[current_pc] = 100;
565 pc_moves[current_pc] = 0;
568 void pc_attack(short who_att,short target)
570 short r1,r2,what_skill1 = 1, what_skill2 = 1, weap1 = 24, weap2 = 24,i,store_hp,skill_item;
571 Boolean dummy;
572 creature_data_type *which_m;
573 short hit_adj, dam_adj, spec_dam = 0,poison_amt;
575 // slice out bad attacks
576 if (adven[who_att].main_status != 1)
577 return;
578 if ((adven[who_att].status[11] > 0) || (adven[who_att].status[12] > 0))
579 return;
581 last_attacked[who_att] = target;
582 which_m = &c_town.monst.dudes[target];
584 for (i = 0; i < 24; i++)
585 if (((adven[who_att].items[i].variety == 1) || (adven[who_att].items[i].variety == 2)) &&
586 (adven[who_att].equip[i] == TRUE))
587 if (weap1 == 24)
588 weap1 = i;
589 else weap2 = i;
591 hit_adj = (-5 * minmax(-8,8,adven[who_att].status[1])) + 5 * minmax(-8,8,which_m->m_d.status[1])
592 - stat_adj(who_att,1) * 5 + (get_encumberance(who_att)) * 5;
594 dam_adj = minmax(-8,8,adven[who_att].status[1]) - minmax(-8,8,which_m->m_d.status[1])
595 + stat_adj(who_att,0);
597 if ((which_m->m_d.status[11] > 0) || (which_m->m_d.status[12] > 0)) {
598 hit_adj -= 80;
599 dam_adj += 10;
603 if ((skill_item = text_pc_has_abil_equip(who_att,37)) < 24) {
604 hit_adj += 5 * (adven[who_att].items[skill_item].item_level / 2 + 1);
605 dam_adj += adven[who_att].items[skill_item].item_level / 2;
607 if ((skill_item = text_pc_has_abil_equip(who_att,43)) < 24) {
608 dam_adj += adven[who_att].items[skill_item].item_level;
609 hit_adj += adven[who_att].items[skill_item].item_level * 2;
612 void_sanctuary(who_att);
614 store_hp = c_town.monst.dudes[target].m_d.health;
616 combat_posing_monster = current_working_monster = who_att;
618 if (weap1 == 24) {
620 sprintf ((char *) create_line, "%s punches. ",(char *) adven[who_att].name);//,hit_adj, dam_adj);
621 add_string_to_buf((char *) create_line);
623 r1 = get_ran(1,0,100) + hit_adj - 20;
624 r1 += 5 * (adven[current_pc].status[6] / 3);
625 r2 = get_ran(1,1,4) + dam_adj;
627 if (r1 <= hit_chance[adven[who_att].skills[what_skill1]]) {
628 damage_monst(target, who_att, r2, 0,400);
630 else {
631 draw_terrain(2);
632 sprintf ((char *) create_line, "%s misses. ",(char *) adven[who_att].name);
633 add_string_to_buf((char *) create_line);
634 play_sound(2);
638 // Don't forget awkward and stat adj.
639 if (weap1 < 24) {
640 what_skill1 = 2 + adven[who_att].items[weap1].type;
642 // safety valve
643 if (what_skill1 == 2)
644 what_skill1 = 3;
646 sprintf ((char *) create_line, "%s swings. ",(char *) adven[who_att].name);//,hit_adj, dam_adj);
647 add_string_to_buf((char *) create_line);
649 r1 = get_ran(1,0,100) - 5 + hit_adj
650 - 5 * adven[who_att].items[weap1].bonus;
651 r1 += 5 * (adven[current_pc].status[6] / 3);
653 if ((weap2 < 24) && (adven[who_att].traits[2] == FALSE))
654 r1 += 25;
656 // race adj.
657 if ((adven[who_att].race == 2) && (adven[who_att].items[weap1].type == 3))
658 r1 -= 10;
660 r2 = get_ran(1,1,adven[who_att].items[weap1].item_level) + dam_adj + 2 + adven[who_att].items[weap1].bonus;
661 if (adven[who_att].items[weap1].ability == 12)
662 r2 = (r2 * (10 - adven[who_att].items[weap1].ability_strength)) / 10;
664 if (r1 <= hit_chance[adven[who_att].skills[what_skill1]]) {
665 spec_dam = calc_spec_dam(adven[who_att].items[weap1].ability,
666 adven[who_att].items[weap1].ability_strength,which_m);
668 // assassinate
669 r1 = get_ran(1,0,100);
670 if ((adven[who_att].level >= which_m->m_d.level - 1)
671 && (adven[who_att].skills[16] >= which_m->m_d.level / 2)
672 && (which_m->m_d.spec_skill != 12)) // Can't assassinate splitters
673 if (r1 < hit_chance[max(adven[who_att].skills[16] - which_m->m_d.level,0)]) {
674 add_string_to_buf(" You assassinate. ");
675 spec_dam += r2;
678 switch (what_skill1) {
679 case 3:
680 if (adven[who_att].items[weap1].item_level < 8)
681 damage_monst(target, who_att, r2, spec_dam, 100);
682 else damage_monst(target, who_att, r2, spec_dam, 200);
683 break;
684 case 4:
685 damage_monst(target, who_att, r2, spec_dam, 400);
686 break;
687 case 5:
688 damage_monst(target, who_att, r2, spec_dam, 300);
689 break;
691 // poison
692 if ((adven[who_att].status[0] > 0) && (adven[who_att].weap_poisoned == weap1)) {
693 poison_amt = adven[who_att].status[0];
694 if (pc_has_abil_equip(who_att,51) < 24)
695 poison_amt += 2;
696 poison_monst(which_m,poison_amt);
697 adven[who_att].status[0] = move_to_zero(adven[who_att].status[0]);
699 if ((adven[who_att].items[weap1].ability == 14) && (get_ran(1,0,1) == 1)) {
700 add_string_to_buf(" Blade drips venom. ");
701 poison_monst(which_m,adven[who_att].items[weap1].ability_strength / 2);
703 if ((adven[who_att].items[weap1].ability == 9) && (get_ran(1,0,1) == 1)) {
704 add_string_to_buf(" Blade drips acid. ");
705 acid_monst(which_m,adven[who_att].items[weap1].ability_strength / 2);
707 if ((adven[who_att].items[weap1].ability == 10) && (get_ran(1,0,1) == 1)) {
708 add_string_to_buf(" Blade drains life. ");
709 heal_pc(who_att,adven[who_att].items[weap1].ability_strength / 2);
712 else {
713 draw_terrain(2);
714 sprintf ((char *) create_line, " %s misses. ",(char *) adven[who_att].name);
715 add_string_to_buf((char *) create_line);
716 if (what_skill1 == 5)
717 play_sound(19);
718 else play_sound(2);
721 if ((weap2 < 24) && (which_m->active > 0)) {
722 what_skill2 = 2 + adven[who_att].items[weap2].type;
724 // safety valve
725 if (what_skill2 == 2)
726 what_skill2 = 3;
729 sprintf ((char *) create_line, "%s swings. ",(char *) adven[who_att].name);//,hit_adj, dam_adj);
730 add_string_to_buf((char *) create_line);
731 r1 = get_ran(1,0,100) + hit_adj - 5 * adven[who_att].items[weap2].bonus;
733 // Ambidextrous?
734 if (adven[who_att].traits[2] == FALSE)
735 r1 += 25;
737 r1 += 5 * (adven[current_pc].status[6] / 3);
738 r2 = get_ran(1,1,adven[who_att].items[weap2].item_level) + dam_adj - 1 + adven[who_att].items[weap2].bonus;
739 if (adven[who_att].items[weap2].ability == 12)
740 r2 = (r2 * (10 - adven[who_att].items[weap2].ability_strength)) / 10;
742 if (r1 <= hit_chance[adven[who_att].skills[what_skill2]]) {
743 spec_dam = calc_spec_dam(adven[who_att].items[weap2].ability,
744 adven[who_att].items[weap2].ability_strength,which_m);
745 switch (what_skill2) {
746 case 3:
747 if (adven[who_att].items[weap1].item_level < 8)
748 damage_monst(target, who_att, r2, spec_dam, 100);
749 else damage_monst(target, who_att, r2, spec_dam, 200);
750 break;
751 case 4:
752 damage_monst(target, who_att, r2, spec_dam, 400);
753 break;
754 case 5:
755 damage_monst(target, who_att, r2, spec_dam, 300);
756 break;
759 if ((adven[who_att].items[weap2].ability == 14) && (get_ran(1,0,1) == 1)) {
760 add_string_to_buf(" Blade drips venom. ");
761 poison_monst(which_m,adven[who_att].items[weap2].ability_strength / 2);
763 if ((adven[who_att].items[weap2].ability == 9) && (get_ran(1,0,1) == 1)) {
764 add_string_to_buf(" Blade drips acid. ");
765 acid_monst(which_m,adven[who_att].items[weap2].ability_strength / 2);
767 if ((adven[who_att].items[weap2].ability == 10) && (get_ran(1,0,1) == 1)) {
768 add_string_to_buf(" Blade drains life. ");
769 heal_pc(who_att,adven[who_att].items[weap2].ability_strength / 2);
773 else {
774 draw_terrain(2);
775 sprintf ((char *) create_line, "%s misses. ",(char *) adven[who_att].name);
776 add_string_to_buf((char *) create_line);
777 if (what_skill2 == 5)
778 play_sound(19);
779 else play_sound(2);
782 adven[who_att].status[0] = move_to_zero(adven[who_att].status[0]);
783 take_ap(4);
785 if (((c_town.monst.dudes[target].m_d.status[10] > 0) || (c_town.monst.dudes[target].m_d.spec_skill == 22))
786 && (store_hp - c_town.monst.dudes[target].m_d.health > 0)) {
787 add_string_to_buf(" Shares damage! ");
788 damage_pc(who_att, store_hp - c_town.monst.dudes[target].m_d.health, 3,-1);
790 combat_posing_monster = current_working_monster = -1;
794 short calc_spec_dam(short abil,short abil_str,creature_data_type *monst) ////
796 short store = 0;
798 switch (abil) {
799 case 1: case 171:
800 store += get_ran(abil_str,1,6);
801 break;
802 case 2:
803 if (monst->m_d.m_type == 7)
804 store += 8 * abil_str;
805 break;
806 case 175:
807 if (monst->m_d.m_type == 7)
808 store += 25 + 8 * abil_str;
809 break;
810 case 174:
811 if (monst->m_d.m_type == 8)
812 store += 20 + 6 * abil_str;
813 break;
814 case 3:
815 if (monst->m_d.m_type == 8)
816 store += 6 * abil_str;
817 break;
818 case 4:
819 if (monst->m_d.m_type == 1)
820 store += 5 * abil_str;
821 break;
822 case 5:
823 if (monst->m_d.m_type == 9)
824 store += 8 * abil_str;
825 break;
826 case 6:
827 if (monst->m_d.m_type == 4)
828 store += 4 * abil_str;
829 break;
830 case 7:
831 if (monst->m_d.m_type == 5)
832 store += 4 * abil_str;
833 break;
834 case 8:
835 if (monst->m_d.m_type == 12)
836 store += 7 * abil_str;
837 break;
838 case 13:
839 scare_monst(monst,abil_str * 10);
840 break;
841 case 173:
842 acid_monst(monst,abil_str);
843 break;
845 return store;
848 void place_target(location target)
850 short i;
852 if (num_targets_left > 0) {
853 if (loc_off_act_area(target) == TRUE) {
854 add_string_to_buf(" Space not in town. ");
855 return;
857 if (can_see(pc_pos[current_pc],target,0) > 4) {
858 add_string_to_buf(" Can't see target. ");
859 return;
861 if (dist(pc_pos[current_pc],target) > ((spell_being_cast >= 100) ? priest_range[spell_being_cast - 100] : mage_range[spell_being_cast])) {
862 add_string_to_buf(" Target out of range.");
863 return;
865 if ((get_obscurity(target.x,target.y) == 5) && (spell_being_cast != 41)) {
866 add_string_to_buf(" Target space obstructed. ");
867 return;
869 if (is_antimagic(target.x,target.y)) {
870 add_string_to_buf(" Target in antimagic field.");
871 return;
873 for (i = 0; i < 8; i++) {
874 if (same_point(spell_targets[i],target) == TRUE) {
875 add_string_to_buf(" Target removed.");
876 num_targets_left++;
877 spell_targets[i].x = 120;
878 play_sound(-1);
879 return;
882 for (i = 0; i < 8; i++)
883 if (spell_targets[i].x == 120) {
884 add_string_to_buf(" Target added.");
885 spell_targets[i] = target;
886 num_targets_left--;
887 play_sound(0);
888 i = 8;
892 if (num_targets_left == 0) {
893 do_combat_cast(spell_targets[0]);
894 overall_mode = 10;
898 // Special spells:
899 // 62 - Carrunos
900 // 63 - Summon Rat
901 // 64 - Ice Wall Balls
902 // 65 - Goo Bomb
903 // 66 - Foul vapors
904 // 67 - SLeep cloud
905 // 68 - Acid spray
906 // 69 - Paralyze beam
907 // 70 - mass sleep
908 void do_combat_cast(location target)
910 short adjust,r1,r2,targ_num,which_mess = 0,s_num,level,bonus = 1,i,item,store_sound = 0;
911 creature_data_type *cur_monst;
912 Boolean freebie = FALSE,ap_taken = FALSE,cost_taken = FALSE;
913 short num_targets = 1,store_m_type = 2;
914 short spray_type_array[15] = {1,1,1,4,4,5,5,5,6,6,7,7,8,8,9};
915 unsigned char summon;
917 location ashes_loc = {0,0};
919 // to wedge in animations, have to kludge like crazy
920 short boom_dam[8] = {0,0,0,0,0,0,0,0};
921 short boom_type[8] = {0,0,0,0,0,0,0,0};
922 location boom_targ[8];
924 if (spell_being_cast >= 1000) {
925 spell_being_cast -= 1000;
926 freebie = TRUE;
927 level = store_item_spell_level;
928 level = minmax(2,20,level);
930 else {
931 level = 1 + adven[current_pc].level / 2;
932 bonus = stat_adj(current_pc,2);
934 force_wall_position = 10;
935 s_num = spell_being_cast % 100;
937 void_sanctuary(current_pc);
938 if (overall_mode == 11) {
939 spell_targets[0] = target;
941 else {
942 num_targets = 8;
945 spell_caster = current_pc;
947 // assign monster summoned, if summoning
948 if (spell_being_cast == 16) {
949 summon = get_summon_monster(1);
952 if (spell_being_cast == 26) {
953 summon = get_summon_monster(1);
955 if (spell_being_cast == 43) {
956 summon = get_summon_monster(2);
958 if (spell_being_cast == 58) {
959 summon = get_summon_monster(3);
961 combat_posing_monster = current_working_monster = current_pc;
963 for (i = 0; i < num_targets; i++)
964 if (spell_targets[i].x != 120) {
965 target = spell_targets[i];
966 spell_targets[i].x = 120; // nullify target as it is used
968 if ((cost_taken == FALSE) && (freebie == FALSE) && (s_num != 52) && (s_num != 35)) {
969 adven[current_pc].cur_sp -= s_cost[spell_being_cast / 100][s_num];
970 cost_taken = TRUE;
972 if ((cost_taken == FALSE) && (freebie == FALSE) && (s_num == 35)) {
973 adven[current_pc].cur_sp -= store_sum_monst_cost;
974 cost_taken = TRUE;
977 if ((adjust = can_see(pc_pos[current_pc],target,0)) > 4) {
978 add_string_to_buf(" Can't see target. ");
980 else if (loc_off_act_area(target) == TRUE) {
981 add_string_to_buf(" Space not in town. ");
983 else if (dist(pc_pos[current_pc],target) > ((spell_being_cast >= 100) ? priest_range[spell_being_cast - 100] : mage_range[spell_being_cast]))
984 add_string_to_buf(" Target out of range.");
985 else if ((get_obscurity(target.x,target.y) == 5) && (spell_being_cast != 41))
986 add_string_to_buf(" Target space obstructed. ");
987 else if (is_antimagic(target.x,target.y))
988 add_string_to_buf(" Target in antimagic field.");
989 else {
990 if (ap_taken == FALSE) {
991 if (freebie == FALSE)
992 take_ap(5);
993 ap_taken = TRUE;
994 draw_terrain(2);
996 boom_targ[i] = target;
997 switch (spell_being_cast) {
999 case 8: case 28: case 65: // web spells
1000 place_spell_pattern(current_pat,target,1,FALSE,current_pc);
1001 break;
1002 case 5: case 17: // fire wall spells
1003 place_spell_pattern(current_pat,target,5,FALSE,current_pc);
1004 break;
1005 case 15: case 66: // stink cloud
1006 place_spell_pattern(current_pat,target,7,FALSE,current_pc);
1007 break;
1008 case 25: case 44: case 126: // force walls
1009 place_spell_pattern(current_pat,target,4,FALSE,current_pc);
1010 break;
1011 case 37: case 64: // ice walls
1012 place_spell_pattern(current_pat,target,8,FALSE,current_pc);
1013 break;
1014 case 51: // antimagic
1015 place_spell_pattern(current_pat,target,6,FALSE,current_pc);
1016 break;
1017 case 19: case 67: // sleep clouds
1018 place_spell_pattern(current_pat,target,12,FALSE,current_pc);
1019 break;
1020 case 60:
1021 make_quickfire(target.x,target.y);
1022 break;
1023 case 45: // spray fields
1024 r1 = get_ran(1,0,14);
1025 place_spell_pattern(current_pat,target,spray_type_array[r1],FALSE,current_pc);
1026 break;
1027 case 159: // wall of blades
1028 place_spell_pattern(current_pat,target,9,FALSE,current_pc);
1029 break;
1030 case 145: case 119: case 18: // wall dispelling
1031 place_spell_pattern(current_pat,target,11,FALSE,current_pc);
1032 break;
1033 case 42: // Fire barrier
1034 play_sound(68);
1035 r1 = get_ran(3,2,7);
1036 hit_space(target,r1,1,TRUE,TRUE);
1037 make_fire_barrier(target.x,target.y);
1038 if (is_fire_barrier(target.x,target.y))
1039 add_string_to_buf(" You create the barrier. ");
1040 else add_string_to_buf(" Failed.");
1041 break;
1042 case 59: // Force barrier
1043 play_sound(68);
1044 r1 = get_ran(7,2,7);
1045 hit_space(target,r1,1,TRUE,TRUE);
1046 make_force_barrier(target.x,target.y);
1047 if (is_force_barrier(target.x,target.y))
1048 add_string_to_buf(" You create the barrier. ");
1049 else add_string_to_buf(" Failed.");
1050 break;
1052 default: // spells which involve animations
1053 start_missile_anim();
1054 switch (spell_being_cast) {
1056 case 157:
1057 add_missile(target,9,1,0,0);
1058 store_sound = 11;
1059 r1 = min(18,(level * 7) / 10 + 2 * bonus);
1060 place_spell_pattern(rad2,target,130 + r1,TRUE,current_pc);
1061 ashes_loc = target;
1062 break;
1064 case 1: case 31:
1065 r1 = (spell_being_cast == 1) ? get_ran(2,1,4) : get_ran(min(20,level + bonus),1,4);
1066 add_missile(target,6,1,0,0);
1067 do_missile_anim(100,pc_pos[current_pc],11);
1068 hit_space(target,r1,(spell_being_cast == 1) ? 3 : 5,1,0);
1069 break;
1070 case 27: // flame arrows
1071 add_missile(target,4,1,0,0);
1072 r1 = get_ran(2,1,4);
1073 boom_type[i] = 1;
1074 boom_dam[i] = r1;
1075 //hit_space(target,r1,1,1,0);
1076 break;
1077 case 129: // smite
1078 add_missile(target,6,1,0,0);
1079 r1 = get_ran(2,1,5);
1080 boom_type[i] = 5;
1081 boom_dam[i] = r1;
1082 //hit_space(target,r1,5,1,0);
1083 break;
1084 case 114:
1085 r1 = get_ran(min(7,2 + bonus + level / 2),1,4);
1086 add_missile(target,14,1,0,0);
1087 do_missile_anim(100,pc_pos[current_pc],24);
1088 hit_space(target,r1,4,1,0);
1089 break;
1090 case 11:
1091 r1 = get_ran(min(10,1 + level / 3 + bonus),1,6);
1092 add_missile(target,2,1,0,0);
1093 do_missile_anim(100,pc_pos[current_pc],11);
1094 hit_space(target,r1,1,1,0);
1095 break;
1096 case 22: case 141:
1097 r1 = min(9,1 + (level * 2) / 3 + bonus) + 1;
1098 add_missile(target,2,1,0,0);
1099 store_sound = 11;
1100 //do_missile_anim(100,pc_pos[current_pc],11);
1101 if (spell_being_cast == 141)
1102 r1 = (r1 * 14) / 10;
1103 else if (r1 > 10) r1 = (r1 * 8) / 10;
1104 if (r1 <= 0) r1 = 1;
1105 place_spell_pattern(square,target,50 + r1,TRUE,current_pc);
1106 ashes_loc = target;
1107 break;
1108 case 40:
1109 add_missile(target,2,1,0,0);
1110 store_sound = 11;
1111 //do_missile_anim(100,pc_pos[current_pc],11);
1112 r1 = min(12,1 + (level * 2) / 3 + bonus) + 2;
1113 if (r1 > 20)
1114 r1 = (r1 * 8) / 10;
1115 place_spell_pattern(rad2,target,50 + r1,TRUE,current_pc);
1116 ashes_loc = target;
1117 break;
1118 case 48: // kill
1119 add_missile(target,9,1,0,0);
1120 do_missile_anim(100,pc_pos[current_pc],11);
1121 r1 = get_ran(3,0,10) + adven[current_pc].level * 2;
1122 hit_space(target,40 + r1,3,1,0);
1123 break;
1124 case 61: // death arrows
1125 add_missile(target,9,1,0,0);
1126 store_sound = 11;
1127 r1 = get_ran(3,0,10) + adven[current_pc].level + 3 * bonus;
1128 boom_type[i] = 3;
1129 boom_dam[i] = r1;
1130 //hit_space(target,40 + r1,3,1,0);
1131 break;
1132 // summoning spells
1133 case 35: case 16: case 26: case 43: case 58: case 50:
1134 case 63: case 115: case 134: case 143: case 150:
1135 add_missile(target,8,1,0,0);
1136 do_missile_anim(50,pc_pos[current_pc],61);
1137 switch (spell_being_cast) {
1138 case 35: // Simulacrum
1139 r2 = get_ran(3,1,4) + stat_adj(current_pc,2);
1140 if (summon_monster(store_sum_monst,target,r2,2) == FALSE)
1141 add_string_to_buf(" Summon failed.");
1142 break;
1143 case 16: // summon beast
1144 r2 = get_ran(3,1,4) + stat_adj(current_pc,2);
1145 if ((summon < 0) || (summon_monster(summon,target,r2,2) == FALSE))
1146 add_string_to_buf(" Summon failed.");
1147 break;
1148 case 26: // summon 1
1149 r2 = get_ran(4,1,4) + stat_adj(current_pc,2);
1150 if ((summon < 0) || (summon_monster(summon,target,r2,2) == FALSE))
1151 add_string_to_buf(" Summon failed.");
1152 break;
1153 case 43: // summon 2
1154 r2 = get_ran(5,1,4) + stat_adj(current_pc,2);
1155 if ((summon < 0) || (summon_monster(summon,target,r2,2) == FALSE))
1156 add_string_to_buf(" Summon failed.");
1157 break;
1158 case 58: // summon 3
1159 r2 = get_ran(7,1,4) + stat_adj(current_pc,2);
1160 if ((summon < 0) || (summon_monster(summon,target,r2,2) == FALSE))
1161 add_string_to_buf(" Summon failed.");
1162 break;
1163 case 50: // Daemon
1164 r2 = get_ran(5,1,4) + stat_adj(current_pc,2);
1165 if (summon_monster(85,target,r2,2) == FALSE)
1166 add_string_to_buf(" Summon failed.");
1167 break;
1168 case 63: // Rat!
1169 r1 = get_ran(3,1,4);
1170 if (summon_monster(80,target,r1,2) == FALSE)
1171 add_string_to_buf(" Summon failed.");
1172 break;
1174 case 115: // summon spirit
1175 r2 = get_ran(2,1,5) + stat_adj(current_pc,2);
1176 if (summon_monster(125,target,r2,2) == FALSE)
1177 add_string_to_buf(" Summon failed.");
1178 break;
1179 case 134: // s to s
1180 r1 = get_ran(1,0,7);
1181 r2 = get_ran(2,1,5) + stat_adj(current_pc,2);
1182 if (summon_monster((r1 == 1) ? 100 : 99,target,r2,2) == FALSE)
1183 add_string_to_buf(" Summon failed.");
1184 break;
1185 case 143: // host
1186 r2 = get_ran(2,1,4) + stat_adj(current_pc,2);
1187 if (summon_monster((i == 0) ? 126 : 125,target,r2,2) == FALSE)
1188 add_string_to_buf(" Summon failed.");
1189 break;
1190 case 150: // guardian
1191 r2 = get_ran(6,1,4) + stat_adj(current_pc,2);
1192 if (summon_monster(122,target,r2,2) == FALSE)
1193 add_string_to_buf(" Summon failed.");
1194 break;
1196 break;
1199 default:
1200 targ_num = monst_there(target);
1201 if (targ_num > T_M)
1202 add_string_to_buf(" Nobody there ");
1203 else {
1204 cur_monst = &c_town.monst.dudes[targ_num];
1205 if ((cur_monst->attitude % 2 != 1) && (spell_being_cast != 7)
1206 && (spell_being_cast != 34))
1207 make_town_hostile();
1208 store_sound = (spell_being_cast >= 50) ? 24 : 25;
1209 switch (spell_being_cast) {
1210 case 68: // spray acid
1211 store_m_type = 0;
1212 acid_monst(cur_monst,level);
1213 break;
1214 case 69: // paralyze
1215 store_m_type = 9;
1216 charm_monst(cur_monst,0,12,500);
1217 break;
1219 case 7: // monster info
1220 store_m_type = -1;
1221 play_sound(52);
1222 party.m_seen[cur_monst->number] = TRUE;
1223 adjust_monst_menu();
1224 display_monst(0,cur_monst,0);
1225 break;
1226 case 34: // Capture soul
1227 store_m_type = 15;
1228 record_monst(cur_monst);
1229 break;
1231 case 52: // Mindduel!
1232 store_m_type = -1;
1233 if ((cur_monst->m_d.mu == 0) && (cur_monst->m_d.cl == 0))
1234 add_string_to_buf(" Can't duel: no magic.");
1235 else {
1236 item = pc_has_abil(current_pc,159);
1237 if (item >= 24)
1238 add_string_to_buf(" You need a smoky crystal. ");
1239 else {
1240 remove_charge(current_pc,item);
1241 do_mindduel(current_pc,cur_monst);
1244 break;
1246 case 117: // charm
1247 store_m_type = 14;
1248 charm_monst(cur_monst,-1 * (bonus + adven[current_pc].level / 8),0,0);
1249 break;
1251 case 118: // disease
1252 store_m_type = 0;
1253 r1 = get_ran(1,0,1);
1254 disease_monst(cur_monst,2 + r1 + bonus);
1255 break;
1257 case 62:
1258 store_m_type = 14;
1259 cur_monst->m_d.health += 20;
1260 store_sound = 55;
1261 break;
1263 case 13:
1264 store_m_type = 14;
1265 dumbfound_monst(cur_monst,1 + bonus / 3);
1266 store_sound = 53;
1267 break;
1269 case 4:
1270 store_m_type = 11;
1271 scare_monst(cur_monst,get_ran(2 + bonus,1,6));
1272 store_sound = 54;
1273 break;
1274 case 24:
1275 store_m_type = 11;
1276 scare_monst(cur_monst,get_ran(min(20,adven[current_pc].level / 2 + bonus),1,
1277 ((spell_being_cast == 24) ? 8 : 6)));
1278 store_sound = 54;
1279 break;
1281 case 12:
1282 store_m_type = 11;
1283 r1 = get_ran(1,0,1);
1284 slow_monst(cur_monst,2 + r1 + bonus);
1285 break;
1287 case 10: case 36:
1288 store_m_type = (spell_being_cast == 36) ? 4 : 11;
1289 poison_monst(cur_monst,2 + bonus / 2);
1290 store_sound = 55;
1291 break;
1292 case 49: // Paralysis
1293 store_m_type = 9;
1294 charm_monst(cur_monst,-10,12,1000);
1295 break;
1296 case 30:
1297 store_m_type = 11;
1298 poison_monst(cur_monst,4 + bonus / 2);
1299 store_sound = 55;
1300 break;
1301 case 46:
1302 store_m_type = 11;
1303 poison_monst(cur_monst,8 + bonus / 2);
1304 store_sound = 55;
1305 break;
1307 case 109: // stumble
1308 store_m_type = 8;
1309 curse_monst(cur_monst,4 + bonus);
1310 break;
1312 case 112:
1313 store_m_type = 8;
1314 curse_monst(cur_monst,2 + bonus);
1315 break;
1317 case 122:
1318 store_m_type = 8;
1319 curse_monst(cur_monst,2 + adven[current_pc].level / 2);
1320 break;
1322 case 103: case 132:
1323 if (cur_monst->m_d.m_type != 8) {
1324 add_string_to_buf(" Not undead. ");
1325 store_m_type = -1;
1326 break;
1328 store_m_type = 8;
1329 r1 = get_ran(1,0,90);
1330 if (r1 > hit_chance[minmax(0,19,bonus * 2 + level * 4 - (cur_monst->m_d.level / 2) + 3)])
1331 add_string_to_buf(" Monster resisted. ");
1332 else {
1333 r1 = get_ran((spell_being_cast == 103) ? 2 : 6, 1, 14);
1335 hit_space(cur_monst->m_loc,r1,4,0,current_pc);
1337 break;
1339 case 155:
1340 if (cur_monst->m_d.m_type != 7) {
1341 add_string_to_buf(" Not a demon. ");
1342 store_m_type = -1;
1343 break;
1345 r1 = get_ran(1,0,100);
1346 if (r1 > hit_chance[minmax(0,19,level * 4 - cur_monst->m_d.level + 10)])
1347 add_string_to_buf(" Demon resisted. ");
1348 else {
1349 r1 = get_ran(8 + bonus * 2, 1, 11);
1350 if (PSD[4][0] == 3) // anama
1351 r1 += 25;
1352 //play_sound(53);
1353 hit_space(cur_monst->m_loc,r1,4,0,current_pc);
1355 break;
1357 if (store_m_type >= 0)
1358 add_missile(target,store_m_type,1,
1359 14 * (cur_monst->m_d.x_width - 1),18 * (cur_monst->m_d.y_width - 1));
1362 break;
1368 do_missile_anim((num_targets > 1) ? 35 : 60,pc_pos[current_pc],store_sound);
1370 // process mass damage
1371 for (i = 0; i < 8; i++)
1372 if (boom_dam[i] > 0)
1373 hit_space(boom_targ[i],boom_dam[i],boom_type[i],1,0);
1375 if (ashes_loc.x > 0)
1376 make_sfx(ashes_loc.x,ashes_loc.y,6);
1378 do_explosion_anim(5,0);
1380 end_missile_anim();
1382 handle_marked_damage();
1383 combat_posing_monster = current_working_monster = -1;
1385 print_buf();
1388 void handle_marked_damage()
1390 short i;
1392 for (i = 0; i < 6; i++)
1393 if (pc_marked_damage[i] > 0)
1395 damage_pc(i,pc_marked_damage[i],10,-1);
1396 pc_marked_damage[i] = 0;
1398 for (i = 0; i < T_M; i++)
1399 if (monst_marked_damage[i] > 0)
1401 damage_monst(i, current_pc, monst_marked_damage[i], 0, 9);
1403 monst_marked_damage[i] = 0;
1407 void load_missile()
1409 short i,bow = 24,arrow = 24,thrown = 24,crossbow = 24,bolts = 24,no_ammo = 24,m_type = 0;
1411 for (i = 0; i < 24; i++) {
1412 if ((adven[current_pc].equip[i] == TRUE) &&
1413 (adven[current_pc].items[i].variety == 6))
1414 thrown = i;
1415 if ((adven[current_pc].equip[i] == TRUE) &&
1416 (adven[current_pc].items[i].variety == 4))
1417 bow = i;
1418 if ((adven[current_pc].equip[i] == TRUE) &&
1419 (adven[current_pc].items[i].variety == 5))
1420 arrow = i;
1421 if ((adven[current_pc].equip[i] == TRUE) &&
1422 (adven[current_pc].items[i].variety == 23))
1423 crossbow = i;
1424 if ((adven[current_pc].equip[i] == TRUE) &&
1425 (adven[current_pc].items[i].variety == 24))
1426 bolts = i;
1427 if ((adven[current_pc].equip[i] == TRUE) &&
1428 (adven[current_pc].items[i].variety == 25))
1429 no_ammo = i;
1432 if (thrown < 24) {
1433 ammo_inv_slot = thrown;
1434 add_string_to_buf("Throw: Select a target. ");
1435 add_string_to_buf(" (Hit 's' to cancel.)");
1436 overall_mode = 13;
1437 current_spell_range = 8;
1438 current_pat = single;
1440 else if (((bolts < 24) && (bow < 24)) || ((arrow < 24) && (crossbow < 24))) {
1441 add_string_to_buf("Fire: Wrong ammunition. ");
1443 else if ((arrow == 24) && (bow < 24)) {
1444 add_string_to_buf("Fire: Equip some arrows. ");
1446 else if ((arrow < 24) && (bow < 24)) {
1447 missile_inv_slot = bow;
1448 ammo_inv_slot = arrow;
1449 overall_mode = 12;
1450 add_string_to_buf("Fire: Select a target. ");
1451 add_string_to_buf(" (Hit 's' to cancel.)");
1452 current_spell_range = 12;
1453 current_pat = single;
1455 else if ((bolts < 24) && (crossbow < 24)) {
1456 missile_inv_slot = crossbow;
1457 ammo_inv_slot = bolts;
1458 overall_mode = 12;
1459 add_string_to_buf("Fire: Select a target. ");
1460 add_string_to_buf(" (Hit 's' to cancel.)");
1461 current_spell_range = 12;
1462 current_pat = single;
1464 else if (no_ammo < 24) {
1465 missile_inv_slot = no_ammo;
1466 ammo_inv_slot = no_ammo;
1467 overall_mode = 12;
1468 add_string_to_buf("Fire: Select a target. ");
1469 add_string_to_buf(" (Hit 's' to cancel.)");
1470 current_spell_range = 12;
1471 current_pat = single;
1473 else add_string_to_buf("Fire: Equip a missile. ");
1476 void fire_missile(location target)
1478 short r1, r2, skill, dam, dam_bonus, hit_bonus, range, targ_monst, spec_dam = 0,poison_amt = 0;
1479 short skill_item,m_type = 0;
1480 creature_data_type *cur_monst;
1481 Boolean exploding = FALSE;
1483 skill = (overall_mode == 12) ? adven[current_pc].skills[7] : adven[current_pc].skills[8];
1484 range = (overall_mode == 12) ? 12 : 8;
1485 dam = adven[current_pc].items[ammo_inv_slot].item_level;
1486 dam_bonus = adven[current_pc].items[ammo_inv_slot].bonus + minmax(-8,8,adven[current_pc].status[1]);
1487 hit_bonus = (overall_mode == 12) ? adven[current_pc].items[missile_inv_slot].bonus : 0;
1488 hit_bonus += stat_adj(current_pc,1) - can_see(pc_pos[current_pc],target,0)
1489 + minmax(-8,8,adven[current_pc].status[1]);
1490 if ((skill_item = pc_has_abil_equip(current_pc,41)) < 24) {
1491 hit_bonus += adven[current_pc].items[skill_item].ability_strength / 2;
1492 dam_bonus += adven[current_pc].items[skill_item].ability_strength / 2;
1495 // race adj.
1496 if (adven[current_pc].race == 1)
1497 hit_bonus += 2;
1499 if (adven[current_pc].items[ammo_inv_slot].ability == 172)
1500 exploding = TRUE;
1501 if (adven[current_pc].items[ammo_inv_slot].variety != 25) {
1502 if (adven[current_pc].items[ammo_inv_slot].ability != 170)
1503 adven[current_pc].items[ammo_inv_slot].charges--;
1504 else adven[current_pc].items[ammo_inv_slot].charges = 1;
1505 if ((pc_has_abil_equip(current_pc,11) < 24) && (adven[current_pc].items[ammo_inv_slot].ability != 170))
1506 adven[current_pc].items[ammo_inv_slot].charges--;
1507 if (adven[current_pc].items[ammo_inv_slot].charges <= 0)
1508 take_item(current_pc,ammo_inv_slot);
1511 // First, some missiles do special things
1512 if (exploding == TRUE) {
1513 take_ap((overall_mode == 12) ? 3 : 2);
1514 add_string_to_buf(" The arrow explodes! ");
1515 run_a_missile(pc_pos[current_pc],target,2,1,5,
1516 0,0,100);
1517 start_missile_anim();
1518 add_missile(target,2,1, 0, 0);
1519 do_missile_anim(100,pc_pos[current_pc], 5);
1520 place_spell_pattern(rad2,target,
1521 50 + adven[current_pc].items[ammo_inv_slot].ability_strength * 2,TRUE,current_pc);
1522 do_explosion_anim(5,0);
1523 end_missile_anim();
1524 handle_marked_damage();
1525 return;
1528 if (dist(pc_pos[current_pc],target) > range)
1529 add_string_to_buf(" Out of range.");
1530 else if (can_see(pc_pos[current_pc],target,0) == 5)
1531 add_string_to_buf(" Can't see target. ");
1532 else {
1533 combat_posing_monster = current_working_monster = current_pc;
1534 draw_terrain(2);
1535 void_sanctuary(current_pc);
1536 //play_sound((overall_mode == 12) ? 12 : 14);
1537 take_ap((overall_mode == 12) ? 3 : 2);
1538 missile_firer = current_pc;
1539 r1 = get_ran(1,0,100) - 5 * hit_bonus - 10;
1540 r1 += 5 * (adven[current_pc].status[6] / 3);
1541 r2 = get_ran(1,1,dam) + dam_bonus;
1542 sprintf ((char *) create_line, "%s fires.",(char *) adven[current_pc].name); // debug
1543 add_string_to_buf((char *) create_line);
1545 switch (overall_mode) {
1546 case 13:
1547 switch (adven[current_pc].items[ammo_inv_slot].item_level) {
1548 case 7:m_type = 10;break;
1549 case 4:m_type = 1;break;
1550 case 8:m_type = 5;break;
1551 case 9:m_type = 7;break;
1552 default:m_type = 10;break;
1554 break;
1555 case 12: case 14:
1556 m_type = (is_magic(adven[current_pc].items[ammo_inv_slot]) == TRUE) ? 4 : 3;
1557 break;
1559 run_a_missile(pc_pos[current_pc],target,m_type,1,(overall_mode == 12) ? 12 : 14,
1560 0,0,100);
1562 if (r1 > hit_chance[skill])
1563 add_string_to_buf(" Missed.");
1564 else if ((targ_monst = monst_there(target)) < T_M) {
1565 cur_monst = &c_town.monst.dudes[targ_monst];
1566 spec_dam = calc_spec_dam(adven[current_pc].items[ammo_inv_slot].ability,
1567 adven[current_pc].items[ammo_inv_slot].ability_strength,cur_monst);
1568 if (adven[current_pc].items[ammo_inv_slot].ability == 176) {
1569 ASB(" There is a flash of light.");
1570 cur_monst->m_d.health += r2;
1572 else damage_monst(targ_monst, current_pc, r2, spec_dam, 1300);
1574 //if (adven[current_pc].items[ammo_inv_slot].ability == 33)
1575 // hit_space(cur_monst->m_loc,get_ran(3,1,6),1,1,1);
1577 // poison
1578 if ((adven[current_pc].status[0] > 0) && (adven[current_pc].weap_poisoned == ammo_inv_slot)) {
1579 poison_amt = adven[current_pc].status[0];
1580 if (pc_has_abil_equip(current_pc,51) < 24)
1581 poison_amt++;
1582 poison_monst(cur_monst,poison_amt);
1586 else hit_space(target,r2,0,1,0);
1590 combat_posing_monster = current_working_monster = -1;
1591 adven[current_pc].status[0] = move_to_zero(adven[current_pc].status[0]);
1592 print_buf();////
1595 // Select next active PC and, if necessary, run monsters
1596 // if monsters go or PC switches (i.e. if need redraw above), return TRUE
1597 Boolean combat_next_step()
1599 Boolean need_stat_reprint = FALSE,to_return = FALSE;
1600 short store_pc; // will print current pc name is active pc changes
1602 store_pc = current_pc;
1603 while (pick_next_pc() == TRUE) {
1604 combat_run_monst();
1605 set_pc_moves();
1606 to_return = TRUE;
1607 // Safety valve
1608 if (party_toast() == TRUE)
1609 return TRUE;
1611 pick_next_pc();
1612 if (current_pc != store_pc)
1613 to_return = TRUE;
1614 center = pc_pos[current_pc];
1615 //if (ensure_redraw == TRUE)
1616 // draw_terrain(0);
1618 adjust_spell_menus();
1620 // In case running monsters affected active PC...
1621 /* if (adven[current_pc].status[3] < 0)
1622 this_pc_hasted = FALSE;
1623 if ((adven[current_pc].main_status != 1) ||
1624 ((adven[current_pc].status[3] < 0) && (party.age % 2 == 0)))
1625 pick_next_pc();
1626 center = pc_pos[current_pc]; */
1628 if ((combat_active_pc == 6) && (current_pc != store_pc)) {
1629 sprintf((char *)create_line, "Active: %s (#%d, %d ap.) ",
1630 adven[current_pc].name,current_pc + 1,pc_moves[current_pc]);
1631 add_string_to_buf((char *)create_line);
1632 print_buf();
1634 if ((current_pc != store_pc) || (to_return == TRUE)) {
1635 put_pc_screen();
1636 set_stat_window(current_pc);
1638 return to_return;
1641 // Find next active PC, return TRUE is monsters need running, and run monsters is slow spells
1642 // active
1643 Boolean pick_next_pc()
1645 Boolean store = FALSE;
1647 if (current_pc == 6)
1648 current_pc = 0;
1650 // If current pc isn't active, fry its moves
1651 if ((combat_active_pc < 6) && (combat_active_pc != current_pc))
1652 pc_moves[current_pc] = 0;
1654 // Find next PC with moves
1655 while ((pc_moves[current_pc] <= 0) && (current_pc < 6)) {
1656 current_pc++;
1657 if ((combat_active_pc < 6) && (combat_active_pc != current_pc))
1658 pc_moves[current_pc] = 0;
1661 // If run out of PC's, return to start and try again
1662 if (current_pc == 6) {
1663 current_pc = 0;
1664 while ((pc_moves[current_pc] <= 0) && (current_pc < 6)) {
1665 current_pc++;
1666 if ((combat_active_pc < 6) && (combat_active_pc != current_pc))
1667 pc_moves[current_pc] = 0;
1669 if (current_pc == 6) {
1670 store = TRUE;
1671 current_pc = 0;
1675 return store;
1679 void combat_run_monst()
1681 short i,j,k,num_monst,item,item_level;
1682 creature_data_type *monst;
1683 Boolean update_stat = FALSE;
1686 monsters_going = TRUE;
1687 do_monster_turn();
1688 monsters_going = FALSE;
1690 process_fields();
1691 party.light_level = move_to_zero(party.light_level);
1692 if ((which_combat_type == 1) && (c_town.town.lighting == 2))
1693 party.light_level = max (0,party.light_level - 9);
1694 if (c_town.town.lighting == 3)
1695 party.light_level = 0;
1697 party.stuff_done[305][2] = move_to_zero(party.stuff_done[305][2]);
1698 party.stuff_done[305][3] = move_to_zero(party.stuff_done[305][3]);
1700 // decrease monster present counter
1701 party.stuff_done[305][9] = move_to_zero(party.stuff_done[305][9]);
1703 dump_gold(1);
1705 party.age++;
1706 if (party.age % 4 == 0)
1707 for (i = 0; i < 6; i++) {
1708 if ((adven[i].status[1] != 0) || (adven[i].status[3] != 0))
1709 update_stat = TRUE;
1710 adven[i].status[1] = move_to_zero(adven[i].status[1]);
1711 adven[i].status[3] = move_to_zero(adven[i].status[3]);
1712 party.stuff_done[305][0] = move_to_zero(party.stuff_done[305][0]);
1713 if ((item = pc_has_abil_equip(i,50)) < 24) {
1714 update_stat = TRUE;
1715 heal_pc(i,get_ran(1,0,adven[i].items[item].item_level + 1));
1718 for (i = 0; i < 6; i++)
1719 if (adven[i].main_status == 1) {
1720 if ((adven[i].status[4] != 0) || (adven[i].status[5] != 0)
1721 || (adven[i].status[8] != 0)|| (adven[i].status[10] != 0)
1722 || (adven[i].status[11] != 0)|| (adven[i].status[12] != 0))
1723 update_stat = TRUE;
1725 adven[i].status[4] = move_to_zero(adven[i].status[4]);
1726 adven[i].status[5] = move_to_zero(adven[i].status[5]);
1727 adven[i].status[8] = move_to_zero(adven[i].status[8]);
1728 adven[i].status[10] = move_to_zero(adven[i].status[10]);
1729 adven[i].status[11] = move_to_zero(adven[i].status[11]);
1730 adven[i].status[12] = move_to_zero(adven[i].status[12]);
1732 // Do special items
1733 if (((item_level = get_prot_level(i,47)) > 0)
1734 && (get_ran(1,0,10) == 5)) {
1735 update_stat = TRUE;
1736 adven[i].status[3] += item_level / 2;
1737 add_string_to_buf("An item hastes you!");
1739 if ((item_level = get_prot_level(i,46)) > 0) {
1740 if (get_ran(1,0,10) == 5) {
1741 update_stat = TRUE;
1742 adven[i].status[1] += item_level / 2;
1743 add_string_to_buf("An item blesses you!");
1750 special_increase_age();
1751 push_things();
1753 if (party.age % 2 == 0)
1754 do_poison();
1755 if (party.age % 3 == 0)
1756 handle_disease();
1757 handle_acid();
1759 if (update_stat == TRUE)
1760 put_pc_screen();
1765 void do_monster_turn()
1767 Boolean acted_yet, had_monst = FALSE,printed_poison = FALSE,printed_disease = FALSE,printed_acid = FALSE;
1768 Boolean redraw_not_yet_done = TRUE;
1769 location monst_loc,targ_space = {0,0},move_targ,l;
1770 short i,j,k,num_monst,num_tries = 0, target,r1,move_target;
1771 creature_data_type *cur_monst;
1772 long dummy;
1773 Boolean pc_adj[6];
1774 short abil_range[40] = {0,6,8,8,10, 10,10,8,6,8, 6,0,0,0,6, 0,0,0,0,4, 10,0,0,6,0,
1775 0,0,0,0,0, 0,0,8,6,9, 0,0,0,0,0};
1776 short abil_odds[40] = {0,5,7,6,6, 5,5,6,6,6, 6,0,0,0,4, 0,0,0,0,4, 8,0,0,7,0,
1777 0,0,0,0,0, 0,0,7,5,6, 0,0,0,0,0};
1779 monsters_going = TRUE; // This affects how graphics are drawn.
1781 num_monst = T_M;
1782 if (overall_mode < 10)
1783 which_combat_type = 1;
1785 for (i = 0; i < num_monst; i++) { // Give monsters ap's, check activity
1787 cur_monst = &c_town.monst.dudes[i];
1789 // See if hostile monster notices party, during combat
1790 if ((cur_monst->active == 1) && (cur_monst->attitude % 2 == 1) && (overall_mode == 10)) {
1791 r1 = get_ran(1,1,100); // Check if see PCs first
1792 r1 += (party.stuff_done[305][0] > 0) ? 45 : 0;
1793 r1 += can_see(cur_monst->m_loc,closest_pc_loc(cur_monst->m_loc),0) * 10;
1794 if (r1 < 50)
1795 cur_monst->active = 2;
1797 for (j = 0; j < T_M; j++)
1798 if (monst_near(j,cur_monst->m_loc,5,1) == TRUE) {
1799 cur_monst->active = 2;
1802 if ((cur_monst->active == 1) && (cur_monst->attitude % 2 == 1)) {
1803 // Now it looks for PC-friendly monsters
1804 // dist check is for efficiency
1805 for (j = 0; j < T_M; j++)
1806 if ((c_town.monst.dudes[j].active > 0) &&
1807 (c_town.monst.dudes[j].attitude % 2 != 1) &&
1808 (dist(cur_monst->m_loc,c_town.monst.dudes[j].m_loc) <= 6) &&
1809 (can_see(cur_monst->m_loc,c_town.monst.dudes[j].m_loc,0) < 5))
1810 cur_monst->active = 2;
1813 // See if friendly, fighting monster see hostile monster. If so, make mobile
1814 // dist check is for efficiency
1815 if ((cur_monst->active == 1) && (cur_monst->attitude == 2)) {
1816 for (j = 0; j < T_M; j++)
1817 if ((c_town.monst.dudes[j].active > 0) && (c_town.monst.dudes[j].attitude % 2 == 1) &&
1818 (dist(cur_monst->m_loc,c_town.monst.dudes[j].m_loc) <= 6)
1819 && (can_see(cur_monst->m_loc,c_town.monst.dudes[j].m_loc,0) < 5)) {
1820 cur_monst->active = 2;
1821 cur_monst->mobile = TRUE;
1824 // End of seeing if monsters see others
1826 cur_monst->m_d.ap = 0;
1827 if (cur_monst->active == 2) { // Begin action loop for angry, active monsters
1828 // First note that hostile monsters are around.
1829 if (cur_monst->attitude % 2 == 1)
1830 party.stuff_done[305][9] = 30;
1832 // Give monster its action points
1833 cur_monst->m_d.ap = cur_monst->m_d.speed;
1834 if (is_town())
1835 cur_monst->m_d.ap = max(1,cur_monst->m_d.ap / 3);
1836 if (party.age % 2 == 0)
1837 if (cur_monst->m_d.status[3] < 0)
1838 cur_monst->m_d.ap = 0;
1839 if (cur_monst->m_d.ap > 0) { // adjust for webs
1840 cur_monst->m_d.ap = max(0,cur_monst->m_d.ap - cur_monst->m_d.status[6] / 2);
1841 if (cur_monst->m_d.ap == 0)
1842 cur_monst->m_d.status[6] = max(0,cur_monst->m_d.status[6] - 2);
1844 if (cur_monst->m_d.status[3] > 0)
1845 cur_monst->m_d.ap *= 2;
1847 if ((cur_monst->m_d.status[11] > 0) || (cur_monst->m_d.status[12] > 0))
1848 cur_monst->m_d.ap = 0;
1849 if (in_scen_debug == TRUE)
1850 cur_monst->m_d.ap = 0;
1851 center_on_monst = FALSE;
1853 // Now take care of summoned monsters
1854 if (cur_monst->active > 0) {
1855 if ((cur_monst->summoned % 100) == 1) {
1856 cur_monst->active = 0;
1857 cur_monst->m_d.ap = 0;
1858 monst_spell_note(cur_monst->number,17);
1860 cur_monst->summoned = move_to_zero(cur_monst->summoned);
1865 for (i = 0; i < num_monst; i++) { // Begin main monster loop, do monster actions
1866 // If party dead, no point
1867 if (party_toast() == TRUE)
1868 return;
1870 futzing = 0; // assume monster is fresh
1872 cur_monst = &c_town.monst.dudes[i];
1875 for (j = 0; j < 6; j++)
1876 if ((adven[j].main_status == 1) && (monst_adjacent(pc_pos[j],i) == TRUE))
1877 pc_adj[j] = TRUE;
1878 else pc_adj[j] = FALSE;
1882 while ((cur_monst->m_d.ap > 0) && (cur_monst->active > 0)) { // Spend each action point
1884 if (is_combat()) { // Pick target. If in town, target already picked
1885 // in do_monsters
1886 target = monst_pick_target(i);
1887 target = switch_target_to_adjacent(i,target);
1888 if (target < 6)
1889 targ_space = pc_pos[target];
1890 else if (target != 6)
1891 targ_space = c_town.monst.dudes[target - 100].m_loc;
1892 monst_target[i] = target;
1894 else {
1895 if (monst_target[i] < 6)
1896 targ_space = c_town.p_loc;
1897 else if (monst_target[i] != 6)
1898 targ_space = c_town.monst.dudes[monst_target[i] - 100].m_loc;
1901 // sprintf((char *)create_line," %d targets %d.",i,target);
1902 // add_string_to_buf((char *) create_line);
1904 if ((monst_target[i] < 0) || ((monst_target[i] > 5) && (monst_target[i] < 100)))
1905 monst_target[i] = 6;
1906 target = monst_target[i];
1908 // Now if in town and monster about to attack, do a redraw, so we see monster
1909 // in right place
1910 if ((target != 6) && (is_town() == TRUE) && (redraw_not_yet_done == TRUE)
1911 && (party_can_see_monst(i) == TRUE)) {
1912 draw_terrain(0);
1913 redraw_not_yet_done = FALSE;
1916 // Draw w. monster in center, if can see
1917 if ((cur_monst->m_d.ap > 0) && (is_combat() == TRUE)
1918 // First make sure it has a target and is close, if not, don't bother
1919 && (cur_monst->attitude > 0) && (cur_monst->m_d.picture_num > 0)
1920 && ((target != 6) || (cur_monst->attitude % 2 == 1))
1921 && (party_can_see_monst(i) == TRUE) ) {
1922 center_on_monst = TRUE;
1923 center = cur_monst->m_loc;
1924 draw_terrain(0);
1925 pause((PSD[306][6] == 3) ? 9 : PSD[306][6]);
1928 combat_posing_monster = current_working_monster = 100 + i;
1930 acted_yet = FALSE;
1933 // Now the monster, if evil, looks at the situation and maybe picks a tactic.
1934 // This only happens when there is >1 a.p. left, and tends to involve
1935 // running to a nice position.
1936 current_monst_tactic = 0;
1937 if ((target != 6) && (cur_monst->m_d.ap > 1) && (futzing == 0)) {
1938 l = closest_pc_loc(cur_monst->m_loc);
1939 if (((cur_monst->m_d.mu > 0) || (cur_monst->m_d.cl > 0)) &&
1940 (dist(cur_monst->m_loc,l) < 5) && (monst_adjacent(l,i) == FALSE))
1941 current_monst_tactic = 1; // this means flee
1944 if ( (((cur_monst->m_d.spec_skill > 0) && (cur_monst->m_d.spec_skill < 4))
1945 || (cur_monst->m_d.spec_skill == 20)) && // Archer?
1946 (dist(cur_monst->m_loc,targ_space) < 6) &&
1947 (monst_adjacent(targ_space,i) == FALSE))
1948 current_monst_tactic = 1; // this means flee
1952 // flee
1953 if ((monst_target[i] < 6) && (((cur_monst->m_d.morale <= 0)
1954 && (cur_monst->m_d.spec_skill != 13) && (cur_monst->m_d.m_type != 8))
1955 || (current_monst_tactic == 1))) {
1956 if (cur_monst->m_d.morale < 0)
1957 cur_monst->m_d.morale++;
1958 if (cur_monst->m_d.health > 50)
1959 cur_monst->m_d.morale++;
1960 r1 = get_ran(1,1,6);
1961 if (r1 == 3)
1962 cur_monst->m_d.morale++;
1963 /*crash*/ if ((adven[monst_target[i]].main_status == 1) && (cur_monst->mobile == TRUE)) {
1964 acted_yet = flee_party (i,cur_monst->m_loc,targ_space);
1965 if (acted_yet == TRUE) take_m_ap(1,cur_monst);
1968 if ((target != 6) && (cur_monst->attitude > 0)
1969 && (monst_can_see(i,targ_space) == TRUE)
1970 && (can_see_monst(targ_space,i) == TRUE)) { // Begin spec. attacks
1972 // sprintf((char *)create_line,"%d: %d %d %d",i,cur_monst->m_d.breath,cur_monst->m_d.mu,cur_monst->m_d.cl);
1973 // add_string_to_buf((char *)create_line);
1975 // Breathe (fire)
1976 if ( (cur_monst->m_d.breath > 0)
1977 && (get_ran(1,1,8) < 4) && (acted_yet == FALSE)) {
1978 //print_nums(cur_monst->m_d.breath,cur_monst->m_d.breath_type,dist(cur_monst->m_loc,targ_space) );
1979 if ((target != 6)
1980 && (dist(cur_monst->m_loc,targ_space) <= 8)) {
1981 acted_yet = monst_breathe(cur_monst,targ_space,cur_monst->m_d.breath_type);
1982 had_monst = TRUE;
1983 acted_yet = TRUE;
1984 take_m_ap(4,cur_monst);
1987 // Mage spell
1988 if ((cur_monst->m_d.mu > 0) && (get_ran(1,1,10) < ((cur_monst->m_d.cl > 0) ? 6 : 9) )
1989 && (acted_yet == FALSE)) {
1990 if (((monst_adjacent(targ_space,i) == FALSE) || (get_ran(1,0,2) < 2) || (cur_monst->number >= 160)
1991 || (cur_monst->m_d.level > 9))
1992 && (dist(cur_monst->m_loc,targ_space) <= 10)) {
1993 acted_yet = monst_cast_mage(cur_monst,target);
1994 had_monst = TRUE;
1995 acted_yet = TRUE;
1996 take_m_ap(5,cur_monst);
1999 // Priest spell
2000 if ((cur_monst->m_d.cl > 0) && (get_ran(1,1,8) < 7) && (acted_yet == FALSE)) {
2001 if (((monst_adjacent(targ_space,i) == FALSE) || (get_ran(1,0,2) < 2) || (cur_monst->m_d.level > 9))
2002 && (dist(cur_monst->m_loc,targ_space) <= 10)) {
2003 acted_yet = monst_cast_priest(cur_monst,target);
2004 had_monst = TRUE;
2005 acted_yet = TRUE;
2006 take_m_ap(4,cur_monst);
2010 // Missile
2011 if ((abil_range[cur_monst->m_d.spec_skill] > 0) // breathing gas short range
2012 && (get_ran(1,1,8) < abil_odds[cur_monst->m_d.spec_skill]) && (acted_yet == FALSE)) {
2013 // Don't fire when adjacent, unless non-gaze magical attack
2014 if (((monst_adjacent(targ_space,i) == FALSE) ||
2015 ((cur_monst->m_d.spec_skill > 7) && (cur_monst->m_d.spec_skill != 20)
2016 && (cur_monst->m_d.spec_skill != 33)))
2017 // missile range
2018 && (dist(cur_monst->m_loc,targ_space) <= abil_range[cur_monst->m_d.spec_skill])) {
2019 print_monst_name(cur_monst->number);
2020 monst_fire_missile(i,cur_monst->m_d.skill,cur_monst->m_d.status[1],
2021 cur_monst->m_d.spec_skill,cur_monst->m_loc,target);
2023 // Vapors don't count as action
2024 if ((cur_monst->m_d.spec_skill == 11) || (cur_monst->m_d.spec_skill == 7) ||
2025 (cur_monst->m_d.spec_skill == 20))
2026 take_m_ap(2,cur_monst);
2027 else if (cur_monst->m_d.spec_skill == 10)
2028 take_m_ap(1,cur_monst);
2029 else take_m_ap(3,cur_monst);
2030 had_monst = TRUE;
2031 acted_yet = TRUE;
2034 } // Special attacks
2036 // Attack pc
2037 if ((monst_target[i] < 6) && (adven[monst_target[i]].main_status == 1)
2038 && (monst_adjacent(targ_space,i) == TRUE) && (cur_monst->attitude % 2 == 1)
2039 && (acted_yet == FALSE)) {
2040 monster_attack_pc(i,monst_target[i]);
2041 take_m_ap(4,cur_monst);
2042 acted_yet = TRUE;
2043 had_monst = TRUE;
2045 // Attack monst
2046 if ((monst_target[i] >= 100) && (c_town.monst.dudes[monst_target[i] - 100].active > 0)
2047 && (monst_adjacent(targ_space,i) == TRUE) && (cur_monst->attitude > 0)
2048 && (acted_yet == FALSE)) {
2049 monster_attack_monster(i,monst_target[i] - 100);
2050 take_m_ap(4,cur_monst);
2051 acted_yet = TRUE;
2052 had_monst = TRUE;
2055 if (acted_yet == TRUE) {
2056 print_buf();
2057 if (j == 0)
2058 pause(8);
2059 FlushEvents(2);
2062 if (overall_mode == 10) {
2063 if ((acted_yet == FALSE) && (cur_monst->mobile == TRUE)) { // move monst
2064 move_target = (monst_target[i] != 6) ? monst_target[i] : closest_pc(cur_monst->m_loc);
2065 if (monst_hate_spot(i,&move_targ) == TRUE) // First, maybe move out of dangerous space
2066 seek_party (i,cur_monst->m_loc,move_targ);
2067 else { // spot is OK, so go nuts
2068 if ((cur_monst->attitude % 2 == 1) && (move_target < 6)) // Monsters seeking party do so
2069 if (adven[move_target].main_status == 1) {
2070 seek_party (i,cur_monst->m_loc,pc_pos[move_target]);
2071 for (k = 0; k < 6; k++)
2072 if ((pc_parry[k] > 99) && (monst_adjacent(pc_pos[k],i) == TRUE)
2073 && (cur_monst->active > 0)) {
2074 pc_parry[k] = 0;
2075 pc_attack(k,i);
2079 if (move_target >= 100) // Monsters seeking monsters do so
2080 if (c_town.monst.dudes[move_target - 100].active > 0) {
2081 seek_party (i,cur_monst->m_loc,c_town.monst.dudes[move_target - 100].m_loc);
2082 for (k = 0; k < 6; k++)
2083 if ((pc_parry[k] > 99) && (monst_adjacent(pc_pos[k],i) == TRUE)
2084 && (cur_monst->active > 0) && (cur_monst->attitude % 2 == 1)) {
2085 pc_parry[k] = 0;
2086 pc_attack(k,i);
2090 if (cur_monst->attitude == 0) {
2091 acted_yet = rand_move (i);
2092 futzing++;
2095 take_m_ap(1,cur_monst);
2097 if ((acted_yet == FALSE) && (cur_monst->mobile == FALSE)) { // drain action points
2098 take_m_ap(1,cur_monst);
2099 futzing++;
2102 else if (acted_yet == FALSE) {
2103 take_m_ap(1,cur_monst);
2104 futzing++;
2107 // pcs attack any fleeing monsters
2108 if ((overall_mode >= 10) && (overall_mode < 20))
2109 for (k = 0; k < 6; k++)
2110 if ((adven[k].main_status == 1) && (monst_adjacent(pc_pos[k],i) == FALSE)
2111 && (pc_adj[k] == TRUE) && (cur_monst->attitude % 2 == 1) && (cur_monst->active > 0) &&
2112 (adven[k].status[8] == 0)) {
2113 combat_posing_monster = current_working_monster = k;
2114 pc_attack(k,i);
2115 combat_posing_monster = current_working_monster = 100 + i;
2116 pc_adj[k] = FALSE;
2119 // Place fields for monsters that create them. Only done when monst sees foe
2120 if ((target != 6) && (can_see(cur_monst->m_loc,targ_space,0) < 5)) { ////
2121 if ((cur_monst->m_d.radiate_1 == 1) && (get_ran(1,0,100) < cur_monst->m_d.radiate_2))
2122 place_spell_pattern(square,cur_monst->m_loc,5,FALSE,7);
2123 if ((cur_monst->m_d.radiate_1 == 2) && (get_ran(1,0,100) < cur_monst->m_d.radiate_2))
2124 place_spell_pattern(square,cur_monst->m_loc,8,FALSE,7);
2125 if ((cur_monst->m_d.radiate_1 == 3) && (get_ran(1,0,100) < cur_monst->m_d.radiate_2))
2126 place_spell_pattern(square,cur_monst->m_loc,4,FALSE,7);
2127 if ((cur_monst->m_d.radiate_1 == 4) && (get_ran(1,0,100) < cur_monst->m_d.radiate_2))
2128 place_spell_pattern(square,cur_monst->m_loc,6,FALSE,7);
2129 if ((cur_monst->m_d.radiate_1 == 5) && (get_ran(1,0,100) < cur_monst->m_d.radiate_2))
2130 place_spell_pattern(square,cur_monst->m_loc,12,FALSE,7);
2131 if ((cur_monst->m_d.radiate_1 == 6) && (get_ran(1,0,100) < cur_monst->m_d.radiate_2))
2132 place_spell_pattern(square,cur_monst->m_loc,7,FALSE,7);
2133 if ((cur_monst->m_d.radiate_1 == 10) && (get_ran(1,0,100) < 5)){
2134 if (summon_monster(cur_monst->m_d.radiate_2,
2135 cur_monst->m_loc,130,cur_monst->attitude) == TRUE)
2136 {monst_spell_note(cur_monst->number,33); play_sound(61);}
2138 if ((cur_monst->m_d.radiate_1 == 11) && (get_ran(1,0,100) < 20)){
2139 if (summon_monster(cur_monst->m_d.radiate_2,
2140 cur_monst->m_loc,130,cur_monst->attitude) == TRUE)
2141 {monst_spell_note(cur_monst->number,33); play_sound(61);}
2143 if ((cur_monst->m_d.radiate_1 == 12) && (get_ran(1,0,100) < 50)){
2144 if (summon_monster(cur_monst->m_d.radiate_2,
2145 cur_monst->m_loc,130,cur_monst->attitude) == TRUE)
2146 {monst_spell_note(cur_monst->number,33); play_sound(61);}
2150 combat_posing_monster = current_working_monster = -1;
2151 // Redraw monster after it goes
2152 if ((cur_monst->attitude > 0) && (cur_monst->active > 0) && (cur_monst->m_d.ap == 0)
2153 && (is_combat()) && (cur_monst->m_d.picture_num > 0) && (party_can_see_monst(i) == TRUE)) {
2154 center = cur_monst->m_loc;
2155 draw_terrain(0);
2159 // If monster dead, take away actions
2160 if (cur_monst->active == 0)
2161 cur_monst->m_d.ap = 0;
2163 //if ((futzing == 1) && (get_ran(1,0,1) == 0)) // If monster's just pissing around, give up
2164 // cur_monst->m_d.ap = 0;
2165 if (futzing > 1) // If monster's just pissing around, give up
2166 cur_monst->m_d.ap = 0;
2167 } // End of monster action loop
2172 for (i = 0; i < num_monst; i++) { // Begin monster time stuff loop
2173 // If party dead, no point
2174 if (party_toast() == TRUE)
2175 return;
2177 cur_monst = &c_town.monst.dudes[i];
2179 if ((cur_monst->active < 0) || (cur_monst->active > 2))
2180 cur_monst->active = 0; // clean up
2181 if (cur_monst->active != 0) { // Take care of monster effects
2182 if (cur_monst->m_d.status[13] > 0) { // Acid
2183 if (printed_acid == FALSE) {
2184 add_string_to_buf("Acid: ");
2185 printed_acid = TRUE;
2187 r1 = get_ran(cur_monst->m_d.status[13],1,6);
2188 damage_monst(i, 6,r1, 0, 3);
2189 cur_monst->m_d.status[13]--;
2192 if (cur_monst->m_d.status[11] == 1)
2193 monst_spell_note(cur_monst->number,29);
2194 cur_monst->m_d.status[11] = move_to_zero(cur_monst->m_d.status[11]);
2195 cur_monst->m_d.status[12] = move_to_zero(cur_monst->m_d.status[12]);
2197 if (party.age % 2 == 0) {
2198 cur_monst->m_d.status[1] = move_to_zero(cur_monst->m_d.status[1]);
2199 cur_monst->m_d.status[3] = move_to_zero(cur_monst->m_d.status[3]);
2200 cur_monst->m_d.status[6] = move_to_zero(cur_monst->m_d.status[6]);
2202 if (cur_monst->m_d.status[2] > 0) { // Poison
2203 if (printed_poison == FALSE) {
2204 add_string_to_buf("Poisoned monsters: ");
2205 printed_poison = TRUE;
2207 r1 = get_ran(cur_monst->m_d.status[2],1,6);
2208 damage_monst(i, 6, r1, 0, 2);
2209 cur_monst->m_d.status[2]--;
2211 if (cur_monst->m_d.status[7] > 0) { // Disease
2212 if (printed_disease == FALSE) {
2213 add_string_to_buf("Diseased monsters: ");
2214 printed_disease = TRUE;
2216 k = get_ran(1,1,5);
2217 switch (k) {
2218 case 1: case 2: poison_monst(cur_monst, 2);break;
2219 case 3: slow_monst(cur_monst,2); break;
2220 case 4: curse_monst(cur_monst,2); break;
2221 case 5: scare_monst(cur_monst,10); break;
2223 if (get_ran(1,1,6) < 4)
2224 cur_monst->m_d.status[7]--;
2229 if (party.age % 4 == 0) {
2230 if (cur_monst->m_d.mp < cur_monst->m_d.max_mp)
2231 cur_monst->m_d.mp += 2;
2232 cur_monst->m_d.status[9] = move_to_zero(cur_monst->m_d.status[9]);
2234 } // end take care of monsters
2237 // If in town, need to restore center
2238 if (overall_mode < 10)
2239 center = c_town.p_loc;
2240 if (had_monst == TRUE)
2241 put_pc_screen();
2242 for (i = 0; i < 6; i++)
2243 pc_parry[i] = 0;
2245 monsters_going = FALSE;
2248 void monster_attack_pc(short who_att,short target)
2250 creature_data_type *attacker;
2251 short r1,r2,i,dam_type = 0,store_hp,sound_type = 0;
2254 attacker = &c_town.monst.dudes[who_att];
2256 // A peaceful monster won't attack
2257 if (attacker->attitude % 2 != 1)
2258 return;
2260 // Draw attacker frames
2261 if ((is_combat())
2262 && ((center_on_monst == TRUE) || (monsters_going == FALSE))) {
2263 if (attacker->m_d.spec_skill != 11)
2264 frame_space(attacker->m_loc,0,attacker->m_d.x_width,attacker->m_d.y_width);
2265 frame_space(pc_pos[target],1,1,1);
2270 if ((attacker->m_d.a[0] != 0) || (attacker->m_d.a[2] != 0))
2271 print_monst_attacks(attacker->number,target);
2273 // Check sanctuary
2274 if (adven[target].status[8] > 0) {
2275 r1 = get_ran(1,0,100);
2276 if (r1 > hit_chance[attacker->m_d.level / 2]) {
2277 add_string_to_buf(" Can't find target! ");
2279 return;
2282 for (i = 0; i < 3; i++) {
2283 if ((attacker->m_d.a[i] > 0) && (adven[target].main_status == 1)) {
2284 // sprintf ((char *) create_line, " Attacks %s.",(char *) adven[target].name);
2285 // add_string_to_buf((char *) create_line);
2287 // Attack roll
2288 r1 = get_ran(1,0,100) - 5 * min(8,attacker->m_d.status[1]) + 5 * adven[target].status[1]
2289 + 5 * stat_adj(target,1) - 15;
2290 r1 += 5 * (attacker->m_d.status[6] / 3);
2291 if (pc_parry[target] < 100)
2292 r1 += 5 * pc_parry[target];
2294 // Damage roll
2295 r2 = get_ran(attacker->m_d.a[i] / 100 + 1,1,attacker->m_d.a[i] % 100)
2296 + min(8,attacker->m_d.status[1]) - adven[target].status[1] + 1;
2297 if (difficulty_adjust() > 2)
2298 r2 = r2 * 2;
2299 if (difficulty_adjust() == 2)
2300 r2 = (r2 * 3) / 2;
2302 if ((adven[target].status[11] > 0) || (adven[target].status[12] > 0)) {
2303 r1 -= 80;
2304 r2 = r2 * 2;
2307 draw_terrain(2);
2308 // Check if hit, and do effects
2309 if (r1 <= hit_chance[(attacker->m_d.skill + 4) / 2]) {
2310 if (attacker->m_d.m_type == 7)
2311 dam_type = 6;
2312 if (attacker->m_d.m_type == 8)
2313 dam_type = 7;
2315 store_hp = adven[target].cur_health;
2316 sound_type = get_monst_sound(attacker,i);
2318 if ((damage_pc(target,r2,sound_type * 100 + 30 + dam_type,
2319 attacker->m_d.m_type) == TRUE) &&
2320 (store_hp - adven[target].cur_health > 0)) {
2321 damaged_message(store_hp - adven[target].cur_health,
2322 (i > 0) ? attacker->m_d.a23_type : attacker->m_d.a1_type);
2324 if (adven[target].status[10] > 0) {
2325 add_string_to_buf(" Shares damage! ");
2326 damage_monst(who_att, 6, store_hp - adven[target].cur_health, 0, 3);
2329 if ((attacker->m_d.poison > 0) && (i == 0)) {
2330 poison_pc(target,attacker->m_d.poison);
2333 // Gremlin
2334 if ((attacker->m_d.spec_skill == 21) && (get_ran(1,0,2) < 2)) {
2335 add_string_to_buf(" Steals food! ");
2336 print_buf();
2337 play_sound(26);
2338 party.food = (long) max(0, (short) (party.food) - get_ran(1,0,10) - 10);
2339 put_pc_screen();
2342 // Disease
2343 if (((attacker->m_d.spec_skill == 25) || (attacker->m_d.spec_skill == 30))
2344 && (get_ran(1,0,2) < 2)) {
2345 add_string_to_buf(" Causes disease! ");
2346 print_buf();
2347 disease_pc(target,(attacker->m_d.spec_skill == 25) ? 6 : 2);
2350 // Undead xp drain
2351 if (((attacker->m_d.spec_skill == 16) || (attacker->m_d.spec_skill == 17))
2352 && (pc_has_abil_equip(target,48) == 24)) {
2353 add_string_to_buf(" Drains life! ");
2354 drain_pc(target,(attacker->m_d.level * 3) / 2);
2355 put_pc_screen();
2358 // Undead slow
2359 if ((attacker->m_d.spec_skill == 18) && (get_ran(1,0,8) < 6) && (pc_has_abil_equip(target,48) == 24)) {
2360 add_string_to_buf(" Stuns! ");
2361 slow_pc(target,2);
2362 put_pc_screen();
2364 // Dumbfound target
2365 if (attacker->m_d.spec_skill == 24) {
2366 add_string_to_buf(" Dumbfounds! ");
2367 dumbfound_pc(target,2);
2368 put_pc_screen();
2371 // Web target
2372 if (attacker->m_d.spec_skill == 27) {
2373 add_string_to_buf(" Webs! ");
2374 web_pc(target,5);
2375 put_pc_screen();
2377 // Sleep target
2378 if (attacker->m_d.spec_skill == 28) {
2379 add_string_to_buf(" Sleeps! ");
2380 sleep_pc(target,6,11,-15);
2381 put_pc_screen();
2383 // Paralyze target
2384 if (attacker->m_d.spec_skill == 29) {
2385 add_string_to_buf(" Paralysis touch! ");
2386 sleep_pc(target,500,12,-5);
2387 put_pc_screen();
2389 // Acid touch
2390 if (attacker->m_d.spec_skill == 31) {
2391 add_string_to_buf(" Acid touch! ");
2392 acid_pc(target,(attacker->m_d.level > 20) ? 4 : 2);
2395 // Freezing touch
2396 if (((attacker->m_d.spec_skill == 15) || (attacker->m_d.spec_skill == 17))
2397 && (get_ran(1,0,8) < 6) && (pc_has_abil_equip(target,48) == 24)) {
2398 add_string_to_buf(" Freezing touch!");
2399 r1 = get_ran(3,1,10);
2400 damage_pc(target,r1,5,-1);
2402 // Killing touch
2403 if (attacker->m_d.spec_skill == 35)
2405 add_string_to_buf(" Killing touch!");
2406 r1 = get_ran(20,1,10);
2407 damage_pc(target,r1,4,-1);
2411 else {
2412 sprintf ((char *) create_line, " Misses.");
2413 add_string_to_buf((char *) create_line);
2414 play_sound(2);
2416 combat_posing_monster = -1;
2417 draw_terrain(2);
2418 combat_posing_monster = 100 + who_att;
2422 if (adven[target].main_status != 1)
2423 i = 3;
2428 void monster_attack_monster(short who_att,short attackee)
2430 creature_data_type *attacker,*target;
2431 short r1,r2,i,dam_type = 0,store_hp,sound_type = 0;
2433 attacker = &c_town.monst.dudes[who_att];
2434 target = &c_town.monst.dudes[attackee];
2436 // Draw attacker frames
2437 if ((is_combat())
2438 && ((center_on_monst == TRUE) || (monsters_going == FALSE))) {
2439 if (attacker->m_d.spec_skill != 11)
2440 frame_space(attacker->m_loc,0,attacker->m_d.x_width,attacker->m_d.y_width);
2441 frame_space(target->m_loc,1,1,1);
2445 if ((attacker->m_d.a[1] != 0) || (attacker->m_d.a[0] != 0))
2446 print_monst_attacks(attacker->number,100 + attackee);
2447 for (i = 0; i < 3; i++) {
2448 if ((attacker->m_d.a[i] > 0) && (target->active != 0)) {
2449 // sprintf ((char *) create_line, " Attacks %s.",(char *) adven[target].name);
2450 // add_string_to_buf((char *) create_line);
2452 // if friendly to party, make able to attack
2453 if (target->attitude == 0)
2454 target->attitude = 2;
2456 // Attack roll
2457 r1 = get_ran(1,0,100) - 5 * min(10,attacker->m_d.status[1])
2458 + 5 * target->m_d.status[1] - 15;
2459 r1 += 5 * (attacker->m_d.status[6] / 3);
2461 // Damage roll
2462 r2 = get_ran(attacker->m_d.a[i] / 100 + 1,1,attacker->m_d.a[i] % 100)
2463 + min(10,attacker->m_d.status[1]) - target->m_d.status[1] + 2;
2465 if ((target->m_d.status[11] > 0) || (target->m_d.status[12] > 0)) {
2466 r1 -= 80;
2467 r2 = r2 * 2;
2470 draw_terrain(2);
2471 // Check if hit, and do effects
2472 if (r1 <= hit_chance[(attacker->m_d.skill + 4) / 2]) {
2473 if (attacker->m_d.m_type == 7)
2474 dam_type = 6;
2475 if (attacker->m_d.m_type == 8)
2476 dam_type = 7;
2477 store_hp = target->m_d.health;
2479 sound_type = get_monst_sound(attacker,i);
2481 if (damage_monst(attackee,7,r2,0,sound_type * 100 + 10 + dam_type) == TRUE) {
2482 damaged_message(store_hp - target->m_d.health,
2483 (i > 0) ? attacker->m_d.a23_type : attacker->m_d.a1_type);
2485 if ((attacker->m_d.poison > 0) && (i == 0)) {
2486 poison_monst(target,attacker->m_d.poison);
2489 // Undead slow
2490 if ((attacker->m_d.spec_skill == 18) && (get_ran(1,0,8) < 6)) {
2491 add_string_to_buf(" Stuns! ");
2492 slow_monst(target,2);
2495 // Web target
2496 if (attacker->m_d.spec_skill == 27) {
2497 add_string_to_buf(" Webs! ");
2498 web_monst(target,4);
2500 // Sleep target
2501 if (attacker->m_d.spec_skill == 28) {
2502 add_string_to_buf(" Sleeps! ");
2503 charm_monst(target,-15,11,6);
2505 // Dumbfound target
2506 if (attacker->m_d.spec_skill == 24) {
2507 add_string_to_buf(" Dumbfounds! ");
2508 dumbfound_monst(target,2);
2510 // Paralyze target
2511 if (attacker->m_d.spec_skill == 29) {
2512 add_string_to_buf(" Paralysis touch! ");
2513 charm_monst(target,-5,12,500);
2515 // Acid touch
2516 if (attacker->m_d.spec_skill == 31) {
2517 add_string_to_buf(" Acid touch! ");
2518 acid_monst(target,3);
2521 // Freezing touch
2522 if (((attacker->m_d.spec_skill == 15) || (attacker->m_d.spec_skill == 17))
2523 && (get_ran(1,0,8) < 6)) {
2524 add_string_to_buf(" Freezing touch!");
2525 r1 = get_ran(3,1,10);
2526 damage_monst(attackee,7,r1,0,5);
2529 // Death touch
2530 if ((attacker->m_d.spec_skill == 35)
2531 && (get_ran(1,0,8) < 6)) {
2532 add_string_to_buf(" Killing touch!");
2533 r1 = get_ran(20,1,10);
2534 damage_monst(attackee,7,r1,0,4);
2538 else {
2539 sprintf ((char *) create_line, " Misses.");
2540 add_string_to_buf((char *) create_line);
2541 play_sound(2);
2543 combat_posing_monster = -1;
2544 draw_terrain(2);
2545 combat_posing_monster = 100 + who_att;
2547 if (target->active == 0)
2548 i = 3;
2554 void monst_fire_missile(short m_num,short skill,short bless,short level,location source,short target)
2555 //short target; // 100 + - monster is target
2557 creature_data_type *m_target;
2558 short r1,r2,dam[40] = {0,1,2,3,4, 6,8,7,0,0, 0,0,0,0,0, 0,0,0,0,0,
2559 8,0,0,0,0, 0,0,0,0,0, 0,0,0,0,6, 0,0,0,0,0},i,j;
2560 location targ_space;
2562 if (target == 6)
2563 return;
2564 if (target >= 100) {
2565 targ_space = c_town.monst.dudes[target - 100].m_loc;
2566 if (c_town.monst.dudes[target - 100].active == 0)
2567 return;
2569 else {
2570 targ_space = (is_combat()) ? pc_pos[target] : c_town.p_loc;
2571 if (adven[target].main_status != 1)
2572 return;
2575 if (target >= 100)
2576 m_target = &c_town.monst.dudes[target - 100];
2577 if (((overall_mode >= 10) && (overall_mode <= 20)) && (center_on_monst == TRUE)) {
2578 frame_space(source,0,c_town.monst.dudes[m_num].m_d.x_width,c_town.monst.dudes[m_num].m_d.y_width);
2579 if (target >= 100)
2580 frame_space(targ_space,1,m_target->m_d.x_width,m_target->m_d.y_width);
2581 else frame_space(targ_space,1,1,1);
2584 draw_terrain(2);
2585 if (level == 32) { // sleep cloud
2586 ASB("Creature breathes.");
2587 run_a_missile(source,targ_space,0,0,44,
2588 0,0,100);
2589 place_spell_pattern(rad2,targ_space,12,FALSE,7);
2591 else if (level == 14) { // vapors
2592 //play_sound(44);
2593 if (target < 100) { // on PC
2594 sprintf ((char *) create_line, " Breathes on %s. ",(char *) adven[target].name);
2595 add_string_to_buf((char *) create_line);
2597 else { // on monst
2598 add_string_to_buf(" Breathes vapors.");
2600 run_a_missile(source,targ_space,12,0,44,
2601 0,0,100);
2602 scloud_space(targ_space.x,targ_space.y);
2604 else if (level == 19) { // webs
2605 //play_sound(14);
2606 if (target < 100) { // on PC
2607 sprintf ((char *) create_line, " Throws web at %s. ",(char *) adven[target].name);
2608 add_string_to_buf((char *) create_line);
2610 else { // on monst
2611 add_string_to_buf(" Throws web.");
2613 run_a_missile(source,targ_space,8,0,14,
2614 0,0,100);
2615 web_space(targ_space.x,targ_space.y);
2617 else if (level == 23) { // paral
2618 play_sound(51);
2619 if (target < 100) { // on PC
2620 sprintf ((char *) create_line, " Fires ray at %s. ",(char *) adven[target].name);
2621 add_string_to_buf((char *) create_line);
2622 sleep_pc(target,100,12,0);
2624 else { // on monst
2625 add_string_to_buf(" Shoots a ray.");
2626 charm_monst(m_target,0,12,100);
2628 //run_a_missile(source,targ_space,8,0,14,
2629 // 0,0,100);
2630 //web_space(targ_space.x,targ_space.y);
2632 else if (level == 8) { // petrify
2633 //play_sound(43);
2634 run_a_missile(source,targ_space,14,0,43,0,0,100);
2635 if (target < 100) { // on PC
2636 sprintf ((char *) create_line, " Gazes at %s. ",(char *) adven[target].name);
2637 add_string_to_buf((char *) create_line);
2638 r1 = get_ran(1,0,20) + adven[target].level / 4 + adven[target].status[1];
2639 if (pc_has_abil_equip(target,49) < 24)
2640 r1 = 20;
2641 if (r1 > 14) {
2642 sprintf ((char *) create_line, " %s resists. ",(char *) adven[target].name);
2643 add_string_to_buf((char *) create_line);
2645 else {
2646 sprintf ((char *) create_line, " %s is turned to stone. ",(char *) adven[target].name);
2647 add_string_to_buf((char *) create_line);
2648 kill_pc(target,4);
2651 else {
2652 monst_spell_note(m_target->number,9);
2653 r1 = get_ran(1,0,20) + m_target->m_d.level / 4 + m_target->m_d.status[1];
2654 if ((r1 > 14) || (m_target->m_d.immunities & 2))
2655 monst_spell_note(m_target->number,10);
2656 else {
2657 monst_spell_note(m_target->number,8);
2658 kill_monst(m_target,7);
2662 else if (level == 9) { /// Drain sp
2663 if (target < 100) { // pc
2664 // modify target is target has no sp
2665 if (adven[target].cur_sp < 4) {
2666 for (i = 0; i < 8; i++) {
2667 j = get_ran(1,0,5);
2668 if ((adven[j].main_status == 1) && (adven[j].cur_sp > 4) &&
2669 (can_see(source,pc_pos[j],0) < 5) && (dist(source,pc_pos[j]) <= 8)) {
2670 target = j;
2671 i = 8;
2672 targ_space = pc_pos[target];
2677 run_a_missile(source,targ_space,8,0,43,0,0,100);
2678 sprintf ((char *) create_line, " Drains %s. ",(char *) adven[target].name);
2679 add_string_to_buf((char *) create_line);
2680 adven[target].cur_sp = adven[target].cur_sp / 2;
2682 else { // on monst
2683 run_a_missile(source,targ_space,8,0,43,0,0,100);
2684 monst_spell_note(m_target->number,11);
2685 if (m_target->m_d.mp >= 4)
2686 m_target->m_d.mp = m_target->m_d.mp / 2;
2687 else m_target->m_d.skill = 1;
2690 else if (level == 10) { // heat ray
2691 run_a_missile(source,targ_space,13,0,51,
2692 0,0,100);
2693 r1 = get_ran(7,1,6);
2694 start_missile_anim();
2695 if (target < 100) { // pc
2696 sprintf ((char *) create_line, " Hits %s with heat ray.",(char *) adven[target].name);
2697 add_string_to_buf((char *) create_line);
2698 damage_pc(target,r1,1,-1);
2700 else { // on monst
2701 add_string_to_buf(" Fires heat ray.");
2702 damage_monst(target - 100,7,r1,0,1);
2704 do_explosion_anim(5,0);
2705 end_missile_anim();
2706 handle_marked_damage();
2708 else if (level == 33) { // acid spit
2709 run_a_missile(source,targ_space,0,1,64,
2710 0,0,100);
2711 //play_sound(64);
2712 if (target < 100) { // pc
2713 sprintf ((char *) create_line, " Spits acid on %s.",(char *) adven[target].name);
2714 add_string_to_buf((char *) create_line);
2715 acid_pc(target,6);
2717 else { // on monst
2718 add_string_to_buf(" Spits acid.");
2719 acid_monst(m_target,6);
2722 else if (target < 100) { // missile on PC
2724 switch (level) {
2725 case 1: case 2: case 20:
2726 run_a_missile(source,targ_space,3,1,12,0,0,100);
2727 sprintf ((char *) create_line, " Shoots at %s.",(char *) adven[target].name);
2728 break;
2729 case 3:
2730 run_a_missile(source,targ_space,5,1,14,0,0,100);
2731 sprintf ((char *) create_line, " Throws spear at %s.",(char *) adven[target].name);
2732 break;
2733 case 7:
2734 run_a_missile(source,targ_space,7,1,14,0,0,100);
2735 sprintf ((char *) create_line, " Throws razordisk at %s.",(char *) adven[target].name);
2736 break;
2737 case 34:
2738 run_a_missile(source,targ_space,5,1,14,0,0,100);
2739 sprintf ((char *) create_line, " Fires spines at %s.",(char *) adven[target].name);
2740 break;
2741 default:
2742 run_a_missile(source,targ_space,12,1,14,0,0,100);
2743 sprintf ((char *) create_line, " Throws rock at %s.",(char *) adven[target].name);
2744 break;
2747 add_string_to_buf((char *) create_line);
2749 // Check sanctuary
2750 if (adven[target].status[8] > 0) {
2751 r1 = get_ran(1,0,100);
2752 if (r1 > hit_chance[level]) {
2753 add_string_to_buf(" Can't find target! ");
2755 return;
2758 r1 = get_ran(1,0,100) - 5 * min(10,bless) + 5 * adven[target].status[1]
2759 - 5 * (can_see(source, pc_pos[target],0));
2760 if (pc_parry[target] < 100)
2761 r1 += 5 * pc_parry[target];
2762 r2 = get_ran(dam[level],1,7) + min(10,bless);
2764 if (r1 <= hit_chance[dam[level] * 2]) {
2765 // sprintf ((char *) create_line, " Hits %s.",(char *) adven[target].name);
2766 // add_string_to_buf((char *) create_line);
2768 if (damage_pc(target,r2,1300,-1) == TRUE) {
2771 else {
2772 sprintf ((char *) create_line, " Misses %s.",(char *) adven[target].name);
2773 add_string_to_buf((char *) create_line);
2777 else { // missile on monst
2778 switch (level) {
2779 case 1: case 2: case 20:
2780 run_a_missile(source,targ_space,3,1,12,0,0,100);
2781 monst_spell_note(m_target->number,12);
2782 break;
2783 case 3:
2784 run_a_missile(source,targ_space,5,1,14,0,0,100);
2785 monst_spell_note(m_target->number,13);
2786 break;
2787 case 7:
2788 run_a_missile(source,targ_space,7,1,14,0,0,100);
2789 monst_spell_note(m_target->number,15);
2790 break;
2791 case 34:
2792 run_a_missile(source,targ_space,5,1,14,0,0,100);
2793 monst_spell_note(m_target->number,32);
2794 break;
2795 default:
2796 run_a_missile(source,targ_space,12,1,14,0,0,100);
2797 monst_spell_note(m_target->number,14);
2798 break;
2800 r1 = get_ran(1,0,100) - 5 * min(10,bless) + 5 * m_target->m_d.status[1]
2801 - 5 * (can_see(source, m_target->m_loc,0));
2802 r2 = get_ran(dam[level],1,7) + min(10,bless);
2804 if (r1 <= hit_chance[dam[level] * 2]) {
2805 // monst_spell_note(m_target->number,16);
2807 damage_monst(target - 100,7,r2,0,1300);
2809 else {
2810 monst_spell_note(m_target->number,18);
2816 Boolean monst_breathe(creature_data_type *caster,location targ_space,short dam_type)
2817 //dam_type; // 0 - fire 1 - cold 2 - magic
2819 short level,type[4] = {1,5,3,4},missile_t[4] = {13,6,8,8};
2820 location l;
2822 draw_terrain(2);
2823 if ((is_combat()) && (center_on_monst == TRUE)) {
2824 frame_space(caster->m_loc,0,caster->m_d.x_width,caster->m_d.y_width);
2826 //if (dam_type < 2)
2827 l = caster->m_loc;
2828 if ((caster->m_d.direction < 4) &&
2829 (caster->m_d.x_width > 1))
2830 l.x++;
2832 dam_type = caster->m_d.breath_type;
2833 run_a_missile(l,targ_space,missile_t[dam_type],0,44,0,0,100);
2834 // play_sound(44);
2835 //else play_sound(64);
2836 level = caster->m_d.breath;
2837 //if (level > 10)
2838 // play_sound(5);
2840 monst_breathe_note(caster->number);
2841 level = get_ran(caster->m_d.breath,1,8);
2842 if (overall_mode < 10)
2843 level = level / 3;
2844 start_missile_anim();
2845 hit_space(targ_space,level,type[dam_type],1,1);
2846 do_explosion_anim(5,0);
2847 end_missile_anim();
2848 handle_marked_damage();
2850 return TRUE;
2853 Boolean monst_cast_mage(creature_data_type *caster,short targ)
2855 short r1,r2,j,spell,i,level,target_levels,friend_levels_near,x;
2856 Boolean acted = FALSE;
2857 location target,vict_loc,ashes_loc = {0,0},l;
2858 creature_data_type *affected;
2859 long dummy;
2860 short caster_array[7][18] = {{1,1,1,2,2, 2,1,3,4,4, 1,1,1,2,2, 2,3,4},
2861 {5,5,5,6,7, 8,9,10,11,11, 2,2,2,5,7, 10,10,5},
2862 {5,5,2,9,11, 12,12,12,14,13, 13,12,12,2,2, 2,2,2},
2863 {15,15,16,17,17, 5,12,12,13,13, 17,17,16,17,16, 2,2,2},
2864 {15,18,19,19,20, 20,21,21,16,17, 18,18,18,18,19, 19,19,20},
2865 {23,23,22,22,21, 21,20,24,19,18, 18,18,18,18,18, 23,23,19},
2866 {23,23,24,25,26, 27,19,22,19,18, 18,18,18,18,26, 24,24,23}};
2867 short emer_spells[7][4] = {{2,0,0,5},
2868 {2,10,11,7},
2869 {2,13,12,13},
2870 {2,13,12,13},
2871 {18,20,19,18},
2872 {18,24,19,24},
2873 {18,26,19,27}};
2876 if (is_antimagic(caster->m_loc.x,caster->m_loc.y)) {
2877 return FALSE;
2879 // is target dead?
2880 if ((targ < 6) && (adven[targ].main_status != 1))
2881 return FALSE;
2882 if ((targ >= 100) && (c_town.monst.dudes[targ - 100].active == 0))
2883 return FALSE;
2885 level = max(1,caster->m_d.mu - caster->m_d.status[9]) - 1;
2887 target = find_fireball_loc(caster->m_loc,1,(caster->attitude % 2 == 1) ? 0 : 1,&target_levels);
2888 friend_levels_near = (caster->attitude % 2 != 1) ? count_levels(caster->m_loc,3) : -1 * count_levels(caster->m_loc,3);
2890 if ((caster->m_d.health * 4 < caster->m_d.m_health) && (get_ran(1,0,10) < 9))
2891 spell = emer_spells[level][3];
2892 else if ((((caster->m_d.status[3] < 0) && (get_ran(1,0,10) < 7)) ||
2893 ((caster->m_d.status[3] == 0) && (get_ran(1,0,10) < 5))) && (emer_spells[level][0] != 0))
2894 spell = emer_spells[level][0];
2895 else if ((friend_levels_near <= -10) && (get_ran(1,0,10) < 7) && (emer_spells[level][1] != 0))
2896 spell = emer_spells[level][1];
2897 else if ((target_levels > 50) && (get_ran(1,0,10) < 7) && (emer_spells[level][2] != 0))
2898 spell = emer_spells[level][2];
2899 else {
2900 r1 = get_ran(1,0,17);
2901 spell = caster_array[level][r1];
2904 // Hastes happen often now, but don't cast them redundantly
2905 if ((caster->m_d.status[3] > 0) && ((spell == 2) || (spell == 18)))
2906 spell = emer_spells[level][3];
2909 // Anything prventing spell?
2910 if ((target.x > 64) && (monst_mage_area_effect[spell - 1] > 0)) {
2911 r1 = get_ran(1,0,9);
2912 spell = caster_array[level][r1];
2913 if ((target.x > 64) && (monst_mage_area_effect[spell - 1] > 0))
2914 return FALSE;
2916 if (monst_mage_area_effect[spell - 1] > 0) {
2917 targ = 6;
2920 if (targ < 6) {
2921 vict_loc = (is_combat()) ? pc_pos[targ] : c_town.p_loc;
2922 if (is_town())
2923 vict_loc = target = c_town.p_loc;
2925 if (targ >= 100)
2926 vict_loc = c_town.monst.dudes[targ - 100].m_loc;
2927 if ((targ == 6) && (is_antimagic(target.x,target.y)))
2928 return FALSE;
2930 // check antimagic
2931 if (is_combat())
2932 if ((targ < 6) && (is_antimagic(pc_pos[targ].x,pc_pos[targ].y)))
2933 return FALSE;
2934 if (is_town())
2935 if ((targ < 6) && (is_antimagic(c_town.p_loc.x,c_town.p_loc.y)))
2936 return FALSE;
2937 if ((targ >= 100) && (is_antimagic(c_town.monst.dudes[targ - 100].m_loc.x,
2938 c_town.monst.dudes[targ - 100].m_loc.y)))
2939 return FALSE;
2942 // How about shockwave? Good idea?
2943 if ((spell == 27) && (caster->attitude % 2 != 1))
2944 spell = 26;
2945 if ((spell == 27) && (caster->attitude % 2 == 1) && (count_levels(caster->m_loc,10) < 45))
2946 spell = 26;
2948 // sprintf((char *)create_line,"m att %d trg %d trg2 x%dy%d spl %d mp %d tl:%d ",caster->attitude,targ,
2949 // (short)target.x,(short)target.y,spell,caster->m_d.mp,target_levels);
2950 // add_string_to_buf((char *) create_line);
2952 l = caster->m_loc;
2953 if ((caster->m_d.direction < 4) && (caster->m_d.x_width > 1))
2954 l.x++;
2956 if (caster->m_d.mp >= monst_mage_cost[spell - 1]) {
2957 monst_cast_spell_note(caster->number,spell,0);
2958 acted = TRUE;
2959 caster->m_d.mp -= monst_mage_cost[spell - 1];
2961 draw_terrain(2);
2962 switch (spell) {
2963 case 1: // spark
2964 run_a_missile(l,vict_loc,6,1,11,0,0,80);
2965 r1 = get_ran(2,1,4);
2966 damage_target(targ,r1,1);
2967 break;
2968 case 2: // minor haste
2969 play_sound(25);
2970 caster->m_d.status[3] += 2;
2971 break;
2972 case 3: // strength
2973 play_sound(25);
2974 caster->m_d.status[1] += 3;
2975 break;
2976 case 4: // flame cloud
2977 run_a_missile(l,vict_loc,2,1,11,0,0,80);
2978 place_spell_pattern(single,vict_loc,5,FALSE,7);
2979 break;
2980 case 5: // flame
2981 run_a_missile(l,vict_loc,2,1,11,0,0,80);
2982 start_missile_anim();
2983 r1 = get_ran(caster->m_d.level,1,4);
2984 damage_target(targ,r1,1);
2985 break;
2986 case 6: // minor poison
2987 run_a_missile(l,vict_loc,11,0,25,0,0,80);
2988 if (targ < 6)
2989 poison_pc(targ,2 + get_ran(1,0,1));
2990 else poison_monst(&c_town.monst.dudes[targ - 100],2 + get_ran(1,0,1));
2991 break;
2992 case 7: // slow
2993 run_a_missile(l,vict_loc,15,0,25,0,0,80);
2994 if (targ < 6)
2995 slow_pc(targ,2 + caster->m_d.level / 2);
2996 else slow_monst(&c_town.monst.dudes[targ - 100],2 + caster->m_d.level / 2);
2997 break;
2998 case 8: // dumbfound
2999 run_a_missile(l,vict_loc,14,0,25,0,0,80);
3000 if (targ < 6)
3001 dumbfound_pc(targ,2);
3002 else dumbfound_monst(&c_town.monst.dudes[targ - 100],2);
3003 break;
3004 case 9: // scloud
3005 run_a_missile(l,target,0,0,25,0,0,80);
3006 place_spell_pattern(square,target,7,FALSE,7);
3007 break;
3008 case 10: // summon beast
3009 r1 = get_summon_monster(1);
3010 if (r1 < 0)
3011 break;
3012 x = get_ran(3,1,4);
3013 //Delay(12,&dummy); // gives sound time to end
3014 play_sound(25);
3015 play_sound(-61);
3016 summon_monster(r1,caster->m_loc,
3017 ((caster->attitude % 2 != 1) ? 0 : 100) + x,caster->attitude);
3018 break;
3019 case 11: // conflagration
3020 run_a_missile(l,target,13,1,25,0,0,80);
3021 place_spell_pattern(rad2,target,5,FALSE,7);
3022 break;
3023 case 12: // fireball
3024 r1 = 1 + (caster->m_d.level * 3) / 4;
3025 if (r1 > 29) r1 = 29;
3026 run_a_missile(l,target,2,1,11,0,0,80);
3027 start_missile_anim();
3028 place_spell_pattern(square,target,50 + r1,TRUE,7);
3029 ashes_loc = target;
3030 break;
3031 case 13: case 20: case 26:// summon
3032 play_sound(25);
3033 if (spell == 13) {
3034 r1 = get_summon_monster(1);
3035 if (r1 < 0)
3036 break;
3037 j = get_ran(2,1,3) + 1;
3039 if (spell == 20) {
3040 r1 = get_summon_monster(2);
3041 if (r1 < 0)
3042 break;
3043 j = get_ran(2,1,2) + 1;
3045 if (spell == 26) {
3046 r1 = get_summon_monster(3);
3047 if (r1 < 0)
3048 break;
3049 j = get_ran(1,2,3);
3051 Delay(12,&dummy); // gives sound time to end
3052 x = get_ran(4,1,4);
3053 for (i = 0; i < j; i++){
3054 play_sound(-61);
3055 if (summon_monster(r1,caster->m_loc,
3056 ((caster->attitude % 2 != 1) ? 0 : 100) + x,caster->attitude) == FALSE) {
3057 add_string_to_buf(" Summon failed."); i = j;}
3059 break;
3060 case 14: // web
3061 play_sound(25);
3062 place_spell_pattern(rad2,target,1,FALSE,7);
3063 break;
3064 case 15: // poison
3065 run_a_missile(l,vict_loc,11,0,25,0,0,80);
3066 x = get_ran(1,0,3);
3067 if (targ < 6)
3068 poison_pc(targ,4 + x);
3069 else poison_monst(&c_town.monst.dudes[targ - 100],4 + x);
3070 break;
3071 case 16: // ice bolt
3072 run_a_missile(l,vict_loc,6,1,11,0,0,80);
3073 r1 = get_ran(5 + (caster->m_d.level / 5),1,8);
3074 start_missile_anim();
3075 damage_target(targ,r1,5);
3076 break;
3077 case 17: // slow gp
3078 play_sound(25);
3079 if (caster->attitude % 2 == 1)
3080 for (i = 0; i < 6; i++)
3081 if (pc_near(i,caster->m_loc,8))
3082 slow_pc(i,2 + caster->m_d.level / 4);
3083 for (i = 0; i < T_M; i++) {
3084 if ((c_town.monst.dudes[i].active != 0) &&
3085 (((c_town.monst.dudes[i].attitude % 2 == 1) && (caster->attitude % 2 != 1)) ||
3086 ((c_town.monst.dudes[i].attitude % 2 != 1) && (caster->attitude % 2 == 1)) ||
3087 ((c_town.monst.dudes[i].attitude % 2 == 1) && (caster->attitude != c_town.monst.dudes[i].attitude)))
3088 && (dist(caster->m_loc,c_town.monst.dudes[i].m_loc) <= 7))
3089 slow_monst(&c_town.monst.dudes[i],2 + caster->m_d.level / 4);
3091 break;
3092 case 18: // major haste
3093 play_sound(25);
3094 for (i = 0; i < T_M; i++)
3095 if ((monst_near(i,caster->m_loc,8,0)) &&
3096 (caster->attitude == c_town.monst.dudes[i].attitude)) {
3097 affected = &c_town.monst.dudes[i];
3098 affected->m_d.status[3] += 3;
3100 play_sound(4);
3101 break;
3102 case 19: // firestorm
3103 run_a_missile(l,target,2,1,11,0,0,80);
3104 r1 = 1 + (caster->m_d.level * 3) / 4 + 3;
3105 if (r1 > 29) r1 = 29;
3106 start_missile_anim();
3107 place_spell_pattern(rad2,target,50 + r1,TRUE,7);
3108 ashes_loc = target;
3109 break;
3114 case 21: // shockstorm
3115 run_a_missile(l,target,6,1,11,0,0,80);
3116 place_spell_pattern(rad2,target,4,FALSE,7);
3117 break;
3118 case 22: // m. poison
3119 run_a_missile(l,vict_loc,11,1,11,0,0,80);
3120 x = get_ran(1,1,2);
3121 if (targ < 6)
3122 poison_pc(targ,6 + x);
3123 else poison_monst(&c_town.monst.dudes[targ - 100],6 + x);
3124 break;
3125 case 23: // kill!!!
3126 run_a_missile(l,vict_loc,9,1,11,0,0,80);
3127 r1 = 35 + get_ran(3,1,10);
3128 start_missile_anim();
3129 damage_target(targ,r1,3);
3130 break;
3131 case 24: // daemon
3132 x = get_ran(3,1,4);
3133 play_sound(25);
3134 play_sound(-61);
3135 Delay(12,&dummy); // gives sound time to end
3136 summon_monster(85,caster->m_loc,
3137 ((caster->attitude % 2 != 1) ? 0 : 100) + x,caster->attitude);
3138 break;
3139 case 25: // major bless
3140 play_sound(25);
3141 for (i = 0; i < T_M; i++)
3142 if ((monst_near(i,caster->m_loc,8,0)) &&
3143 (caster->attitude == c_town.monst.dudes[i].attitude)) {
3144 affected = &c_town.monst.dudes[i];
3145 affected->m_d.health += get_ran(2,1,10);
3146 r1 = get_ran(3,1,4);
3147 affected->m_d.status[1] = min(8,affected->m_d.status[1] + r1);
3148 affected->m_d.status[6] = 0;
3149 if (affected->m_d.status[3] < 0)
3150 affected->m_d.status[3] = 0;
3151 affected->m_d.morale += get_ran(3,1,10);
3153 play_sound(4);
3154 break;
3155 case 27: // shockwave
3156 do_shockwave(caster->m_loc);
3157 break;
3160 else caster->m_d.mp++;
3162 if (ashes_loc.x > 0)
3163 make_sfx(ashes_loc.x,ashes_loc.y,6);
3164 do_explosion_anim(5,0);
3165 end_missile_anim();
3166 handle_marked_damage();
3168 return acted;
3171 Boolean monst_cast_priest(creature_data_type *caster,short targ)
3173 short r1,r2,spell,i,x,level,target_levels,friend_levels_near;
3174 Boolean acted = FALSE;
3175 location target,vict_loc,l;
3176 creature_data_type *affected;
3177 short caster_array[7][10] = {{1,1,1,1,3,3,3,4,4,4},
3178 {5,5,6,6,7,7,8,8,8,9},
3179 {9,6,6,8,11,12,12,5,5,12},
3180 {12,12,13,13,14,9,9,14,14,15},
3181 {19,18,13,19,15,18,18,19,16,18},
3182 {22,18,16,19,18,18,21,22,23,23},
3183 {26,26,25,24,26,22,24,22,26,25}};
3184 short emer_spells[7][4] = {{0,1,0,2},
3185 {0,8,0,2},
3186 {0,8,0,10},
3187 {0,14,0,10},
3188 {0,19,18,17},
3189 {0,19,18,20},
3190 {25,25,26,24}};
3191 location ashes_loc = {0,0};
3194 if ((targ < 6) && (adven[targ].main_status != 1))
3195 return FALSE;
3196 if ((targ >= 100) && (c_town.monst.dudes[targ - 100].active == 0))
3197 return FALSE;
3198 if (is_antimagic(caster->m_loc.x,caster->m_loc.y)) {
3199 return FALSE;
3201 level = max(1,caster->m_d.cl - caster->m_d.status[9]) - 1;
3203 target = find_fireball_loc(caster->m_loc,1,(caster->attitude % 2 == 1) ? 0 : 1,&target_levels);
3204 friend_levels_near = (caster->attitude % 2 != 1) ? count_levels(caster->m_loc,3) : -1 * count_levels(caster->m_loc,3);
3206 if ((caster->m_d.health * 4 < caster->m_d.m_health) && (get_ran(1,0,10) < 9))
3207 spell = emer_spells[level][3];
3208 else if ((caster->m_d.status[3] < 0) && (get_ran(1,0,10) < 7) && (emer_spells[level][0] != 0))
3209 spell = emer_spells[level][0];
3210 else if ((friend_levels_near <= -10) && (get_ran(1,0,10) < 7) && (emer_spells[level][1] != 0))
3211 spell = emer_spells[level][1];
3212 else if ((target_levels > 50 < 0) && (get_ran(1,0,10) < 7) && (emer_spells[level][2] != 0))
3213 spell = emer_spells[level][2];
3214 else {
3215 r1 = get_ran(1,0,9);
3216 spell = caster_array[level][r1];
3221 // Anything preventing spell?
3222 if ((target.x > 64) && (monst_priest_area_effect[spell - 1] > 0)) {
3223 r1 = get_ran(1,0,9);
3224 spell = caster_array[level][r1];
3225 if ((target.x > 64) && (monst_priest_area_effect[spell - 1] > 0))
3226 return FALSE;
3228 if (monst_priest_area_effect[spell - 1] > 0)
3229 targ = 6;
3230 if (targ < 6)
3231 vict_loc = (is_town()) ? c_town.p_loc : pc_pos[targ];
3232 if (targ >= 100)
3233 vict_loc = c_town.monst.dudes[targ - 100].m_loc;
3234 if ((targ == 6) && (is_antimagic(target.x,target.y)))
3235 return FALSE;
3236 if ((targ < 6) && (is_antimagic(pc_pos[targ].x,pc_pos[targ].y)))
3237 return FALSE;
3238 if ((targ >= 100) && (is_antimagic(c_town.monst.dudes[targ - 100].m_loc.x,
3239 c_town.monst.dudes[targ - 100].m_loc.y)))
3240 return FALSE;
3243 // sprintf((char *)create_line,"p att %d trg %d trg2 x%dy%d spl %d mp %d",caster->attitude,targ,
3244 // (short)target.x,(short)target.y,spell,caster->m_d.mp);
3245 // add_string_to_buf((char *) create_line);
3247 // snuff heals if unwounded
3248 if ((caster->m_d.health == caster->m_d.m_health) &&
3249 ((spell == 17) || (spell == 20)))
3250 spell--;
3252 l = caster->m_loc;
3253 if ((caster->m_d.direction < 4) && (caster->m_d.x_width > 1))
3254 l.x++;
3256 if (caster->m_d.mp >= monst_priest_cost[spell - 1]) {
3257 monst_cast_spell_note(caster->number,spell,1);
3258 acted = TRUE;
3259 caster->m_d.mp -= monst_priest_cost[spell - 1];
3260 draw_terrain(2);
3261 switch (spell) {
3262 case 3: // wrack
3263 run_a_missile(l,vict_loc,8,0,24,0,0,80);
3264 r1 = get_ran(2,1,4);
3265 start_missile_anim();
3266 damage_target(targ,r1,4);
3267 break;
3268 case 4: // stumble
3269 play_sound(24);
3270 place_spell_pattern(single,vict_loc,1,FALSE,7);
3271 break;
3272 case 1: case 5: // Blesses
3273 play_sound(24);
3274 caster->m_d.status[1] = min(8,caster->m_d.status[1] + (spell == 1) ? 3 : 5);
3275 play_sound(4);
3276 break;
3277 case 6: // curse
3278 run_a_missile(l,vict_loc,8,0,24,0,0,80);
3279 x = get_ran(1,0,1);
3280 if (targ < 6)
3281 curse_pc(targ,2 + x);
3282 else curse_monst(&c_town.monst.dudes[targ - 100],2 + x);
3283 break;
3284 case 7: // wound
3285 run_a_missile(l,vict_loc,8,0,24,0,0,80);
3286 r1 = get_ran(2,1,6) + 2;
3287 start_missile_anim();
3288 damage_target(targ,r1,3);
3289 break;
3290 case 8: case 22: // summon spirit,summon guardian
3291 play_sound(24);
3292 play_sound(-61);
3294 x = get_ran(3,1,4);
3295 summon_monster(((spell == 8) ? 125 : 122),caster->m_loc,
3296 ((caster->attitude % 2 != 1) ? 0 : 100) + x,caster->attitude);
3297 break;
3298 case 9: // disease
3299 run_a_missile(l,vict_loc,11,0,24,0,0,80);
3300 x = get_ran(1,0,2);
3301 if (targ < 6)
3302 disease_pc(targ,2 + x);
3303 else disease_monst(&c_town.monst.dudes[targ - 100],2 + x);
3304 break;
3305 case 11: // holy scourge
3306 run_a_missile(l,vict_loc,15,0,24,0,0,80);
3307 if (targ < 6) {
3308 r1 = get_ran(1,0,2);
3309 slow_pc(targ,2 + r1);
3310 r1 = get_ran(1,0,2);
3311 curse_pc(targ,3 + r1);
3313 else {
3314 r1 = get_ran(1,0,2);
3315 slow_monst(&c_town.monst.dudes[targ - 100],r1);
3316 r1 = get_ran(1,0,2);
3317 curse_monst(&c_town.monst.dudes[targ - 100],r1);
3319 break;
3320 case 12: // smite
3321 run_a_missile(l,vict_loc,6,0,24,0,0,80);
3322 r1 = get_ran(4,1,6) + 2;
3323 start_missile_anim();
3324 damage_target(targ,r1,5);
3325 break;
3326 case 14: // sticks to snakes
3327 play_sound(24);
3328 r1 = get_ran(1,1,4) + 2;
3329 for (i = 0; i < r1; i++) {
3330 play_sound(-61);
3331 r2 = get_ran(1,0,7);
3332 x = get_ran(3,1,4);
3333 summon_monster((r2 == 1) ? 100 : 99,caster->m_loc,
3334 ((caster->attitude % 2 != 1) ? 0 : 100) + x,caster->attitude);
3336 break;
3337 case 15: // martyr's shield
3338 play_sound(24);
3339 caster->m_d.status[10] = min(10,caster->m_d.status[10] + 5);
3340 break;
3341 case 19: // summon host
3342 play_sound(24);
3343 x = get_ran(3,1,4) + 1;
3344 play_sound(-61);
3345 summon_monster(126,caster->m_loc,
3346 ((caster->attitude % 2 != 1) ? 0 : 100) + x,caster->attitude);
3347 for (i = 0; i < 4; i++) {
3348 play_sound(-61);
3349 if (summon_monster(125,caster->m_loc,
3350 ((caster->attitude % 2 != 1) ? 0 : 100) + x,caster->attitude) == FALSE)
3351 i = 4;
3353 break;
3355 case 13: case 23: // holy scourge,curse all,pestilence
3356 play_sound(24);
3357 r1 = get_ran(2,0,2);
3358 r2 = get_ran(1,0,2);
3359 if (caster->attitude % 2 == 1)
3360 for (i = 0; i < 6; i++)
3361 if (pc_near(i,caster->m_loc,8)) {
3362 if (spell == 13)
3363 curse_pc(i,2 + r1);
3364 if (spell == 23)
3365 disease_pc(i,2 + r2);
3367 for (i = 0; i < T_M; i++) {
3368 if ((c_town.monst.dudes[i].active != 0) &&
3369 (((c_town.monst.dudes[i].attitude % 2 == 1) && (caster->attitude % 2 != 1)) ||
3370 ((c_town.monst.dudes[i].attitude % 2 != 1) && (caster->attitude % 2 == 1)) ||
3371 ((c_town.monst.dudes[i].attitude % 2 == 1) && (caster->attitude != c_town.monst.dudes[i].attitude)))
3372 && (dist(caster->m_loc,c_town.monst.dudes[i].m_loc) <= 7)) {
3373 if (spell == 13)
3374 curse_monst(&c_town.monst.dudes[i],2 + r1);
3375 if (spell == 23)
3376 disease_monst(&c_town.monst.dudes[i],2 + r2);
3379 break;
3381 case 2: case 10: case 17: case 20: // heals
3382 play_sound(24);
3383 switch(spell) {
3384 case 2: r1 = get_ran(2,1,4) + 2; break;
3385 case 10: r1 = get_ran(3,1,6); break;
3386 case 17: r1 = get_ran(5,1,6) + 3; break;
3387 case 20: r1 = 50; break;
3389 caster->m_d.health = min(caster->m_d.health + r1, caster->m_d.m_health);
3390 break;
3391 case 16: case 24:// bless all,revive all
3392 play_sound(24);
3393 r1 = get_ran(2,1,4); r2 = get_ran(3,1,6);
3394 for (i = 0; i < T_M; i++)
3395 if ((monst_near(i,caster->m_loc,8,0)) &&
3396 (caster->attitude == c_town.monst.dudes[i].attitude)) {
3397 affected = &c_town.monst.dudes[i];
3398 if (spell == 16)
3399 affected->m_d.status[1] = min(8,affected->m_d.status[1] + r1);
3400 if (spell == 24)
3401 affected->m_d.health += r1;
3403 play_sound(4);
3404 break;
3405 case 18: // Flamestrike
3406 run_a_missile(l,target,2,0,11,0,0,80);
3407 r1 = 2 + caster->m_d.level / 2 + 2;
3408 start_missile_anim();
3409 place_spell_pattern(square,target,50 + r1,TRUE,7);
3410 ashes_loc = target;
3411 break;
3414 case 21: // holy ravaging
3415 run_a_missile(l,vict_loc,14,0,53,0,0,80);
3416 r1 = get_ran(4,1,8);
3417 r2 = get_ran(1,0,2);
3418 damage_target(targ,r1,3);
3419 if (targ < 6) {
3420 slow_pc(targ,6);
3421 poison_pc(targ,5 + r2);
3423 else {
3424 slow_monst(&c_town.monst.dudes[targ - 100],6);
3425 poison_monst(&c_town.monst.dudes[targ - 100],5 + r2);
3427 break;
3428 case 25: // avatar
3429 play_sound(24);
3430 monst_spell_note(caster->number,26);
3431 caster->m_d.health = caster->m_d.m_health;
3432 caster->m_d.status[1] = 8;
3433 caster->m_d.status[2] = 0;
3434 caster->m_d.status[3] = 8;
3435 caster->m_d.status[6] = 0;
3436 caster->m_d.status[7] = 0;
3437 caster->m_d.status[9] = 0;
3438 caster->m_d.status[10] = 8;
3439 break;
3440 case 26: // divine thud
3441 run_a_missile(l,target,9,0,11,0,0,80);
3442 r1 = (caster->m_d.level * 3) / 4 + 5;
3443 if (r1 > 29) r1 = 29;
3444 start_missile_anim();
3445 place_spell_pattern(rad2,target,130 + r1,TRUE,7 );
3446 ashes_loc = target;
3447 break;
3452 else caster->m_d.mp++;
3453 if (ashes_loc.x > 0)
3454 make_sfx(ashes_loc.x,ashes_loc.y,6);
3455 do_explosion_anim(5,0);
3456 end_missile_anim();
3457 handle_marked_damage();
3459 return acted;
3462 void damage_target(short target,short dam,short type)
3465 if (target == 6) return;
3466 if (target < 6)
3467 damage_pc(target,dam,type,-1);
3468 else damage_monst(target - 100, 7, dam, 0, type);
3472 // target = find_fireball_loc(caster->m_loc,1,(caster->attitude == 1) ? 0 : 1,&target_levels);
3474 location find_fireball_loc(location where,short radius,short mode,short *m)
3475 //short mode; // 0 - hostile casting 1 - friendly casting
3477 location check_loc,cast_loc = {120,0};
3478 short i,j,k,cur_lev,level_max = 10;
3480 for (check_loc.x = 1; check_loc.x < town_size[town_type] - 1; check_loc.x ++)
3481 for (check_loc.y = 1; check_loc.y < town_size[town_type] - 1; check_loc.y ++)
3482 if ((dist(where,check_loc) <= 8) && (can_see(where,check_loc,2) < 5) && (get_obscurity(check_loc.x,check_loc.y) < 5)) {
3484 cur_lev = count_levels(check_loc,radius);
3485 if (mode == 1)
3486 cur_lev = cur_lev * -1;
3487 if ( ((cur_lev > level_max) || ((cur_lev == level_max) && (get_ran(1,0,1) == 0)))
3488 && (dist(where,check_loc) > radius)) {
3489 level_max = cur_lev;
3490 cast_loc = check_loc;
3494 *m = level_max;
3496 return cast_loc;
3499 location closest_pc_loc(location where)
3501 short i;
3502 location pc_where = {120,120};
3504 for (i = 0; i < 6; i++)
3505 if (adven[i].main_status == 1)
3506 if ((dist(where,pc_pos[i])) < (dist(where,pc_where)))
3507 pc_where = pc_pos[i];
3508 return pc_where;
3511 short count_levels(location where,short radius)
3513 short i,store = 0;
3515 for (i = 0; i < T_M; i++)
3516 if (monst_near(i,where,radius,0) == TRUE) {
3517 if (c_town.monst.dudes[i].attitude % 2 == 1)
3518 store = store - c_town.monst.dudes[i].m_d.level;
3519 else store = store + c_town.monst.dudes[i].m_d.level;
3521 if (is_combat()) {
3522 for (i = 0; i < 6; i++)
3523 if (pc_near(i,where,radius) == TRUE)
3524 store = store + 10;
3526 if (is_town())
3527 if ((vdist(where,c_town.p_loc) <= radius) && (can_see(where,c_town.p_loc,2) < 5))
3528 store += 20;
3530 return store;
3533 Boolean pc_near(short pc_num,location where,short radius)
3535 // Assuming not looking
3536 if (overall_mode >= 10) {
3537 if ((adven[pc_num].main_status == 1) && (vdist(pc_pos[pc_num],where) <= radius))
3538 return TRUE;
3539 else return FALSE;
3541 if ((adven[pc_num].main_status == 1) && (vdist(c_town.p_loc,where) <= radius))
3542 return TRUE;
3543 else return FALSE;
3546 /*short pc_there(where)
3547 location where;
3549 short i;
3551 for (i = 0; i < 6; i++)
3552 if ((adven[i].main_status == 1) && (pc_pos[i].x == where.x) && (pc_pos[i].y == where.y))
3553 return i;
3554 return 6;
3555 } */
3557 Boolean monst_near(short m_num,location where,short radius,short active)
3558 //short active; // 0 - any monst 1 - monster need be active
3560 if ((c_town.monst.dudes[m_num].active != 0) && (vdist(c_town.monst.dudes[m_num].m_loc,where) <= radius)
3561 && ((active == 0) || (c_town.monst.dudes[m_num].active == 2)) )
3562 return TRUE;
3563 else return FALSE;
3566 void fireball_space(location loc,short dam)
3568 place_spell_pattern(square,loc,50 + dam,FALSE,7);
3571 void place_spell_pattern(effect_pat_type pat,location center,short type,Boolean prep_for_anim,short who_hit)
3572 //type; // 0 - take codes in pattern, OW make all nonzero this type
3573 // Types 0 - Null 1 - web 2 - fire barrier 3 - force barrier 4 - force wall 5 - fire wall
3574 // 6 - anti-magic field 7 - stink cloud 8 - ice wall 9 - blade wall 10 - quickfire
3575 // 11 - dispel 12 - sleep field
3576 // 50 + i - 80 : id6 fire damage 90 + i - 120 : id6 cold damage 130 + i - 160 : id6 magic dam.
3577 // if prep for anim is TRUE, supporess look checks and go fast
3579 short i,j,r1,k,store = 0;
3580 unsigned char effect;
3581 location spot_hit;
3582 location s_loc,loc;
3583 RECT active;
3584 creature_data_type *which_m;
3585 Boolean monster_hit = FALSE;
3587 location pool_locs[5] = {{13,2},{11,19},{34,22},{46,15},{46,7}};
3589 if (type > 0)
3590 modify_pattern(&pat,type);
3592 // first clip out special results.
3593 if (((is_town()) || ((is_combat()) && (which_combat_type == 1))) && (c_town.town_num == 46) && (center.x == 24) && (center.y == 41)
3594 && (PSD[46][9] == 0) && (type >= 50) && (type < 90)) {
3595 end_missile_anim();
3596 run_a_missile(pc_pos[current_pc],center,2,1,11,0,0,200);
3597 mondo_boom(center,0);
3598 FCD(3464,0);
3599 PSD[46][9] = 1;
3600 for (i = 0; i < 4; i++)
3601 elim_monst(138 + i,46,9);
3602 alter_space(24,41,0);
3603 return;
3605 for (i = 0; i < 5; i++)
3606 store += PSD[20][i];
3607 if (((is_town()) || ((is_combat()) && (which_combat_type == 1))) && (c_town.town_num == 23))
3608 for (i = 0; i < 5; i++)
3609 if ((center.x == pool_locs[i].x) && (center.y == pool_locs[i].y)
3610 && (PSD[20][i] == 0) && (type >= 50) && (type < 90)) {
3611 end_missile_anim();
3612 run_a_missile(pc_pos[current_pc],center,2,1,11,0,0,200);
3613 mondo_boom(center,0);
3614 if (store == 4) {
3615 FCD(3239,0);
3616 PSD[23][3] = 20;
3617 erase_specials();
3619 else FCD(3238,0);
3620 PSD[20][i] = 1;
3621 alter_space(pool_locs[i].x,pool_locs[i].y,0);
3622 return;
3626 active = c_town.town.in_town_rect;
3627 // eliminate barriers that can't be seen
3628 for (i = minmax(active.left + 1,active.right - 1,center.x - 4);
3629 i <= minmax(active.left + 1,active.right - 1,center.x + 4); i++)
3630 for (j = minmax(active.top + 1,active.bottom - 1,center.y - 4);
3631 j <= minmax(active.top + 1,active.bottom - 1,center.y + 4); j++) {
3632 s_loc.x = i; s_loc.y = j;
3633 if (can_see(center,s_loc,0) == 5)
3634 pat.pattern[i - center.x + 4][j - center.y + 4] = 0;
3638 // First actually make barriers, then draw them, then inflict damaging effects.
3639 for (i = minmax(0,town_size[town_type] - 1,center.x - 4); i <= minmax(0,town_size[town_type] - 1,center.x + 4); i++)
3640 for (j = minmax(0,town_size[town_type] - 1,center.y - 4); j <= minmax(0,town_size[town_type] - 1,center.y + 4); j++)
3641 if (get_obscurity(i,j) < 5) {
3642 effect = pat.pattern[i - center.x + 4][j - center.y + 4];
3643 switch (effect) {
3644 case 1: web_space(i,j); break;
3645 case 2: make_fire_barrier(i,j); break;
3646 case 3: make_force_barrier(i,j); break;
3647 case 4:
3648 make_force_wall(i,j); break;
3649 case 5: make_fire_wall(i,j); break;
3650 case 6: make_antimagic(i,j); break;
3651 case 7: scloud_space(i,j); break;
3652 case 8: make_ice_wall(i,j); break;
3653 case 9: make_blade_wall(i,j); break;
3654 case 10:
3655 make_quickfire(i,j);
3656 break;
3657 case 11:
3658 dispel_fields(i,j,0);
3659 break;
3660 case 12: sleep_cloud_space(i,j); break;
3663 draw_terrain(0);
3664 if (is_town()) // now make things move faster if in town
3665 fast_bang = 2;
3667 // Damage to pcs
3668 for (k = 0; k < 6; k++)
3669 for (i = minmax(0,town_size[town_type] - 1,center.x - 4); i <= minmax(0,town_size[town_type] - 1,center.x + 4); i++)
3670 for (j = minmax(0,town_size[town_type] - 1,center.y - 4); j <= minmax(0,town_size[town_type] - 1,center.y + 4); j++) {
3671 spot_hit.x = i;
3672 spot_hit.y = j;
3673 if ((get_obscurity(i,j) < 5) && (adven[k].main_status == 1)
3674 && (((is_combat()) &&(same_point(pc_pos[k],spot_hit) == TRUE)) ||
3675 ((is_town()) && (same_point(c_town.p_loc,spot_hit) == TRUE)))) {
3676 effect = pat.pattern[i - center.x + 4][j - center.y + 4];
3677 switch (effect) {
3678 case 4:
3679 r1 = get_ran(2,1,6);
3680 damage_pc(k,r1,3,-1);
3681 break;
3682 case 5:
3683 r1 = get_ran(1,1,6) + 1;
3684 damage_pc(k,r1,1,-1);
3685 break;
3686 case 8:
3687 r1 = get_ran(2,1,6);
3688 damage_pc(k,r1,5,-1);
3689 break;
3690 case 9:
3691 r1 = get_ran(4,1,8);
3692 damage_pc(k,r1,0,-1);
3693 break;
3694 default:
3695 if ((effect >= 50) && (effect < 80)) {
3696 r1 = get_ran(effect - 50,1,6);
3697 damage_pc(k,r1,1,-1);
3699 if ((effect >= 90) && (effect < 120)) {
3700 r1 = get_ran(effect - 90,1,6);
3701 damage_pc(k,r1,5,-1);
3703 if ((effect >= 130) && (effect < 160)) {
3704 r1 = get_ran(effect - 130,1,6);
3705 damage_pc(k,r1,3,-1);
3707 break;
3712 fast_bang = 0;
3714 // Damage to monsters
3715 for (k = 0; k < T_M; k++)
3716 if ((c_town.monst.dudes[k].active > 0) && (dist(center,c_town.monst.dudes[k].m_loc) <= 5)) {
3717 monster_hit = FALSE;
3718 // First actually make barriers, then draw them, then inflict damaging effects.
3719 for (i = minmax(0,town_size[town_type] - 1,center.x - 4); i <= minmax(0,town_size[town_type] - 1,center.x + 4); i++)
3720 for (j = minmax(0,town_size[town_type] - 1,center.y - 4); j <= minmax(0,town_size[town_type] - 1,center.y + 4); j++) {
3721 spot_hit.x = i;
3722 spot_hit.y = j;
3724 if ((monster_hit == FALSE) && (get_obscurity(i,j) < 5) && (monst_on_space(spot_hit,k) > 0)) {
3726 if (pat.pattern[i - center.x + 4][j - center.y + 4] > 0)
3727 monster_hit = TRUE;
3728 effect = pat.pattern[i - center.x + 4][j - center.y + 4];
3729 switch (effect) {
3730 case 1:
3731 which_m = &c_town.monst.dudes[k];
3732 web_monst(which_m,3);
3733 break;
3734 case 4:
3735 r1 = get_ran(3,1,6);
3736 damage_monst(k, who_hit, r1,0, 3);
3737 break;
3738 case 5:
3739 r1 = get_ran(2,1,6);
3740 which_m = &c_town.monst.dudes[k];
3741 if (which_m->m_d.spec_skill == 22)
3742 break;
3743 damage_monst(k, who_hit, r1,0, 1);
3744 break;
3745 case 7:
3746 which_m = &c_town.monst.dudes[k];
3747 curse_monst(which_m,get_ran(1,1,2));
3748 break;
3749 case 8:
3750 which_m = &c_town.monst.dudes[k];
3751 r1 = get_ran(3,1,6);
3752 if (which_m->m_d.spec_skill == 23)
3753 break;
3754 damage_monst(k, who_hit, r1,0, 5);
3755 break;
3756 case 9:
3757 r1 = get_ran(6,1,8);
3758 damage_monst(k, who_hit, r1,0, 0);
3759 break;
3760 case 12:
3761 which_m = &c_town.monst.dudes[k];
3762 charm_monst(which_m,0,11,3);
3763 break;
3764 default:
3765 if ((effect >= 50) && (effect < 80)) {
3766 r1 = get_ran(effect - 50,1,6);
3767 damage_monst(k,who_hit, r1,0,1);
3769 if ((effect >= 90) && (effect < 120)) {
3770 r1 = get_ran(effect - 90,1,6);
3771 damage_monst(k,who_hit, r1,0, 5);
3773 if ((effect >= 130) && (effect < 160)) {
3774 r1 = get_ran(effect - 130,1,6);
3775 damage_monst(k,who_hit, r1,0, 3 );
3784 void modify_pattern(effect_pat_type *pat,short type)
3786 short i,j;
3788 for (i = 0; i < 9; i++)
3789 for (j = 0; j < 9; j++)
3790 if (pat->pattern[i][j] > 0)
3791 pat->pattern[i][j] = type;
3794 void do_shockwave(location target)
3796 short i;
3798 start_missile_anim();
3799 for (i = 0; i < 6; i++)
3800 if ((dist(target,pc_pos[i]) > 0) && (dist(target,pc_pos[i]) < 11)
3801 && (adven[i].main_status == 1))
3802 damage_pc(i, get_ran(2 + dist(target,pc_pos[i]) / 2, 1, 6), 4,-1);
3803 for (i = 0; i < T_M; i++)
3804 if ((c_town.monst.dudes[i].active != 0) && (dist(target,c_town.monst.dudes[i].m_loc) > 0)
3805 && (dist(target,c_town.monst.dudes[i].m_loc) < 11)
3806 && (can_see(target,c_town.monst.dudes[i].m_loc,0) < 5))
3807 damage_monst(i, current_pc, get_ran(2 + dist(target,c_town.monst.dudes[i].m_loc) / 2 , 1, 6), 0, 4);
3808 do_explosion_anim(5,0);
3809 end_missile_anim();
3810 handle_marked_damage();
3813 void radius_damage(location target,short radius, short dam, short type)////
3815 short i;
3817 if (is_town()) {
3818 for (i = 0; i < 6; i++)
3819 if ((dist(target,c_town.p_loc) > 0) && (dist(target,c_town.p_loc) <= radius)
3820 && (adven[i].main_status == 1))
3821 damage_pc(i, dam, type,-1);
3822 for (i = 0; i < T_M; i++)
3823 if ((c_town.monst.dudes[i].active != 0) && (dist(target,c_town.monst.dudes[i].m_loc) > 0)
3824 && (dist(target,c_town.monst.dudes[i].m_loc) <= radius)
3825 && (can_see(target,c_town.monst.dudes[i].m_loc,0) < 5))
3826 damage_monst(i, current_pc, dam, 0, type);
3827 return;
3830 start_missile_anim();
3831 for (i = 0; i < 6; i++)
3832 if ((dist(target,pc_pos[i]) > 0) && (dist(target,pc_pos[i]) <= radius)
3833 && (adven[i].main_status == 1))
3834 damage_pc(i, dam, type,-1);
3835 for (i = 0; i < T_M; i++)
3836 if ((c_town.monst.dudes[i].active != 0) && (dist(target,c_town.monst.dudes[i].m_loc) > 0)
3837 && (dist(target,c_town.monst.dudes[i].m_loc) <= radius)
3838 && (can_see(target,c_town.monst.dudes[i].m_loc,0) < 5))
3839 damage_monst(i, current_pc, dam, 0, type);
3840 do_explosion_anim(5,0);
3841 end_missile_anim();
3842 handle_marked_damage();
3845 // Slightly kludgy way to only damage PCs in space)
3846 void hit_pcs_in_space(location target,short dam,short type,short report,short hit_all)
3848 //short store_active[T_M],i;
3850 //for (i = 0; i < T_M; i++) {
3851 // store_active[i] = c_town.monst.dudes[i].active;
3852 // c_town.monst.dudes[i].active = 0;
3853 // }
3854 hit_space(target, dam,type, report, 10 + hit_all);
3855 //for (i = 0; i < T_M; i++)
3856 // c_town.monst.dudes[i].active = store_active[i];
3859 void hit_space(location target,short dam,short type,short report,short hit_all)
3860 //type; // 0 - weapon 1 - fire 2 - poison 3 - general magic 4 - unblockable 5 - cold
3861 // 6 - demon 7 - undead
3862 //short report; // 0 - no 1 - print result
3863 //hit_all; // 0 - nail top thing 1 - hit all in space + 10 ... no monsters
3865 short i;
3866 Boolean stop_hitting = FALSE,hit_monsters = TRUE;
3868 // sprintf ((char *) create_line, " %d %d. ",target.x,target.y);
3869 // add_string_to_buf((char *) create_line);
3870 if ((target.x < 0) || (target.x > 63) || (target.y < 0) || (target.y > 63))
3871 return;
3873 if (hit_all >= 10) {
3874 hit_monsters = FALSE;
3875 hit_all -= 10;
3878 if ((is_antimagic(target.x,target.y)) && ((type == 1) || (type == 3) || (type == 5))) {
3879 return;
3882 if (dam <= 0) {
3883 add_string_to_buf(" No damage.");
3884 return;
3887 for (i = 0; i < T_M; i++)
3888 if ((hit_monsters == TRUE) && (c_town.monst.dudes[i].active != 0) && (stop_hitting == FALSE))
3889 if (monst_on_space(target,i)) {
3890 if (processing_fields == TRUE)
3891 damage_monst(i, 6, dam, 0, type);
3892 else damage_monst(i, (monsters_going == TRUE) ? 7 : current_pc, dam, 0, type);
3893 stop_hitting = (hit_all == 1) ? FALSE : TRUE;
3896 if (overall_mode >= 10)
3897 for (i = 0; i < 6; i++)
3898 if ((adven[i].main_status == 1) && (stop_hitting == FALSE))
3899 if (same_point(pc_pos[i],target) == TRUE) {
3900 damage_pc(i,dam,type,-1);
3901 stop_hitting = (hit_all == 1) ? FALSE : TRUE;
3903 if (overall_mode < 10)
3904 if (same_point(target,c_town.p_loc) == TRUE) {
3905 fast_bang = 1;
3906 hit_party(dam,type);
3907 fast_bang = 0;
3908 stop_hitting = (hit_all == 1) ? FALSE : TRUE;
3911 if ((report == 1) && (hit_all == 0) && (stop_hitting == FALSE))
3912 add_string_to_buf(" Missed.");
3918 void do_poison()
3920 short i,r1 = 0;
3921 Boolean some_poison = FALSE;
3923 for (i = 0; i < 6; i++)
3924 if (adven[i].main_status == 1)
3925 if (adven[i].status[2] > 0)
3926 some_poison = TRUE;
3927 if (some_poison == TRUE) {
3928 add_string_to_buf("Poison: ");
3929 for (i = 0; i < 6; i++)
3930 if (adven[i].main_status == 1)
3931 if (adven[i].status[2] > 0) {
3932 r1 = get_ran(adven[i].status[2],1,6);
3933 damage_pc(i,r1,2,-1);
3934 if (get_ran(1,0,8) < 6)
3935 adven[i].status[2] = move_to_zero(adven[i].status[2]);
3936 if (get_ran(1,0,8) < 6)
3937 if (adven[i].traits[6] == TRUE)
3938 adven[i].status[2] = move_to_zero(adven[i].status[2]);
3940 put_pc_screen();
3941 //if (overall_mode < 10)
3942 // boom_space(party.p_loc,overall_mode,2,r1);
3947 void handle_disease()
3949 short i,r1 = 0;
3950 Boolean disease = FALSE;
3952 for (i = 0; i < 6; i++)
3953 if (adven[i].main_status == 1)
3954 if (adven[i].status[7] > 0)
3955 disease = TRUE;
3957 if (disease == TRUE) {
3958 add_string_to_buf("Disease: ");
3959 for (i = 0; i < 6; i++)
3960 if (adven[i].main_status == 1)
3961 if (adven[i].status[7] > 0) {
3962 r1 = get_ran(1,1,10);
3963 switch (r1) {
3964 case 1: case 2:
3965 poison_pc(i,2);
3966 break;
3967 case 3: case 4:
3968 slow_pc(i,2);
3969 break;
3970 case 5:
3971 drain_pc(i,5);
3972 break;
3973 case 6: case 7:
3974 curse_pc(i,3);
3975 break;
3976 case 8:
3977 dumbfound_pc(i,3);
3978 break;
3979 case 9: case 10:
3980 sprintf ((char *) create_line, " %s unaffected. ",
3981 (char *) adven[i].name);
3982 add_string_to_buf((char *) create_line);
3983 break;
3985 r1 = get_ran(1,0,7);
3986 if (adven[i].traits[6] == TRUE)
3987 r1 -= 2;
3988 if ((get_ran(1,0,7) <= 0) || (pc_has_abil_equip(i,67) < 24))
3989 adven[i].status[7] = move_to_zero(adven[i].status[7]);
3991 put_pc_screen();
3995 void handle_acid()
3997 short i,r1 = 0;
3998 Boolean some_acid = FALSE;
4000 for (i = 0; i < 6; i++)
4001 if (adven[i].main_status == 1)
4002 if (adven[i].status[13] > 0)
4003 some_acid = TRUE;
4005 if (some_acid == TRUE) {
4006 add_string_to_buf("Acid: ");
4007 for (i = 0; i < 6; i++)
4008 if (adven[i].main_status == 1)
4009 if (adven[i].status[13] > 0) {
4010 r1 = get_ran(adven[i].status[13],1,6);
4011 damage_pc(i,r1,3,-1);
4012 adven[i].status[13] = move_to_zero(adven[i].status[13]);
4014 if (overall_mode < 10)
4015 boom_space(party.p_loc,overall_mode,3,r1,8);
4019 Boolean no_pcs_left()
4021 short i = 0;
4023 while (i < 6) {
4024 if (adven[i].main_status == 1)
4025 return FALSE;
4026 i++;
4028 return TRUE;
4032 Boolean hit_end_c_button()
4034 Boolean end_ok = TRUE;
4035 short i;
4037 if (which_combat_type == 0) {
4038 end_ok = out_monst_all_dead();
4040 // if (adven[0].extra[7] > 0)
4041 // end_ok = TRUE;
4043 if (end_ok == TRUE)
4044 end_combat();
4045 return end_ok;
4048 Boolean out_monst_all_dead()
4050 short i;
4052 for (i = 0; i < T_M; i++)
4053 if ((c_town.monst.dudes[i].active > 0) && (c_town.monst.dudes[i].attitude % 2 == 1))
4054 return FALSE;
4055 return TRUE;
4058 void end_combat()
4060 short i;
4062 for (i = 0; i < 6; i++) {
4063 if (adven[i].main_status == 5)
4064 adven[i].main_status = 1;
4065 adven[i].status[0] = 0;
4066 adven[i].status[1] = 0;
4067 adven[i].status[3] = 0;
4069 if (which_combat_type == 0) {
4070 overall_mode = 0;
4071 load_area_graphics();
4073 combat_active_pc = 6;
4074 current_pc = store_current_pc;
4075 if (adven[current_pc].main_status != 1)
4076 current_pc = first_active_pc();
4077 put_item_screen(stat_window,0);
4078 draw_buttons(0);
4082 Boolean combat_cast_mage_spell()
4084 short spell_num,target,i,store_sp,bonus = 1,r1,store_sound = 0,store_m_type = 0,num_opp = 0;
4085 char c_line[60];
4086 creature_data_type *which_m;
4087 monster_record_type get_monst;
4089 if (is_antimagic(pc_pos[current_pc].x,pc_pos[current_pc].y)) {
4090 add_string_to_buf(" Not in antimagic field.");
4091 return FALSE;
4093 store_sp = adven[current_pc].cur_sp;
4094 if (adven[current_pc].cur_sp == 0)
4095 add_string_to_buf("Cast: No spell points. ");
4096 else if (adven[current_pc].skills[9] == 0)
4097 add_string_to_buf("Cast: No mage skill. ");
4098 else if (get_encumberance(current_pc) > 1) {
4099 add_string_to_buf("Cast: Too encumbered. ");
4100 take_ap(6);
4101 give_help(40,0,0);
4102 return TRUE;
4104 else {
4107 if (spell_forced == FALSE)
4108 spell_num = pick_spell(current_pc,0,2);
4109 else {
4110 if (repeat_cast_ok(0) == FALSE)
4111 return FALSE;
4112 spell_num = pc_last_cast[0][current_pc];
4115 if (spell_num == 35) {
4116 store_sum_monst = pick_trapped_monst();
4117 if (store_sum_monst == 0)
4118 return FALSE;
4119 get_monst = return_monster_template(store_sum_monst);
4120 if (store_sp < get_monst.level) {
4121 add_string_to_buf("Cast: Not enough spell points. ");
4122 return FALSE;
4124 store_sum_monst_cost = get_monst.level;
4127 bonus = stat_adj(current_pc,2);
4128 combat_posing_monster = current_working_monster = current_pc;
4129 if (spell_num >= 70)
4130 return FALSE;
4131 if (spell_num < 70) {
4132 print_spell_cast(spell_num,0);
4133 if (refer_mage[spell_num] == 0) {
4134 take_ap(6);
4135 draw_terrain(2);
4136 do_mage_spell(current_pc,spell_num);
4137 combat_posing_monster = current_working_monster = -1;
4139 else if (refer_mage[spell_num] == 2) {
4140 start_spell_targeting(spell_num);
4142 else if (refer_mage[spell_num] == 3) {
4143 start_fancy_spell_targeting(spell_num);
4145 else {
4146 start_missile_anim();
4147 take_ap(6);
4148 draw_terrain(2);
4149 switch (spell_num) {
4150 case 54:
4151 adven[current_pc].cur_sp -= s_cost[0][spell_num];
4152 add_string_to_buf(" The ground shakes. ");
4153 do_shockwave(pc_pos[current_pc]);
4154 break;
4156 case 2: case 21: case 3: case 14: case 29:
4157 // target = select_pc(11,0);
4158 target = store_spell_target;
4159 if (target < 6) {
4160 adven[current_pc].cur_sp -= s_cost[0][spell_num];
4161 play_sound(4);
4162 switch (spell_num) {
4163 case 14:
4164 sprintf ((char *) c_line, " %s receives venom. ",
4165 (char *) adven[target].name);
4166 poison_weapon(target,3 + bonus,1);
4167 store_m_type = 11;
4168 break;
4170 case 3:
4171 sprintf ((char *) c_line, " %s stronger. ",
4172 (char *) adven[target].name);
4173 adven[target].status[1] = adven[target].status[1] + 3;
4174 store_m_type = 8;
4175 break;
4176 case 29:
4177 sprintf ((char *) c_line, " %s resistant. ",
4178 (char *) adven[target].name);
4179 adven[target].status[5] = adven[target].status[5] + 5 + bonus;
4180 store_m_type = 15;
4181 break;
4183 default:
4184 i = (spell_num == 2) ? 2 : max(2,adven[current_pc].level / 2 + bonus);
4185 adven[target].status[3] = min(8,
4186 adven[target].status[3] + i);
4187 sprintf ((char *) c_line, " %s hasted. ",
4188 (char *) adven[target].name);
4189 store_m_type = 8;
4190 break;
4192 add_string_to_buf((char *) c_line);
4193 add_missile(pc_pos[target],store_m_type,0,0,0);
4195 break;
4197 case 39: case 55:
4198 store_sound = 25;
4199 adven[current_pc].cur_sp -= s_cost[0][spell_num];
4202 for (i = 0; i < 6; i++)
4203 if (adven[i].main_status == 1) {
4204 adven[i].status[3] = min(8,
4205 adven[i].status[3] + ((spell_num == 39) ? 1 + adven[current_pc].level / 8 + bonus : 3 + bonus));
4206 if (spell_num == 55) {
4207 poison_weapon(i,2,1);
4208 adven[i].status[1] += 4;
4209 add_missile(pc_pos[i],14,0,0,0);
4211 else add_missile(pc_pos[i],8,0,0,0);
4213 //play_sound(4);
4214 if (spell_num == 39)
4215 sprintf ((char *) c_line, " Party hasted. ");
4216 else
4217 sprintf ((char *) c_line, " Party blessed! ");
4218 add_string_to_buf((char *) c_line);
4220 break;
4224 case 32: case 47: case 56: // affect monsters in area spells
4225 adven[current_pc].cur_sp -= s_cost[0][spell_num];
4226 store_sound = 25;
4227 if (spell_num == 47)
4228 store_sound = 54;
4229 switch (spell_num) {
4230 case 32: sprintf ((char *) c_line, " Enemy slowed: "); break;
4231 case 49: sprintf ((char *) c_line, " Enemy ravaged: ");break;
4232 case 47: sprintf ((char *) c_line, " Enemy scared: ");break;
4233 case 56: sprintf ((char *) c_line, " Enemy paralyzed: ");break;
4235 add_string_to_buf((char *) c_line);
4236 for (i = 0; i < T_M; i++) {
4237 if ((c_town.monst.dudes[i].active != 0) && (c_town.monst.dudes[i].attitude % 2 == 1)
4238 && (dist(pc_pos[current_pc],c_town.monst.dudes[i].m_loc) <= mage_range[spell_num])
4239 && (can_see(pc_pos[current_pc],c_town.monst.dudes[i].m_loc,0) < 5)) {
4240 which_m = &c_town.monst.dudes[i];
4241 switch (spell_num) {
4242 case 47:
4243 r1 = get_ran(adven[current_pc].level / 3,1,8);
4244 scare_monst(which_m,r1);
4245 store_m_type = 10;
4246 break;
4247 case 32: case 49:
4248 slow_monst(which_m,5 + bonus);
4249 if (spell_num == 49)
4250 curse_monst(which_m,3 + bonus);
4251 store_m_type = 8;
4252 break;
4253 case 56:
4254 charm_monst(which_m,15,12,1000);
4255 store_m_type = 15;
4256 break;
4258 num_opp++;
4259 add_missile(c_town.monst.dudes[i].m_loc,store_m_type,0,
4260 14 * (which_m->m_d.x_width - 1),18 * (which_m->m_d.y_width - 1));
4264 break;
4269 if (num_opp < 10)
4270 do_missile_anim((num_opp < 5) ? 50 : 25,pc_pos[current_pc],store_sound);
4271 else play_sound(store_sound);
4272 end_missile_anim();
4273 put_pc_screen();
4277 combat_posing_monster = current_working_monster = -1;
4278 // Did anything actually get cast?
4279 if (store_sp == adven[current_pc].cur_sp)
4280 return FALSE;
4281 else return TRUE;
4285 Boolean combat_cast_priest_spell()
4287 short spell_num,target,i,store_sp,bonus,store_sound = 0,store_m_type = 0,num_opp = 0;
4288 char c_line[60];
4289 creature_data_type *which_m;
4290 effect_pat_type protect_pat = {{{0,4,4,4,4,4,4,4,0},
4291 {4,8,8,8,8,8,8,8,4},
4292 {4,8,9,9,9,9,9,8,4},
4293 {4,8,9,6,6,6,9,8,4},
4294 {4,8,9,6,6,6,9,8,4},
4295 {4,8,9,6,6,6,9,8,4},
4296 {4,8,9,9,9,9,9,8,4},
4297 {4,8,8,8,8,8,8,8,4},
4298 {0,4,4,4,4,4,4,4,0}}};
4300 if (is_antimagic(pc_pos[current_pc].x,pc_pos[current_pc].y)) {
4301 add_string_to_buf(" Not in antimagic field.");
4302 return FALSE;
4304 if (spell_forced == FALSE)
4305 spell_num = pick_spell(current_pc,1,2);
4306 else {
4307 if (repeat_cast_ok(1) == FALSE)
4308 return FALSE;
4309 spell_num = pc_last_cast[1][current_pc];
4312 store_sp = adven[current_pc].cur_sp;
4314 if (spell_num >= 70)
4315 return FALSE;
4316 bonus = stat_adj(current_pc,2);
4318 combat_posing_monster = current_working_monster = current_pc;
4320 if (adven[current_pc].cur_sp == 0)
4321 add_string_to_buf("Cast: No spell points. ");
4322 else if (spell_num < 70) {
4323 print_spell_cast(spell_num,1);
4324 if (refer_priest[spell_num] == 0) {
4325 take_ap(5);
4326 draw_terrain(2);
4327 do_priest_spell(current_pc,spell_num);
4329 else if (refer_priest[spell_num] == 2) {
4330 start_spell_targeting(100 + spell_num);
4332 else if (refer_priest[spell_num] == 3) {
4333 start_fancy_spell_targeting(100 + spell_num);
4335 else {
4336 start_missile_anim();
4337 take_ap(5);
4338 draw_terrain(2);
4339 switch (spell_num) {
4340 case 0: case 10:
4341 // target = select_pc(11,0);
4342 target = store_spell_target;
4343 if (target < 6) {
4344 store_sound = 4;
4345 adven[current_pc].cur_sp -= s_cost[1][spell_num];
4346 adven[target].status[1] += (spell_num == 0) ? 2 :
4347 max(2,(adven[current_pc].level * 3) / 4 + 1 + bonus);
4348 sprintf ((char *) c_line, " %s blessed. ",
4349 (char *) adven[target].name);
4350 add_string_to_buf((char *) c_line);
4351 add_missile(pc_pos[target],8,0,0,0);
4353 break;
4355 case 38:
4356 adven[current_pc].cur_sp -= s_cost[1][spell_num];
4357 for (i = 0; i < 6; i++)
4358 if (adven[i].main_status == 1) {
4359 adven[i].status[1] += adven[current_pc].level / 3;
4360 add_missile(pc_pos[i],8,0,0,0);
4362 sprintf ((char *) c_line, " Party blessed. ");
4363 add_string_to_buf((char *) c_line);
4364 store_sound = 4;
4365 break;
4367 case 58:
4368 adven[current_pc].cur_sp -= s_cost[1][spell_num];
4369 sprintf ((char *) c_line, " %s is an avatar! ",
4370 (char *) adven[current_pc].name);
4371 add_string_to_buf((char *) c_line);
4372 heal_pc(current_pc,200);
4373 cure_pc(current_pc,8);
4374 adven[current_pc].status[1] = 8;
4375 adven[current_pc].status[3] = 8;
4376 adven[current_pc].status[4] = 3;
4377 adven[current_pc].status[5] = 8;
4378 adven[current_pc].status[6] = 0;
4379 adven[current_pc].status[7] = 0;
4380 adven[current_pc].status[9] = 0;
4381 adven[current_pc].status[10] = 8;
4382 break;
4384 case 31: case 51: case 53:
4385 adven[current_pc].cur_sp -= s_cost[1][spell_num];
4386 store_sound = 24;
4387 for (i = 0; i < T_M; i++) {
4388 if ((c_town.monst.dudes[i].active != 0) &&(c_town.monst.dudes[i].attitude % 2 == 1) &&
4389 (dist(pc_pos[current_pc],c_town.monst.dudes[i].m_loc) <= priest_range[spell_num])) {
4390 which_m = &c_town.monst.dudes[i];
4391 switch (spell_num) {
4392 case 31:
4393 curse_monst(which_m,3 + bonus);
4394 store_m_type = 8;
4395 break;
4396 case 51:
4397 charm_monst(which_m,28 - bonus,0,0);
4398 store_m_type = 14;
4399 break;
4400 case 53:
4401 disease_monst(which_m,3 + bonus);
4402 store_m_type = 0;
4403 break;
4405 num_opp++;
4406 add_missile(c_town.monst.dudes[i].m_loc,store_m_type,0,
4407 14 * (which_m->m_d.x_width - 1),18 * (which_m->m_d.y_width - 1));
4411 break;
4413 case 52:
4414 adven[current_pc].cur_sp -= s_cost[1][spell_num];
4415 play_sound(24);
4416 add_string_to_buf(" Protective field created.");
4417 place_spell_pattern(protect_pat,pc_pos[current_pc],0,FALSE,6);
4418 break;
4421 if (num_opp < 10)
4422 do_missile_anim((num_opp < 5) ? 50 : 25,pc_pos[current_pc],store_sound);
4423 else play_sound(store_sound);
4424 end_missile_anim();
4425 put_pc_screen();
4428 combat_posing_monster = current_working_monster = -1;
4429 // Did anything actually get cast?
4430 if (store_sp == adven[current_pc].cur_sp)
4431 return FALSE;
4432 else return TRUE;
4435 void start_spell_targeting(short num)
4438 // First, remember what spell was cast.
4439 spell_being_cast = num;
4441 // Then, is num >= 1000, it's a freebie, so remove the 1000
4442 if (num >= 1000)
4443 num -= 1000;
4444 sprintf ((char *) create_line, " Target spell. ");
4445 add_string_to_buf((char *) create_line);
4446 if (num < 100)
4447 add_string_to_buf(" (Hit 'm' to cancel.)");
4448 else add_string_to_buf(" (Hit 'p' to cancel.)");
4449 overall_mode = 11;
4450 current_spell_range = (num >= 100) ? priest_range[num - 100] : mage_range[num];
4451 current_pat = single;
4453 switch (num) { // Different spells have different messages and diff. target shapes
4454 case 19:
4455 current_pat = small_square;
4456 break;
4457 case 18: case 22: case 141: case 126: case 15: case 119:
4458 current_pat = square;
4459 break;
4460 case 17: case 40: case 44: case 28: case 51: case 157: case 145: case 64: case 67:
4461 current_pat = rad2;
4462 break;
4463 case 153: case 65: case 66:
4464 current_pat = rad3;
4465 break;
4466 case 25: case 37: case 159:
4467 add_string_to_buf(" (Hit space to rotate.)");
4468 force_wall_position = 0;
4469 current_pat = field[0];
4470 break;
4474 void start_fancy_spell_targeting(short num)
4476 short i;
4477 location null_loc = {120,0};
4479 // First, remember what spell was cast.
4480 spell_being_cast = num;
4481 // Then, is num >= 1000, it's a freebie, so remove the 1000
4482 if (num >= 1000)
4483 num -= 1000;
4485 for (i = 0; i < 8; i++)
4486 spell_targets[i] = null_loc;
4487 sprintf ((char *) create_line, " Target spell. ");
4488 if (num < 100)
4489 add_string_to_buf(" (Hit 'm' to cancel.)");
4490 else add_string_to_buf(" (Hit 'p' to cancel.)");
4491 add_string_to_buf(" (Hit space to cast.)");
4492 add_string_to_buf((char *) create_line);
4493 overall_mode = 14;
4494 current_pat = single;
4495 current_spell_range = (num >= 100) ? priest_range[num - 100] : mage_range[num];
4497 switch (num) { // Assign special targeting shapes and number of targets
4498 case 129: // smite
4499 num_targets_left = minmax(1,8,adven[current_pc].level / 4 + stat_adj(current_pc,2) / 2);
4500 break;
4501 case 134: // sticks to snakes
4502 num_targets_left = adven[current_pc].level / 5 + stat_adj(current_pc,2) / 2;
4503 break;
4504 case 143: // summon host
4505 num_targets_left = 5;
4506 break;
4507 case 27: // flame arrows
4508 num_targets_left = adven[current_pc].level / 4 + stat_adj(current_pc,2) / 2;
4509 break;
4510 case 36: // venom arrows
4511 num_targets_left = adven[current_pc].level / 5 + stat_adj(current_pc,2) / 2;
4512 break;
4513 case 61: case 49: // paralysis, death arrows
4514 num_targets_left = adven[current_pc].level / 8 + stat_adj(current_pc,2) / 3;
4515 break;
4516 case 45: // spray fields
4517 num_targets_left = adven[current_pc].level / 5 + stat_adj(current_pc,2) / 2;
4518 current_pat = t;
4519 break;
4520 case 26: // summon 1
4521 num_targets_left = minmax(1,7,adven[current_pc].level / 4 + stat_adj(current_pc,2) / 2);
4522 break;
4523 case 43: // summon 2
4524 num_targets_left = minmax(1,6,adven[current_pc].level / 6 + stat_adj(current_pc,2) / 2);
4525 break;
4526 case 58: // summon 3
4527 num_targets_left = minmax(1,5,adven[current_pc].level / 8 + stat_adj(current_pc,2) / 2);
4528 break;
4531 num_targets_left = minmax(1,8,num_targets_left);
4534 void spell_cast_hit_return()
4536 location null_loc = {0,0};
4538 if (force_wall_position < 10) {
4539 force_wall_position = (force_wall_position + 1) % 8;
4540 current_pat = field[force_wall_position];
4544 void process_fields()
4546 short i,j,k,l,m,r1;
4547 location loc;
4548 char qf[64][64];
4549 RECT r;
4551 if (is_out())
4552 return;
4554 if (quickfire) {
4555 r = c_town.town.in_town_rect;
4556 for (i = 0; i < town_size[town_type]; i++)
4557 for (j = 0; j < town_size[town_type]; j++)
4558 qf[i][j] = (is_quickfire(i,j)) ? 2 : 0;
4559 for (k = 0; k < ((is_combat()) ? 4 : 1); k++) {
4560 for (i = r.left + 1; i < r.right ; i++)
4561 for (j = r.top + 1; j < r.bottom ; j++)
4562 if (is_quickfire(i,j) > 0) {
4563 r1 = get_ran(1,1,8);
4564 if (r1 != 1) {
4565 qf[i - 1][j] = 1;
4566 qf[i + 1][j] = 1;
4567 qf[i][j + 1] = 1;
4568 qf[i][j - 1] = 1;
4571 for (i = r.left + 1; i < r.right ; i++)
4572 for (j = r.top + 1; j < r.bottom ; j++)
4573 if (qf[i][j] > 0) {
4574 make_quickfire(i,j);
4579 for (i = 0; i < T_M; i++)
4580 if (c_town.monst.dudes[i].active > 0)
4581 monst_inflict_fields(i);
4583 // First fry PCs, then call to handle damage to monsters
4584 processing_fields = TRUE; // this, in hit_space, makes damage considered to come from whole party
4585 if (force_wall) {
4586 force_wall = FALSE;
4587 for (i = 0; i < town_size[town_type]; i++)
4588 for (j = 0; j < town_size[town_type]; j++)
4589 if (is_force_wall(i,j)) {
4590 r1 = get_ran(3,1,6);
4591 loc.x = i; loc.y = j;
4592 hit_pcs_in_space(loc,r1,3,1,1);
4593 r1 = get_ran(1,1,6);
4594 if (r1 == 2)
4595 take_force_wall(i,j);
4596 else {
4597 force_wall = TRUE;
4601 if (fire_wall) {
4602 fire_wall = FALSE;
4603 for (i = 0; i < town_size[town_type]; i++)
4604 for (j = 0; j < town_size[town_type]; j++)
4605 if (is_fire_wall(i,j)) {
4606 loc.x = i; loc.y = j;
4607 r1 = get_ran(2,1,6) + 1;
4608 hit_pcs_in_space(loc,r1,1,1,1);
4609 r1 = get_ran(1,1,4);
4610 if (r1 == 2)
4611 take_fire_wall(i,j);
4612 else {
4613 fire_wall = TRUE;
4617 if (antimagic) {
4618 antimagic = FALSE;
4619 for (i = 0; i < town_size[town_type]; i++)
4620 for (j = 0; j < town_size[town_type]; j++)
4621 if (is_antimagic(i,j)) {
4622 r1 = get_ran(1,1,8);
4623 if (r1 == 2)
4624 take_antimagic(i,j);
4625 else antimagic = TRUE;
4628 if (scloud) {
4629 scloud = FALSE;
4630 for (i = 0; i < town_size[town_type]; i++)
4631 for (j = 0; j < town_size[town_type]; j++)
4632 if (is_scloud(i,j)) {
4633 r1 = get_ran(1,1,4);
4634 if (r1 == 2)
4635 take_scloud(i,j);
4636 else {
4637 scloud_space(i,j);
4638 scloud = TRUE;
4642 if (sleep_field) {
4643 sleep_field = FALSE;
4644 for (i = 0; i < town_size[town_type]; i++)
4645 for (j = 0; j < town_size[town_type]; j++)
4646 if (is_sleep_cloud(i,j)) {
4647 r1 = get_ran(1,1,4);
4648 if (r1 == 2)
4649 take_sleep_cloud(i,j);
4650 else {
4651 sleep_cloud_space(i,j);
4652 sleep_field = TRUE;
4656 if (ice_wall) {
4657 ice_wall = FALSE;
4658 for (i = 0; i < town_size[town_type]; i++)
4659 for (j = 0; j < town_size[town_type]; j++)
4660 if (is_ice_wall(i,j)) {
4661 loc.x = i; loc.y = j;
4662 r1 = get_ran(3,1,6);
4663 hit_pcs_in_space(loc,r1,5,1,1);
4664 r1 = get_ran(1,1,6);
4665 if (r1 == 1)
4666 take_ice_wall(i,j);
4667 else {
4668 ice_wall = TRUE;
4672 if (blade_wall) {
4673 blade_wall = FALSE;
4674 for (i = 0; i < town_size[town_type]; i++)
4675 for (j = 0; j < town_size[town_type]; j++)
4676 if (is_blade_wall(i,j)) {
4677 loc.x = i; loc.y = j;
4678 r1 = get_ran(6,1,8);
4679 hit_pcs_in_space(loc,r1,0,1,1);
4680 r1 = get_ran(1,1,5);
4681 if (r1 == 1)
4682 take_blade_wall(i,j);
4683 else {
4684 blade_wall = TRUE;
4689 processing_fields = FALSE;
4690 monsters_going = TRUE; // this changes who the damage is considered to come from
4691 // in hit_space
4693 if (quickfire) {
4694 for (i = 0; i < town_size[town_type]; i++)
4695 for (j = 0; j < town_size[town_type]; j++)
4696 if (is_quickfire(i,j)) {
4697 loc.x = i; loc.y = j;
4698 r1 = get_ran(2,1,8);
4699 hit_pcs_in_space(loc,r1,1,1,1);
4703 monsters_going = FALSE;
4706 void scloud_space(short m,short n)
4708 location target;
4709 creature_data_type *which_m;
4710 short i;
4712 target.x = (char) m;
4713 target.y = (char) n;
4715 make_scloud(m,n);
4717 if (overall_mode >= 10)
4718 for (i = 0; i < 6; i++)
4719 if (adven[i].main_status == 1)
4720 if (same_point(pc_pos[i],target) == TRUE) {
4721 curse_pc(i,get_ran(1,1,2));
4723 if (overall_mode < 10)
4724 if (same_point(target,c_town.p_loc) == TRUE) {
4725 for (i = 0; i < 6; i++)
4726 if (adven[i].main_status == 1)
4727 curse_pc(i,get_ran(1,1,2));
4731 void web_space(short m,short n)
4733 location target;
4734 creature_data_type *which_m;
4735 short i;
4737 target.x = (char) m;
4738 target.y = (char) n;
4740 make_web(m,n);
4742 if (overall_mode >= 10)
4743 for (i = 0; i < 6; i++)
4744 if (adven[i].main_status == 1)
4745 if (same_point(pc_pos[i],target) == TRUE) {
4746 web_pc(i,3);
4748 if (overall_mode < 10)
4749 if (same_point(target,c_town.p_loc) == TRUE) {
4750 for (i = 0; i < 6; i++)
4751 web_pc(i,3);
4754 void sleep_cloud_space(short m,short n)
4756 location target;
4757 creature_data_type *which_m;
4758 short i;
4760 target.x = (char) m;
4761 target.y = (char) n;
4763 make_sleep_cloud(m,n);
4765 if (overall_mode >= 10)
4766 for (i = 0; i < 6; i++)
4767 if (adven[i].main_status == 1)
4768 if (same_point(pc_pos[i],target) == TRUE) {
4769 sleep_pc(i,3,11,0);
4771 if (overall_mode < 10)
4772 if (same_point(target,c_town.p_loc) == TRUE) {
4773 for (i = 0; i < 6; i++)
4774 sleep_pc(i,3,11,0);
4779 void take_m_ap(short num,creature_data_type *monst)
4781 monst->m_d.ap = max(0,monst->m_d.ap - num);
4784 void add_new_action(short pc_num)
4786 if (pc_num < 6)
4787 pc_moves[pc_num]++;
4790 short get_monst_sound(creature_data_type *attacker,short which_att) {
4791 short type,strength,i;
4793 type = (which_att == 0) ? attacker->m_d.a1_type : attacker->m_d.a23_type;
4794 strength = attacker->m_d.a[which_att];
4796 switch (type) {
4797 case 3:
4798 return 11;
4799 break;
4800 case 4:
4801 return 4;
4802 break;
4803 case 1:
4804 return 9;
4805 break;
4806 case 2:
4807 return 10;
4808 break;
4810 default:
4811 if (attacker->m_d.m_type == 0) {
4812 if (strength > 9)
4813 return 3;
4814 else return 2;
4816 if ((attacker->m_d.m_type == 0) ||(attacker->m_d.m_type == 6) ||(attacker->m_d.m_type == 9) ){
4817 return 2;
4819 if (attacker->m_d.m_type == 4)
4820 return 1;
4821 if (attacker->m_d.m_type == 5)
4822 return 4;
4823 return 0;
4824 break;
4826 return 0;