ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_attack.C
(Generate patch)

Comparing deliantra/server/server/spell_attack.C (file contents):
Revision 1.3 by elmex, Tue Aug 15 16:19:55 2006 UTC vs.
Revision 1.41 by root, Sat Jun 9 21:16:12 2007 UTC

1/* 1/*
2 * static char *rcsid_spell_attack_c = 2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 * "$Id: spell_attack.C,v 1.3 2006/08/15 16:19:55 elmex Exp $"; 3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5 * Copyright (©) 2002-2003,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 *
8 * Crossfire TRT is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with Crossfire TRT; if not, write to the Free Software Foundation, Inc. 51
20 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 * The authors can be reached via e-mail to <crossfire@schmorp.de>
4 */ 23 */
5
6
7/*
8 CrossFire, A Multiplayer game for X-windows
9
10 Copyright (C) 2002-2003 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26
27 The authors can be reached via e-mail at crossfire-devel@real-time.com
28*/
29 24
30/* This file contains all the spell attack code. Grouping this code 25/* This file contains all the spell attack code. Grouping this code
31 * together should hopefully make it easier to find the relevent bits 26 * together should hopefully make it easier to find the relevent bits
32 * of code 27 * of code
33 */ 28 */
34 29
35#include <global.h> 30#include <global.h>
36#include <object.h> 31#include <object.h>
37#include <living.h> 32#include <living.h>
38#ifndef __CEXTRACT__
39#include <sproto.h> 33#include <sproto.h>
40#endif
41#include <spells.h> 34#include <spells.h>
42#include <sounds.h> 35#include <sounds.h>
43 36
44/* this function checks to see if a spell pushes objects as well 37/* this function checks to see if a spell pushes objects as well
45 * as flies over and damages them (only used for cones for now) 38 * as flies over and damages them (only used for cones for now)
46 * but moved here so it could be applied to bolts too 39 * but moved here so it could be applied to bolts too
47 * op is the spell object. 40 * op is the spell object.
48 */ 41 */
49 42
43void
50void check_spell_knockback(object *op) { 44check_spell_knockback (object *op)
45{
51 object *tmp, *tmp2; /* object on the map */ 46 object *tmp, *tmp2; /* object on the map */
52 int weight_move; 47 int weight_move;
53 int frictionmod=2; /*poor man's physics - multipy targets weight by this amount */ 48 int frictionmod = 2; /*poor man's physics - multipy targets weight by this amount */
54 49
55 if(! op->weight) { /*shouldn't happen but if cone object has no weight drop out*/ 50 if (!op->weight)
51 { /*shouldn't happen but if cone object has no weight drop out */
56 /*LOG (llevDebug, "DEBUG: arch weighs nothing\n");*/ 52 /*LOG (llevDebug, "DEBUG: arch weighs nothing\n"); */
57 return; 53 return;
58 }else{ 54 }
55 else
56 {
59 weight_move = op->weight +(op->weight * op->level) / 3; 57 weight_move = op->weight + (op->weight * op->level) / 3;
60 /*LOG (llevDebug, "DEBUG: arch weighs %d and masses %d (%s,level %d)\n", op->weight,weight_move,op->name,op->level);*/ 58 /*LOG (llevDebug, "DEBUG: arch weighs %d and masses %d (%s,level %d)\n", op->weight,weight_move,op->name,op->level); */
61 } 59 }
62 60
63 for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above) 61 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp != NULL; tmp = tmp->above)
64 { 62 {
65 int num_sections = 1; 63 int num_sections = 1;
66 64
67 /* don't move DM */ 65 /* don't move DM */
68 if(QUERY_FLAG(tmp, FLAG_WIZ)) 66 if (QUERY_FLAG (tmp, FLAG_WIZ))
69 return; 67 return;
70 68
71 /* don't move parts of objects */ 69 /* don't move parts of objects */
72 if(tmp->head) continue; 70 if (tmp->head)
71 continue;
73 72
74 /* don't move floors or immobile objects */ 73 /* don't move floors or immobile objects */
75 if(QUERY_FLAG(tmp,FLAG_IS_FLOOR)||(!QUERY_FLAG(tmp,FLAG_ALIVE)&&QUERY_FLAG(tmp,FLAG_NO_PICK))) continue; 74 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR) || (!QUERY_FLAG (tmp, FLAG_ALIVE) && QUERY_FLAG (tmp, FLAG_NO_PICK)))
75 continue;
76 76
77 /* count the object's sections */ 77 /* count the object's sections */
78 for(tmp2 = tmp; tmp2!=NULL;tmp2=tmp2->more) num_sections++; 78 for (tmp2 = tmp; tmp2 != NULL; tmp2 = tmp2->more)
79 num_sections++;
79 80
80 /* I'm not sure if it makes sense to divide by num_sections - bigger 81 /* I'm not sure if it makes sense to divide by num_sections - bigger
81 * objects should be harder to move, and we are moving the entire 82 * objects should be harder to move, and we are moving the entire
82 * object, not just the head, so the total weight should be relevant. 83 * object, not just the head, so the total weight should be relevant.
83 */ 84 */
84 85
85 /* surface area? -tm */ 86 /* surface area? -tm */
86 87
87 if (tmp->move_type & MOVE_FLYING) 88 if (tmp->move_type & MOVE_FLYING)
88 frictionmod = 1 ; /* flying objects loose the friction modifier */ 89 frictionmod = 1; /* flying objects loose the friction modifier */
89 90
90 if(rndm(0, weight_move-1) > ((tmp->weight / num_sections) * frictionmod)) { /* move it. */ 91 if (rndm (0, weight_move - 1) > ((tmp->weight / num_sections) * frictionmod))
92 { /* move it. */
91 /* move_object is really for monsters, but looking at 93 /* move_object is really for monsters, but looking at
92 * the move_object function, it appears that it should 94 * the move_object function, it appears that it should
93 * also be safe for objects. 95 * also be safe for objects.
94 * This does return if successful or not, but 96 * This does return if successful or not, but
95 * I don't see us doing anything useful with that information 97 * I don't see us doing anything useful with that information
96 * right now. 98 * right now.
97 */ 99 */
98 move_object(tmp, absdir(op->stats.sp)); 100 move_object (tmp, absdir (op->stats.sp));
99 } 101 }
100 102
101 } 103 }
102} 104}
103 105
104/*************************************************************************** 106/***************************************************************************
109 111
110/* Causes op to fork. op is the original bolt, tmp 112/* Causes op to fork. op is the original bolt, tmp
111 * is the first piece of the fork. 113 * is the first piece of the fork.
112 */ 114 */
113 115
116void
114void forklightning(object *op, object *tmp) { 117forklightning (object *op, object *tmp)
118{
115 int new_dir=1; /* direction or -1 for left, +1 for right 0 if no new bolt */ 119 int new_dir = 1; /* direction or -1 for left, +1 for right 0 if no new bolt */
116 int t_dir; /* stores temporary dir calculation */ 120 int t_dir; /* stores temporary dir calculation */
117 mapstruct *m; 121 maptile *m;
118 sint16 sx,sy; 122 sint16 sx, sy;
119 object *new_bolt; 123 object *new_bolt;
120 124
121 /* pick a fork direction. tmp->stats.Con is the left bias 125 /* pick a fork direction. tmp->stats.Con is the left bias
122 * i.e., the chance in 100 of forking LEFT 126 * i.e., the chance in 100 of forking LEFT
123 * Should start out at 50, down to 25 for one already going left 127 * Should start out at 50, down to 25 for one already going left
124 * down to 0 for one going 90 degrees left off original path 128 * down to 0 for one going 90 degrees left off original path
125 */ 129 */
126 130
127 if(rndm(0, 99) < tmp->stats.Con) /* fork left */ 131 if (rndm (0, 99) < tmp->stats.Con) /* fork left */
128 new_dir = -1; 132 new_dir = -1;
129 133
130 /* check the new dir for a wall and in the map*/ 134 /* check the new dir for a wall and in the map */
131 t_dir = absdir(tmp->direction + new_dir); 135 t_dir = absdir (tmp->direction + new_dir);
132 136
133 if(get_map_flags(tmp->map,&m, tmp->x + freearr_x[t_dir],tmp->y + freearr_y[t_dir], 137 if (get_map_flags (tmp->map, &m, tmp->x + freearr_x[t_dir], tmp->y + freearr_y[t_dir], &sx, &sy) & P_OUT_OF_MAP)
134 &sx, &sy) & P_OUT_OF_MAP) 138 return;
135 return;
136 139
137 if (OB_TYPE_MOVE_BLOCK(tmp, GET_MAP_MOVE_BLOCK(m, sx, sy))) 140 if (OB_TYPE_MOVE_BLOCK (tmp, GET_MAP_MOVE_BLOCK (m, sx, sy)))
138 return; 141 return;
139 142
140 /* OK, we made a fork */ 143 /* OK, we made a fork */
141 new_bolt = get_object(); 144 new_bolt = tmp->clone ();
142 145
143 copy_object(tmp,new_bolt);
144
145 /* reduce chances of subsequent forking */ 146 /* reduce chances of subsequent forking */
146 new_bolt->stats.Dex -= 10; 147 new_bolt->stats.Dex -= 10;
147 tmp->stats.Dex -= 10; /* less forks from main bolt too */ 148 tmp->stats.Dex -= 10; /* less forks from main bolt too */
148 new_bolt->stats.Con += 25 * new_dir; /* adjust the left bias */ 149 new_bolt->stats.Con += 25 * new_dir; /* adjust the left bias */
149 new_bolt->speed_left = -0.1; 150 new_bolt->speed_left = -0.1f;
150 new_bolt->direction = t_dir; 151 new_bolt->direction = t_dir;
151 new_bolt->duration++; 152 new_bolt->duration++;
152 new_bolt->x=sx;
153 new_bolt->y=sy;
154 new_bolt->stats.dam /= 2; /* reduce daughter bolt damage */ 153 new_bolt->stats.dam /= 2; /* reduce daughter bolt damage */
155 new_bolt->stats.dam++; 154 new_bolt->stats.dam++;
156 tmp->stats.dam /= 2; /* reduce father bolt damage */ 155 tmp->stats.dam /= 2; /* reduce father bolt damage */
157 tmp->stats.dam++; 156 tmp->stats.dam++;
158 new_bolt = insert_ob_in_map(new_bolt,m,op,0); 157 if ((new_bolt = m->insert (new_bolt, sx, sy, op)))
159 update_turn_face(new_bolt); 158 update_turn_face (new_bolt);
160} 159}
161 160
162/* move_bolt: moves bolt 'op'. Basically, it just advances a space, 161/* move_bolt: moves bolt 'op'. Basically, it just advances a space,
163 * and checks for various things that may stop it. 162 * and checks for various things that may stop it.
164 */ 163 */
165 164
165void
166void move_bolt(object *op) { 166move_bolt (object *op)
167 object *tmp; 167{
168 int mflags; 168 int mflags;
169 sint16 x, y; 169 sint16 x, y;
170 mapstruct *m; 170 maptile *m;
171 171
172 if(--(op->duration)<0) { 172 if (--op->duration < 0)
173 remove_ob(op);
174 free_object(op);
175 return;
176 } 173 {
174 op->destroy ();
175 return;
176 }
177
177 hit_map(op,0,op->attacktype,1); 178 hit_map (op, 0, op->attacktype, 1);
178 179
179 if(!op->direction) 180 if (!op->direction)
180 return;
181
182 if (--op->range<0) {
183 op->range=0;
184 } else {
185 x = op->x+DIRX(op);
186 y = op->y+DIRY(op);
187 m = op->map;
188 mflags = get_map_flags(m, &m, x, y, &x, &y);
189
190 if (mflags & P_OUT_OF_MAP) return;
191
192 /* We are about to run into something - we may bounce */
193 /* Calling reflwall is pretty costly, as it has to look at all the objects
194 * on the space. So only call reflwall if we think the data it returns
195 * will be useful.
196 */
197 if (OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, x, y)) ||
198 ((mflags & P_IS_ALIVE) && reflwall(m, x, y, op))) {
199
200 if(!QUERY_FLAG(op, FLAG_REFLECTING))
201 return;
202
203 /* Since walls don't run diagonal, if the bolt is in
204 * one of 4 main directions, it just reflects back in the
205 * opposite direction. However, if the bolt is travelling
206 * on the diagonal, it is trickier - eg, a bolt travelling
207 * northwest bounces different if it hits a north/south
208 * wall (bounces to northeast) vs an east/west (bounces
209 * to the southwest.
210 */
211 if(op->direction&1)
212 op->direction=absdir(op->direction+4);
213 else {
214 int left, right;
215 int mflags;
216
217 /* Need to check for P_OUT_OF_MAP: if the bolt is tavelling
218 * over a corner in a tiled map, it is possible that
219 * op->direction is within an adjacent map but either
220 * op->direction-1 or op->direction+1 does not exist.
221 */
222 mflags = get_map_flags(op->map, &m, op->x+freearr_x[absdir(op->direction-1)],
223 op->y+freearr_y[absdir(op->direction-1)], &x, &y);
224
225 left = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, x, y));
226
227 mflags = get_map_flags(op->map, &m, op->x+freearr_x[absdir(op->direction+1)],
228 op->y+freearr_y[absdir(op->direction+1)], &x, &y);
229 right = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, x, y));
230
231 if(left==right)
232 op->direction=absdir(op->direction+4);
233 else if(left)
234 op->direction=absdir(op->direction+2);
235 else if(right)
236 op->direction=absdir(op->direction-2);
237 }
238 update_turn_face(op); /* A bolt *must* be IS_TURNABLE */
239 return; 181 return;
240 }
241 else { /* Create a copy of this object and put it ahead */
242 tmp=get_object();
243 copy_object(op,tmp);
244 tmp->speed_left= -0.1;
245 tmp->x+=DIRX(tmp),tmp->y+=DIRY(tmp);
246 tmp = insert_ob_in_map(tmp,op->map,op,0);
247 /* To make up for the decrease at the top of the function */
248 tmp->duration++;
249 182
250 /* New forking code. Possibly create forks of this object 183 if (--op->range < 0)
251 * going off in other directions.
252 */
253
254 if(rndm(0, 99)< tmp->stats.Dex) { /* stats.Dex % of forking */
255 forklightning(op,tmp);
256 }
257 /* In this way, the object left behind sticks on the space, but
258 * doesn't create any bolts that continue to move onward.
259 */
260 op->range = 0; 184 op->range = 0;
261 } /* copy object and move it along */ 185 else
262 } /* if move bolt along */ 186 {
187 x = op->x + DIRX (op);
188 y = op->y + DIRY (op);
189 m = op->map;
190 mflags = get_map_flags (m, &m, x, y, &x, &y);
191
192 if (mflags & P_OUT_OF_MAP)
193 return;
194
195 /* We are about to run into something - we may bounce */
196 /* Calling reflwall is pretty costly, as it has to look at all the objects
197 * on the space. So only call reflwall if we think the data it returns
198 * will be useful.
199 */
200 if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y)) || ((mflags & P_IS_ALIVE) && reflwall (m, x, y, op)))
201 {
202 if (!QUERY_FLAG (op, FLAG_REFLECTING))
203 return;
204
205 /* Since walls don't run diagonal, if the bolt is in
206 * one of 4 main directions, it just reflects back in the
207 * opposite direction. However, if the bolt is travelling
208 * on the diagonal, it is trickier - eg, a bolt travelling
209 * northwest bounces different if it hits a north/south
210 * wall (bounces to northeast) vs an east/west (bounces
211 * to the southwest.
212 */
213 if (op->direction & 1)
214 op->direction = absdir (op->direction + 4);
215 else
216 {
217 int left, right;
218 int mflags;
219
220 /* Need to check for P_OUT_OF_MAP: if the bolt is tavelling
221 * over a corner in a tiled map, it is possible that
222 * op->direction is within an adjacent map but either
223 * op->direction-1 or op->direction+1 does not exist.
224 */
225 mflags = get_map_flags (op->map, &m, op->x + freearr_x[absdir (op->direction - 1)],
226 op->y + freearr_y[absdir (op->direction - 1)], &x, &y);
227
228 left = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y));
229
230 mflags = get_map_flags (op->map, &m, op->x + freearr_x[absdir (op->direction + 1)],
231 op->y + freearr_y[absdir (op->direction + 1)], &x, &y);
232 right = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y));
233
234 if (left == right)
235 op->direction = absdir (op->direction + 4);
236 else if (left)
237 op->direction = absdir (op->direction + 2);
238 else if (right)
239 op->direction = absdir (op->direction - 2);
240 }
241
242 update_turn_face (op); /* A bolt *must* be IS_TURNABLE */
243 return;
244 }
245 else
246 { /* Create a copy of this object and put it ahead */
247 object *tmp = op->clone ();
248
249 m->insert (tmp, x, y, op);
250 tmp->speed_left = -0.1f;
251 /* To make up for the decrease at the top of the function */
252 tmp->duration++;
253
254 /* New forking code. Possibly create forks of this object
255 * going off in other directions.
256 */
257 if (rndm (0, 99) < tmp->stats.Dex)
258 { /* stats.Dex % of forking */
259 forklightning (op, tmp);
260 }
261
262 /* In this way, the object left behind sticks on the space, but
263 * doesn't create any bolts that continue to move onward.
264 */
265 op->range = 0;
266 } /* copy object and move it along */
267 } /* if move bolt along */
263} 268}
264 269
265/* fire_bolt 270/* fire_bolt
266 * object op (cast from caster) files a bolt in dir. 271 * object op (cast from caster) files a bolt in dir.
267 * spob is the spell object for the bolt. 272 * spob is the spell object for the bolt.
268 * we remove the magic flag - that can be derived from 273 * we remove the magic flag - that can be derived from
269 * spob->attacktype. 274 * spob->attacktype.
270 * This function sets up the appropriate owner and skill 275 * This function sets up the appropriate owner and skill
271 * pointers. 276 * pointers.
272 */ 277 */
273 278int
274int fire_bolt(object *op,object *caster,int dir,object *spob, object *skill) { 279fire_bolt (object *op, object *caster, int dir, object *spob, object *skill)
280{
275 object *tmp=NULL; 281 object *tmp = NULL;
276 int mflags; 282 int mflags;
277 283
278 if (!spob->other_arch) 284 if (!spob->other_arch)
279 return 0; 285 return 0;
280 286
281 tmp=arch_to_object(spob->other_arch); 287 tmp = arch_to_object (spob->other_arch);
282 if(tmp==NULL) 288 if (tmp == NULL)
283 return 0; 289 return 0;
284 290
285 /* peterm: level dependency for bolts */ 291 /* peterm: level dependency for bolts */
286 tmp->stats.dam = spob->stats.dam + SP_level_dam_adjust(caster,spob); 292 tmp->stats.dam = spob->stats.dam + SP_level_dam_adjust (caster, spob);
287 tmp->attacktype = spob->attacktype; 293 tmp->attacktype = spob->attacktype;
288 if (spob->slaying) tmp->slaying = add_refcount(spob->slaying); 294 if (spob->slaying)
295 tmp->slaying = spob->slaying;
289 tmp->range = spob->range + SP_level_range_adjust(caster,spob); 296 tmp->range = spob->range + SP_level_range_adjust (caster, spob);
290 tmp->duration = spob->duration + SP_level_duration_adjust(caster,spob); 297 tmp->duration = spob->duration + SP_level_duration_adjust (caster, spob);
291 tmp->stats.Dex = spob->stats.Dex; 298 tmp->stats.Dex = spob->stats.Dex;
292 tmp->stats.Con = spob->stats.Con; 299 tmp->stats.Con = spob->stats.Con;
293 300
294 tmp->direction=dir; 301 tmp->direction = dir;
295 if(QUERY_FLAG(tmp, FLAG_IS_TURNABLE)) 302 if (QUERY_FLAG (tmp, FLAG_IS_TURNABLE))
296 SET_ANIMATION(tmp, dir); 303 SET_ANIMATION (tmp, dir);
297 304
298 set_owner(tmp,op); 305 tmp->set_owner (op);
299 set_spell_skill(op, caster, spob, tmp); 306 set_spell_skill (op, caster, spob, tmp);
300 307
301 tmp->x=op->x + DIRX(tmp); 308 tmp->x = op->x + DIRX (tmp);
302 tmp->y=op->y + DIRY(tmp); 309 tmp->y = op->y + DIRY (tmp);
303 tmp->map = op->map; 310 tmp->map = op->map;
304 311
312 maptile *newmap;
305 mflags = get_map_flags(tmp->map, &tmp->map, tmp->x, tmp->y, &tmp->x, &tmp->y); 313 mflags = get_map_flags (tmp->map, &newmap, tmp->x, tmp->y, &tmp->x, &tmp->y);
306 if (mflags & P_OUT_OF_MAP) { 314 if (mflags & P_OUT_OF_MAP)
307 free_object(tmp);
308 return 0;
309 } 315 {
316 tmp->destroy ();
317 return 0;
318 }
319
320 tmp->map = newmap;
321
310 if (OB_TYPE_MOVE_BLOCK(tmp, GET_MAP_MOVE_BLOCK(tmp->map, tmp->x, tmp->y))) { 322 if (OB_TYPE_MOVE_BLOCK (tmp, GET_MAP_MOVE_BLOCK (tmp->map, tmp->x, tmp->y)))
323 {
311 if(!QUERY_FLAG(tmp, FLAG_REFLECTING)) { 324 if (!QUERY_FLAG (tmp, FLAG_REFLECTING))
312 free_object(tmp); 325 {
326 tmp->destroy ();
313 return 0; 327 return 0;
314 } 328 }
315 tmp->x=op->x; 329
316 tmp->y=op->y; 330 tmp->x = op->x;
331 tmp->y = op->y;
317 tmp->direction=absdir(tmp->direction+4); 332 tmp->direction = absdir (tmp->direction + 4);
318 tmp->map = op->map; 333 tmp->map = op->map;
319 } 334 }
320 if ((tmp = insert_ob_in_map(tmp,tmp->map,op,0)) != NULL) 335
336 if ((tmp = tmp->insert_at (tmp, op)))
321 move_bolt (tmp); 337 move_bolt (tmp);
338
322 return 1; 339 return 1;
323} 340}
324
325
326 341
327/*************************************************************************** 342/***************************************************************************
328 * 343 *
329 * BULLET/BALL CODE 344 * BULLET/BALL CODE
330 * 345 *
332 347
333/* expands an explosion. op is a piece of the 348/* expands an explosion. op is a piece of the
334 * explosion - this expans it in the different directions. 349 * explosion - this expans it in the different directions.
335 * At least that is what I think this does. 350 * At least that is what I think this does.
336 */ 351 */
352void
337void explosion(object *op) { 353explosion (object *op)
338 object *tmp; 354{
339 mapstruct *m=op->map; 355 maptile *m = op->map;
340 int i; 356 int i;
341 357
342 if(--(op->duration)<0) { 358 if (--op->duration < 0)
343 remove_ob(op);
344 free_object(op);
345 return;
346 } 359 {
360 op->destroy ();
361 return;
362 }
363
347 hit_map(op,0,op->attacktype,0); 364 hit_map (op, 0, op->attacktype, 0);
348 365
349 if(op->range>0) { 366 if (op->range > 0)
350 for(i=1;i<9;i++) { 367 {
368 for (i = 1; i < 9; i++)
369 {
351 sint16 dx,dy; 370 sint16 dx, dy;
352 371
353 dx=op->x+freearr_x[i]; 372 dx = op->x + freearr_x[i];
354 dy=op->y+freearr_y[i]; 373 dy = op->y + freearr_y[i];
374
355 /* ok_to_put_more already does things like checks for walls, 375 /* ok_to_put_more already does things like checks for walls,
356 * out of map, etc. 376 * out of map, etc.
357 */ 377 */
358 if(ok_to_put_more(op->map,dx,dy,op,op->attacktype)) { 378 if (ok_to_put_more (op->map, dx, dy, op, op->attacktype))
359 tmp=get_object(); 379 {
360 copy_object(op,tmp); 380 object *tmp = op->clone ();
361 tmp->state=0; 381
362 tmp->speed_left= -0.21; 382 tmp->state = 0;
363 tmp->range--; 383 tmp->speed_left = -0.21f;
364 tmp->value=0; 384 tmp->range--;
365 tmp->x=dx; 385 tmp->value = 0;
366 tmp->y=dy; 386
367 insert_ob_in_map(tmp,m,op,0); 387 m->insert (tmp, dx, dy, op);
388 }
389 }
368 } 390 }
369 }
370 }
371} 391}
372
373 392
374/* Causes an object to explode, eg, a firebullet, 393/* Causes an object to explode, eg, a firebullet,
375 * poison cloud ball, etc. op is the object to 394 * poison cloud ball, etc. op is the object to
376 * explode. 395 * explode.
377 */ 396 */
397void
378void explode_bullet(object *op) 398explode_bullet (object *op)
379{ 399{
380 tag_t op_tag = op->count;
381 object *tmp, *owner; 400 object *tmp, *owner;
382 401
383 if (op->other_arch == NULL) { 402 if (op->other_arch == NULL)
403 {
384 LOG (llevError, "BUG: explode_bullet(): op without other_arch\n"); 404 LOG (llevError, "BUG: explode_bullet(): op without other_arch\n");
385 remove_ob (op); 405 op->destroy ();
386 free_object (op); 406 return;
387 return;
388 } 407 }
389 408
390 if (op->env) { 409 if (op->env)
391 object *env; 410 {
392
393 env = object_get_env_recursive(op); 411 object *env = object_get_env_recursive (op);
394 if (env->map == NULL || out_of_map (env->map, env->x, env->y)) { 412 if (env->map == NULL || out_of_map (env->map, env->x, env->y))
413 {
395 LOG (llevError, "BUG: explode_bullet(): env out of map\n"); 414 LOG (llevError, "BUG: explode_bullet(): env out of map\n");
396 remove_ob (op); 415 op->destroy ();
397 free_object (op);
398 return; 416 return;
399 } 417 }
400 remove_ob (op); 418
401 op->x = env->x; 419 op->insert_at (env, op, INS_NO_MERGE | INS_NO_WALK_ON);
402 op->y = env->y; 420 }
403 insert_ob_in_map(op, env->map, op, INS_NO_MERGE | INS_NO_WALK_ON);
404 } else if (out_of_map (op->map, op->x, op->y)) { 421 else if (out_of_map (op->map, op->x, op->y))
422 {
405 LOG (llevError, "BUG: explode_bullet(): op out of map\n"); 423 LOG (llevError, "BUG: explode_bullet(): op out of map\n");
406 remove_ob (op); 424 op->destroy ();
407 free_object (op); 425 return;
408 return;
409 } 426 }
410 427
411 // elmex Tue Aug 15 17:46:51 CEST 2006: Prevent explosions of any kind on safe maps 428 // elmex Tue Aug 15 17:46:51 CEST 2006: Prevent explosions of any kind on safe maps
412 // NOTE: If this breaks something important: remove this. I can't think of anything 429 // NOTE: If this breaks something important: remove this. I can't think of anything
413 // bad at the moment that might happen from this. 430 // bad at the moment that might happen from this.
414 if (get_map_flags (op->map, NULL, op->x, op->y, NULL, NULL) & P_SAFE_MAP) 431 if (get_map_flags (op->map, NULL, op->x, op->y, NULL, NULL) & P_SAFE)
415 { 432 {
416 remove_ob (op); 433 op->destroy ();
417 free_object (op); 434 return;
435 }
436
437 if (op->attacktype)
438 {
439 hit_map (op, 0, op->attacktype, 1);
440 if (op->destroyed ())
418 return; 441 return;
419 } 442 }
420 443
421 if (op->attacktype) {
422 hit_map (op, 0, op->attacktype, 1);
423 if (was_destroyed (op, op_tag))
424 return;
425 }
426
427 /* other_arch contains what this explodes into */ 444 /* other_arch contains what this explodes into */
428 tmp = arch_to_object (op->other_arch); 445 tmp = arch_to_object (op->other_arch);
429 446
430 copy_owner (tmp, op); 447 tmp->set_owner (op);
431 if (tmp->skill) FREE_AND_CLEAR_STR(tmp->skill); 448 tmp->skill = op->skill;
432 if (op->skill) tmp->skill = add_refcount(op->skill);
433 449
434 owner = get_owner(op); 450 owner = op->owner;
451
435 if ((tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER) && owner && 452 if ((tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER) && owner && !tailor_god_spell (tmp, owner))
436 !tailor_god_spell(tmp, owner)) {
437 remove_ob (op);
438 free_object (op);
439 return;
440 } 453 {
441 tmp->x = op->x; 454 op->destroy ();
442 tmp->y = op->y; 455 return;
456 }
443 457
444 /* special for bombs - it actually has sane values for these */ 458 /* special for bombs - it actually has sane values for these */
445 if (op->type == SPELL_EFFECT && op->subtype == SP_BOMB) { 459 if (op->type == SPELL_EFFECT && op->subtype == SP_BOMB)
460 {
446 tmp->attacktype = op->attacktype; 461 tmp->attacktype = op->attacktype;
447 tmp->range = op->range; 462 tmp->range = op->range;
448 tmp->stats.dam = op->stats.dam; 463 tmp->stats.dam = op->stats.dam;
449 tmp->duration = op->duration; 464 tmp->duration = op->duration;
450 } else { 465 }
451 if (op->attacktype & AT_MAGIC) tmp->attacktype|=AT_MAGIC; 466 else
467 {
468 if (op->attacktype & AT_MAGIC)
469 tmp->attacktype |= AT_MAGIC;
470
452 /* Spell doc describes what is going on here */ 471 /* Spell doc describes what is going on here */
453 tmp->stats.dam = op->dam_modifier; 472 tmp->stats.dam = op->dam_modifier;
454 tmp->range = op->stats.maxhp; 473 tmp->range = op->stats.maxhp;
455 tmp->duration = op->stats.hp; 474 tmp->duration = op->stats.hp;
456 /* Used for spell tracking - just need a unique val for this spell - 475 /* Used for spell tracking - just need a unique val for this spell -
457 * the count of the parent should work fine. 476 * the count of the parent should work fine.
458 */ 477 */
459 tmp->stats.maxhp = op->count; 478 tmp->stats.maxhp = op->count;
460 } 479 }
461 480
462 /* Set direction of cone explosion */ 481 /* Set direction of cone explosion */
463 if (tmp->type == SPELL_EFFECT && tmp->subtype == SP_CONE) 482 if (tmp->type == SPELL_EFFECT && tmp->subtype == SP_CONE)
464 tmp->stats.sp = op->direction; 483 tmp->stats.sp = op->direction;
465 484
466 /* Prevent recursion */ 485 /* Prevent recursion */
467 op->move_on = 0; 486 op->move_on = 0;
468 487
469 insert_ob_in_map(tmp, op->map, op, 0); 488 tmp->insert_at (op, op);
470 /* remove the firebullet */ 489 /* remove the firebullet */
471 if ( ! was_destroyed (op, op_tag)) { 490 op->destroy ();
472 remove_ob (op);
473 free_object (op);
474 }
475} 491}
476
477
478 492
479/* checks to see what op should do, given the space it is on 493/* checks to see what op should do, given the space it is on
480 * (eg, explode, damage player, etc) 494 * (eg, explode, damage player, etc)
481 */ 495 */
482 496void
483void check_bullet(object *op) 497check_bullet (object *op)
484{ 498{
485 tag_t op_tag = op->count, tmp_tag;
486 object *tmp; 499 object *tmp;
487 int dam, mflags; 500 int dam, mflags;
488 mapstruct *m; 501 maptile *m;
489 sint16 sx, sy; 502 sint16 sx, sy;
490 503
491 mflags = get_map_flags(op->map,&m, op->x, op->y, &sx, &sy); 504 mflags = get_map_flags (op->map, &m, op->x, op->y, &sx, &sy);
492 505
493 if (!(mflags & P_IS_ALIVE) && !OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, sx, sy))) 506 if (!(mflags & P_IS_ALIVE) && !OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
494 return; 507 return;
495 508
496 if (op->other_arch) { 509 if (op->other_arch)
510 {
497 /* explode object will also remove op */ 511 /* explode object will also remove op */
498 explode_bullet (op); 512 explode_bullet (op);
499 return; 513 return;
500 } 514 }
501 515
502 /* If nothing alive on this space, no reason to do anything further */ 516 /* If nothing alive on this space, no reason to do anything further */
503 if (!(mflags & P_IS_ALIVE)) return; 517 if (!(mflags & P_IS_ALIVE))
518 return;
504 519
505 for (tmp = get_map_ob (op->map,op->x,op->y); tmp != NULL; tmp = tmp->above) 520 for (tmp = op->ms ().bot; tmp; tmp = tmp->above)
506 { 521 {
507 if (QUERY_FLAG (tmp, FLAG_ALIVE)) { 522 if (QUERY_FLAG (tmp, FLAG_ALIVE))
508 tmp_tag = tmp->count; 523 {
509 dam = hit_player (tmp, op->stats.dam, op, op->attacktype, 1); 524 dam = hit_player (tmp, op->stats.dam, op, op->attacktype, 1);
510 if (was_destroyed (op, op_tag) || ! was_destroyed (tmp, tmp_tag) 525 if (op->destroyed () || !tmp->destroyed () || (op->stats.dam -= dam) < 0)
511 || (op->stats.dam -= dam) < 0)
512 { 526 {
513 if(!QUERY_FLAG(op,FLAG_REMOVED)) { 527 if (!QUERY_FLAG (op, FLAG_REMOVED))
514 remove_ob (op); 528 {
515 free_object(op); 529 op->destroy ();
516 return; 530 return;
517 } 531 }
518 } 532 }
519 } 533 }
520 } 534 }
521} 535}
522
523 536
524/* Basically, we move 'op' one square, and if it hits something, 537/* Basically, we move 'op' one square, and if it hits something,
525 * call check_bullet. 538 * call check_bullet.
526 * This function is only applicable to bullets, but not to all 539 * This function is only applicable to bullets, but not to all
527 * fired arches (eg, bolts). 540 * fired arches (eg, bolts).
528 */ 541 */
529 542void
530void move_bullet(object *op) 543move_bullet (object *op)
531{ 544{
532 sint16 new_x, new_y; 545 sint16 new_x, new_y;
533 int mflags; 546 int mflags;
534 mapstruct *m; 547 maptile *m;
535 548
536#if 0 549#if 0
537 /* We need a better general purpose way to do this */ 550 /* We need a better general purpose way to do this */
538 551
539 /* peterm: added to make comet leave a trail of burnouts 552 /* peterm: added to make comet leave a trail of burnouts
540 it's an unadulterated hack, but the effect is cool. */ 553 it's an unadulterated hack, but the effect is cool. */
541 if(op->stats.sp == SP_METEOR) { 554 if (op->stats.sp == SP_METEOR)
555 {
542 replace_insert_ob_in_map("fire_trail",op); 556 replace_insert_ob_in_map ("fire_trail", op);
543 if (was_destroyed (op, op_tag)) 557 if (op->destroyed ())
544 return; 558 return;
545 } /* end addition. */ 559 } /* end addition. */
546#endif 560#endif
547 561
548 /* Reached the end of its life - remove it */ 562 /* Reached the end of its life - remove it */
549 if (--op->range <=0) { 563 if (--op->range <= 0)
564 {
550 if (op->other_arch) { 565 if (op->other_arch)
551 explode_bullet (op); 566 explode_bullet (op);
552 } else { 567 else
553 remove_ob (op); 568 op->destroy ();
554 free_object (op); 569
555 }
556 return; 570 return;
557 } 571 }
558 572
559 new_x = op->x + DIRX(op); 573 new_x = op->x + DIRX (op);
560 new_y = op->y + DIRY(op); 574 new_y = op->y + DIRY (op);
561 m = op->map; 575 m = op->map;
562 mflags = get_map_flags(m, &m, new_x, new_y, &new_x, &new_y); 576 mflags = get_map_flags (m, &m, new_x, new_y, &new_x, &new_y);
563 577
564 if (mflags & P_OUT_OF_MAP) { 578 if (mflags & P_OUT_OF_MAP)
565 remove_ob (op); 579 {
566 free_object (op); 580 op->destroy ();
567 return; 581 return;
568 } 582 }
569 583
570 if ( ! op->direction || OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, new_x, new_y))) { 584 if (!op->direction || OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, new_x, new_y)))
585 {
571 if (op->other_arch) { 586 if (op->other_arch)
572 explode_bullet (op); 587 explode_bullet (op);
573 } else { 588 else
574 remove_ob (op); 589 op->destroy ();
575 free_object (op); 590
576 }
577 return; 591 return;
578 } 592 }
579 593
580 remove_ob (op); 594 if (!(op = m->insert (op, new_x, new_y, op)))
581 op->x = new_x;
582 op->y = new_y;
583 if ((op = insert_ob_in_map (op, m, op,0)) == NULL)
584 return; 595 return;
585 596
586 if (reflwall (op->map, op->x, op->y, op)) { 597 if (reflwall (op->map, op->x, op->y, op))
598 {
587 op->direction = absdir (op->direction + 4); 599 op->direction = absdir (op->direction + 4);
588 update_turn_face (op); 600 update_turn_face (op);
589 } else { 601 }
602 else
590 check_bullet (op); 603 check_bullet (op);
591 }
592} 604}
593
594
595
596 605
597/* fire_bullet 606/* fire_bullet
598 * object op (cast from caster) files a bolt in dir. 607 * object op (cast from caster) files a bolt in dir.
599 * spob is the spell object for the bolt. 608 * spob is the spell object for the bolt.
600 * we remove the magic flag - that can be derived from 609 * we remove the magic flag - that can be derived from
601 * spob->attacktype. 610 * spob->attacktype.
602 * This function sets up the appropriate owner and skill 611 * This function sets up the appropriate owner and skill
603 * pointers. 612 * pointers.
604 */ 613 */
605 614int
606int fire_bullet(object *op,object *caster,int dir,object *spob) { 615fire_bullet (object *op, object *caster, int dir, object *spob)
616{
607 object *tmp=NULL; 617 object *tmp = NULL;
608 int mflags; 618 int mflags;
609 619
610 if (!spob->other_arch) 620 if (!spob->other_arch)
611 return 0; 621 return 0;
612 622
613 tmp=arch_to_object(spob->other_arch); 623 tmp = arch_to_object (spob->other_arch);
614 if(tmp==NULL) 624 if (tmp == NULL)
615 return 0; 625 return 0;
616 626
617 /* peterm: level dependency for bolts */ 627 /* peterm: level dependency for bolts */
618 tmp->stats.dam = spob->stats.dam + SP_level_dam_adjust(caster,spob); 628 tmp->stats.dam = spob->stats.dam + SP_level_dam_adjust (caster, spob);
619 tmp->attacktype = spob->attacktype; 629 tmp->attacktype = spob->attacktype;
620 if (spob->slaying) tmp->slaying = add_refcount(spob->slaying); 630 if (spob->slaying)
631 tmp->slaying = spob->slaying;
621 632
622 tmp->range = 50; 633 tmp->range = 50;
623 634
624 /* Need to store duration/range for the ball to use */ 635 /* Need to store duration/range for the ball to use */
625 tmp->stats.hp = spob->duration + SP_level_duration_adjust(caster,spob); 636 tmp->stats.hp = spob->duration + SP_level_duration_adjust (caster, spob);
626 tmp->stats.maxhp = spob->range + SP_level_range_adjust(caster,spob); 637 tmp->stats.maxhp = spob->range + SP_level_range_adjust (caster, spob);
627 tmp->dam_modifier = spob->stats.food + SP_level_dam_adjust(caster,spob); 638 tmp->dam_modifier = spob->stats.food + SP_level_dam_adjust (caster, spob);
628 639
629 tmp->direction=dir; 640 tmp->direction = dir;
630 if(QUERY_FLAG(tmp, FLAG_IS_TURNABLE)) 641 if (QUERY_FLAG (tmp, FLAG_IS_TURNABLE))
631 SET_ANIMATION(tmp, dir); 642 SET_ANIMATION (tmp, dir);
632 643
633 set_owner(tmp,op); 644 tmp->set_owner (op);
634 set_spell_skill(op, caster, spob, tmp); 645 set_spell_skill (op, caster, spob, tmp);
635 646
636 tmp->x=op->x + freearr_x[dir]; 647 tmp->x = op->x + freearr_x[dir];
637 tmp->y=op->y + freearr_y[dir]; 648 tmp->y = op->y + freearr_y[dir];
638 tmp->map = op->map; 649 tmp->map = op->map;
639 650
651 maptile *newmap;
640 mflags = get_map_flags(tmp->map, &tmp->map, tmp->x, tmp->y, &tmp->x, &tmp->y); 652 mflags = get_map_flags (tmp->map, &newmap, tmp->x, tmp->y, &tmp->x, &tmp->y);
641 if (mflags & P_OUT_OF_MAP) { 653 if (mflags & P_OUT_OF_MAP)
642 free_object(tmp);
643 return 0;
644 } 654 {
655 tmp->destroy ();
656 return 0;
657 }
658
659 tmp->map = newmap;
660
645 if (OB_TYPE_MOVE_BLOCK(tmp, GET_MAP_MOVE_BLOCK(tmp->map, tmp->x, tmp->y))) { 661 if (OB_TYPE_MOVE_BLOCK (tmp, GET_MAP_MOVE_BLOCK (tmp->map, tmp->x, tmp->y)))
662 {
646 if(!QUERY_FLAG(tmp, FLAG_REFLECTING)) { 663 if (!QUERY_FLAG (tmp, FLAG_REFLECTING))
647 free_object(tmp); 664 {
665 tmp->destroy ();
648 return 0; 666 return 0;
649 } 667 }
650 tmp->x=op->x; 668
651 tmp->y=op->y; 669 tmp->x = op->x;
670 tmp->y = op->y;
652 tmp->direction=absdir(tmp->direction+4); 671 tmp->direction = absdir (tmp->direction + 4);
653 tmp->map = op->map; 672 tmp->map = op->map;
654 } 673 }
655 if ((tmp = insert_ob_in_map(tmp,tmp->map,op,0)) != NULL) { 674
675 if ((tmp = tmp->insert_at (tmp, op)))
656 check_bullet (tmp); 676 check_bullet (tmp);
657 } 677
658 return 1; 678 return 1;
659} 679}
660
661
662
663 680
664/***************************************************************************** 681/*****************************************************************************
665 * 682 *
666 * CONE RELATED FUNCTIONS 683 * CONE RELATED FUNCTIONS
667 * 684 *
668 *****************************************************************************/ 685 *****************************************************************************/
669 686
670
671/* drops an object based on what is in the cone's "other_arch" */ 687/* drops an object based on what is in the cone's "other_arch" */
688void
672void cone_drop(object *op) { 689cone_drop (object *op)
690{
673 object *new_ob = arch_to_object(op->other_arch); 691 object *new_ob = arch_to_object (op->other_arch);
674 692
675 new_ob->x = op->x;
676 new_ob->y = op->y;
677 new_ob->level = op->level; 693 new_ob->level = op->level;
678 set_owner(new_ob,op->owner); 694 new_ob->set_owner (op->owner);
679 695
680 /* preserve skill ownership */ 696 /* preserve skill ownership */
681 if(op->skill && op->skill != new_ob->skill) { 697 if (op->skill && op->skill != new_ob->skill)
682 if (new_ob->skill) free_string(new_ob->skill); 698 new_ob->skill = op->skill;
683 new_ob->skill = add_refcount(op->skill); 699
684 } 700 new_ob->insert_at (op, op);
685 insert_ob_in_map(new_ob,op->map,op,0);
686
687} 701}
688 702
689/* move_cone: causes cone object 'op' to move a space/hit creatures */ 703/* move_cone: causes cone object 'op' to move a space/hit creatures */
690 704
705void
691void move_cone(object *op) { 706move_cone (object *op)
707{
692 int i; 708 int i;
693 tag_t tag;
694 709
695 /* if no map then hit_map will crash so just ignore object */ 710 /* if no map then hit_map will crash so just ignore object */
696 if (! op->map) { 711 if (!op->map)
697 LOG(llevError,"Tried to move_cone object %s without a map.\n",
698 op->name ? op->name : "unknown");
699 op->speed = 0;
700 update_ob_speed (op);
701 return;
702 } 712 {
713 LOG (llevError, "Tried to move_cone object %s without a map.\n", op->name ? &op->name : "unknown");
714 op->set_speed (0);
715 return;
716 }
703 717
704 /* lava saves it's life, but not yours :) */ 718 /* lava saves it's life, but not yours :) */
705 if (QUERY_FLAG(op, FLAG_LIFESAVE)) { 719 if (QUERY_FLAG (op, FLAG_LIFESAVE))
720 {
706 hit_map(op,0,op->attacktype,0); 721 hit_map (op, 0, op->attacktype, 0);
707 return; 722 return;
708 } 723 }
709 724
710#if 0 725#if 0
711 /* Disable this - enabling it makes monsters easier, as 726 /* Disable this - enabling it makes monsters easier, as
712 * when their cone dies when they die. 727 * when their cone dies when they die.
713 */ 728 */
714 /* If no owner left, the spell dies out. */ 729 /* If no owner left, the spell dies out. */
715 if(get_owner(op)==NULL) { 730 if (op->owner == NULL)
716 remove_ob(op); 731 {
717 free_object(op); 732 op->destroy ();
718 return; 733 return;
719 } 734 }
720#endif 735#endif
721 736
722 tag = op->count;
723 hit_map(op,0,op->attacktype,0); 737 hit_map (op, 0, op->attacktype, 0);
724 738
725 /* Check to see if we should push anything. 739 /* Check to see if we should push anything.
726 * Spell objects with weight push whatever they encounter to some 740 * Spell objects with weight push whatever they encounter to some
727 * degree. 741 * degree.
728 */ 742 */
743 if (op->weight)
729 if(op->weight) check_spell_knockback(op); 744 check_spell_knockback (op);
730 745
731 if (was_destroyed (op, tag)) 746 if (op->destroyed ())
747 return;
748
749 if ((op->duration--) < 0)
750 {
751 op->destroy ();
732 return; 752 return;
733
734 if((op->duration--)<0) {
735 remove_ob(op);
736 free_object(op);
737 return;
738 } 753 }
739 /* Object has hit maximum range, so don't have it move 754 /* Object has hit maximum range, so don't have it move
740 * any further. When the duration above expires, 755 * any further. When the duration above expires,
741 * then the object will get removed. 756 * then the object will get removed.
742 */ 757 */
743 if (--op->range < 0) { 758 if (--op->range < 0)
744 op->range=0; /* just so it doesn't wrap */
745 return;
746 } 759 {
760 op->range = 0; /* just so it doesn't wrap */
761 return;
762 }
747 763
748 for(i= -1;i<2;i++) { 764 for (i = -1; i < 2; i++)
749 sint16 x=op->x+freearr_x[absdir(op->stats.sp+i)], 765 {
750 y=op->y+freearr_y[absdir(op->stats.sp+i)]; 766 sint16 x = op->x + freearr_x[absdir (op->stats.sp + i)], y = op->y + freearr_y[absdir (op->stats.sp + i)];
751 767
752 if(ok_to_put_more(op->map,x,y,op,op->attacktype)) { 768 if (ok_to_put_more (op->map, x, y, op, op->attacktype))
753 object *tmp=get_object(); 769 {
754 copy_object(op, tmp); 770 object *tmp = op->clone ();
755 tmp->x=x;
756 tmp->y=y;
757 771
758 tmp->duration = op->duration + 1; 772 tmp->duration = op->duration + 1;
759 773
760 /* Use for spell tracking - see ok_to_put_more() */ 774 /* Use for spell tracking - see ok_to_put_more() */
761 tmp->stats.maxhp = op->stats.maxhp; 775 tmp->stats.maxhp = op->stats.maxhp;
762 insert_ob_in_map(tmp,op->map,op,0); 776
763 if (tmp->other_arch) cone_drop(tmp); 777 op->map->insert (tmp, x, y, op);
764 } 778
779 if (tmp->other_arch)
780 cone_drop (tmp);
781 }
765 } 782 }
766} 783}
767 784
768/* cast_cone: casts a cone spell. 785/* cast_cone: casts a cone spell.
769 * op: person firing the object. 786 * op: person firing the object.
771 * dir: direction to fire in. 788 * dir: direction to fire in.
772 * spell: spell that is being fired. It uses other_arch for the archetype 789 * spell: spell that is being fired. It uses other_arch for the archetype
773 * to fire. 790 * to fire.
774 * returns 0 on failure, 1 on success. 791 * returns 0 on failure, 1 on success.
775 */ 792 */
793int
776int cast_cone(object *op, object *caster,int dir, object *spell) 794cast_cone (object *op, object *caster, int dir, object *spell)
777{ 795{
778 object *tmp; 796 object *tmp;
779 int i,success=0,range_min= -1,range_max=1; 797 int i, success = 0, range_min = -1, range_max = 1;
780 mapstruct *m; 798 maptile *m;
781 sint16 sx, sy; 799 sint16 sx, sy;
782 MoveType movetype; 800 MoveType movetype;
783 801
784 if (!spell->other_arch) return 0; 802 if (!spell->other_arch)
785
786 if (op->type == PLAYER && QUERY_FLAG(op, FLAG_UNDEAD) &&
787 op->attacktype & AT_TURN_UNDEAD) {
788 new_draw_info(NDI_UNIQUE, 0,op,
789 "Your undead nature prevents you from turning undead!");
790 return 0; 803 return 0;
804
805 if (op->type == PLAYER && QUERY_FLAG (op, FLAG_UNDEAD) && op->attacktype & AT_TURN_UNDEAD)
791 } 806 {
807 new_draw_info (NDI_UNIQUE, 0, op, "Your undead nature prevents you from turning undead!");
808 return 0;
809 }
792 810
793 if(!dir) { 811 if (!dir)
794 range_min= 0;
795 range_max=8;
796 } 812 {
813 range_min = 0;
814 range_max = 8;
815 }
797 816
798 /* Need to know what the movetype of the object we are about 817 /* Need to know what the movetype of the object we are about
799 * to create is, so we can know if the space we are about to 818 * to create is, so we can know if the space we are about to
800 * insert it into is blocked. 819 * insert it into is blocked.
801 */ 820 */
802 movetype = spell->other_arch->clone.move_type; 821 movetype = spell->other_arch->move_type;
803 822
804 for(i=range_min;i<=range_max;i++) { 823 for (i = range_min; i <= range_max; i++)
824 {
805 sint16 x,y, d; 825 sint16 x, y, d;
806 826
807 /* We can't use absdir here, because it never returns 827 /* We can't use absdir here, because it never returns
808 * 0. If this is a rune, we want to hit the person on top 828 * 0. If this is a rune, we want to hit the person on top
809 * of the trap (d==0). If it is not a rune, then we don't want 829 * of the trap (d==0). If it is not a rune, then we don't want
810 * to hit that person. 830 * to hit that person.
811 */ 831 */
812 d = dir + i; 832 d = dir + i;
813 while (d < 0) d+=8; 833 while (d < 0)
814 while (d > 8) d-=8; 834 d += 8;
835 while (d > 8)
836 d -= 8;
815 837
816 /* If it's not a rune, we don't want to blast the caster. 838 /* If it's not a rune, we don't want to blast the caster.
817 * In that case, we have to see - if dir is specified, 839 * In that case, we have to see - if dir is specified,
818 * turn this into direction 8. If dir is not specified (all 840 * turn this into direction 8. If dir is not specified (all
819 * direction) skip - otherwise, one line would do more damage 841 * direction) skip - otherwise, one line would do more damage
820 * becase 0 direction will go through 9 directions - necessary 842 * becase 0 direction will go through 9 directions - necessary
821 * for the rune code. 843 * for the rune code.
822 */ 844 */
823 if (caster->type != RUNE && d==0) { 845 if (caster->type != RUNE && d == 0)
824 if (dir!=0) d=8; 846 {
825 else continue; 847 if (dir != 0)
826 } 848 d = 8;
849 else
850 continue;
851 }
827 852
828 x = op->x+freearr_x[d]; 853 x = op->x + freearr_x[d];
829 y = op->y+freearr_y[d]; 854 y = op->y + freearr_y[d];
830 855
831 if(get_map_flags(op->map, &m, x,y, &sx, &sy) & P_OUT_OF_MAP) 856 if (get_map_flags (op->map, &m, x, y, &sx, &sy) & P_OUT_OF_MAP)
832 continue; 857 continue;
833 858
834 if ((movetype & GET_MAP_MOVE_BLOCK(m, sx, sy)) == movetype) 859 if ((movetype & GET_MAP_MOVE_BLOCK (m, sx, sy)) == movetype)
835 continue; 860 continue;
836 861
837 success=1; 862 success = 1;
838 tmp=arch_to_object(spell->other_arch); 863 tmp = arch_to_object (spell->other_arch);
839 set_owner(tmp,op); 864 tmp->set_owner (op);
840 set_spell_skill(op, caster, spell, tmp); 865 set_spell_skill (op, caster, spell, tmp);
841 tmp->level = caster_level (caster, spell); 866 tmp->level = caster_level (caster, spell);
842 tmp->x = sx;
843 tmp->y = sy;
844 tmp->attacktype=spell->attacktype; 867 tmp->attacktype = spell->attacktype;
845 868
846 /* holy word stuff */ 869 /* holy word stuff */
847 if((tmp->attacktype & AT_HOLYWORD) || (tmp->attacktype & AT_GODPOWER)) { 870 if ((tmp->attacktype & AT_HOLYWORD) || (tmp->attacktype & AT_GODPOWER))
848 if(!tailor_god_spell(tmp,op)) return 0; 871 if (!tailor_god_spell (tmp, op))
849 } 872 return 0;
850 873
851 if(dir) 874 if (dir)
852 tmp->stats.sp=dir; 875 tmp->stats.sp = dir;
853 else 876 else
854 tmp->stats.sp=i; 877 tmp->stats.sp = i;
855 878
856 tmp->range=spell->range + SP_level_range_adjust(caster,spell); 879 tmp->range = spell->range + SP_level_range_adjust (caster, spell);
857 880
858 /* If casting it in all directions, it doesn't go as far */ 881 /* If casting it in all directions, it doesn't go as far */
859 if (dir == 0) { 882 if (dir == 0)
883 {
860 tmp->range /= 4; 884 tmp->range /= 4;
861 if (tmp->range < 2 && spell->range >=2) tmp->range = 2; 885 if (tmp->range < 2 && spell->range >= 2)
862 } 886 tmp->range = 2;
887 }
888
863 tmp->stats.dam=spell->stats.dam + SP_level_dam_adjust(caster,spell); 889 tmp->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell);
864 tmp->duration=spell->duration + SP_level_duration_adjust(caster,spell); 890 tmp->duration = spell->duration + SP_level_duration_adjust (caster, spell);
865 891
866 /* Special bonus for fear attacks */ 892 /* Special bonus for fear attacks */
867 if (tmp->attacktype & AT_FEAR) { 893 if (tmp->attacktype & AT_FEAR)
868 if (caster->type == PLAYER) tmp->duration += fear_bonus[caster->stats.Cha]; 894 {
869 else 895 if (caster->type == PLAYER)
896 tmp->duration += fear_bonus[caster->stats.Cha];
897 else
870 tmp->duration += caster->level/3; 898 tmp->duration += caster->level / 3;
871 } 899 }
900
872 if (tmp->attacktype & (AT_HOLYWORD | AT_TURN_UNDEAD)) { 901 if (tmp->attacktype & (AT_HOLYWORD | AT_TURN_UNDEAD))
873 if (caster->type == PLAYER) tmp->duration += turn_bonus[caster->stats.Wis]/5; 902 {
874 else 903 if (caster->type == PLAYER)
904 tmp->duration += turn_bonus[caster->stats.Wis] / 5;
905 else
875 tmp->duration += caster->level/3; 906 tmp->duration += caster->level / 3;
876 } 907 }
877 908
878
879 if ( !(tmp->move_type & MOVE_FLY_LOW)) 909 if (!(tmp->move_type & MOVE_FLY_LOW))
880 LOG (llevDebug, "cast_cone(): arch %s doesn't have flying 1\n", 910 LOG (llevDebug, "cast_cone(): arch %s doesn't have flying 1\n", &spell->other_arch->archname);
881 spell->other_arch->name);
882 911
883 if (!tmp->move_on && tmp->stats.dam) { 912 if (!tmp->move_on && tmp->stats.dam)
884 LOG (llevDebug, 913 LOG (llevDebug, "cast_cone(): arch %s doesn't have move_on set\n", &spell->other_arch->archname);
885 "cast_cone(): arch %s doesn't have move_on set\n",
886 spell->other_arch->name);
887 }
888 insert_ob_in_map(tmp,m,op,0);
889 914
915 m->insert (tmp, sx, sy, op);
916
890 /* This is used for tracking spells so that one effect doesn't hit 917 /* This is used for tracking spells so that one effect doesn't hit
891 * a single space too many times. 918 * a single space too many times.
892 */ 919 */
893 tmp->stats.maxhp = tmp->count; 920 tmp->stats.maxhp = tmp->count;
894 921
895 if(tmp->other_arch) cone_drop(tmp); 922 if (tmp->other_arch)
923 cone_drop (tmp);
896 } 924 }
925
897 return success; 926 return success;
898} 927}
899 928
900/**************************************************************************** 929/****************************************************************************
901 * 930 *
902 * BOMB related code 931 * BOMB related code
903 * 932 *
904 ****************************************************************************/ 933 ****************************************************************************/
905 934
906
907/* This handles an exploding bomb. 935/* This handles an exploding bomb.
908 * op is the original bomb object. 936 * op is the original bomb object.
909 */ 937 */
938void
910void animate_bomb(object *op) { 939animate_bomb (object *op)
940{
911 int i; 941 int i;
912 object *env, *tmp; 942 object *env, *tmp;
913 archetype *at;
914 943
915 if(op->state!=NUM_ANIMATIONS(op)-1) 944 if (op->state != NUM_ANIMATIONS (op) - 1)
916 return; 945 return;
917 946
918
919 env = object_get_env_recursive(op); 947 env = object_get_env_recursive (op);
920 948
921 if (op->env) { 949 if (op->env)
950 {
922 if (env->map == NULL) 951 if (env->map == NULL)
923 return;
924
925 if (env->type == PLAYER)
926 esrv_del_item(env->contr, op->count);
927
928 remove_ob(op);
929 op->x = env->x;
930 op->y = env->y;
931 if ((op = insert_ob_in_map (op, env->map, op,0)) == NULL)
932 return;
933 }
934
935 // elmex Tue Aug 15 17:46:51 CEST 2006: Prevent bomb from exploding
936 // on a safe map. I don't like this special casing, but it seems to be neccessary
937 // as bombs can be carried.
938 if (get_map_flags (op->map, NULL, op->x, op->y, NULL, NULL) & P_SAFE_MAP)
939 {
940 remove_ob (op);
941 free_object (op);
942 return; 952 return;
953
954 if (env->type == PLAYER)
955 esrv_del_item (env->contr, op->count);
956
957 if (!(op = op->insert_at (env, op)))
958 return;
943 } 959 }
944 960
961 // elmex Tue Aug 15 17:46:51 CEST 2006: Prevent bomb from exploding
962 // on a safe map. I don't like this special casing, but it seems to be neccessary
963 // as bombs can be carried.
964 if (get_map_flags (op->map, NULL, op->x, op->y, NULL, NULL) & P_SAFE)
965 {
966 op->destroy ();
967 return;
968 }
969
945 /* This copies a lot of the code from the fire bullet, 970 /* This copies a lot of the code from the fire bullet,
946 * but using the cast_bullet isn't really feasible, 971 * but using the cast_bullet isn't really feasible,
947 * so just set up the appropriate values. 972 * so just set up the appropriate values.
948 */ 973 */
949 at = find_archetype(SPLINT); 974 if (archetype *at = archetype::find (SPLINT))
950 if (at) { 975 {
951 for(i=1;i<9;i++) { 976 for (i = 1; i < 9; i++)
977 {
952 if (out_of_map(op->map, op->x + freearr_x[i], op->y + freearr_x[i])) 978 if (out_of_map (op->map, op->x + freearr_x[i], op->y + freearr_x[i]))
953 continue; 979 continue;
980
954 tmp = arch_to_object(at); 981 tmp = arch_to_object (at);
955 tmp->direction = i; 982 tmp->direction = i;
956 tmp->range = op->range; 983 tmp->range = op->range;
957 tmp->stats.dam = op->stats.dam; 984 tmp->stats.dam = op->stats.dam;
958 tmp->duration = op->duration; 985 tmp->duration = op->duration;
959 tmp->attacktype = op->attacktype; 986 tmp->attacktype = op->attacktype;
960 copy_owner (tmp, op); 987 tmp->set_owner (op);
961 if(op->skill && op->skill != tmp->skill) { 988 if (op->skill && op->skill != tmp->skill)
962 if (tmp->skill) free_string(tmp->skill); 989 tmp->skill = op->skill;
963 tmp->skill = add_refcount(op->skill); 990
991 if (QUERY_FLAG (tmp, FLAG_IS_TURNABLE))
992 SET_ANIMATION (tmp, i);
993
994 op->map->insert (tmp, op->x + freearr_x[i], op->y + freearr_x[i], op);
995 move_bullet (tmp);
996 }
964 } 997 }
965 if(QUERY_FLAG(tmp, FLAG_IS_TURNABLE))
966 SET_ANIMATION(tmp, i);
967 tmp->x = op->x + freearr_x[i];
968 tmp->y = op->y + freearr_x[i];
969 insert_ob_in_map(tmp, op->map, op, 0);
970 move_bullet(tmp);
971 }
972 }
973 998
974 explode_bullet(op); 999 explode_bullet (op);
975} 1000}
976 1001
1002int
977int create_bomb(object *op,object *caster,int dir, object *spell) { 1003create_bomb (object *op, object *caster, int dir, object *spell)
1004{
978 1005
979 object *tmp; 1006 object *tmp;
980 int mflags; 1007 int mflags;
981 sint16 dx=op->x+freearr_x[dir], dy=op->y+freearr_y[dir]; 1008 sint16 dx = op->x + freearr_x[dir], dy = op->y + freearr_y[dir];
982 mapstruct *m; 1009 maptile *m;
983 1010
984 mflags = get_map_flags(op->map, &m, dx,dy, &dx,&dy); 1011 mflags = get_map_flags (op->map, &m, dx, dy, &dx, &dy);
985 if ((mflags & P_OUT_OF_MAP) || (GET_MAP_MOVE_BLOCK(m, dx, dy) & MOVE_WALK)) { 1012 if ((mflags & P_OUT_OF_MAP) || (GET_MAP_MOVE_BLOCK (m, dx, dy) & MOVE_WALK))
1013 {
986 new_draw_info(NDI_UNIQUE, 0,op,"There is something in the way."); 1014 new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way.");
987 return 0; 1015 return 0;
988 } 1016 }
989 tmp=arch_to_object(spell->other_arch); 1017 tmp = arch_to_object (spell->other_arch);
990 1018
991 /* level dependencies for bomb */ 1019 /* level dependencies for bomb */
992 tmp->range=spell->range + SP_level_range_adjust(caster,spell); 1020 tmp->range = spell->range + SP_level_range_adjust (caster, spell);
993 tmp->stats.dam=spell->stats.dam + SP_level_dam_adjust(caster,spell); 1021 tmp->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell);
994 tmp->duration = spell->duration + SP_level_duration_adjust(caster,spell); 1022 tmp->duration = spell->duration + SP_level_duration_adjust (caster, spell);
995 tmp->attacktype = spell->attacktype; 1023 tmp->attacktype = spell->attacktype;
996 1024
997 set_owner(tmp,op); 1025 tmp->set_owner (op);
998 set_spell_skill(op, caster, spell, tmp); 1026 set_spell_skill (op, caster, spell, tmp);
999 tmp->x=dx; 1027
1000 tmp->y=dy; 1028 m->insert (tmp, dx, dy, op);
1001 insert_ob_in_map(tmp,m,op,0);
1002 return 1; 1029 return 1;
1003} 1030}
1004 1031
1005/**************************************************************************** 1032/****************************************************************************
1006 * 1033 *
1007 * smite related spell code. 1034 * smite related spell code.
1015 * dir is the direction to look in. 1042 * dir is the direction to look in.
1016 * range is how far out to look. 1043 * range is how far out to look.
1017 * type is the type of spell - either SPELL_MANA or SPELL_GRACE. 1044 * type is the type of spell - either SPELL_MANA or SPELL_GRACE.
1018 * this info is used for blocked magic/unholy spaces. 1045 * this info is used for blocked magic/unholy spaces.
1019 */ 1046 */
1020 1047object *
1021object *get_pointed_target(object *op, int dir, int range, int type) { 1048get_pointed_target (object *op, int dir, int range, int type)
1049{
1022 object *target; 1050 object *target;
1023 sint16 x,y; 1051 sint16 x, y;
1024 int dist, mflags; 1052 int dist, mflags;
1025 mapstruct *mp; 1053 maptile *mp;
1026 1054
1027 if (dir==0) return NULL; 1055 if (dir == 0)
1028
1029 for (dist=1; dist<range; dist++) {
1030 x = op->x + freearr_x[dir] * dist;
1031 y = op->y + freearr_y[dir] * dist;
1032 mp = op->map;
1033 mflags = get_map_flags(op->map, &mp, x, y, &x, &y);
1034
1035 if (mflags & P_OUT_OF_MAP) return NULL;
1036 if ((type & SPELL_MANA) && (mflags & P_NO_MAGIC)) return NULL;
1037 if ((type & SPELL_GRACE) && (mflags & P_NO_CLERIC)) return NULL;
1038 if (GET_MAP_MOVE_BLOCK(mp, x, y) & MOVE_FLY_LOW) return NULL;
1039
1040 if (mflags & P_IS_ALIVE) {
1041 for(target=get_map_ob(mp,x,y); target; target=target->above) {
1042 if(QUERY_FLAG(target->head?target->head:target,FLAG_MONSTER)) {
1043 return target;
1044 }
1045 }
1046 }
1047 }
1048 return NULL; 1056 return NULL;
1049}
1050 1057
1058 for (dist = 1; dist < range; dist++)
1059 {
1060 x = op->x + freearr_x[dir] * dist;
1061 y = op->y + freearr_y[dir] * dist;
1062 mp = op->map;
1063 mflags = get_map_flags (op->map, &mp, x, y, &x, &y);
1064
1065 if (mflags & P_OUT_OF_MAP)
1066 return NULL;
1067 if ((type & SPELL_MANA) && (mflags & P_NO_MAGIC))
1068 return NULL;
1069 if ((type & SPELL_GRACE) && (mflags & P_NO_CLERIC))
1070 return NULL;
1071 if (GET_MAP_MOVE_BLOCK (mp, x, y) & MOVE_FLY_LOW)
1072 return NULL;
1073
1074 if (mflags & P_IS_ALIVE)
1075 for (target = GET_MAP_OB (mp, x, y); target; target = target->above)
1076 if (QUERY_FLAG (target, FLAG_MONSTER))
1077 return target;
1078 }
1079
1080 return NULL;
1081}
1051 1082
1052/* cast_smite_arch() - the priest points to a creature and causes 1083/* cast_smite_arch() - the priest points to a creature and causes
1053 * a 'godly curse' to decend. 1084 * a 'godly curse' to decend.
1054 * usual params - 1085 * usual params -
1055 * op = player 1086 * op = player
1056 * caster = object casting the spell. 1087 * caster = object casting the spell.
1057 * dir = direction being cast 1088 * dir = direction being cast
1058 * spell = spell object 1089 * spell = spell object
1059 */ 1090 */
1060 1091
1092int
1061int cast_smite_spell (object *op, object *caster,int dir, object *spell) { 1093cast_smite_spell (object *op, object *caster, int dir, object *spell)
1094{
1062 object *effect, *target; 1095 object *effect, *target;
1063 object *god = find_god(determine_god(op)); 1096 object *god = find_god (determine_god (op));
1064 int range; 1097 int range;
1065 1098
1066 range = spell->range + SP_level_range_adjust(caster,spell); 1099 range = spell->range + SP_level_range_adjust (caster, spell);
1067 target = get_pointed_target(op,dir, 50, spell->stats.grace?SPELL_GRACE:SPELL_MANA); 1100 target = get_pointed_target (op, dir, 50, spell->stats.grace ? SPELL_GRACE : SPELL_MANA);
1068 1101
1069 /* Bunch of conditions for casting this spell. Note that only 1102 /* Bunch of conditions for casting this spell. Note that only
1070 * require a god if this is a cleric spell (requires grace). 1103 * require a god if this is a cleric spell (requires grace).
1071 * This makes this spell much more general purpose - it can be used 1104 * This makes this spell much more general purpose - it can be used
1072 * by wizards also, which is good, because I think this is a very 1105 * by wizards also, which is good, because I think this is a very
1073 * interesting spell. 1106 * interesting spell.
1074 * if it is a cleric spell, you need a god, and the creature 1107 * if it is a cleric spell, you need a god, and the creature
1075 * can't be friendly to your god. 1108 * can't be friendly to your god.
1076 */ 1109 */
1077 1110
1078 if(!target || QUERY_FLAG(target,FLAG_REFL_SPELL) 1111 if (!target || QUERY_FLAG (target, FLAG_REFL_SPELL)
1079 ||(!god && spell->stats.grace) 1112 || (!god && spell->stats.grace)
1080 ||(target->title && god && !strcmp(target->title,god->name)) 1113 || (target->title && god && !strcmp (target->title, god->name)) || (target->race && god && strstr (target->race, god->race)))
1081 ||(target->race && god && strstr(target->race,god->race))) { 1114 {
1082 new_draw_info(NDI_UNIQUE,0,op,"Your request is unheeded."); 1115 new_draw_info (NDI_UNIQUE, 0, op, "Your request is unheeded.");
1083 return 0; 1116 return 0;
1084 } 1117 }
1085 1118
1086 if (spell->other_arch) 1119 if (spell->other_arch)
1087 effect = arch_to_object(spell->other_arch); 1120 effect = arch_to_object (spell->other_arch);
1088 else 1121 else
1089 return 0; 1122 return 0;
1090 1123
1091 /* tailor the effect by priest level and worshipped God */ 1124 /* tailor the effect by priest level and worshipped God */
1092 effect->level = caster_level (caster, spell); 1125 effect->level = caster_level (caster, spell);
1093 effect->attacktype = spell->attacktype; 1126 effect->attacktype = spell->attacktype;
1094 if (effect->attacktype & (AT_HOLYWORD | AT_GODPOWER)) { 1127 if (effect->attacktype & (AT_HOLYWORD | AT_GODPOWER))
1128 {
1095 if(tailor_god_spell(effect,op)) 1129 if (tailor_god_spell (effect, op))
1096 new_draw_info_format(NDI_UNIQUE,0,op, 1130 new_draw_info_format (NDI_UNIQUE, 0, op, "%s answers your call!", determine_god (op));
1097 "%s answers your call!",determine_god(op));
1098 else { 1131 else
1132 {
1099 new_draw_info(NDI_UNIQUE,0,op,"Your request is ignored."); 1133 new_draw_info (NDI_UNIQUE, 0, op, "Your request is ignored.");
1100 return 0; 1134 return 0;
1101 } 1135 }
1102 } 1136 }
1103 1137
1104 /* size of the area of destruction */ 1138 /* size of the area of destruction */
1105 effect->range=spell->range + 1139 effect->range = spell->range + SP_level_range_adjust (caster, spell);
1106 SP_level_range_adjust(caster,spell); 1140 effect->duration = spell->duration + SP_level_range_adjust (caster, spell);
1107 effect->duration=spell->duration +
1108 SP_level_range_adjust(caster,spell);
1109 1141
1110 if (effect->attacktype & AT_DEATH) { 1142 if (effect->attacktype & AT_DEATH)
1111 effect->level=spell->stats.dam + 1143 {
1112 SP_level_dam_adjust(caster,spell); 1144 effect->level = spell->stats.dam + SP_level_dam_adjust (caster, spell);
1113 1145
1114 /* casting death spells at undead isn't a good thing */ 1146 /* casting death spells at undead isn't a good thing */
1115 if QUERY_FLAG(target, FLAG_UNDEAD) { 1147 if (QUERY_FLAG (target, FLAG_UNDEAD))
1148 {
1116 if(random_roll(0, 2, op, PREFER_LOW)) { 1149 if (random_roll (0, 2, op, PREFER_LOW))
1150 {
1117 new_draw_info(NDI_UNIQUE,0,op,"Idiot! Your spell boomerangs!"); 1151 new_draw_info (NDI_UNIQUE, 0, op, "Idiot! Your spell boomerangs!");
1118 effect->x=op->x; 1152 effect->x = op->x;
1119 effect->y=op->y; 1153 effect->y = op->y;
1120 } else { 1154 }
1121 new_draw_info_format(NDI_UNIQUE,0,op,"The %s looks stronger!", 1155 else
1122 query_name(target)); 1156 {
1157 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s looks stronger!", query_name (target));
1123 target->stats.hp = target->stats.maxhp*2; 1158 target->stats.hp = target->stats.maxhp * 2;
1124 free_object(effect); 1159 effect->destroy ();
1125 return 0; 1160 return 0;
1161 }
1162 }
1126 } 1163 }
1127 } 1164 else
1128 } else { 1165 {
1129 /* how much woe to inflict :) */ 1166 /* how much woe to inflict :) */
1130 effect->stats.dam=spell->stats.dam + 1167 effect->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell);
1131 SP_level_dam_adjust(caster,spell);
1132 } 1168 }
1133 1169
1134 set_owner(effect,op); 1170 effect->set_owner (op);
1135 set_spell_skill(op, caster, spell, effect); 1171 set_spell_skill (op, caster, spell, effect);
1136 1172
1137 /* ok, tell it where to be, and insert! */ 1173 /* ok, tell it where to be, and insert! */
1138 effect->x=target->x; 1174 effect->insert_at (target, op);
1139 effect->y=target->y; 1175
1140 insert_ob_in_map(effect,target->map,op,0);
1141
1142 return 1; 1176 return 1;
1143} 1177}
1144 1178
1145 1179
1146/**************************************************************************** 1180/****************************************************************************
1147 * 1181 *
1149 * note that the fire_bullet is used to fire the missile. The 1183 * note that the fire_bullet is used to fire the missile. The
1150 * code here is just to move the missile. 1184 * code here is just to move the missile.
1151 ****************************************************************************/ 1185 ****************************************************************************/
1152 1186
1153/* op is a missile that needs to be moved */ 1187/* op is a missile that needs to be moved */
1188void
1154void move_missile(object *op) { 1189move_missile (object *op)
1190{
1155 int i, mflags; 1191 int i, mflags;
1156 object *owner; 1192 object *owner;
1157 sint16 new_x, new_y; 1193 sint16 new_x, new_y;
1158 mapstruct *m; 1194 maptile *m;
1159 1195
1160 if (op->range-- <=0) { 1196 if (op->range-- <= 0)
1161 remove_ob(op);
1162 free_object(op);
1163 return;
1164 } 1197 {
1198 op->destroy ();
1199 return;
1200 }
1165 1201
1166 owner = get_owner(op); 1202 owner = op->owner;
1167#if 0 1203#if 0
1168 /* It'd make things nastier if this wasn't here - spells cast by 1204 /* It'd make things nastier if this wasn't here - spells cast by
1169 * monster that are then killed would continue to survive 1205 * monster that are then killed would continue to survive
1170 */ 1206 */
1171 if (owner == NULL) { 1207 if (owner == NULL)
1172 remove_ob(op); 1208 {
1173 free_object(op); 1209 op->destroy ();
1174 return; 1210 return;
1175 } 1211 }
1176#endif 1212#endif
1177 1213
1178 new_x = op->x + DIRX(op); 1214 new_x = op->x + DIRX (op);
1179 new_y = op->y + DIRY(op); 1215 new_y = op->y + DIRY (op);
1180 1216
1181 mflags = get_map_flags(op->map, &m, new_x, new_y, &new_x, &new_y); 1217 mflags = get_map_flags (op->map, &m, new_x, new_y, &new_x, &new_y);
1182 1218
1183 if (!(mflags & P_OUT_OF_MAP) &&
1184 ((mflags & P_IS_ALIVE) || OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, new_x, new_y)))) { 1219 if (!(mflags & P_OUT_OF_MAP) && ((mflags & P_IS_ALIVE) || OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, new_x, new_y))))
1185 tag_t tag = op->count; 1220 {
1186 hit_map (op, op->direction, AT_MAGIC, 1); 1221 hit_map (op, op->direction, AT_MAGIC, 1);
1187 /* Basically, missile only hits one thing then goes away. 1222 /* Basically, missile only hits one thing then goes away.
1188 * we need to remove it if someone hasn't already done so. 1223 * we need to remove it if someone hasn't already done so.
1189 */ 1224 */
1190 if ( ! was_destroyed (op, tag)) { 1225 if (!op->destroyed ())
1191 remove_ob (op); 1226 op->destroy ();
1192 free_object(op);
1193 }
1194 return;
1195 }
1196 1227
1197 remove_ob(op); 1228 return;
1229 }
1230
1231 op->remove ();
1232
1198 if ( ! op->direction || (mflags & P_OUT_OF_MAP)) { 1233 if (!op->direction || (mflags & P_OUT_OF_MAP))
1199 free_object(op);
1200 return;
1201 } 1234 {
1202 op->x = new_x; 1235 op->destroy ();
1203 op->y = new_y; 1236 return;
1204 op->map = m; 1237 }
1205 i=spell_find_dir(op->map, op->x, op->y, get_owner(op)); 1238
1239 i = spell_find_dir (m, new_x, new_y, op->owner);
1206 if(i > 0 && i != op->direction){ 1240 if (i > 0 && i != op->direction)
1241 {
1207 op->direction=i; 1242 op->direction = i;
1208 SET_ANIMATION(op, op->direction); 1243 SET_ANIMATION (op, op->direction);
1209 } 1244 }
1210 insert_ob_in_map(op,op->map,op,0); 1245
1246 m->insert (op, new_x, new_y, op);
1211} 1247}
1212 1248
1213/**************************************************************************** 1249/****************************************************************************
1214 * Destruction 1250 * Destruction
1215 ****************************************************************************/ 1251 ****************************************************************************/
1252
1216/* make_object_glow() - currently only makes living objects glow. 1253/* make_object_glow() - currently only makes living objects glow.
1217 * we do this by creating a force and inserting it in the 1254 * we do this by creating a force and inserting it in the
1218 * object. if time is 0, the object glows permanently. To truely 1255 * object. if time is 0, the object glows permanently. To truely
1219 * make this work for non-living objects, we would have to 1256 * make this work for non-living objects, we would have to
1220 * give them the capability to have an inventory. b.t. 1257 * give them the capability to have an inventory. b.t.
1221 */ 1258 */
1222 1259
1260int
1223int make_object_glow(object *op, int radius, int time) { 1261make_object_glow (object *op, int radius, int time)
1262{
1224 object *tmp; 1263 object *tmp;
1225 1264
1226 /* some things are unaffected... */ 1265 /* some things are unaffected... */
1227 if(op->path_denied&PATH_LIGHT) 1266 if (op->path_denied & PATH_LIGHT)
1228 return 0; 1267 return 0;
1229 1268
1230 tmp=get_archetype(FORCE_NAME); 1269 tmp = get_archetype (FORCE_NAME);
1231 tmp->speed = 0.01; 1270 tmp->speed = 0.01;
1232 tmp->stats.food = time; 1271 tmp->stats.food = time;
1233 SET_FLAG(tmp, FLAG_IS_USED_UP); 1272 SET_FLAG (tmp, FLAG_IS_USED_UP);
1234 tmp->glow_radius=radius; 1273 tmp->glow_radius = radius;
1235 if (tmp->glow_radius > MAX_LIGHT_RADII) 1274 if (tmp->glow_radius > MAX_LIGHT_RADII)
1236 tmp->glow_radius = MAX_LIGHT_RADII; 1275 tmp->glow_radius = MAX_LIGHT_RADII;
1237 1276
1238 tmp->x=op->x; 1277 tmp->x = op->x;
1239 tmp->y=op->y; 1278 tmp->y = op->y;
1240 if(tmp->speed<MIN_ACTIVE_SPEED) tmp->speed = MIN_ACTIVE_SPEED; /* safety */ 1279 if (tmp->speed < MIN_ACTIVE_SPEED)
1280 tmp->speed = MIN_ACTIVE_SPEED; /* safety */
1241 tmp=insert_ob_in_ob(tmp,op); 1281 tmp = insert_ob_in_ob (tmp, op);
1242 if (tmp->glow_radius > op->glow_radius) 1282 if (tmp->glow_radius > op->glow_radius)
1243 op->glow_radius = tmp->glow_radius; 1283 op->glow_radius = tmp->glow_radius;
1244 1284
1245 if(!tmp->env||op!=tmp->env) { 1285 if (!tmp->env || op != tmp->env)
1286 {
1246 LOG(llevError,"make_object_glow() failed to insert glowing force in %s\n", 1287 LOG (llevError, "make_object_glow() failed to insert glowing force in %s\n", &op->name);
1247 op->name); 1288 return 0;
1248 return 0;
1249 } 1289 }
1250 return 1; 1290 return 1;
1251} 1291}
1252 1292
1253 1293int
1254
1255
1256int cast_destruction(object *op, object *caster, object *spell_ob) { 1294cast_destruction (object *op, object *caster, object *spell_ob)
1295{
1257 int i,j, range, mflags, friendly=0, dam, dur; 1296 int i, j, range, mflags, friendly = 0, dam, dur;
1258 sint16 sx,sy; 1297 sint16 sx, sy;
1259 mapstruct *m; 1298 maptile *m;
1260 object *tmp; 1299 object *tmp;
1261 const char *skill; 1300 const char *skill;
1262 1301
1263 range = spell_ob->range + SP_level_range_adjust(caster, spell_ob); 1302 range = spell_ob->range + SP_level_range_adjust (caster, spell_ob);
1264 dam = spell_ob->stats.dam + SP_level_dam_adjust(caster, spell_ob); 1303 dam = spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob);
1265 dur = spell_ob->duration + SP_level_duration_adjust(caster, spell_ob); 1304 dur = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
1266 if (QUERY_FLAG(op, FLAG_FRIENDLY) || op->type == PLAYER) friendly=1; 1305 if (QUERY_FLAG (op, FLAG_FRIENDLY) || op->type == PLAYER)
1306 friendly = 1;
1267 1307
1268 /* destruction doesn't use another spell object, so we need 1308 /* destruction doesn't use another spell object, so we need
1269 * update op's skill pointer so that exp is properly awarded. 1309 * update op's skill pointer so that exp is properly awarded.
1270 * We do some shortcuts here - since this is just temporary 1310 * We do some shortcuts here - since this is just temporary
1271 * and we'll reset the values back, we don't need to go through 1311 * and we'll reset the values back, we don't need to go through
1272 * the full share string/free_string route. 1312 * the full share string/free_string route.
1273 */ 1313 */
1274 skill = op->skill; 1314 skill = op->skill;
1315 if (caster == op)
1275 if (caster == op) op->skill = spell_ob->skill; 1316 op->skill = spell_ob->skill;
1276 else if (caster->skill) op->skill = caster->skill; 1317 else if (caster->skill)
1318 op->skill = caster->skill;
1319 else
1277 else op->skill = NULL; 1320 op->skill = NULL;
1278 1321
1279 change_skill(op, find_skill_by_name(op, op->skill), 1); 1322 op->change_skill (find_skill_by_name (op, op->skill));
1280 1323
1281 for(i= -range; i<range; i++) { 1324 for (i = -range; i < range; i++)
1325 {
1282 for(j=-range; j<range ; j++) { 1326 for (j = -range; j < range; j++)
1327 {
1283 m = op->map; 1328 m = op->map;
1284 sx = op->x + i; 1329 sx = op->x + i;
1285 sy = op->y + j; 1330 sy = op->y + j;
1331
1286 mflags = get_map_flags(m, &m, sx, sy, &sx, &sy); 1332 mflags = get_map_flags (m, &m, sx, sy, &sx, &sy);
1287 if (mflags & P_OUT_OF_MAP) continue; 1333 if (mflags & P_OUT_OF_MAP)
1334 continue;
1335
1288 if (mflags & P_IS_ALIVE) { 1336 if (mflags & P_IS_ALIVE)
1289 for (tmp=get_map_ob(m, sx, sy); tmp; tmp=tmp->above) { 1337 {
1338 for (tmp = GET_MAP_OB (m, sx, sy); tmp; tmp = tmp->above)
1290 if (QUERY_FLAG(tmp, FLAG_ALIVE) || tmp->type==PLAYER) break; 1339 if (QUERY_FLAG (tmp, FLAG_ALIVE) || tmp->type == PLAYER)
1291 } 1340 break;
1292 if (tmp) {
1293 if (tmp->head) tmp=tmp->head;
1294 1341
1342 if (tmp)
1343 {
1344 if (tmp->head)
1345 tmp = tmp->head;
1346
1295 if ((friendly && !QUERY_FLAG(tmp, FLAG_FRIENDLY) && tmp->type!=PLAYER) || 1347 if ((friendly && !QUERY_FLAG (tmp, FLAG_FRIENDLY) && tmp->type != PLAYER) ||
1296 (!friendly && (QUERY_FLAG(tmp, FLAG_FRIENDLY) || tmp->type==PLAYER))) { 1348 (!friendly && (QUERY_FLAG (tmp, FLAG_FRIENDLY) || tmp->type == PLAYER)))
1297 if (spell_ob->subtype == SP_DESTRUCTION) { 1349 {
1350 if (spell_ob->subtype == SP_DESTRUCTION)
1351 {
1298 hit_player(tmp,dam,op,spell_ob->attacktype,0); 1352 hit_player (tmp, dam, op, spell_ob->attacktype, 0);
1299 if (spell_ob->other_arch) { 1353 if (spell_ob->other_arch)
1300 tmp = arch_to_object(spell_ob->other_arch); 1354 m->insert (arch_to_object (spell_ob->other_arch), sx, sy, op);
1301 tmp->x = sx; 1355 }
1302 tmp->y = sy; 1356 else if (spell_ob->subtype == SP_FAERY_FIRE && tmp->resist[ATNR_MAGIC] != 100)
1303 insert_ob_in_map(tmp, m, op, 0); 1357 {
1304 }
1305 }
1306 else if (spell_ob->subtype == SP_FAERY_FIRE &&
1307 tmp->resist[ATNR_MAGIC]!=100) {
1308 if (make_object_glow(tmp, 1, dur) && spell_ob->other_arch) { 1358 if (make_object_glow (tmp, 1, dur) && spell_ob->other_arch)
1309 object *effect = arch_to_object(spell_ob->other_arch); 1359 m->insert (arch_to_object (spell_ob->other_arch), sx, sy, op);
1310 effect->x = sx; 1360 }
1311 effect->y = sy; 1361 }
1312 insert_ob_in_map(effect, m, op, 0); 1362 }
1313 } 1363 }
1314 } 1364 }
1315 }
1316 }
1317 } 1365 }
1318 } 1366
1319 }
1320 op->skill = skill; 1367 op->skill = skill;
1321 return 1; 1368 return 1;
1322} 1369}
1323 1370
1324/*************************************************************************** 1371/***************************************************************************
1325 * 1372 *
1326 * CURSE 1373 * CURSE
1327 * 1374 *
1328 ***************************************************************************/ 1375 ***************************************************************************/
1329 1376
1377int
1330int cast_curse(object *op, object *caster, object *spell_ob, int dir) { 1378cast_curse (object *op, object *caster, object *spell_ob, int dir)
1379{
1331 object *god = find_god(determine_god(op)); 1380 object *god = find_god (determine_god (op));
1332 object *tmp, *force; 1381 object *tmp, *force;
1333 1382
1334 tmp = get_pointed_target(op, (dir==0)?op->direction:dir, 1383 tmp = get_pointed_target (op, (dir == 0) ? op->direction : dir, spell_ob->range, SPELL_GRACE);
1335 spell_ob->range, SPELL_GRACE);
1336 if (!tmp) { 1384 if (!tmp)
1337 new_draw_info(NDI_UNIQUE, 0, op,
1338 "There is no one in that direction to curse.");
1339 return 0;
1340 } 1385 {
1386 new_draw_info (NDI_UNIQUE, 0, op, "There is no one in that direction to curse.");
1387 return 0;
1388 }
1341 1389
1342 /* If we've already got a force of this type, don't add a new one. */ 1390 /* If we've already got a force of this type, don't add a new one. */
1343 for(force=tmp->inv; force!=NULL; force=force->below) { 1391 for (force = tmp->inv; force != NULL; force = force->below)
1392 {
1344 if (force->type==FORCE && force->subtype == FORCE_CHANGE_ABILITY) { 1393 if (force->type == FORCE && force->subtype == FORCE_CHANGE_ABILITY)
1394 {
1345 if (force->name == spell_ob->name) { 1395 if (force->name == spell_ob->name)
1346 break; 1396 {
1347 } 1397 break;
1398 }
1348 else if (spell_ob->race && spell_ob->race == force->name) { 1399 else if (spell_ob->race && spell_ob->race == force->name)
1349 new_draw_info_format(NDI_UNIQUE, 0, op, 1400 {
1350 "You can not cast %s while %s is in effect", 1401 new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &force->name_pl);
1351 spell_ob->name, force->name_pl); 1402 return 0;
1352 return 0; 1403 }
1404 }
1353 } 1405 }
1354 }
1355 }
1356 1406
1357 if(force==NULL) { 1407 if (force == NULL)
1408 {
1358 force=get_archetype(FORCE_NAME); 1409 force = get_archetype (FORCE_NAME);
1359 force->subtype = FORCE_CHANGE_ABILITY; 1410 force->subtype = FORCE_CHANGE_ABILITY;
1360 free_string(force->name);
1361 if (spell_ob->race) 1411 if (spell_ob->race)
1362 force->name = add_refcount(spell_ob->race); 1412 force->name = spell_ob->race;
1363 else
1364 force->name = add_refcount(spell_ob->name);
1365 free_string(force->name_pl);
1366 force->name_pl = add_refcount(spell_ob->name);
1367
1368 } else { 1413 else
1414 force->name = spell_ob->name;
1415
1416 force->name_pl = spell_ob->name;
1417
1418 }
1419 else
1420 {
1369 int duration; 1421 int duration;
1370 1422
1371 duration = spell_ob->duration + SP_level_duration_adjust(caster, spell_ob) * 50; 1423 duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1372 if (duration > force->duration) { 1424 if (duration > force->duration)
1425 {
1373 force->duration = duration; 1426 force->duration = duration;
1374 new_draw_info(NDI_UNIQUE, 0, op, "You recast the spell while in effect."); 1427 new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
1375 } else { 1428 }
1429 else
1430 {
1376 new_draw_info(NDI_UNIQUE, 0, op, "Recasting the spell had no effect."); 1431 new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect.");
1377 } 1432 }
1378 return 1; 1433 return 1;
1379 } 1434 }
1380 force->duration = spell_ob->duration + SP_level_duration_adjust(caster, spell_ob) * 50; 1435 force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1381 force->speed = 1.0; 1436 force->speed = 1.f;
1382 force->speed_left = -1.0; 1437 force->speed_left = -1.f;
1383 SET_FLAG(force, FLAG_APPLIED); 1438 SET_FLAG (force, FLAG_APPLIED);
1384 1439
1385 if(god) { 1440 if (god)
1441 {
1386 if (spell_ob->last_grace) 1442 if (spell_ob->last_grace)
1387 force->path_repelled=god->path_repelled; 1443 force->path_repelled = god->path_repelled;
1388 if (spell_ob->last_grace) 1444 if (spell_ob->last_grace)
1389 force->path_denied=god->path_denied; 1445 force->path_denied = god->path_denied;
1390 new_draw_info_format(NDI_UNIQUE, 0,tmp, 1446 new_draw_info_format (NDI_UNIQUE, 0, tmp, "You are a victim of %s's curse!", &god->name);
1391 "You are a victim of %s's curse!",god->name); 1447 }
1392 } else 1448 else
1393 new_draw_info(NDI_UNIQUE, 0,op,"Your curse seems empty."); 1449 new_draw_info (NDI_UNIQUE, 0, op, "Your curse seems empty.");
1394 1450
1395 1451
1396 if(tmp!=op && op->type==PLAYER) 1452 if (tmp != op && op->type == PLAYER)
1397 new_draw_info_format(NDI_UNIQUE, 0, op, "You curse %s!",tmp->name); 1453 new_draw_info_format (NDI_UNIQUE, 0, op, "You curse %s!", &tmp->name);
1398 1454
1399 force->stats.ac = spell_ob->stats.ac; 1455 force->stats.ac = spell_ob->stats.ac;
1400 force->stats.wc = spell_ob->stats.wc; 1456 force->stats.wc = spell_ob->stats.wc;
1401 1457
1402 change_abil(tmp,force); /* Mostly to display any messages */ 1458 change_abil (tmp, force); /* Mostly to display any messages */
1403 insert_ob_in_ob(force,tmp); 1459 insert_ob_in_ob (force, tmp);
1404 fix_player(tmp); 1460 tmp->update_stats ();
1405 return 1; 1461 return 1;
1406 1462
1407} 1463}
1408
1409 1464
1410/********************************************************************** 1465/**********************************************************************
1411 * mood change 1466 * mood change
1412 * Arguably, this may or may not be an attack spell. But since it 1467 * Arguably, this may or may not be an attack spell. But since it
1413 * effects monsters, it seems best to put it into this file 1468 * effects monsters, it seems best to put it into this file
1414 ***********************************************************************/ 1469 ***********************************************************************/
1415 1470
1416/* This covers the various spells that change the moods of monsters - 1471/* This covers the various spells that change the moods of monsters -
1417 * makes them angry, peacful, friendly, etc. 1472 * makes them angry, peacful, friendly, etc.
1418 */ 1473 */
1474int
1419int mood_change(object *op, object *caster, object *spell) { 1475mood_change (object *op, object *caster, object *spell)
1476{
1420 object *tmp, *god, *head; 1477 object *tmp, *god, *head;
1421 int done_one, range, mflags, level, at, best_at; 1478 int done_one, range, mflags, level, at, best_at;
1422 sint16 x, y, nx, ny; 1479 sint16 x, y, nx, ny;
1423 mapstruct *m; 1480 maptile *m;
1424 const char *race; 1481 const char *race;
1425 1482
1426 /* We precompute some values here so that we don't have to keep 1483 /* We precompute some values here so that we don't have to keep
1427 * doing it over and over again. 1484 * doing it over and over again.
1428 */ 1485 */
1429 god=find_god(determine_god(op)); 1486 god = find_god (determine_god (op));
1430 level=caster_level(caster, spell); 1487 level = caster_level (caster, spell);
1431 range = spell->range + SP_level_range_adjust(caster, spell); 1488 range = spell->range + SP_level_range_adjust (caster, spell);
1432 1489
1433 /* On the bright side, no monster should ever have a race of GOD_... 1490 /* On the bright side, no monster should ever have a race of GOD_...
1434 * so even if the player doesn't worship a god, if race=GOD_.., it 1491 * so even if the player doesn't worship a god, if race=GOD_.., it
1435 * won't ever match anything. 1492 * won't ever match anything.
1436 */ 1493 */
1437 if (!spell->race) race=NULL; 1494 if (!spell->race)
1495 race = NULL;
1438 else if (god && !strcmp(spell->race, "GOD_SLAYING")) race = god->slaying; 1496 else if (god && !strcmp (spell->race, "GOD_SLAYING"))
1497 race = god->slaying;
1439 else if (god && !strcmp(spell->race, "GOD_FRIEND")) race = god->race; 1498 else if (god && !strcmp (spell->race, "GOD_FRIEND"))
1499 race = god->race;
1500 else
1440 else race = spell->race; 1501 race = spell->race;
1441
1442 1502
1443 for (x = op->x - range; x <= op->x + range; x++) 1503 for (x = op->x - range; x <= op->x + range; x++)
1444 for (y = op->y - range; y <= op->y + range; y++) { 1504 for (y = op->y - range; y <= op->y + range; y++)
1445 1505 {
1446 done_one=0; 1506 done_one = 0;
1447 m = op->map; 1507 m = op->map;
1448 nx = x; 1508 nx = x;
1449 ny = y; 1509 ny = y;
1450 mflags = get_map_flags(m, &m, x, y, &nx, &ny); 1510 mflags = get_map_flags (m, &m, x, y, &nx, &ny);
1451 if (mflags & P_OUT_OF_MAP) continue; 1511 if (mflags & P_OUT_OF_MAP)
1512 continue;
1452 1513
1453 /* If there is nothing living on this space, no need to go further */ 1514 /* If there is nothing living on this space, no need to go further */
1454 if (!(mflags & P_IS_ALIVE)) continue; 1515 if (!(mflags & P_IS_ALIVE))
1516 continue;
1455 1517
1518 // players can only affect spaces that they can actually see
1519 if (caster && caster->contr
1520 && caster->contr->visibility_at (m, nx, ny) < 70)
1521 continue;
1522
1456 for (tmp = get_map_ob(m, nx, ny); tmp; tmp = tmp->above) 1523 for (tmp = GET_MAP_TOP (m, nx, ny); tmp; tmp = tmp->below)
1457 if (QUERY_FLAG(tmp, FLAG_MONSTER)) break; 1524 if (QUERY_FLAG (tmp, FLAG_MONSTER))
1525 break;
1458 1526
1459 /* There can be living objects that are not monsters */ 1527 /* There can be living objects that are not monsters */
1460 if (!tmp || tmp->type==PLAYER) continue; 1528 if (!tmp || tmp->type == PLAYER)
1529 continue;
1461 1530
1462 /* Only the head has meaningful data, so resolve to that */ 1531 /* Only the head has meaningful data, so resolve to that */
1463 if (tmp->head) head=tmp->head; 1532 if (tmp->head)
1464 else head=tmp; 1533 head = tmp->head;
1534 else
1535 head = tmp;
1465 1536
1466 /* Make sure the race is OK. Likewise, only effect undead if spell specifically allows it */ 1537 /* Make sure the race is OK. Likewise, only effect undead if spell specifically allows it */
1467 if (race && head->race && !strstr(race, head->race)) continue; 1538 if (race && head->race && !strstr (race, head->race))
1539 continue;
1540
1468 if (QUERY_FLAG(head, FLAG_UNDEAD) && !QUERY_FLAG(spell, FLAG_UNDEAD)) continue; 1541 if (QUERY_FLAG (head, FLAG_UNDEAD) && !QUERY_FLAG (spell, FLAG_UNDEAD))
1542 continue;
1469 1543
1470 /* Now do a bunch of stuff related to saving throws */ 1544 /* Now do a bunch of stuff related to saving throws */
1471 best_at = -1; 1545 best_at = -1;
1472 if (spell->attacktype) { 1546 if (spell->attacktype)
1547 {
1473 for (at=0; at < NROFATTACKS; at++) 1548 for (at = 0; at < NROFATTACKS; at++)
1474 if (spell->attacktype & (1 << at)) 1549 if (spell->attacktype & (1 << at))
1475 if (best_at == -1 || head->resist[at] > head->resist[best_at]) best_at = at; 1550 if (best_at == -1 || head->resist[at] > head->resist[best_at])
1551 best_at = at;
1476 1552
1477 if (best_at == -1) at=0; 1553 if (best_at == -1)
1554 at = 0;
1478 else { 1555 else
1556 {
1479 if (head->resist[best_at] == 100) continue; 1557 if (head->resist[best_at] == 100)
1480 else at = head->resist[best_at] / 5; 1558 continue;
1481 } 1559 else
1560 at = head->resist[best_at] / 5;
1561 }
1482 at -= level / 5; 1562 at -= level / 5;
1483 if (did_make_save(head, head->level, at)) continue; 1563 if (did_make_save (head, head->level, at))
1484 } 1564 continue;
1565 }
1485 else /* spell->attacktype */ 1566 else /* spell->attacktype */
1567 {
1486 /* 1568 /*
1487 Spell has no attacktype (charm & such), so we'll have a specific saving: 1569 Spell has no attacktype (charm & such), so we'll have a specific saving:
1488 * if spell level < monster level, no go 1570 * if spell level < monster level, no go
1489 * else, chance of effect = 20 + min( 50, 2 * ( spell level - monster level ) ) 1571 * else, chance of effect = 20 + min( 50, 2 * ( spell level - monster level ) )
1490 1572
1491 The chance will then be in the range [20-70] percent, not too bad. 1573 The chance will then be in the range [20-70] percent, not too bad.
1492 1574
1493 This is required to fix the 'charm monster' abuse, where a player level 1 can 1575 This is required to fix the 'charm monster' abuse, where a player level 1 can
1494 charm a level 125 monster... 1576 charm a level 125 monster...
1495 1577
1496 Ryo, august 14th 1578 Ryo, august 14th
1497 */ 1579 */
1498 {
1499 if ( head->level > level ) continue; 1580 if (head->level > level)
1581 continue;
1582
1500 if ( random_roll( 0, 100, caster, PREFER_LOW ) >= ( 20 + MIN( 50, 2 * ( level - head->level ) ) ) ) 1583 if (random_roll (0, 100, caster, PREFER_LOW) >= (20 + MIN (50, 2 * (level - head->level))))
1501 /* Failed, no effect */ 1584 /* Failed, no effect */
1502 continue; 1585 continue;
1503 } 1586 }
1504 1587
1505 /* Done with saving throw. Now start effecting the monster */ 1588 /* Done with saving throw. Now start affecting the monster */
1506 1589
1507 /* aggravation */ 1590 /* aggravation */
1508 if (QUERY_FLAG(spell, FLAG_MONSTER)) { 1591 if (QUERY_FLAG (spell, FLAG_MONSTER))
1592 {
1509 CLEAR_FLAG(head, FLAG_SLEEP); 1593 CLEAR_FLAG (head, FLAG_SLEEP);
1510 if (QUERY_FLAG(head, FLAG_FRIENDLY))
1511 remove_friendly_object(head); 1594 remove_friendly_object (head);
1595 done_one = 1;
1596 head->enemy = op;
1597 }
1512 1598
1513 done_one = 1;
1514 head->enemy = op;
1515 }
1516
1517 /* calm monsters */ 1599 /* calm monsters */
1518 if (QUERY_FLAG(spell, FLAG_UNAGGRESSIVE) && !QUERY_FLAG(head, FLAG_UNAGGRESSIVE)) { 1600 if (QUERY_FLAG (spell, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (head, FLAG_UNAGGRESSIVE))
1601 {
1519 SET_FLAG(head, FLAG_UNAGGRESSIVE); 1602 SET_FLAG (head, FLAG_UNAGGRESSIVE);
1520 head->enemy = NULL; 1603 head->enemy = NULL;
1521 done_one = 1; 1604 done_one = 1;
1522 } 1605 }
1523 1606
1524 /* berserk monsters */ 1607 /* berserk monsters */
1525 if (QUERY_FLAG(spell, FLAG_BERSERK) && !QUERY_FLAG(head, FLAG_BERSERK)) { 1608 if (QUERY_FLAG (spell, FLAG_BERSERK) && !QUERY_FLAG (head, FLAG_BERSERK))
1609 {
1526 SET_FLAG(head, FLAG_BERSERK); 1610 SET_FLAG (head, FLAG_BERSERK);
1527 done_one = 1; 1611 done_one = 1;
1528 } 1612 }
1613
1529 /* charm */ 1614 /* charm */
1530 if (QUERY_FLAG(spell, FLAG_NO_ATTACK) && !QUERY_FLAG(head, FLAG_FRIENDLY)) { 1615 if (QUERY_FLAG (spell, FLAG_NO_ATTACK) && !QUERY_FLAG (head, FLAG_FRIENDLY))
1531 SET_FLAG(head, FLAG_FRIENDLY); 1616 {
1532 /* Prevent uncontolled outbreaks of self replicating monsters. 1617 /* Prevent uncontolled outbreaks of self replicating monsters.
1533 Typical use case is charm, go somwhere, use aggravation to make hostile. 1618 Typical use case is charm, go somwhere, use aggravation to make hostile.
1534 This could lead to fun stuff like mice outbreak in bigworld and server crawl. */ 1619 This could lead to fun stuff like mice outbreak in bigworld and server crawl. */
1535 CLEAR_FLAG(head, FLAG_GENERATOR); 1620 CLEAR_FLAG (head, FLAG_GENERATOR);
1536 set_owner(head, op); 1621 head->set_owner (op);
1537 set_spell_skill(op, caster, spell, head); 1622 set_spell_skill (op, caster, spell, head);
1538 add_friendly_object(head); 1623 add_friendly_object (head);
1539 head->attack_movement = PETMOVE; 1624 head->attack_movement = PETMOVE;
1540 done_one = 1; 1625 done_one = 1;
1541 change_exp(op, head->stats.exp / 2, head->skill, SK_EXP_ADD_SKILL); 1626 change_exp (op, head->stats.exp / 2, head->skill, SK_EXP_ADD_SKILL);
1542 head->stats.exp = 0; 1627 head->stats.exp = 0;
1543 } 1628 }
1544 1629
1545 /* If a monster was effected, put an effect in */ 1630 /* If a monster was effected, put an effect in */
1546 if (done_one && spell->other_arch) { 1631 if (done_one && spell->other_arch)
1547 tmp = arch_to_object(spell->other_arch); 1632 m->insert (arch_to_object (spell->other_arch), nx, ny, op);
1548 tmp->x = nx; 1633 } /* for y */
1549 tmp->y = ny;
1550 insert_ob_in_map(tmp, m, op, 0);
1551 }
1552 } /* for y */
1553 1634
1554 return 1; 1635 return 1;
1555} 1636}
1556 1637
1557 1638
1558/* Move_ball_spell: This handles ball type spells that just sort of wander 1639/* Move_ball_spell: This handles ball type spells that just sort of wander
1559 * about. was called move_ball_lightning, but since more than the ball 1640 * about. was called move_ball_lightning, but since more than the ball
1560 * lightning spell used it, that seemed misnamed. 1641 * lightning spell used it, that seemed misnamed.
1561 * op is the spell effect. 1642 * op is the spell effect.
1562 * note that duration is handled by process_object() in time.c 1643 * note that duration is handled by process_object() in time.c
1563 */ 1644 */
1564 1645
1646void
1565void move_ball_spell(object *op) { 1647move_ball_spell (object *op)
1648{
1566 int i,j,dam_save,dir, mflags; 1649 int i, j, dam_save, dir, mflags;
1567 sint16 nx,ny, hx, hy; 1650 sint16 nx, ny, hx, hy;
1568 object *owner; 1651 object *owner;
1569 mapstruct *m; 1652 maptile *m;
1570 1653
1571 owner = get_owner(op); 1654 owner = op->owner;
1572 1655
1573 /* the following logic makes sure that the ball doesn't move into a wall, 1656 /* the following logic makes sure that the ball doesn't move into a wall,
1574 * and makes sure that it will move along a wall to try and get at it's 1657 * and makes sure that it will move along a wall to try and get at it's
1575 * victim. The block immediately below more or less chooses a random 1658 * victim. The block immediately below more or less chooses a random
1576 * offset to move the ball, eg, keep it mostly on course, with some 1659 * offset to move the ball, eg, keep it mostly on course, with some
1577 * deviations. 1660 * deviations.
1578 */ 1661 */
1579 1662
1580 dir = 0; 1663 dir = 0;
1581 if(!(rndm(0, 3))) 1664 if (!(rndm (0, 3)))
1582 j = rndm(0, 1); 1665 j = rndm (0, 1);
1583 else j=0; 1666 else
1667 j = 0;
1584 1668
1585 for(i = 1; i < 9; i++) { 1669 for (i = 1; i < 9; i++)
1670 {
1586 /* i bit 0: alters sign of offset 1671 /* i bit 0: alters sign of offset
1587 * other bits (i / 2): absolute value of offset 1672 * other bits (i / 2): absolute value of offset
1588 */ 1673 */
1589 1674
1590 int offset = ((i ^ j) & 1) ? (i / 2) : - (i / 2); 1675 int offset = ((i ^ j) & 1) ? (i / 2) : -(i / 2);
1591 int tmpdir = absdir (op->direction + offset); 1676 int tmpdir = absdir (op->direction + offset);
1592 1677
1593 nx = op->x + freearr_x[tmpdir]; 1678 nx = op->x + freearr_x[tmpdir];
1594 ny = op->y + freearr_y[tmpdir]; 1679 ny = op->y + freearr_y[tmpdir];
1595 if ( ! (get_map_flags(op->map, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP) && 1680 if (!(get_map_flags (op->map, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP) && !(OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, nx, ny))))
1596 !(OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, nx, ny)))) { 1681 {
1597 dir = tmpdir; 1682 dir = tmpdir;
1598 break; 1683 break;
1599 } 1684 }
1600 } 1685 }
1601 if (dir == 0) { 1686 if (dir == 0)
1602 nx = op->x;
1603 ny = op->y;
1604 m = op->map;
1605 } 1687 {
1688 nx = op->x;
1689 ny = op->y;
1690 m = op->map;
1691 }
1606 1692
1607 remove_ob(op); 1693 m->insert (op, nx, ny, op);
1608 op->y=ny; 1694
1609 op->x=nx;
1610 insert_ob_in_map(op,m,op,0);
1611
1612 dam_save = op->stats.dam; /* save the original dam: we do halfdam on 1695 dam_save = op->stats.dam; /* save the original dam: we do halfdam on
1613 surrounding squares */ 1696 surrounding squares */
1614 1697
1615 /* loop over current square and neighbors to hit. 1698 /* loop over current square and neighbors to hit.
1616 * if this has an other_arch field, we insert that in 1699 * if this has an other_arch field, we insert that in
1617 * the surround spaces. 1700 * the surround spaces.
1618 */ 1701 */
1619 for(j=0;j<9;j++) { 1702 for (j = 0; j < 9; j++)
1620 object *new_ob; 1703 {
1621
1622 hx = nx+freearr_x[j]; 1704 hx = nx + freearr_x[j];
1623 hy = ny+freearr_y[j]; 1705 hy = ny + freearr_y[j];
1624 1706
1625 m = op->map; 1707 m = op->map;
1626 mflags = get_map_flags(m, &m, hx, hy, &hx, &hy); 1708 mflags = get_map_flags (m, &m, hx, hy, &hx, &hy);
1627 1709
1628 if (mflags & P_OUT_OF_MAP) continue; 1710 if (mflags & P_OUT_OF_MAP)
1711 continue;
1629 1712
1630 /* first, don't ever, ever hit the owner. Don't hit out 1713 /* first, don't ever, ever hit the owner. Don't hit out
1631 * of the map either. 1714 * of the map either.
1632 */ 1715 */
1633 1716
1634 if((mflags & P_IS_ALIVE) && (!owner || owner->x!=hx || owner->y!=hy || !on_same_map(owner,op))) { 1717 if ((mflags & P_IS_ALIVE) && (!owner || owner->x != hx || owner->y != hy || !on_same_map (owner, op)))
1635 if(j) op->stats.dam = dam_save/2; 1718 {
1719 if (j)
1720 op->stats.dam = dam_save / 2;
1636 hit_map(op,j,op->attacktype,1); 1721 hit_map (op, j, op->attacktype, 1);
1637 1722
1638 } 1723 }
1639 1724
1640 /* insert the other arch */ 1725 /* insert the other arch */
1641 if(op->other_arch && !(OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, hx, hy)))) { 1726 if (op->other_arch && !(OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, hx, hy))))
1642 new_ob = arch_to_object(op->other_arch); 1727 m->insert (arch_to_object (op->other_arch), hx, hy, op);
1643 new_ob->x = hx;
1644 new_ob->y = hy;
1645 insert_ob_in_map(new_ob,m,op,0);
1646 }
1647 } 1728 }
1648 1729
1649 /* restore to the center location and damage*/ 1730 /* restore to the center location and damage */
1650 op->stats.dam = dam_save; 1731 op->stats.dam = dam_save;
1651 1732
1652 i=spell_find_dir(op->map,op->x,op->y,get_owner(op)); 1733 i = spell_find_dir (op->map, op->x, op->y, op->owner);
1653 1734
1654 if(i>=0) { /* we have a preferred direction! */ 1735 if (i >= 0)
1736 { /* we have a preferred direction! */
1655 /* pick another direction if the preferred dir is blocked. */ 1737 /* pick another direction if the preferred dir is blocked. */
1656 if (get_map_flags(op->map,&m, nx + freearr_x[i], ny + freearr_y[i],&hx,&hy) & P_OUT_OF_MAP || 1738 if (get_map_flags (op->map, &m, nx + freearr_x[i], ny + freearr_y[i], &hx, &hy) & P_OUT_OF_MAP ||
1657 OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, hx, hy))) { 1739 OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, hx, hy)))
1658 i= absdir(i + rndm(0, 2) -1); /* -1, 0, +1 */ 1740 i = absdir (i + rndm (0, 2) - 1); /* -1, 0, +1 */
1659 } 1741
1660 op->direction=i; 1742 op->direction = i;
1661 } 1743 }
1662} 1744}
1663 1745
1664 1746
1665/* move_swarm_spell: peterm 1747/* move_swarm_spell: peterm
1668 * is a special type of object that casts swarms of other types 1750 * is a special type of object that casts swarms of other types
1669 * of spells. Which spell it casts is flexible. It fires the spells 1751 * of spells. Which spell it casts is flexible. It fires the spells
1670 * from a set of squares surrounding the caster, in a given direction. 1752 * from a set of squares surrounding the caster, in a given direction.
1671 */ 1753 */
1672 1754
1755void
1673void move_swarm_spell(object *op) 1756move_swarm_spell (object *op)
1674{ 1757{
1675 static int cardinal_adjust[9] = { -3, -2, -1, 0, 0, 0, 1, 2, 3 };
1676 static int diagonal_adjust[10] = { -3, -2, -2, -1, 0, 0, 1, 2, 2, 3 };
1677 sint16 target_x, target_y, origin_x, origin_y;
1678 int basedir, adjustdir;
1679 mapstruct *m;
1680 object *owner;
1681
1682 owner = get_owner(op);
1683 if(op->duration == 0 || owner == NULL) {
1684 remove_ob(op);
1685 free_object(op);
1686 return;
1687 }
1688 op->duration--;
1689
1690 basedir = op->direction;
1691 if(basedir == 0) {
1692 /* spray in all directions! 8) */
1693 basedir = rndm(1, 8);
1694 }
1695
1696#if 0 1758#if 0
1697 // this is bogus: it causes wrong places to be checked below 1759 static int cardinal_adjust[9] = { -3, -2, -1, 0, 0, 0, 1, 2, 3 };
1698 // (a wall 2 cells away will block the effect...) and 1760 static int diagonal_adjust[10] = { -3, -2, -2, -1, 0, 0, 1, 2, 2, 3 };
1699 // doesn't work for SP_BULLET anyhow, so again tests the wrong 1761 sint16 target_x, target_y, origin_x, origin_y;
1700 // space. 1762 int adjustdir;
1701 // should be fixed later, but correctness before featurs... 1763 maptile *m;
1702 // (schmorp)
1703
1704 /* new offset calculation to make swarm element distribution
1705 * more uniform
1706 */
1707 if(op->duration) {
1708 if(basedir & 1) {
1709 adjustdir = cardinal_adjust[rndm(0, 8)];
1710 } else {
1711 adjustdir = diagonal_adjust[rndm(0, 9)];
1712 }
1713 } else {
1714 adjustdir = 0; /* fire the last one from forward. */
1715 }
1716
1717 target_x = op->x + freearr_x[absdir(basedir + adjustdir)];
1718 target_y = op->y + freearr_y[absdir(basedir + adjustdir)];
1719
1720 /* back up one space so we can hit point-blank targets, but this
1721 * necessitates extra out_of_map check below
1722 */
1723 origin_x = target_x - freearr_x[basedir];
1724 origin_y = target_y - freearr_y[basedir];
1725
1726
1727 /* spell pointer is set up for the spell this casts. Since this
1728 * should just be a pointer to the spell in some inventory,
1729 * it is unlikely to disappear by the time we need it. However,
1730 * do some sanity checking anyways.
1731 */
1732
1733 if (op->spell && op->spell->type == SPELL &&
1734 !(get_map_flags(op->map, &m, target_x, target_y, &target_x, &target_y) & P_OUT_OF_MAP) &&
1735 !(OB_TYPE_MOVE_BLOCK(op->spell, GET_MAP_MOVE_BLOCK(m, target_x, target_y)))) {
1736
1737 /* Bullet spells have a bunch more customization that needs to be done */
1738 if (op->spell->subtype == SP_BULLET)
1739 fire_bullet(owner, op, basedir, op->spell);
1740 else if (op->spell->subtype == SP_MAGIC_MISSILE)
1741 fire_arch_from_position (owner, op, origin_x, origin_y, basedir, op->spell);
1742 }
1743#endif 1764#endif
1765 int basedir;
1766 object *owner;
1744 1767
1768 owner = op->owner;
1769 if (op->duration == 0 || owner == NULL)
1770 {
1771 op->destroy ();
1772 return;
1773 }
1774
1775 op->duration--;
1776
1777 basedir = op->direction;
1778 if (basedir == 0)
1779 {
1780 /* spray in all directions! 8) */
1781 basedir = rndm (1, 8);
1782 }
1783
1784#if 0
1785 // this is bogus: it causes wrong places to be checked below
1786 // (a wall 2 cells away will block the effect...) and
1787 // doesn't work for SP_BULLET anyhow, so again tests the wrong
1788 // space.
1789 // should be fixed later, but correctness before features...
1790 // (schmorp)
1791
1792 /* new offset calculation to make swarm element distribution
1793 * more uniform
1794 */
1795 if (op->duration)
1796 {
1797 if (basedir & 1)
1798 {
1799 adjustdir = cardinal_adjust[rndm (0, 8)];
1800 }
1801 else
1802 {
1803 adjustdir = diagonal_adjust[rndm (0, 9)];
1804 }
1805 }
1806 else
1807 {
1808 adjustdir = 0; /* fire the last one from forward. */
1809 }
1810
1811 target_x = op->x + freearr_x[absdir (basedir + adjustdir)];
1812 target_y = op->y + freearr_y[absdir (basedir + adjustdir)];
1813
1814 /* back up one space so we can hit point-blank targets, but this
1815 * necessitates extra out_of_map check below
1816 */
1817 origin_x = target_x - freearr_x[basedir];
1818 origin_y = target_y - freearr_y[basedir];
1819
1820
1745 /* spell pointer is set up for the spell this casts. Since this 1821 /* spell pointer is set up for the spell this casts. Since this
1746 * should just be a pointer to the spell in some inventory, 1822 * should just be a pointer to the spell in some inventory,
1747 * it is unlikely to disappear by the time we need it. However, 1823 * it is unlikely to disappear by the time we need it. However,
1748 * do some sanity checking anyways. 1824 * do some sanity checking anyways.
1749 */ 1825 */
1826
1827 if (op->spell && op->spell->type == SPELL &&
1828 !(get_map_flags (op->map, &m, target_x, target_y, &target_x, &target_y) & P_OUT_OF_MAP) &&
1829 !(OB_TYPE_MOVE_BLOCK (op->spell, GET_MAP_MOVE_BLOCK (m, target_x, target_y))))
1750 1830 {
1831
1832 /* Bullet spells have a bunch more customization that needs to be done */
1833 if (op->spell->subtype == SP_BULLET)
1834 fire_bullet (owner, op, basedir, op->spell);
1835 else if (op->spell->subtype == SP_MAGIC_MISSILE)
1836 fire_arch_from_position (owner, op, origin_x, origin_y, basedir, op->spell);
1837 }
1838#endif
1839
1840 /* spell pointer is set up for the spell this casts. Since this
1841 * should just be a pointer to the spell in some inventory,
1842 * it is unlikely to disappear by the time we need it. However,
1843 * do some sanity checking anyways.
1844 */
1845
1751 if (op->spell && op->spell->type == SPELL) 1846 if (op->spell && op->spell->type == SPELL)
1752 { 1847 {
1753 /* Bullet spells have a bunch more customization that needs to be done */ 1848 /* Bullet spells have a bunch more customization that needs to be done */
1754 if (op->spell->subtype == SP_BULLET) 1849 if (op->spell->subtype == SP_BULLET)
1755 fire_bullet(owner, op, basedir, op->spell); 1850 fire_bullet (owner, op, basedir, op->spell);
1756 else if (op->spell->subtype == SP_MAGIC_MISSILE) 1851 else if (op->spell->subtype == SP_MAGIC_MISSILE)
1757 fire_arch_from_position (owner, op, op->x, op->y, basedir, op->spell); 1852 fire_arch_from_position (owner, op, op->x, op->y, basedir, op->spell);
1758 } 1853 }
1759} 1854}
1760 1855
1761 1856
1762 1857
1763 1858
1771 * dir: the direction everything will be fired in 1866 * dir: the direction everything will be fired in
1772 * spell - the spell that is this spell. 1867 * spell - the spell that is this spell.
1773 * n: the number to be fired. 1868 * n: the number to be fired.
1774 */ 1869 */
1775 1870
1871int
1776int fire_swarm (object *op, object *caster, object *spell, int dir) 1872fire_swarm (object *op, object *caster, object *spell, int dir)
1777{ 1873{
1778 object *tmp; 1874 object *tmp;
1779 int i; 1875 int i;
1780 1876
1781 if (!spell->other_arch) return 0; 1877 if (!spell->other_arch)
1878 return 0;
1782 1879
1783 tmp=get_archetype(SWARM_SPELL); 1880 tmp = get_archetype (SWARM_SPELL);
1784 tmp->x=op->x;
1785 tmp->y=op->y;
1786 set_owner(tmp,op); /* needed so that if swarm elements kill, caster gets xp.*/ 1881 tmp->set_owner (op); /* needed so that if swarm elements kill, caster gets xp. */
1787 set_spell_skill(op, caster, spell, tmp); 1882 set_spell_skill (op, caster, spell, tmp);
1788 1883
1789 tmp->level=caster_level(caster, spell); /*needed later, to get level dep. right.*/ 1884 tmp->level = caster_level (caster, spell); /*needed later, to get level dep. right. */
1790 tmp->spell = arch_to_object(spell->other_arch); 1885 tmp->spell = arch_to_object (spell->other_arch);
1791 1886
1792 tmp->attacktype = tmp->spell->attacktype; 1887 tmp->attacktype = tmp->spell->attacktype;
1793 1888
1794 if (tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER) { 1889 if (tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER)
1795 if ( ! tailor_god_spell (tmp, op)) 1890 if (!tailor_god_spell (tmp, op))
1796 return 1; 1891 return 1;
1797 } 1892
1798 tmp->duration = SP_level_duration_adjust(caster, spell); 1893 tmp->duration = SP_level_duration_adjust (caster, spell);
1799 for (i=0; i< spell->duration; i++) 1894 for (i = 0; i < spell->duration; i++)
1800 tmp->duration += die_roll(1, 3, op, PREFER_HIGH); 1895 tmp->duration += die_roll (1, 3, op, PREFER_HIGH);
1801 1896
1802 tmp->direction=dir; 1897 tmp->direction = dir;
1803 tmp->invisible=1; 1898 tmp->invisible = 1;
1804 insert_ob_in_map(tmp,op->map,op,0); 1899
1900 tmp->insert_at (op, op);
1805 return 1; 1901 return 1;
1806} 1902}
1807 1903
1808 1904
1809/* See the spells documentation file for why this is its own 1905/* See the spells documentation file for why this is its own
1810 * function. 1906 * function.
1811 */ 1907 */
1908int
1812int cast_light(object *op,object *caster,object *spell, int dir) { 1909cast_light (object *op, object *caster, object *spell, int dir)
1910{
1813 object *target=NULL,*tmp=NULL; 1911 object *target = NULL, *tmp = NULL;
1814 sint16 x,y; 1912 sint16 x, y;
1815 int dam, mflags; 1913 int dam, mflags;
1816 mapstruct *m; 1914 maptile *m;
1817 1915
1818 dam = spell->stats.dam + SP_level_dam_adjust(caster,spell); 1916 dam = spell->stats.dam + SP_level_dam_adjust (caster, spell);
1819 1917
1820 if(!dir) { 1918 if (!dir)
1919 {
1821 new_draw_info(NDI_UNIQUE, 0,op,"In what direction?"); 1920 new_draw_info (NDI_UNIQUE, 0, op, "In what direction?");
1822 return 0; 1921 return 0;
1823 } 1922 }
1824 1923
1825 x=op->x+freearr_x[dir]; 1924 x = op->x + freearr_x[dir];
1826 y=op->y+freearr_y[dir]; 1925 y = op->y + freearr_y[dir];
1827 m = op->map; 1926 m = op->map;
1828 1927
1829 mflags = get_map_flags(m, &m, x, y, &x, &y); 1928 mflags = get_map_flags (m, &m, x, y, &x, &y);
1830 1929
1831 if (mflags & P_OUT_OF_MAP) { 1930 if (mflags & P_OUT_OF_MAP)
1931 {
1832 new_draw_info(NDI_UNIQUE, 0,op,"Nothing is there."); 1932 new_draw_info (NDI_UNIQUE, 0, op, "Nothing is there.");
1833 return 0; 1933 return 0;
1834 } 1934 }
1835 1935
1836 if (mflags & P_IS_ALIVE && spell->attacktype) { 1936 if (mflags & P_IS_ALIVE && spell->attacktype)
1837 for(target=get_map_ob(m,x,y);target;target=target->above) 1937 {
1938 for (target = GET_MAP_OB (m, x, y); target; target = target->above)
1838 if(QUERY_FLAG(target,FLAG_MONSTER)) { 1939 if (QUERY_FLAG (target, FLAG_MONSTER))
1940 {
1839 /* oky doky. got a target monster. Lets make a blinding attack */ 1941 /* oky doky. got a target monster. Lets make a blinding attack */
1840 if(target->head) target = target->head; 1942 if (target->head)
1943 target = target->head;
1841 (void) hit_player(target,dam,op,spell->attacktype,1); 1944 (void) hit_player (target, dam, op, spell->attacktype, 1);
1842 return 1; /* one success only! */ 1945 return 1; /* one success only! */
1946 }
1843 } 1947 }
1844 }
1845 1948
1846 /* no live target, perhaps a wall is in the way? */ 1949 /* no live target, perhaps a wall is in the way? */
1847 if (OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, x, y))) { 1950 if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y)))
1951 {
1848 new_draw_info(NDI_UNIQUE, 0,op,"Something is in the way."); 1952 new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way.");
1849 return 0; 1953 return 0;
1850 } 1954 }
1851 1955
1852 /* ok, looks groovy to just insert a new light on the map */ 1956 /* ok, looks groovy to just insert a new light on the map */
1853 tmp=arch_to_object(spell->other_arch); 1957 tmp = arch_to_object (spell->other_arch);
1854 if(!tmp) { 1958 if (!tmp)
1959 {
1855 LOG(llevError,"Error: spell arch for cast_light() missing.\n"); 1960 LOG (llevError, "Error: spell arch for cast_light() missing.\n");
1856 return 0; 1961 return 0;
1857 } 1962 }
1858 tmp->stats.food = spell->duration + SP_level_duration_adjust(caster,spell); 1963 tmp->stats.food = spell->duration + SP_level_duration_adjust (caster, spell);
1859 if (tmp->glow_radius) { 1964 if (tmp->glow_radius)
1965 {
1860 tmp->glow_radius= spell->range + SP_level_range_adjust(caster,spell); 1966 tmp->glow_radius = spell->range + SP_level_range_adjust (caster, spell);
1861 if (tmp->glow_radius > MAX_LIGHT_RADII) tmp->glow_radius = MAX_LIGHT_RADII; 1967 if (tmp->glow_radius > MAX_LIGHT_RADII)
1968 tmp->glow_radius = MAX_LIGHT_RADII;
1862 } 1969 }
1863 tmp->x=x; 1970
1864 tmp->y=y; 1971 m->insert (tmp, x, y, op);
1865 insert_ob_in_map(tmp,m,op,0);
1866 return 1; 1972 return 1;
1867} 1973}
1868 1974
1869 1975
1870 1976
1871 1977
1874 * op is the player/monster, caster is the object, dir is the direction 1980 * op is the player/monster, caster is the object, dir is the direction
1875 * to cast, disease_arch is the specific disease, and type is the spell number 1981 * to cast, disease_arch is the specific disease, and type is the spell number
1876 * perhaps this should actually be in disease.c? 1982 * perhaps this should actually be in disease.c?
1877 */ 1983 */
1878 1984
1985int
1879int cast_cause_disease(object *op, object *caster, object *spell, int dir) { 1986cast_cause_disease (object *op, object *caster, object *spell, int dir)
1987{
1880 sint16 x,y; 1988 sint16 x, y;
1881 int i, mflags, range, dam_mod, dur_mod; 1989 int i, mflags, range, dam_mod, dur_mod;
1882 object *walk; 1990 object *walk;
1883 mapstruct *m; 1991 maptile *m;
1884 1992
1885 x = op->x; 1993 x = op->x;
1886 y = op->y; 1994 y = op->y;
1887 1995
1888 /* If casting from a scroll, no direction will be available, so refer to the 1996 /* If casting from a scroll, no direction will be available, so refer to the
1889 * direction the player is pointing. 1997 * direction the player is pointing.
1890 */ 1998 */
1999 if (!dir)
1891 if (!dir) dir=op->facing; 2000 dir = op->facing;
2001 if (!dir)
1892 if (!dir) return 0; /* won't find anything if casting on ourself, so just return */ 2002 return 0; /* won't find anything if casting on ourself, so just return */
1893 2003
1894 /* Calculate these once here */ 2004 /* Calculate these once here */
1895 range = spell->range + SP_level_range_adjust(caster, spell); 2005 range = spell->range + SP_level_range_adjust (caster, spell);
1896 dam_mod = SP_level_dam_adjust(caster, spell); 2006 dam_mod = SP_level_dam_adjust (caster, spell);
1897 dur_mod = SP_level_duration_adjust(caster, spell); 2007 dur_mod = SP_level_duration_adjust (caster, spell);
1898 2008
1899 /* search in a line for a victim */ 2009 /* search in a line for a victim */
1900 for(i=1; i<range; i++) { 2010 for (i = 1; i < range; i++)
2011 {
1901 x = op->x + i * freearr_x[dir]; 2012 x = op->x + i * freearr_x[dir];
1902 y = op->y + i * freearr_y[dir]; 2013 y = op->y + i * freearr_y[dir];
1903 m = op->map; 2014 m = op->map;
1904 2015
1905 mflags = get_map_flags(m, &m, x, y, &x, &y); 2016 mflags = get_map_flags (m, &m, x, y, &x, &y);
1906 2017
1907 if (mflags & P_OUT_OF_MAP) return 0; 2018 if (mflags & P_OUT_OF_MAP)
2019 return 0;
1908 2020
1909 /* don't go through walls - presume diseases are airborne */ 2021 /* don't go through walls - presume diseases are airborne */
1910 if (GET_MAP_MOVE_BLOCK(m, x, y) & MOVE_FLY_LOW) return 0; 2022 if (GET_MAP_MOVE_BLOCK (m, x, y) & MOVE_FLY_LOW)
2023 return 0;
1911 2024
1912 /* Only bother looking on this space if there is something living here */ 2025 /* Only bother looking on this space if there is something living here */
1913 if (mflags & P_IS_ALIVE) { 2026 if (mflags & P_IS_ALIVE)
2027 {
1914 /* search this square for a victim */ 2028 /* search this square for a victim */
1915 for(walk=get_map_ob(m,x,y);walk;walk=walk->above) 2029 for (walk = GET_MAP_OB (m, x, y); walk; walk = walk->above)
1916 if (QUERY_FLAG(walk,FLAG_MONSTER) || (walk->type==PLAYER)) { /* found a victim */ 2030 if (QUERY_FLAG (walk, FLAG_MONSTER) || (walk->type == PLAYER))
2031 { /* found a victim */
1917 object *disease = arch_to_object(spell->other_arch); 2032 object *disease = arch_to_object (spell->other_arch);
1918 2033
1919 set_owner(disease,op); 2034 disease->set_owner (op);
1920 set_spell_skill(op, caster, spell, disease); 2035 set_spell_skill (op, caster, spell, disease);
1921 disease->stats.exp = 0; 2036 disease->stats.exp = 0;
1922 disease->level = caster_level(caster, spell); 2037 disease->level = caster_level (caster, spell);
1923 2038
1924 /* do level adjustments */ 2039 /* do level adjustments */
1925 if(disease->stats.wc) 2040 if (disease->stats.wc)
1926 disease->stats.wc += dur_mod/2; 2041 disease->stats.wc += dur_mod / 2;
1927 2042
1928 if(disease->magic> 0) 2043 if (disease->magic > 0)
1929 disease->magic += dur_mod/4; 2044 disease->magic += dur_mod / 4;
1930 2045
1931 if(disease->stats.maxhp>0) 2046 if (disease->stats.maxhp > 0)
1932 disease->stats.maxhp += dur_mod; 2047 disease->stats.maxhp += dur_mod;
1933 2048
1934 if(disease->stats.maxgrace>0) 2049 if (disease->stats.maxgrace > 0)
1935 disease->stats.maxgrace += dur_mod; 2050 disease->stats.maxgrace += dur_mod;
1936 2051
1937 if(disease->stats.dam) { 2052 if (disease->stats.dam)
1938 if(disease->stats.dam > 0) 2053 {
1939 disease->stats.dam += dam_mod; 2054 if (disease->stats.dam > 0)
1940 else disease->stats.dam -= dam_mod; 2055 disease->stats.dam += dam_mod;
1941 } 2056 else
2057 disease->stats.dam -= dam_mod;
2058 }
1942 2059
1943 if(disease->last_sp) { 2060 if (disease->last_sp)
1944 disease->last_sp -= 2*dam_mod; 2061 {
1945 if(disease->last_sp <1) disease->last_sp = 1; 2062 disease->last_sp -= 2 * dam_mod;
1946 } 2063 if (disease->last_sp < 1)
2064 disease->last_sp = 1;
2065 }
1947 2066
1948 if(disease->stats.maxsp) { 2067 if (disease->stats.maxsp)
1949 if(disease->stats.maxsp > 0) 2068 {
1950 disease->stats.maxsp += dam_mod; 2069 if (disease->stats.maxsp > 0)
1951 else disease->stats.maxsp -= dam_mod; 2070 disease->stats.maxsp += dam_mod;
1952 } 2071 else
1953 2072 disease->stats.maxsp -= dam_mod;
2073 }
2074
1954 if(disease->stats.ac) 2075 if (disease->stats.ac)
1955 disease->stats.ac += dam_mod; 2076 disease->stats.ac += dam_mod;
1956 2077
1957 if(disease->last_eat) 2078 if (disease->last_eat)
1958 disease->last_eat -= dam_mod; 2079 disease->last_eat -= dam_mod;
1959 2080
1960 if(disease->stats.hp) 2081 if (disease->stats.hp)
1961 disease->stats.hp -= dam_mod; 2082 disease->stats.hp -= dam_mod;
1962 2083
1963 if(disease->stats.sp) 2084 if (disease->stats.sp)
1964 disease->stats.sp -= dam_mod; 2085 disease->stats.sp -= dam_mod;
1965 2086
1966 if(infect_object(walk,disease,1)) { 2087 if (infect_object (walk, disease, 1))
1967 object *flash; /* visual effect for inflicting disease */ 2088 {
1968
1969 new_draw_info_format(NDI_UNIQUE, 0, op, "You inflict %s on %s!",disease->name,walk->name); 2089 new_draw_info_format (NDI_UNIQUE, 0, op, "You inflict %s on %s!", &disease->name, &walk->name);
1970 2090
1971 free_object(disease); /* don't need this one anymore */ 2091 disease->destroy (); /* don't need this one anymore */
1972 flash=get_archetype(ARCH_DETECT_MAGIC); 2092 walk->map->insert (get_archetype ("detect_magic"), x, y, op);
1973 flash->x = x; 2093 return 1;
1974 flash->y = y; 2094 }
1975 flash->map = walk->map; 2095
1976 insert_ob_in_map(flash,walk->map,op,0); 2096 disease->destroy ();
1977 return 1; 2097 }
1978 } 2098 } /* if living creature */
1979 free_object(disease); 2099 } /* for range of spaces */
1980 } 2100
1981 } /* if living creature */
1982 } /* for range of spaces */
1983 new_draw_info(NDI_UNIQUE,0,op,"No one caught anything!"); 2101 new_draw_info (NDI_UNIQUE, 0, op, "No one caught anything!");
1984 return 1; 2102 return 1;
1985} 2103}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines