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

Comparing deliantra/server/server/attack.C (file contents):
Revision 1.2 by root, Fri Aug 25 17:11:53 2006 UTC vs.
Revision 1.24 by root, Sat Dec 9 16:11:09 2006 UTC

1/*
2 * static char *rcsid_attack_c =
3 * "$Id: attack.C,v 1.2 2006/08/25 17:11:53 root Exp $";
4 */
5/* 1/*
6 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
7 3
8 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
9 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
20 16
21 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 20
25 The authors can be reached via e-mail to crossfire-devel@real-time.com 21 The authors can be reached via e-mail to <crossfire@schmorp.de>
26*/ 22*/
27#include <assert.h> 23#include <assert.h>
28#include <global.h> 24#include <global.h>
29#include <living.h> 25#include <living.h>
30#include <material.h> 26#include <material.h>
31#include <skills.h> 27#include <skills.h>
32 28
33#ifndef __CEXTRACT__ 29#ifndef __CEXTRACT__
34#include <sproto.h> 30# include <sproto.h>
35#endif 31#endif
36 32
37#include <sounds.h> 33#include <sounds.h>
38 34
39typedef struct att_msg_str { 35typedef struct att_msg_str
36{
40 char *msg1; 37 char *msg1;
41 char *msg2; 38 char *msg2;
42} att_msg; 39} att_msg;
43 40
44/*#define ATTACK_DEBUG*/ 41/*#define ATTACK_DEBUG*/
45 42
46/* cancels object *op. Cancellation basically means an object loses 43/* cancels object *op. Cancellation basically means an object loses
47 * its magical benefits. 44 * its magical benefits.
48 */ 45 */
46void
49void cancellation(object *op) 47cancellation (object *op)
50{ 48{
51 object *tmp; 49 object *tmp;
52 50
53 if (op->invisible) 51 if (op->invisible)
54 return; 52 return;
55 53
56 if (QUERY_FLAG (op, FLAG_ALIVE) || op->type == CONTAINER || op->type == THROWN_OBJ) { 54 if (QUERY_FLAG (op, FLAG_ALIVE) || op->type == CONTAINER || op->type == THROWN_OBJ)
55 {
57 /* Recur through the inventory */ 56 /* Recur through the inventory */
58 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) 57 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
59 if (!did_make_save_item(tmp, AT_CANCELLATION,op)) 58 if (!did_make_save_item (tmp, AT_CANCELLATION, op))
60 cancellation(tmp); 59 cancellation (tmp);
61 } 60 }
62 else if(FABS(op->magic)<=(rndm(0, 5))) { 61 else if (FABS (op->magic) <= (rndm (0, 5)))
62 {
63 /* Nullify this object. This code could probably be more complete */ 63 /* Nullify this object. This code could probably be more complete */
64 /* in what abilities it should cancel */ 64 /* in what abilities it should cancel */
65 op->magic=0; 65 op->magic = 0;
66 CLEAR_FLAG(op, FLAG_DAMNED); 66 CLEAR_FLAG (op, FLAG_DAMNED);
67 CLEAR_FLAG(op, FLAG_CURSED); 67 CLEAR_FLAG (op, FLAG_CURSED);
68 CLEAR_FLAG(op, FLAG_KNOWN_MAGICAL); 68 CLEAR_FLAG (op, FLAG_KNOWN_MAGICAL);
69 CLEAR_FLAG(op, FLAG_KNOWN_CURSED); 69 CLEAR_FLAG (op, FLAG_KNOWN_CURSED);
70 if (op->env && op->env->type == PLAYER) { 70 if (op->env && op->env->type == PLAYER)
71 {
71 esrv_send_item (op->env, op); 72 esrv_send_item (op->env, op);
72 } 73 }
73 } 74 }
74} 75}
75 76
76 77
77 78
78/* did_make_save_item just checks to make sure the item actually 79/* did_make_save_item just checks to make sure the item actually
79 * made its saving throw based on the tables. It does not take 80 * made its saving throw based on the tables. It does not take
80 * any further action (like destroying the item). 81 * any further action (like destroying the item).
81 */ 82 */
82 83
84int
83int did_make_save_item(object *op, int type, object *originator) { 85did_make_save_item (object *op, int type, object *originator)
86{
84 int i, roll, saves=0, attacks=0, number; 87 int i, roll, saves = 0, attacks = 0, number;
85 materialtype_t *mt; 88 materialtype_t *mt;
86 89
87 if (op->materialname == NULL) { 90 if (op->materialname == NULL)
91 {
88 for (mt = materialt; mt != NULL && mt->next != NULL; mt=mt->next) { 92 for (mt = materialt; mt != NULL && mt->next != NULL; mt = mt->next)
93 {
89 if (op->material & mt->material) 94 if (op->material & mt->material)
90 break; 95 break;
91 } 96 }
97 }
92 } else 98 else
93 mt = name_to_material(op->materialname); 99 mt = name_to_material (op->materialname);
94 if (mt == NULL) 100 if (mt == NULL)
95 return TRUE;
96 roll = rndm(1, 20);
97
98 /* the attacktypes have no meaning for object saves
99 * If the type is only magic, don't adjust type - basically, if
100 * pure magic is hitting an object, it should save. However, if it
101 * is magic teamed with something else, then strip out the
102 * magic type, and instead let the fire, cold, or whatever component
103 * destroy the item. Otherwise, you get the case of poisoncloud
104 * destroying objects because it has magic attacktype.
105 */
106 if (type != AT_MAGIC)
107 type &= ~(AT_CONFUSION|AT_DRAIN|AT_GHOSTHIT|AT_POISON|AT_SLOW|
108 AT_PARALYZE|AT_TURN_UNDEAD|AT_FEAR|AT_DEPLETE|AT_DEATH|
109 AT_COUNTERSPELL|AT_HOLYWORD|AT_BLIND|AT_LIFE_STEALING|
110 AT_MAGIC);
111
112 if (type == 0)
113 return TRUE;
114 if (roll == 20)
115 return TRUE;
116 if (roll == 1)
117 return FALSE;
118
119 for (number=0; number < NROFATTACKS; number++) {
120 i = 1<<number;
121 if (!(i&type))
122 continue;
123 attacks++;
124 if (op->resist[number] == 100)
125 saves++;
126 else if (roll >= mt->save[number] - op->magic - op->resist[number]/100)
127 saves++;
128 else if ((20-mt->save[number])/3 > originator->stats.dam)
129 saves++;
130 }
131
132 if (saves==attacks || attacks==0)
133 return TRUE;
134 if ((saves==0) || (rndm(1, attacks) > saves))
135 return FALSE;
136 return TRUE; 101 return TRUE;
102 roll = rndm (1, 20);
103
104 /* the attacktypes have no meaning for object saves
105 * If the type is only magic, don't adjust type - basically, if
106 * pure magic is hitting an object, it should save. However, if it
107 * is magic teamed with something else, then strip out the
108 * magic type, and instead let the fire, cold, or whatever component
109 * destroy the item. Otherwise, you get the case of poisoncloud
110 * destroying objects because it has magic attacktype.
111 */
112 if (type != AT_MAGIC)
113 type &= ~(AT_CONFUSION | AT_DRAIN | AT_GHOSTHIT | AT_POISON | AT_SLOW |
114 AT_PARALYZE | AT_TURN_UNDEAD | AT_FEAR | AT_DEPLETE | AT_DEATH |
115 AT_COUNTERSPELL | AT_HOLYWORD | AT_BLIND | AT_LIFE_STEALING | AT_MAGIC);
116
117 if (type == 0)
118 return TRUE;
119 if (roll == 20)
120 return TRUE;
121 if (roll == 1)
122 return FALSE;
123
124 for (number = 0; number < NROFATTACKS; number++)
125 {
126 i = 1 << number;
127 if (!(i & type))
128 continue;
129 attacks++;
130 if (op->resist[number] == 100)
131 saves++;
132 else if (roll >= mt->save[number] - op->magic - op->resist[number] / 100)
133 saves++;
134 else if ((20 - mt->save[number]) / 3 > originator->stats.dam)
135 saves++;
136 }
137
138 if (saves == attacks || attacks == 0)
139 return TRUE;
140 if ((saves == 0) || (rndm (1, attacks) > saves))
141 return FALSE;
142 return TRUE;
137} 143}
138 144
139/* This function calls did_make_save_item. It then performs the 145/* This function calls did_make_save_item. It then performs the
140 * appropriate actions to the item (such as burning the item up, 146 * appropriate actions to the item (such as burning the item up,
141 * calling cancellation, etc.) 147 * calling cancellation, etc.)
142 */ 148 */
143 149
150void
144void save_throw_object (object *op, int type, object *originator) 151save_throw_object (object *op, int type, object *originator)
145{ 152{
146 if ( ! did_make_save_item (op, type,originator)) 153 if (!did_make_save_item (op, type, originator))
147 { 154 {
148 object *env=op->env; 155 object *env = op->env;
149 int x=op->x,y=op->y; 156 int x = op->x, y = op->y;
150 mapstruct *m=op->map; 157 maptile *m = op->map;
151 158
152 op = stop_item (op); 159 op = stop_item (op);
153 if (op == NULL) 160 if (op == NULL)
154 return; 161 return;
155 162
156 /* Hacked the following so that type LIGHTER will work. 163 /* Hacked the following so that type LIGHTER will work.
157 * Also, objects which are potenital "lights" that are hit by 164 * Also, objects which are potenital "lights" that are hit by
158 * flame/elect attacks will be set to glow. "lights" are any 165 * flame/elect attacks will be set to glow. "lights" are any
159 * object with +/- glow_radius and an "other_arch" to change to. 166 * object with +/- glow_radius and an "other_arch" to change to.
160 * (and please note that we cant fail our save and reach this 167 * (and please note that we cant fail our save and reach this
161 * function if the object doesnt contain a material that can burn. 168 * function if the object doesnt contain a material that can burn.
162 * So forget lighting magical swords on fire with this!) -b.t. 169 * So forget lighting magical swords on fire with this!) -b.t.
163 */ 170 */
164 if(type&(AT_FIRE|AT_ELECTRICITY) 171 if (type & (AT_FIRE | AT_ELECTRICITY) && op->other_arch && QUERY_FLAG (op, FLAG_IS_LIGHTABLE))
165 &&op->other_arch&&QUERY_FLAG(op, FLAG_IS_LIGHTABLE)) {
166 const char *arch=op->other_arch->name;
167
168 op = decrease_ob_nr (op, 1);
169 if (op)
170 fix_stopped_item (op, m, originator);
171 if((op = get_archetype(arch))!=NULL) {
172 if(env) {
173 op->x=env->x,op->y=env->y;
174 insert_ob_in_ob(op,env);
175 if (env->contr)
176 esrv_send_item(env, op);
177 } else {
178 op->x=x,op->y=y;
179 insert_ob_in_map(op,m,originator,0);
180 }
181 }
182 return;
183 } 172 {
184 if(type&AT_CANCELLATION) { /* Cancellation. */ 173 const char *arch = op->other_arch->name;
185 cancellation(op); 174
175 op = decrease_ob_nr (op, 1);
176
177 if (op)
186 fix_stopped_item (op, m, originator); 178 fix_stopped_item (op, m, originator);
187 return; 179
188 } 180 if ((op = get_archetype (arch)) != NULL)
189 if(op->nrof>1) { 181 {
190 op = decrease_ob_nr(op,rndm(0, op->nrof-1));
191 if (op) 182 if (env)
192 fix_stopped_item (op, m, originator); 183 {
193 } else { 184 op->x = env->x, op->y = env->y;
194 if (op->env) {
195 object *tmp= is_player_inv(op->env);
196
197 if (tmp) {
198 esrv_del_item(tmp->contr, op->count);
199 }
200 }
201 if ( ! QUERY_FLAG (op, FLAG_REMOVED))
202 remove_ob(op);
203 free_object(op);
204 }
205 if(type&(AT_FIRE|AT_ELECTRICITY)) {
206 if(env) {
207 op=get_archetype("burnout");
208 op->x=env->x,op->y=env->y;
209 insert_ob_in_ob(op,env); 185 insert_ob_in_ob (op, env);
210 } else { 186 if (env->contr)
187 esrv_send_item (env, op);
188 }
189 else
190 {
191 op->x = x, op->y = y;
211 replace_insert_ob_in_map("burnout",originator); 192 insert_ob_in_map (op, m, originator, 0);
212 } 193 }
213 } 194 }
214 return; 195
215 }
216 /* The value of 50 is arbitrary. */
217 if(type&AT_COLD &&(op->resist[ATNR_COLD]<50) &&
218 !QUERY_FLAG(op,FLAG_NO_PICK)&&(RANDOM()&2)) {
219 object *tmp;
220 archetype *at = find_archetype("icecube");
221 if (at == NULL)
222 return; 196 return;
223 op = stop_item (op); 197 }
224 if (op == NULL) 198
199 if (type & AT_CANCELLATION)
200 { /* Cancellation. */
201 cancellation (op);
202 fix_stopped_item (op, m, originator);
225 return; 203 return;
226 if ((tmp = present_arch(at,op->map,op->x,op->y)) == NULL) { 204 }
227 tmp = arch_to_object(at); 205
228 tmp->x=op->x,tmp->y=op->y; 206 if (op->nrof > 1)
229 /* This was in the old (pre new movement code) -
230 * icecubes have slow_move set to 1 - don't want
231 * that for ones we create.
232 */
233 tmp->move_slow_penalty=0;
234 tmp->move_slow=0;
235 insert_ob_in_map(tmp,op->map,originator,0);
236 } 207 {
208 op = decrease_ob_nr (op, rndm (0, op->nrof - 1));
209
210 if (op)
211 fix_stopped_item (op, m, originator);
212 }
213 else
214 {
215 if (op->env)
216 {
217 object *tmp = is_player_inv (op->env);
218
219 if (tmp)
220 esrv_del_item (tmp->contr, op->count);
221 }
222
237 if ( ! QUERY_FLAG (op, FLAG_REMOVED)) 223 if (!QUERY_FLAG (op, FLAG_REMOVED))
238 remove_ob(op); 224 remove_ob (op);
225
226 free_object (op);
227 }
228
229 if (type & (AT_FIRE | AT_ELECTRICITY))
230 if (env)
231 {
232 op = get_archetype ("burnout");
233 op->x = env->x, op->y = env->y;
239 (void) insert_ob_in_ob(op,tmp); 234 insert_ob_in_ob (op, env);
235 }
236 else
237 replace_insert_ob_in_map ("burnout", originator);
238
239 return;
240 }
241
242 /* The value of 50 is arbitrary. */
243 if (type & AT_COLD && (op->resist[ATNR_COLD] < 50) && !QUERY_FLAG (op, FLAG_NO_PICK) && (RANDOM () & 2))
244 {
245 object *tmp;
246 archetype *at = archetype::find ("icecube");
247
248 if (at == NULL)
240 return; 249 return;
250
251 op = stop_item (op);
252 if (op == NULL)
253 return;
254
255 if ((tmp = present_arch (at, op->map, op->x, op->y)) == NULL)
256 {
257 tmp = arch_to_object (at);
258 tmp->x = op->x, tmp->y = op->y;
259 /* This was in the old (pre new movement code) -
260 * icecubes have slow_move set to 1 - don't want
261 * that for ones we create.
262 */
263 tmp->move_slow_penalty = 0;
264 tmp->move_slow = 0;
265 insert_ob_in_map (tmp, op->map, originator, 0);
266 }
267
268 if (!QUERY_FLAG (op, FLAG_REMOVED))
269 remove_ob (op);
270
271 insert_ob_in_ob (op, tmp);
272 return;
241 } 273 }
242} 274}
243 275
244/* Object op is hitting the map. 276/* Object op is hitting the map.
245 * op is going in direction 'dir' 277 * op is going in direction 'dir'
246 * type is the attacktype of the object. 278 * type is the attacktype of the object.
247 * full_hit is set if monster area does not matter. 279 * full_hit is set if monster area does not matter.
248 * returns 1 if it hits something, 0 otherwise. 280 * returns 1 if it hits something, 0 otherwise.
249 */ 281 */
250 282
283int
251int hit_map(object *op, int dir, int type, int full_hit) { 284hit_map (object *op, int dir, int type, int full_hit)
285{
252 object *tmp, *next; 286 object *tmp, *next;
253 mapstruct *map; 287 maptile *map;
254 sint16 x, y; 288 sint16 x, y;
255 int retflag=0; /* added this flag.. will return 1 if it hits a monster */ 289 int retflag = 0; /* added this flag.. will return 1 if it hits a monster */
256 290
257 tag_t op_tag, next_tag=0;
258
259 if (QUERY_FLAG (op, FLAG_FREED)) { 291 if (QUERY_FLAG (op, FLAG_FREED))
292 {
260 LOG (llevError, "BUG: hit_map(): free object\n"); 293 LOG (llevError, "BUG: hit_map(): free object\n");
261 return 0; 294 return 0;
262 } 295 }
263 296
264 if (QUERY_FLAG (op, FLAG_REMOVED) || op->env != NULL) { 297 if (QUERY_FLAG (op, FLAG_REMOVED) || op->env != NULL)
298 {
265 LOG (llevError, "BUG: hit_map(): hitter (arch %s, name %s) not on a map\n", 299 LOG (llevError, "BUG: hit_map(): hitter (arch %s, name %s) not on a map\n", &op->arch->name, &op->name);
266 op->arch->name, op->name); 300 return 0;
267 return 0;
268 } 301 }
269 302
270 if ( ! op->map) { 303 if (!op->map)
304 {
271 LOG (llevError,"BUG: hit_map(): %s has no map\n", op->name); 305 LOG (llevError, "BUG: hit_map(): %s has no map\n", &op->name);
272 return 0; 306 return 0;
273 } 307 }
274 308
275 if (op->head) op=op->head; 309 if (op->head)
310 op = op->head;
276 311
277 op_tag = op->count;
278
279 map = op->map; 312 map = op->map;
280 x = op->x + freearr_x[dir]; 313 x = op->x + freearr_x[dir];
281 y = op->y + freearr_y[dir]; 314 y = op->y + freearr_y[dir];
282 if (get_map_flags(map, &map, x, y, &x, &y) & P_OUT_OF_MAP)
283 return 0;
284 315
285 /* peterm: a few special cases for special attacktypes --counterspell 316 int mflags = get_map_flags (map, &map, x, y, &x, &y);
286 * must be out here because it strikes things which are not alive
287 */
288 317
289 if (type & AT_COUNTERSPELL) { 318 // elmex: a safe map tile can't be hit!
290 counterspell(op,dir); /* see spell_effect.c */ 319 // this should prevent most harmful effects on items and players there.
291 320 if (mflags & (P_OUT_OF_MAP | P_SAFE))
292 /* If the only attacktype is counterspell or magic, don't need
293 * to do any further processing.
294 */
295 if(!(type & ~(AT_COUNTERSPELL|AT_MAGIC))){
296 return 0;
297 }
298 type &= ~AT_COUNTERSPELL;
299 }
300
301 if(type & AT_CHAOS){
302 shuffle_attack(op,1); /*1 flag tells it to change the face */
303 update_object(op,UP_OBJ_FACE);
304 type &= ~AT_CHAOS;
305 }
306
307 next = get_map_ob (map, x, y);
308 if (next)
309 next_tag = next->count;
310
311 while (next) {
312 if (was_destroyed (next, next_tag)) {
313 /* There may still be objects that were above 'next', but there is no
314 * simple way to find out short of copying all object references and
315 * tags into a temporary array before we start processing the first
316 * object. That's why we just abort.
317 *
318 * This happens whenever attack spells (like fire) hit a pile
319 * of objects. This is not a bug - nor an error. The errormessage
320 * below was spamming the logs for absolutely no reason.
321 */
322 /* LOG (llevDebug, "hit_map(): next object destroyed\n"); */
323 break;
324 }
325 tmp = next;
326 next = tmp->above;
327 if (next)
328 next_tag = next->count;
329
330 if (QUERY_FLAG (tmp, FLAG_FREED)) {
331 LOG (llevError, "BUG: hit_map(): found freed object\n");
332 break;
333 }
334
335 /* Something could have happened to 'tmp' while 'tmp->below' was processed.
336 * For example, 'tmp' was put in an icecube.
337 * This is one of the few cases where on_same_map should not be used.
338 */
339 if (tmp->map != map || tmp->x != x || tmp->y != y)
340 continue;
341
342 /* Need to hit everyone in the transport with this spell */
343 if (tmp->type == TRANSPORT) {
344 object *pl;
345
346 for (pl=tmp->inv; pl; pl=pl->below) {
347 if (pl->type == PLAYER)
348 hit_player(pl,op->stats.dam,op,type,full_hit);
349 }
350 }
351
352 if (QUERY_FLAG (tmp, FLAG_ALIVE)) {
353 hit_player(tmp,op->stats.dam,op,type,full_hit);
354 retflag |=1;
355 if (was_destroyed (op, op_tag))
356 break;
357 }
358 /* Here we are potentially destroying an object. If the object has
359 * NO_PASS set, it is also immune - you can't destroy walls. Note
360 * that weak walls have is_alive set, which prevent objects from
361 * passing over/through them. We don't care what type of movement
362 * the wall blocks - if it blocks any type of movement, can't be
363 * destroyed right now.
364 */
365 else if ((tmp->material || tmp->materialname) && op->stats.dam > 0 &&
366 !tmp->move_block) {
367 save_throw_object(tmp,type,op);
368 if (was_destroyed (op, op_tag))
369 break;
370 }
371 }
372 return 0; 321 return 0;
373}
374 322
323 /* peterm: a few special cases for special attacktypes --counterspell
324 * must be out here because it strikes things which are not alive
325 */
326
327 if (type & AT_COUNTERSPELL)
328 {
329 counterspell (op, dir); /* see spell_effect.c */
330
331 /* If the only attacktype is counterspell or magic, don't need
332 * to do any further processing.
333 */
334 if (!(type & ~(AT_COUNTERSPELL | AT_MAGIC)))
335 return 0;
336
337 type &= ~AT_COUNTERSPELL;
338 }
339
340 if (type & AT_CHAOS)
341 {
342 shuffle_attack (op, 1); /*1 flag tells it to change the face */
343 update_object (op, UP_OBJ_FACE);
344 type &= ~AT_CHAOS;
345 }
346
347 next = get_map_ob (map, x, y);
348
349 while (next)
350 {
351 if (next->destroyed ())
352 {
353 /* There may still be objects that were above 'next', but there is no
354 * simple way to find out short of copying all object references and
355 * tags into a temporary array before we start processing the first
356 * object. That's why we just abort.
357 *
358 * This happens whenever attack spells (like fire) hit a pile
359 * of objects. This is not a bug - nor an error. The errormessage
360 * below was spamming the logs for absolutely no reason.
361 */
362 /* LOG (llevDebug, "hit_map(): next object destroyed\n"); */
363 break;
364 }
365
366 tmp = next;
367 next = tmp->above;
368
369 if (tmp->destroyed ())
370 {
371 LOG (llevError, "BUG: hit_map(): found freed object\n");
372 break;
373 }
374
375 /* Something could have happened to 'tmp' while 'tmp->below' was processed.
376 * For example, 'tmp' was put in an icecube.
377 * This is one of the few cases where on_same_map should not be used.
378 */
379 if (tmp->map != map || tmp->x != x || tmp->y != y)
380 continue;
381
382 if (QUERY_FLAG (tmp, FLAG_ALIVE))
383 {
384 hit_player (tmp, op->stats.dam, op, type, full_hit);
385 retflag |= 1;
386 if (op->destroyed ())
387 break;
388 }
389
390 /* Here we are potentially destroying an object. If the object has
391 * NO_PASS set, it is also immune - you can't destroy walls. Note
392 * that weak walls have is_alive set, which prevent objects from
393 * passing over/through them. We don't care what type of movement
394 * the wall blocks - if it blocks any type of movement, can't be
395 * destroyed right now.
396 */
397 else if ((tmp->material || tmp->materialname) && op->stats.dam > 0 && !tmp->move_block)
398 {
399 save_throw_object (tmp, type, op);
400 if (op->destroyed ())
401 break;
402 }
403 }
404
405 return 0;
406}
407
408void
375void attack_message(int dam, int type, object *op, object *hitter) { 409attack_message (int dam, int type, object *op, object *hitter)
410{
376 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF]; 411 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF];
377 int i, found=0; 412 int i, found = 0;
378 mapstruct *map; 413 maptile *map;
379 object *next, *tmp; 414 object *next, *tmp;
380 415
381 /* put in a few special messages for some of the common attacktypes 416 /* put in a few special messages for some of the common attacktypes
382 * a player might have. For example, fire, electric, cold, etc 417 * a player might have. For example, fire, electric, cold, etc
383 * [garbled 20010919] 418 * [garbled 20010919]
384 */ 419 */
385 420
386 if (dam == 9998 && op->type == DOOR) { 421 if (dam == 9998 && op->type == DOOR)
422 {
387 sprintf(buf1, "unlock %s", op->name); 423 sprintf (buf1, "unlock %s", &op->name);
388 sprintf(buf2, " unlocks"); 424 sprintf (buf2, " unlocks");
389 found++; 425 found++;
426 }
427 if (dam < 0)
390 } 428 {
391 if(dam<0) {
392 sprintf(buf1, "hit %s", op->name); 429 sprintf (buf1, "hit %s", &op->name);
393 sprintf(buf2, " hits"); 430 sprintf (buf2, " hits");
394 found++; 431 found++;
432 }
395 } else if(dam==0) { 433 else if (dam == 0)
434 {
396 sprintf(buf1, "missed %s", op->name); 435 sprintf (buf1, "missed %s", &op->name);
397 sprintf(buf2, " misses"); 436 sprintf (buf2, " misses");
398 found++; 437 found++;
438 }
399 } else if ((hitter->type == DISEASE || hitter->type == SYMPTOM || 439 else if ((hitter->type == DISEASE || hitter->type == SYMPTOM ||
400 hitter->type == POISONING || 440 hitter->type == POISONING || (type & AT_POISON && IS_LIVE (op))) && !found)
401 (type & AT_POISON && IS_LIVE(op))) && !found) { 441 {
402 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_SUFFER][i].level != -1; 442 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_SUFFER][i].level != -1; i++)
403 i++) 443 if (dam < attack_mess[ATM_SUFFER][i].level || attack_mess[ATM_SUFFER][i + 1].level == -1)
404 if (dam < attack_mess[ATM_SUFFER][i].level 444 {
405 || attack_mess[ATM_SUFFER][i+1].level == -1) { 445 sprintf (buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1, &op->name, attack_mess[ATM_SUFFER][i].buf2);
406 sprintf(buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1,
407 op->name, attack_mess[ATM_SUFFER][i].buf2);
408 strcpy (buf2, attack_mess[ATM_SUFFER][i].buf3); 446 strcpy (buf2, attack_mess[ATM_SUFFER][i].buf3);
409 found++; 447 found++;
410 break; 448 break;
449 }
411 } 450 }
412 } else if (op->type == DOOR && !found) { 451 else if (op->type == DOOR && !found)
452 {
413 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_DOOR][i].level != -1; 453 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_DOOR][i].level != -1; i++)
414 i++) 454 if (dam < attack_mess[ATM_DOOR][i].level || attack_mess[ATM_DOOR][i + 1].level == -1)
415 if (dam < attack_mess[ATM_DOOR][i].level 455 {
416 || attack_mess[ATM_DOOR][i+1].level == -1) { 456 sprintf (buf1, "%s %s%s", attack_mess[ATM_DOOR][i].buf1, &op->name, attack_mess[ATM_DOOR][i].buf2);
417 sprintf(buf1, "%s %s%s", attack_mess[ATM_DOOR][i].buf1,
418 op->name, attack_mess[ATM_DOOR][i].buf2);
419 strcpy (buf2, attack_mess[ATM_DOOR][i].buf3); 457 strcpy (buf2, attack_mess[ATM_DOOR][i].buf3);
420 found++; 458 found++;
421 break; 459 break;
460 }
422 } 461 }
423 } else if (hitter->type == PLAYER && IS_LIVE(op)) { 462 else if (hitter->type == PLAYER && IS_LIVE (op))
463 {
424 if (USING_SKILL(hitter, SK_KARATE)) { 464 if (USING_SKILL (hitter, SK_KARATE))
465 {
425 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_KARATE][i].level != -1; 466 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_KARATE][i].level != -1; i++)
426 i++) 467 if (dam < attack_mess[ATM_KARATE][i].level || attack_mess[ATM_KARATE][i + 1].level == -1)
427 if (dam < attack_mess[ATM_KARATE][i].level 468 {
428 || attack_mess[ATM_KARATE][i+1].level == -1) { 469 sprintf (buf1, "%s %s%s", attack_mess[ATM_KARATE][i].buf1, &op->name, attack_mess[ATM_KARATE][i].buf2);
429 sprintf(buf1, "%s %s%s", attack_mess[ATM_KARATE][i].buf1,
430 op->name, attack_mess[ATM_KARATE][i].buf2);
431 strcpy (buf2, attack_mess[ATM_KARATE][i].buf3); 470 strcpy (buf2, attack_mess[ATM_KARATE][i].buf3);
432 found++; 471 found++;
433 break; 472 break;
473 }
434 } 474 }
435 } else if (USING_SKILL(hitter, SK_CLAWING)) { 475 else if (USING_SKILL (hitter, SK_CLAWING))
476 {
436 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_CLAW][i].level != -1; 477 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_CLAW][i].level != -1; i++)
437 i++) 478 if (dam < attack_mess[ATM_CLAW][i].level || attack_mess[ATM_CLAW][i + 1].level == -1)
438 if (dam < attack_mess[ATM_CLAW][i].level 479 {
439 || attack_mess[ATM_CLAW][i+1].level == -1) { 480 sprintf (buf1, "%s %s%s", attack_mess[ATM_CLAW][i].buf1, &op->name, attack_mess[ATM_CLAW][i].buf2);
440 sprintf(buf1, "%s %s%s", attack_mess[ATM_CLAW][i].buf1,
441 op->name, attack_mess[ATM_CLAW][i].buf2);
442 strcpy (buf2, attack_mess[ATM_CLAW][i].buf3); 481 strcpy (buf2, attack_mess[ATM_CLAW][i].buf3);
443 found++; 482 found++;
444 break; 483 break;
484 }
445 } 485 }
446 } else if (USING_SKILL(hitter, SK_PUNCHING)) { 486 else if (USING_SKILL (hitter, SK_PUNCHING))
487 {
447 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_PUNCH][i].level != -1; 488 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_PUNCH][i].level != -1; i++)
448 i++) 489 if (dam < attack_mess[ATM_PUNCH][i].level || attack_mess[ATM_PUNCH][i + 1].level == -1)
449 if (dam < attack_mess[ATM_PUNCH][i].level 490 {
450 || attack_mess[ATM_PUNCH][i+1].level == -1) { 491 sprintf (buf1, "%s %s%s", attack_mess[ATM_PUNCH][i].buf1, &op->name, attack_mess[ATM_PUNCH][i].buf2);
451 sprintf(buf1, "%s %s%s", attack_mess[ATM_PUNCH][i].buf1,
452 op->name, attack_mess[ATM_PUNCH][i].buf2);
453 strcpy (buf2, attack_mess[ATM_PUNCH][i].buf3); 492 strcpy (buf2, attack_mess[ATM_PUNCH][i].buf3);
454 found++; 493 found++;
455 break; 494 break;
495 }
456 } 496 }
457 }
458 } 497 }
459 if (found) { 498 if (found)
460 /* done */ 499 {
500 /* done */
501 }
461 } else if (IS_ARROW(hitter) && (type == AT_PHYSICAL || type == AT_MAGIC)) { 502 else if (IS_ARROW (hitter) && (type == AT_PHYSICAL || type == AT_MAGIC))
503 {
462 sprintf(buf1, "hit"); /* just in case */ 504 sprintf (buf1, "hit"); /* just in case */
463 for (i=0; i < MAXATTACKMESS; i++) 505 for (i = 0; i < MAXATTACKMESS; i++)
464 if (dam < attack_mess[ATM_ARROW][i].level 506 if (dam < attack_mess[ATM_ARROW][i].level || attack_mess[ATM_ARROW][i + 1].level == -1)
465 || attack_mess[ATM_ARROW][i+1].level == -1) { 507 {
466 strcpy (buf2, attack_mess[ATM_ARROW][i].buf3); 508 strcpy (buf2, attack_mess[ATM_ARROW][i].buf3);
467 found++; 509 found++;
468 break; 510 break;
511 }
469 } 512 }
470 } else if (type & AT_DRAIN && IS_LIVE(op)) { 513 else if (type & AT_DRAIN && IS_LIVE (op))
514 {
471 /* drain is first, because some items have multiple attypes */ 515 /* drain is first, because some items have multiple attypes */
472 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_DRAIN][i].level != -1; 516 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_DRAIN][i].level != -1; i++)
473 i++) 517 if (dam < attack_mess[ATM_DRAIN][i].level || attack_mess[ATM_DRAIN][i + 1].level == -1)
474 if (dam < attack_mess[ATM_DRAIN][i].level 518 {
475 || attack_mess[ATM_DRAIN][i+1].level == -1) { 519 sprintf (buf1, "%s %s%s", attack_mess[ATM_DRAIN][i].buf1, &op->name, attack_mess[ATM_DRAIN][i].buf2);
476 sprintf(buf1, "%s %s%s", attack_mess[ATM_DRAIN][i].buf1,
477 op->name, attack_mess[ATM_DRAIN][i].buf2);
478 strcpy (buf2, attack_mess[ATM_DRAIN][i].buf3); 520 strcpy (buf2, attack_mess[ATM_DRAIN][i].buf3);
479 found++; 521 found++;
480 break; 522 break;
523 }
481 } 524 }
482 } else if (type & AT_ELECTRICITY && IS_LIVE(op)) { 525 else if (type & AT_ELECTRICITY && IS_LIVE (op))
526 {
483 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_ELEC][i].level != -1; 527 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_ELEC][i].level != -1; i++)
484 i++) 528 if (dam < attack_mess[ATM_ELEC][i].level || attack_mess[ATM_ELEC][i + 1].level == -1)
485 if (dam < attack_mess[ATM_ELEC][i].level 529 {
486 || attack_mess[ATM_ELEC][i+1].level == -1) { 530 sprintf (buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1, &op->name, attack_mess[ATM_ELEC][i].buf2);
487 sprintf(buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1,
488 op->name, attack_mess[ATM_ELEC][i].buf2);
489 strcpy (buf2, attack_mess[ATM_ELEC][i].buf3); 531 strcpy (buf2, attack_mess[ATM_ELEC][i].buf3);
490 found++; 532 found++;
491 break; 533 break;
534 }
492 } 535 }
493 } else if (type & AT_COLD && IS_LIVE(op)) { 536 else if (type & AT_COLD && IS_LIVE (op))
537 {
494 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_COLD][i].level != -1; 538 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_COLD][i].level != -1; i++)
495 i++) 539 if (dam < attack_mess[ATM_COLD][i].level || attack_mess[ATM_COLD][i + 1].level == -1)
496 if (dam < attack_mess[ATM_COLD][i].level 540 {
497 || attack_mess[ATM_COLD][i+1].level == -1) { 541 sprintf (buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1, &op->name, attack_mess[ATM_COLD][i].buf2);
498 sprintf(buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1,
499 op->name, attack_mess[ATM_COLD][i].buf2);
500 strcpy (buf2, attack_mess[ATM_COLD][i].buf3); 542 strcpy (buf2, attack_mess[ATM_COLD][i].buf3);
501 found++; 543 found++;
502 break; 544 break;
545 }
503 } 546 }
504 } else if (type & AT_FIRE) { 547 else if (type & AT_FIRE)
548 {
505 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_FIRE][i].level != -1; 549 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_FIRE][i].level != -1; i++)
506 i++) 550 if (dam < attack_mess[ATM_FIRE][i].level || attack_mess[ATM_FIRE][i + 1].level == -1)
507 if (dam < attack_mess[ATM_FIRE][i].level 551 {
508 || attack_mess[ATM_FIRE][i+1].level == -1) { 552 sprintf (buf1, "%s %s%s", attack_mess[ATM_FIRE][i].buf1, &op->name, attack_mess[ATM_FIRE][i].buf2);
509 sprintf(buf1, "%s %s%s", attack_mess[ATM_FIRE][i].buf1,
510 op->name, attack_mess[ATM_FIRE][i].buf2);
511 strcpy (buf2, attack_mess[ATM_FIRE][i].buf3); 553 strcpy (buf2, attack_mess[ATM_FIRE][i].buf3);
512 found++; 554 found++;
513 break; 555 break;
556 }
514 } 557 }
515 } else if (hitter->current_weapon != NULL) { 558 else if (hitter->current_weapon != NULL)
516 int mtype; 559 {
560 int mtype;
561
517 switch (hitter->current_weapon->weapontype) { 562 switch (hitter->current_weapon->weapontype)
518 case WEAP_HIT: mtype = ATM_BASIC; break; 563 {
519 case WEAP_SLASH: mtype = ATM_SLASH; break; 564 case WEAP_HIT:
520 case WEAP_PIERCE: mtype = ATM_PIERCE; break; 565 mtype = ATM_BASIC;
521 case WEAP_CLEAVE: mtype = ATM_CLEAVE; break; 566 break;
522 case WEAP_SLICE: mtype = ATM_SLICE; break; 567 case WEAP_SLASH:
523 case WEAP_STAB: mtype = ATM_STAB; break; 568 mtype = ATM_SLASH;
524 case WEAP_WHIP: mtype = ATM_WHIP; break; 569 break;
525 case WEAP_CRUSH: mtype = ATM_CRUSH; break; 570 case WEAP_PIERCE:
526 case WEAP_BLUD: mtype = ATM_BLUD; break; 571 mtype = ATM_PIERCE;
527 default: mtype = ATM_BASIC; break; 572 break;
528 } 573 case WEAP_CLEAVE:
574 mtype = ATM_CLEAVE;
575 break;
576 case WEAP_SLICE:
577 mtype = ATM_SLICE;
578 break;
579 case WEAP_STAB:
580 mtype = ATM_STAB;
581 break;
582 case WEAP_WHIP:
583 mtype = ATM_WHIP;
584 break;
585 case WEAP_CRUSH:
586 mtype = ATM_CRUSH;
587 break;
588 case WEAP_BLUD:
589 mtype = ATM_BLUD;
590 break;
591 default:
592 mtype = ATM_BASIC;
593 break;
594 }
529 for (i=0; i < MAXATTACKMESS && attack_mess[mtype][i].level != -1; 595 for (i = 0; i < MAXATTACKMESS && attack_mess[mtype][i].level != -1; i++)
530 i++) 596 if (dam < attack_mess[mtype][i].level || attack_mess[mtype][i + 1].level == -1)
531 if (dam < attack_mess[mtype][i].level 597 {
532 || attack_mess[mtype][i+1].level == -1) { 598 sprintf (buf1, "%s %s%s", attack_mess[mtype][i].buf1, &op->name, attack_mess[mtype][i].buf2);
533 sprintf(buf1, "%s %s%s", attack_mess[mtype][i].buf1,
534 op->name, attack_mess[mtype][i].buf2);
535 strcpy (buf2, attack_mess[mtype][i].buf3); 599 strcpy (buf2, attack_mess[mtype][i].buf3);
536 found++; 600 found++;
537 break; 601 break;
602 }
538 } 603 }
539 } else { 604 else
605 {
540 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_BASIC][i].level != -1; 606 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_BASIC][i].level != -1; i++)
541 i++) 607 if (dam < attack_mess[ATM_BASIC][i].level || attack_mess[ATM_BASIC][i + 1].level == -1)
542 if (dam < attack_mess[ATM_BASIC][i].level 608 {
543 || attack_mess[ATM_BASIC][i+1].level == -1) { 609 sprintf (buf1, "%s %s%s", attack_mess[ATM_BASIC][i].buf1, &op->name, attack_mess[ATM_BASIC][i].buf2);
544 sprintf(buf1, "%s %s%s", attack_mess[ATM_BASIC][i].buf1,
545 op->name, attack_mess[ATM_BASIC][i].buf2);
546 strcpy (buf2, attack_mess[ATM_BASIC][i].buf3); 610 strcpy (buf2, attack_mess[ATM_BASIC][i].buf3);
547 found++; 611 found++;
548 break; 612 break;
613 }
549 } 614 }
550 }
551 615
552 if (!found) { 616 if (!found)
617 {
553 strcpy (buf1, "hit"); 618 strcpy (buf1, "hit");
554 strcpy (buf2, " hits"); 619 strcpy (buf2, " hits");
555 } 620 }
556 621
557 /* bail out if a monster is casting spells */ 622 /* bail out if a monster is casting spells */
558 if (!(hitter->type == PLAYER ||
559 (get_owner(hitter) != NULL && hitter->owner->type == PLAYER))) 623 if (!(hitter->type == PLAYER || (get_owner (hitter) != NULL && hitter->owner->type == PLAYER)))
560 return; 624 return;
561 625
562 /* scale down magic considerably. */ 626 /* scale down magic considerably. */
563 if (type & AT_MAGIC && rndm(0, 5)) 627 if (type & AT_MAGIC && rndm (0, 5))
564 return; 628 return;
565 629
566 /* Did a player hurt another player? Inform both! */ 630 /* Did a player hurt another player? Inform both! */
567 if(op->type==PLAYER &&
568 (get_owner(hitter)==NULL?hitter->type:hitter->owner->type)==PLAYER) { 631 if (op->type == PLAYER && (get_owner (hitter) == NULL ? hitter->type : hitter->owner->type) == PLAYER)
632 {
569 if(get_owner(hitter)!=NULL) 633 if (get_owner (hitter) != NULL)
570 sprintf(buf,"%s's %s%s you.", 634 sprintf (buf, "%s's %s%s you.", &hitter->owner->name, &hitter->name, buf2);
571 hitter->owner->name, hitter->name, buf2); 635 else
572 else { 636 {
573 sprintf(buf,"%s%s you.",hitter->name, buf2); 637 sprintf (buf, "%s%s you.", &hitter->name, buf2);
574 if (dam != 0) { 638 if (dam != 0)
575 if (dam < 10) 639 {
640 if (dam < 10)
576 play_sound_player_only(op->contr, SOUND_PLAYER_IS_HIT1,0,0); 641 play_sound_player_only (op->contr, SOUND_PLAYER_IS_HIT1, 0, 0);
577 else if (dam < 20) 642 else if (dam < 20)
578 play_sound_player_only(op->contr, SOUND_PLAYER_IS_HIT2,0,0); 643 play_sound_player_only (op->contr, SOUND_PLAYER_IS_HIT2, 0, 0);
579 else 644 else
580 play_sound_player_only(op->contr, SOUND_PLAYER_IS_HIT3,0,0); 645 play_sound_player_only (op->contr, SOUND_PLAYER_IS_HIT3, 0, 0);
581 } 646 }
582 } 647 }
583 new_draw_info(NDI_BLACK, 0,op,buf); 648 new_draw_info (NDI_BLACK, 0, op, buf);
584 } /* end of player hitting player */ 649 } /* end of player hitting player */
585 650
586 if(hitter->type==PLAYER) { 651 if (hitter->type == PLAYER)
652 {
587 sprintf(buf,"You %s.",buf1); 653 sprintf (buf, "You %s.", buf1);
588 if (dam != 0) { 654 if (dam != 0)
655 {
589 if (dam < 10) 656 if (dam < 10)
590 play_sound_player_only(hitter->contr, SOUND_PLAYER_HITS1,0,0); 657 play_sound_player_only (hitter->contr, SOUND_PLAYER_HITS1, 0, 0);
591 else if (dam < 20) 658 else if (dam < 20)
592 play_sound_player_only(hitter->contr, SOUND_PLAYER_HITS2,0,0); 659 play_sound_player_only (hitter->contr, SOUND_PLAYER_HITS2, 0, 0);
593 else 660 else
594 play_sound_player_only(hitter->contr, SOUND_PLAYER_HITS3,0,0); 661 play_sound_player_only (hitter->contr, SOUND_PLAYER_HITS3, 0, 0);
595 } 662 }
596 new_draw_info(NDI_BLACK, 0, hitter, buf); 663 new_draw_info (NDI_BLACK, 0, hitter, buf);
664 }
597 } else if(get_owner(hitter)!=NULL&&hitter->owner->type==PLAYER) { 665 else if (get_owner (hitter) != NULL && hitter->owner->type == PLAYER)
666 {
598 /* look for stacked spells and start reducing the message chances */ 667 /* look for stacked spells and start reducing the message chances */
599 if (hitter->type == SPELL_EFFECT && 668 if (hitter->type == SPELL_EFFECT && (hitter->subtype == SP_EXPLOSION || hitter->subtype == SP_BULLET || hitter->subtype == SP_CONE))
600 (hitter->subtype == SP_EXPLOSION || 669 {
601 hitter->subtype == SP_BULLET || 670 i = 4;
602 hitter->subtype == SP_CONE)) {
603 i=4;
604 map = hitter->map; 671 map = hitter->map;
605 if (out_of_map(map, hitter->x, hitter->y)) 672 if (out_of_map (map, hitter->x, hitter->y))
673 return;
674 next = get_map_ob (map, hitter->x, hitter->y);
675 if (next)
676 while (next)
677 {
678 if (next->type == SPELL_EFFECT && (next->subtype == SP_EXPLOSION || next->subtype == SP_BULLET || next->subtype == SP_CONE))
679 i *= 3;
680 tmp = next;
681 next = tmp->above;
682 }
683 if (i < 0)
684 return;
685 if (rndm (0, i) != 0)
686 return;
687 }
688 else if (rndm (0, 5) != 0)
606 return; 689 return;
607 next = get_map_ob(map, hitter->x, hitter->y);
608 if (next)
609 while(next) {
610 if (next->type == SPELL_EFFECT &&
611 (next->subtype == SP_EXPLOSION || next->subtype==SP_BULLET ||
612 next->subtype == SP_CONE))
613 i*=3;
614 tmp = next;
615 next = tmp->above;
616 }
617 if (i < 0)
618 return;
619 if (rndm(0, i) != 0)
620 return;
621 } else if (rndm(0, 5) != 0)
622 return;
623 sprintf(buf,"Your %s%s %s.", hitter->name, buf2, op->name); 690 sprintf (buf, "Your %s%s %s.", &hitter->name, buf2, &op->name);
624 play_sound_map(op->map, op->x, op->y, SOUND_PLAYER_HITS4); 691 play_sound_map (op->map, op->x, op->y, SOUND_PLAYER_HITS4);
625 new_draw_info(NDI_BLACK, 0, hitter->owner, buf); 692 new_draw_info (NDI_BLACK, 0, hitter->owner, buf);
626 } 693 }
627} 694}
628 695
629 696
697static int
630static int get_attack_mode (object **target, object **hitter, 698get_attack_mode (object **target, object **hitter, int *simple_attack)
631 int *simple_attack)
632{ 699{
633 if (QUERY_FLAG (*target, FLAG_FREED) || QUERY_FLAG (*hitter, FLAG_FREED)) { 700 if (QUERY_FLAG (*target, FLAG_FREED) || QUERY_FLAG (*hitter, FLAG_FREED))
701 {
634 LOG (llevError, "BUG: get_attack_mode(): freed object\n"); 702 LOG (llevError, "BUG: get_attack_mode(): freed object\n");
635 return 1; 703 return 1;
636 } 704 }
637 if ((*target)->head) 705 if ((*target)->head)
638 *target = (*target)->head; 706 *target = (*target)->head;
639 if ((*hitter)->head) 707 if ((*hitter)->head)
640 *hitter = (*hitter)->head; 708 *hitter = (*hitter)->head;
641 if ((*hitter)->env != NULL || (*target)->env != NULL) { 709 if ((*hitter)->env != NULL || (*target)->env != NULL)
710 {
642 *simple_attack = 1; 711 *simple_attack = 1;
643 return 0; 712 return 0;
644 } 713 }
645 if (QUERY_FLAG (*target, FLAG_REMOVED) 714 if (QUERY_FLAG (*target, FLAG_REMOVED)
646 || QUERY_FLAG (*hitter, FLAG_REMOVED)
647 || (*hitter)->map == NULL || !on_same_map((*hitter), (*target))) 715 || QUERY_FLAG (*hitter, FLAG_REMOVED) || (*hitter)->map == NULL || !on_same_map ((*hitter), (*target)))
648 { 716 {
649 LOG (llevError, "BUG: hitter (arch %s, name %s) with no relation to " 717 LOG (llevError, "BUG: hitter (arch %s, name %s) with no relation to " "target\n", &(*hitter)->arch->name, &(*hitter)->name);
650 "target\n", (*hitter)->arch->name, (*hitter)->name);
651 return 1; 718 return 1;
652 } 719 }
653 *simple_attack = 0; 720 *simple_attack = 0;
654 return 0; 721 return 0;
655} 722}
656 723
724static int
657static int abort_attack (object *target, object *hitter, int simple_attack) 725abort_attack (object *target, object *hitter, int simple_attack)
658{ 726{
727
659/* Check if target and hitter are still in a relation similar to the one 728/* Check if target and hitter are still in a relation similar to the one
660 * determined by get_attack_mode(). Returns true if the relation has changed. 729 * determined by get_attack_mode(). Returns true if the relation has changed.
661 */ 730 */
662 int new_mode; 731 int new_mode;
663 732
664 if (hitter->env == target || target->env == hitter) 733 if (hitter->env == target || target->env == hitter)
665 new_mode = 1; 734 new_mode = 1;
666 else if (QUERY_FLAG (hitter, FLAG_REMOVED) 735 else if (QUERY_FLAG (hitter, FLAG_REMOVED) || QUERY_FLAG (target, FLAG_REMOVED) || hitter->map == NULL || !on_same_map (hitter, target))
667 || QUERY_FLAG (target, FLAG_REMOVED)
668 || hitter->map == NULL || !on_same_map(hitter, target))
669 return 1; 736 return 1;
670 else 737 else
671 new_mode = 0; 738 new_mode = 0;
672 return new_mode != simple_attack; 739 return new_mode != simple_attack;
673} 740}
674 741
675static void thrown_item_effect (object *, object *); 742static void thrown_item_effect (object *, object *);
676 743
744static int
677static int attack_ob_simple (object *op, object *hitter, int base_dam, 745attack_ob_simple (object *op, object *hitter, int base_dam, int base_wc)
678 int base_wc)
679{ 746{
680 int simple_attack, roll, dam=0; 747 int simple_attack, roll, dam = 0;
681 uint32 type; 748 uint32 type;
682 const char *op_name = NULL; 749 shstr op_name;
683 tag_t op_tag, hitter_tag;
684 750
685 if (get_attack_mode (&op, &hitter, &simple_attack)) 751 if (get_attack_mode (&op, &hitter, &simple_attack))
752 goto error;
753
754 if (hitter->current_weapon)
755 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op)))
756 return RESULT_INT (0);
757
758 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter)))
759 return RESULT_INT (0);
760
761 /*
762 * A little check to make it more difficult to dance forward and back
763 * to avoid ever being hit by monsters.
764 */
765 if (!simple_attack && QUERY_FLAG (op, FLAG_MONSTER) && op->speed_left > -(FABS (op->speed)) * 0.3)
766 {
767 /* Decrease speed BEFORE calling process_object. Otherwise, an
768 * infinite loop occurs, with process_object calling move_monster,
769 * which then gets here again. By decreasing the speed before
770 * we call process_object, the 'if' statement above will fail.
771 */
772 op->speed_left--;
773 process_object (op);
774 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
686 goto error; 775 goto error;
687
688 /* Lauwenmark: Handle for plugin attack event */
689 execute_event(op, EVENT_ATTACK,hitter,hitter,NULL,SCRIPT_FIX_ALL);
690
691 /* Lauwenmark: This is used to handle script_weapons with weapons.
692 * Only used for players.
693 */
694 if (hitter->type==PLAYER)
695 { 776 }
696 if (hitter->current_weapon != NULL) 777
697 { 778 op_name = op->name;
698 /* Lauwenmark: Handle for plugin attack event */ 779
699 execute_event(hitter, EVENT_ATTACK,hitter->current_weapon, 780 roll = random_roll (1, 20, hitter, PREFER_HIGH);
700 op,NULL,SCRIPT_FIX_ALL); 781
782 /* Adjust roll for various situations. */
783 if (!simple_attack)
784 roll += adj_attackroll (hitter, op);
785
786 /* See if we hit the creature */
787 if (roll == 20 || op->stats.ac >= base_wc - roll)
788 {
789 int hitdam = base_dam;
790
791 if (settings.casting_time == TRUE)
701 } 792 {
793 if ((hitter->type == PLAYER) && (hitter->casting_time > -1))
794 {
795 hitter->casting_time = -1;
796 new_draw_info (NDI_UNIQUE, 0, hitter, "You attacked and lost " "your spell!");
702 } 797 }
703 op_tag = op->count;
704 hitter_tag = hitter->count;
705
706 /*
707 * A little check to make it more difficult to dance forward and back
708 * to avoid ever being hit by monsters.
709 */
710 if ( ! simple_attack && QUERY_FLAG (op, FLAG_MONSTER)
711 && op->speed_left > -(FABS(op->speed))*0.3)
712 {
713 /* Decrease speed BEFORE calling process_object. Otherwise, an
714 * infinite loop occurs, with process_object calling move_monster,
715 * which then gets here again. By decreasing the speed before
716 * we call process_object, the 'if' statement above will fail.
717 */
718 op->speed_left--;
719 process_object(op);
720 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag)
721 || abort_attack (op, hitter, simple_attack))
722 goto error;
723 }
724
725 add_refcount(op_name = op->name);
726
727 roll=random_roll(1, 20, hitter, PREFER_HIGH);
728
729 /* Adjust roll for various situations. */
730 if ( ! simple_attack)
731 roll += adj_attackroll(hitter,op);
732
733 /* See if we hit the creature */
734 if(roll==20 || op->stats.ac>=base_wc-roll) {
735 int hitdam = base_dam;
736 if (settings.casting_time == TRUE) {
737 if ((hitter->type == PLAYER)&&(hitter->casting_time > -1)){
738 hitter->casting_time = -1;
739 new_draw_info(NDI_UNIQUE, 0,hitter,"You attacked and lost "
740 "your spell!");
741 }
742 if ((op->casting_time > -1)&&(hitdam > 0)){ 798 if ((op->casting_time > -1) && (hitdam > 0))
743 op->casting_time = -1;
744 if (op->type == PLAYER) {
745 new_draw_info(NDI_UNIQUE, 0,op,"You were hit and lost "
746 "your spell!");
747 new_draw_info_format(NDI_ALL|NDI_UNIQUE,5,NULL,
748 "%s was hit by %s and lost a spell.",
749 op_name,hitter->name);
750 }
751 }
752 }
753 if ( ! simple_attack)
754 { 799 {
755 /* If you hit something, the victim should *always* wake up. 800 op->casting_time = -1;
756 * Before, invisible hitters could avoid doing this.
757 * -b.t. */
758 if (QUERY_FLAG (op, FLAG_SLEEP))
759 CLEAR_FLAG(op,FLAG_SLEEP);
760
761 /* If the victim can't see the attacker, it may alert others
762 * for help. */
763 if (op->type != PLAYER && ! can_see_enemy (op, hitter)
764 && ! get_owner (op) && rndm(0, op->stats.Int))
765 npc_call_help (op);
766
767 /* if you were hidden and hit by a creature, you are discovered*/
768 if (op->hide && QUERY_FLAG (hitter, FLAG_ALIVE)) {
769 make_visible (op);
770 if (op->type == PLAYER) 801 if (op->type == PLAYER)
771 new_draw_info (NDI_UNIQUE, 0, op, 802 {
772 "You were hit by a wild attack. " 803 new_draw_info (NDI_UNIQUE, 0, op, "You were hit and lost " "your spell!");
773 "You are no longer hidden!"); 804 new_draw_info_format (NDI_ALL | NDI_UNIQUE, 5, NULL, "%s was hit by %s and lost a spell.", &op_name, &hitter->name);
805 }
774 } 806 }
807 }
808 if (!simple_attack)
809 {
810 /* If you hit something, the victim should *always* wake up.
811 * Before, invisible hitters could avoid doing this.
812 * -b.t. */
813 if (QUERY_FLAG (op, FLAG_SLEEP))
814 CLEAR_FLAG (op, FLAG_SLEEP);
775 815
816 /* If the victim can't see the attacker, it may alert others
817 * for help. */
818 if (op->type != PLAYER && !can_see_enemy (op, hitter) && !get_owner (op) && rndm (0, op->stats.Int))
819 npc_call_help (op);
820
821 /* if you were hidden and hit by a creature, you are discovered */
822 if (op->hide && QUERY_FLAG (hitter, FLAG_ALIVE))
823 {
824 make_visible (op);
825 if (op->type == PLAYER)
826 new_draw_info (NDI_UNIQUE, 0, op, "You were hit by a wild attack. " "You are no longer hidden!");
827 }
828
776 /* thrown items (hitter) will have various effects 829 /* thrown items (hitter) will have various effects
777 * when they hit the victim. For things like thrown daggers, 830 * when they hit the victim. For things like thrown daggers,
778 * this sets 'hitter' to the actual dagger, and not the 831 * this sets 'hitter' to the actual dagger, and not the
779 * wrapper object. 832 * wrapper object.
780 */ 833 */
781 thrown_item_effect (hitter, op); 834 thrown_item_effect (hitter, op);
782 if (was_destroyed (hitter, hitter_tag) 835 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
783 || was_destroyed (op, op_tag)
784 || abort_attack (op, hitter, simple_attack))
785 goto leave; 836 goto leave;
786 } 837 }
787 838
788 /* Need to do at least 1 damage, otherwise there is no point 839 /* Need to do at least 1 damage, otherwise there is no point
789 * to go further and it will cause FPE's below. 840 * to go further and it will cause FPE's below.
790 */ 841 */
791 if (hitdam<=0) hitdam=1; 842 if (hitdam <= 0)
843 hitdam = 1;
792 844
793 type=hitter->attacktype; 845 type = hitter->attacktype;
794 if(!type) type=AT_PHYSICAL; 846
847 if (!type)
848 type = AT_PHYSICAL;
849
795 /* Handle monsters that hit back */ 850 /* Handle monsters that hit back */
796 if ( ! simple_attack && QUERY_FLAG (op, FLAG_HITBACK) 851 if (!simple_attack && QUERY_FLAG (op, FLAG_HITBACK) && QUERY_FLAG (hitter, FLAG_ALIVE))
797 && QUERY_FLAG (hitter, FLAG_ALIVE)) 852 {
798 {
799 if (op->attacktype & AT_ACID && hitter->type==PLAYER) 853 if (op->attacktype & AT_ACID && hitter->type == PLAYER)
800 new_draw_info(NDI_UNIQUE, 0,hitter,"You are splashed by acid!\n"); 854 new_draw_info (NDI_UNIQUE, 0, hitter, "You are splashed by acid!\n");
801 hit_player(hitter, random_roll(0, (op->stats.dam), hitter, 855
802 PREFER_LOW),op, op->attacktype, 1); 856 hit_player (hitter, random_roll (0, (op->stats.dam), hitter, PREFER_LOW), op, op->attacktype, 1);
803 if (was_destroyed (op, op_tag) 857
804 || was_destroyed (hitter, hitter_tag) 858 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
805 || abort_attack (op, hitter, simple_attack))
806 goto leave; 859 goto leave;
807 } 860 }
808 861
809 /* In the new attack code, it should handle multiple attack 862 /* In the new attack code, it should handle multiple attack
810 * types in its area, so remove it from here. 863 * types in its area, so remove it from here.
811 */ 864 */
812 dam=hit_player(op, random_roll(1, hitdam, hitter, PREFER_HIGH), 865 dam = hit_player (op, random_roll (1, hitdam, hitter, PREFER_HIGH), hitter, type, 1);
813 hitter, type, 1); 866
814 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) 867 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
815 || abort_attack (op, hitter, simple_attack))
816 goto leave; 868 goto leave;
817 } /* end of if hitter hit op */ 869 } /* end of if hitter hit op */
818 /* if we missed, dam=0 */ 870 /* if we missed, dam=0 */
819 871
820 /*attack_message(dam, type, op, hitter);*/ 872 /*attack_message(dam, type, op, hitter); */
821 873
822 goto leave; 874 goto leave;
823 875
824 error: 876error:
825 dam = 1; 877 dam = 1;
826 goto leave;
827 878
828 leave: 879leave:
829 if (op_name)
830 free_string (op_name);
831 880
832 return dam; 881 return dam;
833} 882}
834 883
884int
835int attack_ob (object *op, object *hitter) 885attack_ob (object *op, object *hitter)
836{ 886{
837 887
838 if (hitter->head) 888 if (hitter->head)
839 hitter = hitter->head; 889 hitter = hitter->head;
840 return attack_ob_simple (op, hitter, hitter->stats.dam, hitter->stats.wc); 890 return attack_ob_simple (op, hitter, hitter->stats.dam, hitter->stats.wc);
841} 891}
842 892
843/* op is the arrow, tmp is what is stopping the arrow. 893/* op is the arrow, tmp is what is stopping the arrow.
844 * 894 *
845 * Returns 1 if op was inserted into tmp's inventory, 0 otherwise. 895 * Returns 1 if op was inserted into tmp's inventory, 0 otherwise.
846 */ 896 */
897static int
847static int stick_arrow (object *op, object *tmp) 898stick_arrow (object *op, object *tmp)
848{ 899{
849 /* If the missile hit a player, we insert it in their inventory. 900 /* If the missile hit a player, we insert it in their inventory.
850 * However, if the missile is heavy, we don't do so (assume it falls 901 * However, if the missile is heavy, we don't do so (assume it falls
851 * to the ground after a hit). What a good value for this is up to 902 * to the ground after a hit). What a good value for this is up to
852 * debate - 5000 is 5 kg, so arrows, knives, and other light weapons 903 * debate - 5000 is 5 kg, so arrows, knives, and other light weapons
853 * stick around. 904 * stick around.
854 */ 905 */
855 if (op->weight <= 5000 && tmp->stats.hp >= 0) { 906 if (op->weight <= 5000 && tmp->stats.hp >= 0)
907 {
856 if(tmp->head != NULL) 908 if (tmp->head != NULL)
857 tmp = tmp->head; 909 tmp = tmp->head;
910
858 remove_ob (op); 911 remove_ob (op);
859 op = insert_ob_in_ob(op,tmp); 912 op = insert_ob_in_ob (op, tmp);
913
860 if (tmp->type== PLAYER) 914 if (tmp->type == PLAYER)
861 esrv_send_item (tmp, op); 915 esrv_send_item (tmp, op);
916
862 return 1; 917 return 1;
918 }
863 } else 919 else
864 return 0; 920 return 0;
865} 921}
866 922
867/* hit_with_arrow() disassembles the missile, attacks the victim and 923/* hit_with_arrow() disassembles the missile, attacks the victim and
868 * reassembles the missile. 924 * reassembles the missile.
869 * 925 *
870 * It returns a pointer to the reassembled missile, or NULL if the missile 926 * It returns a pointer to the reassembled missile, or NULL if the missile
871 * isn't available anymore. 927 * isn't available anymore.
872 */ 928 */
929object *
873object *hit_with_arrow (object *op, object *victim) 930hit_with_arrow (object *op, object *victim)
874{ 931{
875 object *container, *hitter; 932 object *container, *hitter;
876 int hit_something = 0; 933 int hit_something = 0;
877 tag_t victim_tag, hitter_tag;
878 sint16 victim_x, victim_y;
879 934
880 /* Disassemble missile */ 935 /* Disassemble missile */
881 if (op->inv) { 936 if (op->inv)
937 {
882 container = op; 938 container = op;
883 hitter = op->inv; 939 hitter = op->inv;
884 remove_ob (hitter); 940 remove_ob (hitter);
885 insert_ob_in_map(hitter, container->map,hitter,INS_NO_MERGE | INS_NO_WALK_ON); 941 insert_ob_in_map (hitter, container->map, hitter, INS_NO_MERGE | INS_NO_WALK_ON);
886 /* Note that we now have an empty THROWN_OBJ on the map. Code that 942 /* Note that we now have an empty THROWN_OBJ on the map. Code that
887 * might be called until this THROWN_OBJ is either reassembled or 943 * might be called until this THROWN_OBJ is either reassembled or
888 * removed at the end of this function must be able to deal with empty 944 * removed at the end of this function must be able to deal with empty
889 * THROWN_OBJs. */ 945 * THROWN_OBJs. */
890 } else { 946 }
947 else
948 {
891 container = NULL; 949 container = 0;
892 hitter = op; 950 hitter = op;
893 } 951 }
894 952
895 /* Try to hit victim */ 953 /* Try to hit victim */
896 victim_x = victim->x;
897 victim_y = victim->y;
898 victim_tag = victim->count;
899 hitter_tag = hitter->count;
900 /* Lauwenmark: Handling plugin attack event for thrown items */
901 if (execute_event(op, EVENT_ATTACK,hitter,victim,NULL,SCRIPT_FIX_ALL) == 0)
902 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, 954 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc);
903 op->stats.wc);
904 955
905 /* Arrow attacks door, rune of summoning is triggered, demon is put on 956 /* Arrow attacks door, rune of summoning is triggered, demon is put on
906 * arrow, move_apply() calls this function, arrow sticks in demon, 957 * arrow, move_apply() calls this function, arrow sticks in demon,
907 * attack_ob_simple() returns, and we've got an arrow that still exists 958 * attack_ob_simple() returns, and we've got an arrow that still exists
908 * but is no longer on the map. Ugh. (Beware: Such things can happen at 959 * but is no longer on the map. Ugh. (Beware: Such things can happen at
909 * other places as well!) 960 * other places as well!)
910 */ 961 */
911 if (was_destroyed (hitter, hitter_tag) || hitter->env != NULL) { 962 if (hitter->destroyed () || hitter->env != NULL)
963 {
912 if (container) { 964 if (container)
965 {
913 remove_ob (container); 966 remove_ob (container);
914 free_object (container); 967 free_object (container);
915 } 968 }
969
916 return NULL; 970 return 0;
917 } 971 }
918 972
919 /* Missile hit victim */ 973 /* Missile hit victim */
920 /* if the speed is > 10, then this is a fast moving arrow, we go straight 974 /* if the speed is > 10, then this is a fast moving arrow, we go straight
921 * through the target 975 * through the target
922 */ 976 */
923 if (hit_something && op->speed <= 10.0) 977 if (hit_something && op->speed <= 10.0)
924 { 978 {
925 /* Stop arrow */ 979 /* Stop arrow */
926 if (container == NULL) { 980 if (!container)
981 {
927 hitter = fix_stopped_arrow (hitter); 982 hitter = fix_stopped_arrow (hitter);
928 if (hitter == NULL) 983 if (!hitter)
929 return NULL; 984 return 0;
985 }
930 } else { 986 else
987 {
931 remove_ob (container); 988 remove_ob (container);
932 free_object (container); 989 free_object (container);
933 } 990 }
934 991
935 /* Try to stick arrow into victim */ 992 /* Try to stick arrow into victim */
936 if ( ! was_destroyed (victim, victim_tag) 993 if (!victim->destroyed () && stick_arrow (hitter, victim))
937 && stick_arrow (hitter, victim))
938 return NULL; 994 return 0;
939 995
940 /* Else try to put arrow on victim's map square 996 /* Else try to put arrow on victim's map square
941 * remove check for P_WALL here. If the arrow got to this 997 * remove check for P_WALL here. If the arrow got to this
942 * space, that is good enough - with the new movement code, 998 * space, that is good enough - with the new movement code,
943 * there is now the potential for lots of spaces where something 999 * there is now the potential for lots of spaces where something
944 * can fly over but not otherwise move over. What is the correct 1000 * can fly over but not otherwise move over. What is the correct
945 * way to handle those otherwise? 1001 * way to handle those otherwise?
946 */ 1002 */
947 if (victim_x != hitter->x || victim_y != hitter->y) { 1003 if (victim->x != hitter->x || victim->y != hitter->y)
1004 {
948 remove_ob (hitter); 1005 remove_ob (hitter);
949 hitter->x = victim_x; 1006 hitter->x = victim->x;
950 hitter->y = victim_y; 1007 hitter->y = victim->y;
951 insert_ob_in_map (hitter, victim->map, hitter,0); 1008 insert_ob_in_map (hitter, victim->map, hitter, 0);
1009 }
952 } else { 1010 else
953 /* Else leave arrow where it is */ 1011 /* Else leave arrow where it is */
954 merge_ob (hitter, NULL); 1012 merge_ob (hitter, NULL);
955 } 1013
956 return NULL; 1014 return 0;
957 } 1015 }
958 1016
959 if (hit_something && op->speed >= 10.0) 1017 if (hit_something && op->speed >= 10.0)
960 op->speed -= 1.0; 1018 op->speed -= 1.0;
961 1019
962 /* Missile missed victim - reassemble missile */ 1020 /* Missile missed victim - reassemble missile */
963 if (container) { 1021 if (container)
1022 {
964 remove_ob (hitter); 1023 remove_ob (hitter);
965 insert_ob_in_ob (hitter, container); 1024 insert_ob_in_ob (hitter, container);
966 } 1025 }
1026
967 return op; 1027 return op;
968} 1028}
969 1029
970 1030
1031void
971void tear_down_wall(object *op) 1032tear_down_wall (object *op)
972{ 1033{
973 int perc=0; 1034 int perc = 0;
974 1035
975 if (!op->stats.maxhp) { 1036 if (!op->stats.maxhp)
1037 {
976 LOG(llevError, "TEAR_DOWN wall %s had no maxhp.\n", op->name); 1038 LOG (llevError, "TEAR_DOWN wall %s had no maxhp.\n", &op->name);
977 perc = 1; 1039 perc = 1;
1040 }
978 } else if(!GET_ANIM_ID(op)) { 1041 else if (!GET_ANIM_ID (op))
1042 {
979 /* Object has been called - no animations, so remove it */ 1043 /* Object has been called - no animations, so remove it */
980 if(op->stats.hp<0) { 1044 if (op->stats.hp < 0)
1045 {
981 remove_ob(op); /* Should update LOS */ 1046 remove_ob (op); /* Should update LOS */
982 free_object(op); 1047 free_object (op);
983 /* Don't know why this is here - remove_ob should do it for us */ 1048 /* Don't know why this is here - remove_ob should do it for us */
984 /*update_position(m, x, y);*/ 1049 /*update_position(m, x, y); */
985 } 1050 }
986 return; /* no animations, so nothing more to do */ 1051 return; /* no animations, so nothing more to do */
987 } 1052 }
988 perc = NUM_ANIMATIONS(op) 1053 perc = NUM_ANIMATIONS (op) - ((int) NUM_ANIMATIONS (op) * op->stats.hp) / op->stats.maxhp;
989 - ((int)NUM_ANIMATIONS(op)*op->stats.hp)/op->stats.maxhp;
990 if (perc >= (int) NUM_ANIMATIONS(op)) 1054 if (perc >= (int) NUM_ANIMATIONS (op))
991 perc = NUM_ANIMATIONS(op)-1; 1055 perc = NUM_ANIMATIONS (op) - 1;
992 else if (perc < 1) 1056 else if (perc < 1)
993 perc = 1; 1057 perc = 1;
994 SET_ANIMATION(op, perc); 1058 SET_ANIMATION (op, perc);
995 update_object(op,UP_OBJ_FACE); 1059 update_object (op, UP_OBJ_FACE);
996 if(perc==NUM_ANIMATIONS(op)-1) { /* Reached the last animation */ 1060 if (perc == NUM_ANIMATIONS (op) - 1)
1061 { /* Reached the last animation */
997 if(op->face==blank_face) { 1062 if (op->face == blank_face)
1063 {
998 /* If the last face is blank, remove the ob */ 1064 /* If the last face is blank, remove the ob */
999 remove_ob(op); /* Should update LOS */ 1065 remove_ob (op); /* Should update LOS */
1000 free_object(op); 1066 free_object (op);
1001 1067
1002 /* remove_ob should call update_position for us */ 1068 /* remove_ob should call update_position for us */
1003 /*update_position(m, x, y);*/ 1069 /*update_position(m, x, y); */
1004 1070
1005 } else { /* The last face was not blank, leave an image */ 1071 }
1072 else
1073 { /* The last face was not blank, leave an image */
1006 CLEAR_FLAG(op, FLAG_BLOCKSVIEW); 1074 CLEAR_FLAG (op, FLAG_BLOCKSVIEW);
1007 update_all_los(op->map, op->x, op->y); 1075 update_all_los (op->map, op->x, op->y);
1008 op->move_block = 0; 1076 op->move_block = 0;
1009 CLEAR_FLAG(op, FLAG_ALIVE); 1077 CLEAR_FLAG (op, FLAG_ALIVE);
1010 } 1078 }
1011 } 1079 }
1012} 1080}
1013 1081
1082void
1014void scare_creature(object *target, object *hitter) 1083scare_creature (object *target, object *hitter)
1015{ 1084{
1016 object *owner = get_owner(hitter); 1085 object *owner = get_owner (hitter);
1017 1086
1018 if (!owner) owner=hitter; 1087 if (!owner)
1088 owner = hitter;
1019 1089
1020 SET_FLAG(target, FLAG_SCARED); 1090 SET_FLAG (target, FLAG_SCARED);
1021 if (!target->enemy) target->enemy=owner; 1091 if (!target->enemy)
1092 target->enemy = owner;
1022} 1093}
1023 1094
1024 1095
1025/* This returns the amount of damage hitter does to op with the 1096/* This returns the amount of damage hitter does to op with the
1026 * appropriate attacktype. Only 1 attacktype should be set at a time. 1097 * appropriate attacktype. Only 1 attacktype should be set at a time.
1027 * This doesn't damage the player, but returns how much it should 1098 * This doesn't damage the player, but returns how much it should
1028 * take. However, it will do other effects (paralyzation, slow, etc.) 1099 * take. However, it will do other effects (paralyzation, slow, etc.)
1029 * Note - changed for PR code - we now pass the attack number and not 1100 * Note - changed for PR code - we now pass the attack number and not
1030 * the attacktype. Makes it easier for the PR code. */ 1101 * the attacktype. Makes it easier for the PR code. */
1031 1102
1103int
1032int hit_player_attacktype(object *op, object *hitter, int dam, 1104hit_player_attacktype (object *op, object *hitter, int dam, uint32 attacknum, int magic)
1033 uint32 attacknum, int magic) { 1105{
1034 1106
1035 int doesnt_slay = 1; 1107 int doesnt_slay = 1;
1036 1108
1037 /* Catch anyone that may be trying to send us a bitmask instead of the number */ 1109 /* Catch anyone that may be trying to send us a bitmask instead of the number */
1038 if (attacknum >= NROFATTACKS) { 1110 if (attacknum >= NROFATTACKS)
1111 {
1039 LOG(llevError, "hit_player_attacktype: Invalid attacknumber passed: %u\n", attacknum); 1112 LOG (llevError, "hit_player_attacktype: Invalid attacknumber passed: %u\n", attacknum);
1040 return 0; 1113 return 0;
1041 }
1042 1114 }
1115
1043 if (dam < 0) { 1116 if (dam < 0)
1117 {
1044 LOG(llevError,"hit_player_attacktype called with negative damage: %d\n", dam); 1118 LOG (llevError, "hit_player_attacktype called with negative damage: %d\n", dam);
1045 return 0; 1119 return 0;
1046 }
1047 1120 }
1121
1048 /* AT_INTERNAL is supposed to do exactly dam. Put a case here so 1122 /* AT_INTERNAL is supposed to do exactly dam. Put a case here so
1049 * people can't mess with that or it otherwise get confused. */ 1123 * people can't mess with that or it otherwise get confused. */
1050 if (attacknum == ATNR_INTERNAL) return dam; 1124 if (attacknum == ATNR_INTERNAL)
1051 1125 return dam;
1126
1052 if (hitter->slaying) { 1127 if (hitter->slaying)
1128 {
1053 if(((op->race != NULL) && strstr(hitter->slaying, op->race)) || 1129 if (((op->race != NULL) && strstr (hitter->slaying, op->race)) ||
1054 (op->arch && (op->arch->name != NULL) && 1130 (op->arch && (op->arch->name != NULL) && strstr (op->arch->name, hitter->slaying)))
1055 strstr(op->arch->name, hitter->slaying)) 1131 {
1056 ){ 1132 doesnt_slay = 0;
1057 doesnt_slay = 0; 1133 dam *= 3;
1058 dam *= 3;
1059 } 1134 }
1060 } 1135 }
1061 1136
1062 /* Adjust the damage for resistance. Note that neg. values increase damage. */ 1137 /* Adjust the damage for resistance. Note that neg. values increase damage. */
1063 if (op->resist[attacknum]) { 1138 if (op->resist[attacknum])
1139 {
1064 /* basically: dam = dam*(100-op->resist[attacknum])/100; 1140 /* basically: dam = dam*(100-op->resist[attacknum])/100;
1065 * in case 0>dam>1, we try to "simulate" a float value-effect */ 1141 * in case 0>dam>1, we try to "simulate" a float value-effect */
1066 dam *= (100-op->resist[attacknum]); 1142 dam *= (100 - op->resist[attacknum]);
1067 if (dam >= 100) dam /= 100; 1143 if (dam >= 100)
1144 dam /= 100;
1068 else 1145 else
1069 dam = (dam > (random_roll(0, 99, op, PREFER_LOW))) ? 1 : 0; 1146 dam = (dam > (random_roll (0, 99, op, PREFER_LOW))) ? 1 : 0;
1070 } 1147 }
1071 1148
1072 /* Special hack. By default, if immune to something, you 1149 /* Special hack. By default, if immune to something, you
1073 * shouldn't need to worry. However, acid is an exception, since 1150 * shouldn't need to worry. However, acid is an exception, since
1074 * it can still damage your items. Only include attacktypes if 1151 * it can still damage your items. Only include attacktypes if
1075 * special processing is needed */ 1152 * special processing is needed */
1076 1153
1077 if ((op->resist[attacknum] >= 100) && 1154 if ((op->resist[attacknum] >= 100) && doesnt_slay && (attacknum != ATNR_ACID))
1078 doesnt_slay && (attacknum != ATNR_ACID))
1079 return 0; 1155 return 0;
1080 1156
1081 /* Keep this in order - makes things easier to find */ 1157 /* Keep this in order - makes things easier to find */
1158
1159 switch (attacknum)
1082 1160 {
1083 switch(attacknum) {
1084 case ATNR_PHYSICAL: 1161 case ATNR_PHYSICAL:
1085 /* here also check for diseases */ 1162 /* here also check for diseases */
1086 check_physically_infect(op, hitter); 1163 check_physically_infect (op, hitter);
1087 break; 1164 break;
1088 1165
1089 /* Don't need to do anything for: 1166 /* Don't need to do anything for:
1090 magic, 1167 magic,
1091 fire, 1168 fire,
1092 electricity, 1169 electricity,
1093 cold */ 1170 cold */
1094 1171
1095 case ATNR_CONFUSION: 1172 case ATNR_CONFUSION:
1096 case ATNR_POISON: 1173 case ATNR_POISON:
1097 case ATNR_SLOW: 1174 case ATNR_SLOW:
1098 case ATNR_PARALYZE: 1175 case ATNR_PARALYZE:
1099 case ATNR_FEAR: 1176 case ATNR_FEAR:
1100 case ATNR_CANCELLATION: 1177 case ATNR_CANCELLATION:
1101 case ATNR_DEPLETE: 1178 case ATNR_DEPLETE:
1102 case ATNR_BLIND: 1179 case ATNR_BLIND:
1103 { 1180 {
1104 /* chance for inflicting a special attack depends on the 1181 /* chance for inflicting a special attack depends on the
1105 * difference between attacker's and defender's level 1182 * difference between attacker's and defender's level
1106 */ 1183 */
1107 int level_diff = MIN(110, MAX(0, op->level - hitter->level)); 1184 int level_diff = MIN (110, MAX (0, op->level - hitter->level));
1108 1185
1109 /* First, only creatures/players with speed can be affected. 1186 /* First, only creatures/players with speed can be affected.
1110 * Second, just getting hit doesn't mean it always affects 1187 * Second, just getting hit doesn't mean it always affects
1111 * you. Third, you still get a saving through against the 1188 * you. Third, you still get a saving through against the
1112 * effect. 1189 * effect.
1113 */ 1190 */
1114 if (op->speed && 1191 if (op->speed &&
1115 (QUERY_FLAG(op, FLAG_MONSTER) || op->type==PLAYER) && 1192 (QUERY_FLAG (op, FLAG_MONSTER) || op->type == PLAYER) &&
1116 !(rndm(0, (attacknum == ATNR_SLOW?6:3)-1)) && 1193 !(rndm (0, (attacknum == ATNR_SLOW ? 6 : 3) - 1)) && !did_make_save (op, level_diff, op->resist[attacknum] / 10))
1117 !did_make_save(op, level_diff, op->resist[attacknum]/10)) { 1194 {
1118 1195
1119 /* Player has been hit by something */ 1196 /* Player has been hit by something */
1120 if (attacknum == ATNR_CONFUSION) confuse_player(op,hitter,dam); 1197 if (attacknum == ATNR_CONFUSION)
1121 else if (attacknum == ATNR_POISON) poison_player(op,hitter,dam); 1198 confuse_player (op, hitter, dam);
1122 else if (attacknum == ATNR_SLOW) slow_player(op,hitter,dam); 1199 else if (attacknum == ATNR_POISON)
1123 else if (attacknum == ATNR_PARALYZE) paralyze_player(op,hitter,dam); 1200 poison_player (op, hitter, dam);
1124 else if (attacknum == ATNR_FEAR) scare_creature(op, hitter); 1201 else if (attacknum == ATNR_SLOW)
1125 else if (attacknum == ATNR_CANCELLATION) cancellation(op); 1202 slow_player (op, hitter, dam);
1126 else if (attacknum == ATNR_DEPLETE) drain_stat(op); 1203 else if (attacknum == ATNR_PARALYZE)
1127 else if (attacknum == ATNR_BLIND && !QUERY_FLAG(op,FLAG_UNDEAD) && 1204 paralyze_player (op, hitter, dam);
1128 !QUERY_FLAG(op,FLAG_GENERATOR)) blind_player(op,hitter,dam); 1205 else if (attacknum == ATNR_FEAR)
1129 } 1206 scare_creature (op, hitter);
1207 else if (attacknum == ATNR_CANCELLATION)
1208 cancellation (op);
1209 else if (attacknum == ATNR_DEPLETE)
1210 drain_stat (op);
1211 else if (attacknum == ATNR_BLIND && !QUERY_FLAG (op, FLAG_UNDEAD) && !QUERY_FLAG (op, FLAG_GENERATOR))
1212 blind_player (op, hitter, dam);
1213 }
1130 dam = 0; /* These are all effects and don't do real damage */ 1214 dam = 0; /* These are all effects and don't do real damage */
1131 } 1215 }
1132 break; 1216 break;
1133 case ATNR_ACID: 1217 case ATNR_ACID:
1134 { 1218 {
1135 int flag=0; 1219 int flag = 0;
1136 1220
1137 /* Items only get corroded if you're not on a battleground and 1221 /* Items only get corroded if you're not on a battleground and
1138 * if your acid resistance is below 50%. */ 1222 * if your acid resistance is below 50%. */
1139 if (!op_on_battleground(op, NULL, NULL) && 1223 if (!op_on_battleground (op, NULL, NULL) && (op->resist[ATNR_ACID] < 50))
1140 (op->resist[ATNR_ACID] < 50)) 1224 {
1141 { 1225 object *tmp;
1142 object *tmp; 1226
1143 for(tmp=op->inv; tmp!=NULL; tmp=tmp->below) { 1227 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1144 if(tmp->invisible) 1228 {
1145 continue; 1229 if (tmp->invisible)
1146 if(!QUERY_FLAG(tmp, FLAG_APPLIED) || 1230 continue;
1147 (tmp->resist[ATNR_ACID] >= 10)) 1231 if (!QUERY_FLAG (tmp, FLAG_APPLIED) || (tmp->resist[ATNR_ACID] >= 10))
1148 /* >= 10% acid res. on itmes will protect these */ 1232 /* >= 10% acid res. on itmes will protect these */
1149 continue; 1233 continue;
1150 if(!(tmp->material & M_IRON)) 1234 if (!(tmp->material & M_IRON))
1151 continue; 1235 continue;
1152 if(tmp->magic < -4) /* Let's stop at -5 */ 1236 if (tmp->magic < -4) /* Let's stop at -5 */
1153 continue; 1237 continue;
1154 if(tmp->type==RING || 1238 if (tmp->type == RING ||
1155 /* removed boots and gloves from exclusion list in 1239 /* removed boots and gloves from exclusion list in
1156 PR */ 1240 PR */
1157 tmp->type==GIRDLE || 1241 tmp->type == GIRDLE || tmp->type == AMULET || tmp->type == WAND || tmp->type == ROD || tmp->type == HORN)
1158 tmp->type==AMULET ||
1159 tmp->type==WAND ||
1160 tmp->type==ROD ||
1161 tmp->type==HORN)
1162 continue; /* To avoid some strange effects */ 1242 continue; /* To avoid some strange effects */
1163 1243
1164 /* High damage acid has better chance of corroding 1244 /* High damage acid has better chance of corroding
1165 objects */ 1245 objects */
1166 if(rndm(0, dam+4) > 1246 if (rndm (0, dam + 4) > random_roll (0, 39, op, PREFER_HIGH) + 2 * tmp->magic)
1167 random_roll(0, 39, op, PREFER_HIGH)+2*tmp->magic) { 1247 {
1168 if(op->type == PLAYER) 1248 if (op->type == PLAYER)
1169 /* Make this more visible */ 1249 /* Make this more visible */
1170 new_draw_info_format(NDI_UNIQUE|NDI_RED,0, op, 1250 new_draw_info_format (NDI_UNIQUE | NDI_RED, 0, op,
1171 "The %s's acid corrodes your %s!", 1251 "The %s's acid corrodes your %s!", query_name (hitter), query_name (tmp));
1172 query_name(hitter), query_name(tmp)); 1252 flag = 1;
1173 flag = 1; 1253 tmp->magic--;
1174 tmp->magic--; 1254 if (op->type == PLAYER)
1175 if(op->type == PLAYER) 1255 esrv_send_item (op, tmp);
1176 esrv_send_item(op, tmp); 1256 }
1177 } 1257 }
1178 } 1258 if (flag)
1179 if(flag)
1180 fix_player(op); /* Something was corroded */ 1259 fix_player (op); /* Something was corroded */
1181 } 1260 }
1182 } 1261 }
1183 break; 1262 break;
1184 case ATNR_DRAIN: 1263 case ATNR_DRAIN:
1185 { 1264 {
1186 /* rate is the proportion of exp drained. High rate means 1265 /* rate is the proportion of exp drained. High rate means
1187 * not much is drained, low rate means a lot is drained. 1266 * not much is drained, low rate means a lot is drained.
1188 */ 1267 */
1189 int rate; 1268 int rate;
1190 1269
1191 if(op->resist[ATNR_DRAIN] >= 0) 1270 if (op->resist[ATNR_DRAIN] >= 0)
1192 rate = 400 + op->resist[ATNR_DRAIN] * 3; 1271 rate = 400 + op->resist[ATNR_DRAIN] * 3;
1193 else 1272 else
1194 rate = 400 * 100 / (100 - op->resist[ATNR_DRAIN]); 1273 rate = 400 * 100 / (100 - op->resist[ATNR_DRAIN]);
1195 1274
1196 if(op->stats.exp <= rate) { 1275 if (op->stats.exp <= rate)
1276 {
1197 if(op->type == GOLEM) 1277 if (op->type == GOLEM)
1198 dam = 999; /* Its force is "sucked" away. 8) */ 1278 dam = 999; /* Its force is "sucked" away. 8) */
1199 else 1279 else
1200 /* If we can't drain, lets try to do physical damage */ 1280 /* If we can't drain, lets try to do physical damage */
1201 dam = hit_player_attacktype(op, hitter, dam, ATNR_PHYSICAL, magic); 1281 dam = hit_player_attacktype (op, hitter, dam, ATNR_PHYSICAL, magic);
1202 } else { 1282 }
1283 else
1284 {
1203 /* Randomly give the hitter some hp */ 1285 /* Randomly give the hitter some hp */
1204 if(hitter->stats.hp<hitter->stats.maxhp && 1286 if (hitter->stats.hp < hitter->stats.maxhp &&
1205 (op->level > hitter->level) && 1287 (op->level > hitter->level) && random_roll (0, (op->level - hitter->level + 2), hitter, PREFER_HIGH) > 3)
1206 random_roll(0, (op->level-hitter->level+2), hitter, PREFER_HIGH)>3) 1288 hitter->stats.hp++;
1207 hitter->stats.hp++;
1208 1289
1209 /* Can't do drains on battleground spaces. 1290 /* Can't do drains on battleground spaces.
1210 * Move the wiz check up here - before, the hitter wouldn't gain exp 1291 * Move the wiz check up here - before, the hitter wouldn't gain exp
1211 * exp, but the wiz would still lose exp! If drainee is a wiz, 1292 * exp, but the wiz would still lose exp! If drainee is a wiz,
1212 * nothing happens. 1293 * nothing happens.
1213 * Try to credit the owner. We try to display player -> player drain 1294 * Try to credit the owner. We try to display player -> player drain
1214 * attacks, hence all the != PLAYER checks. 1295 * attacks, hence all the != PLAYER checks.
1215 */ 1296 */
1216 if (!op_on_battleground(hitter, NULL, NULL) && !QUERY_FLAG(op,FLAG_WAS_WIZ)) { 1297 if (!op_on_battleground (hitter, NULL, NULL) && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1217 object *owner = get_owner(hitter); 1298 {
1299 object *owner = get_owner (hitter);
1218 1300
1219 if (owner && owner != hitter) { 1301 if (owner && owner != hitter)
1302 {
1220 if (op->type != PLAYER || owner->type != PLAYER) 1303 if (op->type != PLAYER || owner->type != PLAYER)
1221 change_exp(owner, op->stats.exp/(rate*2), 1304 change_exp (owner, op->stats.exp / (rate * 2),
1222 hitter->chosen_skill? hitter->chosen_skill->skill:NULL, SK_EXP_TOTAL); 1305 hitter->chosen_skill ? hitter->chosen_skill->skill : (const char *) 0, SK_EXP_TOTAL);
1306 }
1223 } else if (op->type != PLAYER || hitter->type != PLAYER) { 1307 else if (op->type != PLAYER || hitter->type != PLAYER)
1308 {
1224 change_exp(hitter, op->stats.exp/(rate*2), 1309 change_exp (hitter, op->stats.exp / (rate * 2),
1225 hitter->chosen_skill?hitter->chosen_skill->skill:NULL, 0); 1310 hitter->chosen_skill ? hitter->chosen_skill->skill : (const char *) 0, 0);
1226 } 1311 }
1227 change_exp(op,-op->stats.exp/rate, NULL, 0); 1312 change_exp (op, -op->stats.exp / rate, NULL, 0);
1228 } 1313 }
1229 dam = 1; /* Drain is an effect. Still return 1 - otherwise, if you have pure 1314 dam = 1; /* Drain is an effect. Still return 1 - otherwise, if you have pure
1230 * drain attack, you won't know that you are actually sucking out EXP, 1315 * drain attack, you won't know that you are actually sucking out EXP,
1231 * as the messages will say you missed 1316 * as the messages will say you missed
1232 */ 1317 */
1233 } 1318 }
1234 } 1319 }
1235 break; 1320 break;
1236 case ATNR_TURN_UNDEAD: 1321 case ATNR_TURN_UNDEAD:
1237 { 1322 {
1238 if (QUERY_FLAG(op,FLAG_UNDEAD)) { 1323 if (QUERY_FLAG (op, FLAG_UNDEAD))
1239 object *owner = get_owner(hitter) == NULL ? hitter : get_owner(hitter); 1324 {
1325 object *owner = hitter->owner ? (object *)hitter->owner : hitter;
1240 object *god = find_god (determine_god (owner)); 1326 object *god = find_god (determine_god (owner));
1241 int div = 1; 1327 int div = 1;
1242 1328
1243 /* if undead are not an enemy of your god, you turn them 1329 /* if undead are not an enemy of your god, you turn them
1244 * at half strength */ 1330 * at half strength */
1245 if (! god || ! god->slaying || 1331 if (!god || !god->slaying || strstr (god->slaying, undead_name) == NULL)
1246 strstr (god->slaying, undead_name) == NULL)
1247 div = 2; 1332 div = 2;
1248 /* Give a bonus if you resist turn undead */ 1333 /* Give a bonus if you resist turn undead */
1249 if (op->level * div < 1334 if (op->level * div < (turn_bonus[owner->stats.Wis] + owner->level + (op->resist[ATNR_TURN_UNDEAD] / 100)))
1250 (turn_bonus[owner->stats.Wis]+owner->level + 1335 scare_creature (op, owner);
1251 (op->resist[ATNR_TURN_UNDEAD]/100))) 1336 }
1252 scare_creature(op, owner); 1337 else
1253 }
1254 else
1255 dam = 0; /* don't damage non undead - should we damage 1338 dam = 0; /* don't damage non undead - should we damage
1256 undead? */ 1339 undead? */
1340 }
1257 } break; 1341 break;
1258 case ATNR_DEATH: 1342 case ATNR_DEATH:
1259 deathstrike_player(op, hitter, &dam); 1343 deathstrike_player (op, hitter, &dam);
1260 break; 1344 break;
1261 case ATNR_CHAOS: 1345 case ATNR_CHAOS:
1262 LOG(llevError, 1346 LOG (llevError, "%s was hit by %s with non-specific chaos.\n", query_name (op), query_name (hitter));
1263 "%s was hit by %s with non-specific chaos.\n", 1347 dam = 0;
1264 query_name(op), 1348 break;
1265 query_name(hitter));
1266 dam = 0;
1267 break;
1268 case ATNR_COUNTERSPELL: 1349 case ATNR_COUNTERSPELL:
1269 LOG(llevError, 1350 LOG (llevError, "%s was hit by %s with counterspell attack.\n", query_name (op), query_name (hitter));
1270 "%s was hit by %s with counterspell attack.\n", 1351 dam = 0;
1271 query_name(op),
1272 query_name(hitter));
1273 dam = 0;
1274 /* This should never happen. Counterspell is handled 1352 /* This should never happen. Counterspell is handled
1275 * seperately and filtered out. If this does happen, 1353 * seperately and filtered out. If this does happen,
1276 * Counterspell has no effect on anything but spells, so it 1354 * Counterspell has no effect on anything but spells, so it
1277 * does no damage. */ 1355 * does no damage. */
1278 break; 1356 break;
1279 case ATNR_HOLYWORD: 1357 case ATNR_HOLYWORD:
1280 { 1358 {
1281 /* This has already been handled by hit_player, 1359 /* This has already been handled by hit_player,
1282 * no need to check twice -- DAMN */ 1360 * no need to check twice -- DAMN */
1283 1361 object *owner = hitter->owner ? (object *)hitter->owner : hitter;
1284 object *owner = get_owner(hitter)==NULL?hitter:get_owner(hitter); 1362
1285
1286 /* As with turn undead above, give a bonus on the saving throw */ 1363 /* As with turn undead above, give a bonus on the saving throw */
1287 if((op->level+(op->resist[ATNR_HOLYWORD]/100)) < 1364 if ((op->level + (op->resist[ATNR_HOLYWORD] / 100)) < owner->level + turn_bonus[owner->stats.Wis])
1288 owner->level+turn_bonus[owner->stats.Wis])
1289 scare_creature(op, owner); 1365 scare_creature (op, owner);
1366 }
1290 } break; 1367 break;
1291 case ATNR_LIFE_STEALING: 1368 case ATNR_LIFE_STEALING:
1292 { 1369 {
1293 int new_hp; 1370 int new_hp;
1371
1294 /* this is replacement to drain for players, instead of taking 1372 /* this is replacement to drain for players, instead of taking
1295 * exp it takes hp. It is geared for players, probably not 1373 * exp it takes hp. It is geared for players, probably not
1296 * much use giving it to monsters 1374 * much use giving it to monsters
1297 * 1375 *
1298 * life stealing doesn't do a lot of damage, but it gives the 1376 * life stealing doesn't do a lot of damage, but it gives the
1299 * damage it does do to the player. Given that, 1377 * damage it does do to the player. Given that,
1300 * it only does 1/10'th normal damage (hence the divide by 1378 * it only does 1/10'th normal damage (hence the divide by
1301 * 1000). 1379 * 1000).
1302 */ 1380 */
1303 /* You can't steal life from something undead */ 1381 /* You can't steal life from something undead */
1304 if ((op->type == GOLEM) || (QUERY_FLAG(op, FLAG_UNDEAD))) return 0; 1382 if ((op->type == GOLEM) || (QUERY_FLAG (op, FLAG_UNDEAD)))
1383 return 0;
1305 /* If drain protection is higher than life stealing, use that */ 1384 /* If drain protection is higher than life stealing, use that */
1306 if (op->resist[ATNR_DRAIN] >= op->resist[ATNR_LIFE_STEALING]) 1385 if (op->resist[ATNR_DRAIN] >= op->resist[ATNR_LIFE_STEALING])
1307 dam = (dam*(100 - op->resist[ATNR_DRAIN])) / 3000; 1386 dam = (dam * (100 - op->resist[ATNR_DRAIN])) / 3000;
1387 else
1308 else dam = (dam*(100 - op->resist[ATNR_LIFE_STEALING])) / 3000; 1388 dam = (dam * (100 - op->resist[ATNR_LIFE_STEALING])) / 3000;
1309 /* You die at -1 hp, not zero. */ 1389 /* You die at -1 hp, not zero. */
1310 if (dam > (op->stats.hp+1)) dam = op->stats.hp+1; 1390 if (dam > (op->stats.hp + 1))
1391 dam = op->stats.hp + 1;
1311 new_hp = hitter->stats.hp + dam; 1392 new_hp = hitter->stats.hp + dam;
1312 if (new_hp > hitter->stats.maxhp) new_hp = hitter->stats.maxhp; 1393 if (new_hp > hitter->stats.maxhp)
1313 if (new_hp > hitter->stats.hp) hitter->stats.hp = new_hp; 1394 new_hp = hitter->stats.maxhp;
1395 if (new_hp > hitter->stats.hp)
1396 hitter->stats.hp = new_hp;
1397 }
1314 } 1398 }
1315 }
1316 return dam; 1399 return dam;
1317} 1400}
1318 1401
1319 1402
1320/* GROS: This code comes from hit_player. It has been made external to 1403/* GROS: This code comes from hit_player. It has been made external to
1321 * allow script procedures to "kill" objects in a combat-like fashion. 1404 * allow script procedures to "kill" objects in a combat-like fashion.
1330 * This function was a bit of a mess with hitter getting changed, 1413 * This function was a bit of a mess with hitter getting changed,
1331 * values being stored away but not used, etc. I've cleaned it up 1414 * values being stored away but not used, etc. I've cleaned it up
1332 * a bit - I think it should be functionally equivalant. 1415 * a bit - I think it should be functionally equivalant.
1333 * MSW 2002-07-17 1416 * MSW 2002-07-17
1334 */ 1417 */
1418int
1335int kill_object(object *op,int dam, object *hitter, int type) 1419kill_object (object *op, int dam, object *hitter, int type)
1336{ 1420{
1337 char buf[MAX_BUF]; 1421 char buf[MAX_BUF];
1338 const char *skill; 1422 const char *skill;
1339 int maxdam=0; 1423 int maxdam = 0;
1340 int battleg=0; /* true if op standing on battleground */ 1424 int battleg = 0; /* true if op standing on battleground */
1341 int pk=0; /* true if op and what controls hitter are both players*/ 1425 int pk = 0; /* true if op and what controls hitter are both players */
1342 object *owner=NULL; 1426 object *owner = NULL;
1343 object *skop=NULL; 1427 object *skop = NULL;
1344 1428
1345 if (op->stats.hp>=0) 1429 if (op->stats.hp >= 0)
1346 return -1; 1430 return -1;
1347 1431
1348 if (INVOKE_OBJECT (KILL, op, ARG_OBJECT (hitter))) 1432 if (INVOKE_OBJECT (KILL, op, ARG_OBJECT (hitter)))
1349 return 0; 1433 return 0;
1350 1434
1351 /* maxdam needs to be the amount of damage it took to kill 1435 /* maxdam needs to be the amount of damage it took to kill
1352 * this creature. The function(s) that call us have already 1436 * this creature. The function(s) that call us have already
1353 * adjusted the creatures HP total, so that is negative. 1437 * adjusted the creatures HP total, so that is negative.
1354 */ 1438 */
1355 maxdam = dam + op->stats.hp + 1; 1439 maxdam = dam + op->stats.hp + 1;
1356 1440
1357 if(QUERY_FLAG(op,FLAG_BLOCKSVIEW)) 1441 if (QUERY_FLAG (op, FLAG_BLOCKSVIEW))
1358 update_all_los(op->map,op->x, op->y); /* makes sure los will be recalculated */ 1442 update_all_los (op->map, op->x, op->y); /* makes sure los will be recalculated */
1359 1443
1360 if(op->type==DOOR) { 1444 if (op->type == DOOR)
1445 {
1361 op->speed = 0.1; 1446 op->speed = 0.1;
1362 update_ob_speed(op); 1447 update_ob_speed (op);
1363 op->speed_left= -0.05; 1448 op->speed_left = -0.05;
1364 return maxdam; 1449 return maxdam;
1365 } 1450 }
1451
1366 if(QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER) { 1452 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER)
1453 {
1367 remove_friendly_object(op); 1454 remove_friendly_object (op);
1368 if (get_owner (op) != NULL && op->owner->type == PLAYER && 1455
1369 op->owner->contr->ranges[range_golem] == op) { 1456 if (get_owner (op) && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op)
1370 op->owner->contr->ranges[range_golem]=NULL; 1457 op->owner->contr->ranges[range_golem] = 0;
1371 op->owner->contr->golem_count=0;
1372 }
1373 1458
1374 remove_ob(op); 1459 remove_ob (op);
1375 free_object(op); 1460 free_object (op);
1376 return maxdam; 1461 return maxdam;
1377 } 1462 }
1378 1463
1379 /* Now lets start dealing with experience we get for killing something */ 1464 /* Now lets start dealing with experience we get for killing something */
1380 1465
1381 owner=get_owner(hitter); 1466 owner = get_owner (hitter);
1382 if(owner==NULL) 1467 if (!owner)
1383 owner=hitter; 1468 owner = hitter;
1384 1469
1385 /* is the victim (op) standing on battleground? */ 1470 /* is the victim (op) standing on battleground? */
1386 if (op_on_battleground(op, NULL, NULL)) battleg=1; 1471 if (op_on_battleground (op, NULL, NULL))
1387 1472 battleg = 1;
1473
1388 /* is this player killing?*/ 1474 /* is this player killing? */
1389 if (op->type == PLAYER && owner->type == PLAYER) pk=1; 1475 if (op->type == PLAYER && owner->type == PLAYER)
1476 pk = 1;
1390 1477
1391 /* Player killed something */ 1478 /* Player killed something */
1392 if(owner->type==PLAYER) { 1479 if (owner->type == PLAYER)
1480 {
1393 Log_Kill(owner->name, 1481 Log_Kill (owner->name,
1394 query_name(op),op->type, 1482 query_name (op), op->type, (owner != hitter) ? query_name (hitter) : NULL, (owner != hitter) ? hitter->type : 0);
1395 (owner!=hitter) ? query_name(hitter) : NULL,
1396 (owner!=hitter) ? hitter->type : 0);
1397 1483
1398 /* Log players killing other players - makes it easier to detect 1484 /* Log players killing other players - makes it easier to detect
1399 * and filter out malicious player killers - that is why the 1485 * and filter out malicious player killers - that is why the
1400 * ip address is included. 1486 * ip address is included.
1401 */ 1487 */
1402 if (op->type == PLAYER && !battleg) { 1488 if (op->type == PLAYER && !battleg)
1489 {
1403 time_t t=time(NULL); 1490 time_t t = time (NULL);
1404 struct tm *tmv; 1491 struct tm *tmv;
1405 char buf[256]; 1492 char buf[256];
1406 1493
1407 tmv = localtime(&t); 1494 tmv = localtime (&t);
1408 strftime(buf, 256,"%a %b %d %H:%M:%S %Y", tmv); 1495 strftime (buf, 256, "%a %b %d %H:%M:%S %Y", tmv);
1409 1496
1410 LOG(llevInfo,"%s PLAYER_KILL_PLAYER: %s (%s) killed %s\n", 1497 LOG (llevInfo, "%s PLAYER_KILL_PLAYER: %s (%s) killed %s\n", buf, &owner->name, owner->contr->socket.host, query_name (op));
1411 buf, owner->name, owner->contr->socket.host, query_name(op)); 1498 }
1412 }
1413 1499
1414 /* try to filter some things out - basically, if you are 1500 /* try to filter some things out - basically, if you are
1415 * killing a level 1 creature and your level 20, you 1501 * killing a level 1 creature and your level 20, you
1416 * probably don't want to see that. 1502 * probably don't want to see that.
1417 */ 1503 */
1418 if ( owner->level < op->level * 2|| op->stats.exp>1000) { 1504 if (owner->level < op->level * 2 || op->stats.exp > 1000)
1505 {
1419 if(owner!=hitter) { 1506 if (owner != hitter)
1420 new_draw_info_format(NDI_BLACK, 0, owner, 1507 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter));
1421 "You killed %s with %s.",query_name(op), 1508 else
1422 query_name(hitter)); 1509 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op));
1423 } 1510
1424 else {
1425 new_draw_info_format(NDI_BLACK, 0, owner,
1426 "You killed %s.",query_name(op));
1427 }
1428 /* Only play sounds for melee kills */ 1511 /* Only play sounds for melee kills */
1429 if (hitter->type == PLAYER) 1512 if (hitter->type == PLAYER)
1430 play_sound_map(owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS); 1513 play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS);
1431 } 1514 }
1432 1515
1433 /* If a player kills another player, not on 1516 /* If a player kills another player, not on
1434 * battleground, the "killer" looses 1 luck. Since this is 1517 * battleground, the "killer" looses 1 luck. Since this is
1435 * not reversible, it's actually quite a pain IMHO. -AV 1518 * not reversible, it's actually quite a pain IMHO. -AV
1436 * Fix bug in that we were changing the luck of the hitter, not 1519 * Fix bug in that we were changing the luck of the hitter, not
1437 * player that the object belonged to - so if you killed another player 1520 * player that the object belonged to - so if you killed another player
1438 * with spells, pets, whatever, there was no penalty. 1521 * with spells, pets, whatever, there was no penalty.
1439 * Changed to make luck penalty configurable in settings. 1522 * Changed to make luck penalty configurable in settings.
1440 */ 1523 */
1441 if(op->type == PLAYER && owner != op && !battleg) 1524 if (op->type == PLAYER && owner != op && !battleg)
1442 change_luck(owner, -settings.pk_luck_penalty); 1525 change_luck (owner, -settings.pk_luck_penalty);
1443 1526
1444 /* This code below deals with finding the appropriate skill 1527 /* This code below deals with finding the appropriate skill
1445 * to credit exp to. This is a bit problematic - we should 1528 * to credit exp to. This is a bit problematic - we should
1446 * probably never really have to look at current_weapon->skill 1529 * probably never really have to look at current_weapon->skill
1447 */ 1530 */
1448 skill = NULL; 1531 skill = 0;
1449 if (hitter->skill && hitter->type!=PLAYER) skill = hitter->skill; 1532
1533 if (hitter->skill && hitter->type != PLAYER)
1534 skill = hitter->skill;
1450 else if (owner->chosen_skill) { 1535 else if (owner->chosen_skill)
1536 {
1451 skill = owner->chosen_skill->skill; 1537 skill = owner->chosen_skill->skill;
1452 skop = owner->chosen_skill; 1538 skop = owner->chosen_skill;
1453 } 1539 }
1454 else if (QUERY_FLAG(owner, FLAG_READY_WEAPON)) skill=owner->current_weapon->skill; 1540 else if (QUERY_FLAG (owner, FLAG_READY_WEAPON))
1455 else 1541 skill = owner->current_weapon->skill;
1542 else
1456 LOG(llevError,"kill_object - unable to find skill that killed monster\n"); 1543 LOG (llevError, "kill_object - unable to find skill that killed monster\n");
1457 1544
1458 /* We have the skill we want to credit to - now find the object this goes 1545 /* We have the skill we want to credit to - now find the object this goes
1459 * to. Make sure skop is an actual skill, and not a skill tool! 1546 * to. Make sure skop is an actual skill, and not a skill tool!
1460 */ 1547 */
1461 if ((!skop || skop->type != SKILL) && skill) { 1548 if ((!skop || skop->type != SKILL) && skill)
1462 int i; 1549 {
1550 int i;
1463 1551
1464 for (i=0; i<NUM_SKILLS; i++) 1552 for (i = 0; i < NUM_SKILLS; i++)
1553 if (owner->contr->last_skill_ob[i] && !strcmp (owner->contr->last_skill_ob[i]->skill, skill))
1554 {
1465 if (owner->contr->last_skill_ob[i] && 1555 skop = owner->contr->last_skill_ob[i];
1466 !strcmp(owner->contr->last_skill_ob[i]->skill, skill)) { 1556 break;
1467 skop = owner->contr->last_skill_ob[i]; 1557 }
1468 break; 1558 }
1469 }
1470 }
1471 } /* Was it a player that hit somethign */ 1559 } /* Was it a player that hit somethign */
1472 else { 1560 else
1473 skill = NULL; 1561 skill = 0;
1474 }
1475 1562
1476 /* Pet (or spell) killed something. */ 1563 /* Pet (or spell) killed something. */
1477 if(owner != hitter ) { 1564 if (owner != hitter)
1478 (void) sprintf(buf,"%s killed %s with %s%s%s.",owner->name, 1565 sprintf (buf, "%s killed %s with %s%s%s.", &owner->name,
1479 query_name(op),query_name(hitter), battleg? " (duel)":"", pk? " (pk)":""); 1566 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : "");
1480 }
1481 else { 1567 else
1482 (void) sprintf(buf,"%s killed %s%s%s%s.",hitter->name,op->name, 1568 sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name,
1483 (QUERY_FLAG(hitter, FLAG_MONSTER)) || hitter->type == PLAYER ? 1569 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ?
1484 " in hand to hand combat":"", battleg? " (duel)":"", pk? " (pk)":""); 1570 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : "");
1485 } 1571
1486 /* These may have been set in the player code section above */ 1572 /* These may have been set in the player code section above */
1573 if (!skop)
1487 if (!skop) skop = hitter->chosen_skill; 1574 skop = hitter->chosen_skill;
1488 if (!skill && skop) skill=skop->skill;
1489 1575
1576 if (!skill && skop)
1577 skill = skop->skill;
1578
1490 new_draw_info(NDI_ALL, op->type==PLAYER?1:10, NULL, buf); 1579 new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf);
1491 1580
1492
1493 /* If you didn't kill yourself, and your not the wizard */ 1581 /* If you didn't kill yourself, and your not the wizard */
1494 if(owner!=op && !QUERY_FLAG(op, FLAG_WAS_WIZ)) { 1582 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1495 int exp; 1583 {
1584 int exp;
1496 1585
1497 /* Really don't give much experience for killing other players */ 1586 /* Really don't give much experience for killing other players */
1498 // schmorp: temporary? reduce the amount of exp gained for pking enourmously 1587 // schmorp: temporarily? reduce the amount of exp gained for pking enourmously
1499 if (op->type==PLAYER) { 1588 if (op->type == PLAYER)
1500 if (battleg) {
1501 new_draw_info(NDI_UNIQUE, 0,owner, "Your foe has fallen!");
1502 new_draw_info(NDI_UNIQUE, 0,owner, "VICTORY!!!");
1503 }
1504 else
1505 exp = op->stats.exp / 1000;
1506 } 1589 {
1590 if (battleg)
1591 {
1592 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!");
1593 new_draw_info (NDI_UNIQUE, 0, owner, "VICTORY!!!");
1594 }
1507 else 1595 else
1596 exp = op->stats.exp / 1000;
1597 }
1598 else
1508 exp = calc_skill_exp(owner, op, skop); 1599 exp = calc_skill_exp (owner, op, skop);
1509 1600
1510 /* if op is standing on "battleground" (arena), no way to gain 1601 /* if op is standing on "battleground" (arena), no way to gain
1511 * exp by killing him 1602 * exp by killing him
1512 */ 1603 */
1513 if (battleg) exp = 0; 1604 if (battleg)
1605 exp = 0;
1514 1606
1515 /* Don't know why this is set this way - doesn't make 1607 /* Don't know why this is set this way - doesn't make
1516 * sense to just divide everything by two for no reason. 1608 * sense to just divide everything by two for no reason.
1517 */ 1609 */
1518 1610
1519 if (!settings.simple_exp) 1611 if (!settings.simple_exp)
1520 exp=exp/2; 1612 exp = exp / 2;
1521 1613
1522 if(owner->type!=PLAYER || owner->contr->party==NULL) { 1614 if (owner->type != PLAYER || owner->contr->party == NULL)
1523 change_exp(owner,exp, skill, 0); 1615 change_exp (owner, exp, skill, 0);
1524 } 1616 else
1525 else { 1617 {
1526 int shares=0,count=0; 1618 int shares = 0, count = 0;
1527
1528 player *pl; 1619 player *pl;
1529
1530 partylist *party=owner->contr->party; 1620 partylist *party = owner->contr->party;
1621
1531#ifdef PARTY_KILL_LOG 1622#ifdef PARTY_KILL_LOG
1532 add_kill_to_party(party, query_name(owner), query_name(op), exp); 1623 add_kill_to_party (party, query_name (owner), query_name (op), exp);
1533#endif 1624#endif
1534 for(pl=first_player;pl!=NULL;pl=pl->next) { 1625 for (pl = first_player; pl != NULL; pl = pl->next)
1535 if(party && pl->ob->contr->party==party && on_same_map(pl->ob, owner)) { 1626 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1536 count++; 1627 {
1628 count++;
1537 shares+=(pl->ob->level+4); 1629 shares += (pl->ob->level + 4);
1538 } 1630 }
1631
1632 if (count == 1 || shares > exp || !shares)
1633 change_exp (owner, exp, skill, SK_EXP_TOTAL);
1634 else
1635 {
1636 int share = exp / shares, given = 0, nexp;
1637
1638 for (pl = first_player; pl != NULL; pl = pl->next)
1639 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1640 {
1641 nexp = (pl->ob->level + 4) * share;
1642 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL);
1643 given += nexp;
1644 }
1645
1646 exp -= given;
1647 /* give any remainder to the player */
1648 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL);
1649 }
1650 } /* else part of a party */
1651 } /* end if person didn't kill himself */
1652
1653 if (op->type != PLAYER)
1654 {
1655 if (QUERY_FLAG (op, FLAG_FRIENDLY))
1656 {
1657 object *owner1 = get_owner (op);
1658
1659 if (owner1 && owner1->type == PLAYER)
1660 {
1661 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0);
1662 /* Maybe we should include the owner that killed this, maybe not */
1663 new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name);
1664 }
1665
1666 remove_friendly_object (op);
1667 }
1668
1669 remove_ob (op);
1670 free_object (op);
1539 } 1671 }
1540 if(count==1 || shares>exp) 1672 else
1541 change_exp(owner,exp, skill, SK_EXP_TOTAL);
1542 else {
1543 int share=exp/shares,given=0,nexp;
1544 for(pl=first_player;pl!=NULL;pl=pl->next) {
1545 if(party && pl->ob->contr->party==party && on_same_map(pl->ob, owner)) {
1546 nexp=(pl->ob->level+4)*share;
1547 change_exp(pl->ob,nexp, skill, SK_EXP_TOTAL);
1548 given+=nexp;
1549 }
1550 }
1551 exp-=given;
1552 /* give any remainder to the player */
1553 change_exp(owner,exp, skill, SK_EXP_ADD_SKILL);
1554 }
1555 } /* else part of a party */
1556
1557 } /* end if person didn't kill himself */
1558
1559 if(op->type!=PLAYER) {
1560 if(QUERY_FLAG(op,FLAG_FRIENDLY)) {
1561 object *owner1 = get_owner(op);
1562
1563 if(owner1!= NULL && owner1->type == PLAYER) {
1564 play_sound_player_only(owner1->contr, SOUND_PET_IS_KILLED,0,0);
1565 /* Maybe we should include the owner that killed this, maybe not */
1566 new_draw_info_format(NDI_UNIQUE, 0,owner1,"Your pet, the %s, is killed by %s.",
1567 op->name,hitter->name);
1568 }
1569 remove_friendly_object(op);
1570 }
1571 remove_ob(op);
1572 free_object(op);
1573 } 1673 {
1574 /* Player has been killed! */ 1674 /* Player has been killed! */
1675 if (owner->type == PLAYER)
1676 snprintf (op->contr->killer, sizeof (op->contr->killer), "%s the %s", &owner->name, owner->contr->title);
1575 else { 1677 else
1576 if(owner->type==PLAYER) { 1678 assign (op->contr->killer, hitter->name);
1577 snprintf(op->contr->killer, BIG_NAME, "%s the %s",owner->name,owner->contr->title);
1578 }
1579 else {
1580 strncpy(op->contr->killer,hitter->name,BIG_NAME);
1581 op->contr->killer[BIG_NAME-1]='\0';
1582 }
1583 } 1679 }
1680
1584 /* This was return -1 - that doesn't seem correct - if we return -1, process 1681 /* This was return -1 - that doesn't seem correct - if we return -1, process
1585 * continues in the calling function. 1682 * continues in the calling function.
1586 */ 1683 */
1587 return maxdam; 1684 return maxdam;
1588} 1685}
1589 1686
1590/* Find out if this is friendly fire (PVP and attacker is peaceful) or not 1687/* Find out if this is friendly fire (PVP and attacker is peaceful) or not
1591 * Returns 0 this is not friendly fire 1688 * Returns 0 this is not friendly fire
1592 */ 1689 */
1593 1690
1691int
1594int friendly_fire(object *op, object *hitter){ 1692friendly_fire (object *op, object *hitter)
1693{
1595 object *owner; 1694 object *owner;
1596 int friendlyfire; 1695 int friendlyfire;
1597
1598 if (hitter->head) hitter=hitter->head;
1599 1696
1697 if (hitter->head)
1698 hitter = hitter->head;
1699
1600 friendlyfire = 0; 1700 friendlyfire = 0;
1601 1701
1602 if(op->type == PLAYER) { 1702 if (op->type == PLAYER)
1703 {
1603 if (op_on_battleground (hitter, 0, 0)) 1704 if (op_on_battleground (hitter, 0, 0))
1604 return 0; 1705 return 0;
1605 1706
1606 if(hitter->type == PLAYER && hitter->contr->peaceful == 1) 1707 if (hitter->type == PLAYER && hitter->contr->peaceful == 1)
1607 return 1; 1708 return 1;
1608 1709
1609 if((owner = get_owner(hitter))!=NULL) { 1710 if ((owner = get_owner (hitter)) != NULL)
1711 {
1610 if(owner->type == PLAYER && owner->contr->peaceful == 1) 1712 if (owner->type == PLAYER && owner->contr->peaceful == 1)
1611 friendlyfire = 2; 1713 friendlyfire = 2;
1612 } 1714 }
1613 1715
1614 if (hitter->type == SPELL || hitter->type == POISONING || 1716 if (hitter->type == SPELL || hitter->type == POISONING || hitter->type == DISEASE || hitter->type == RUNE)
1615 hitter->type == DISEASE || hitter->type == RUNE)
1616 friendlyfire = 0; 1717 friendlyfire = 0;
1617 } 1718 }
1618 return friendlyfire; 1719 return friendlyfire;
1619} 1720}
1620 1721
1621 1722
1622/* This isn't used just for players, but in fact most objects. 1723/* This isn't used just for players, but in fact most objects.
1623 * op is the object to be hit, dam is the amount of damage, hitter 1724 * op is the object to be hit, dam is the amount of damage, hitter
1628 */ 1729 */
1629 1730
1630 /* Oct 95 - altered the following slightly for MULTIPLE_GODS hack 1731 /* Oct 95 - altered the following slightly for MULTIPLE_GODS hack
1631 * which needs new attacktype AT_HOLYWORD to work . b.t. */ 1732 * which needs new attacktype AT_HOLYWORD to work . b.t. */
1632 1733
1734int
1633int hit_player(object *op,int dam, object *hitter, int type, int full_hit) { 1735hit_player (object *op, int dam, object *hitter, int type, int full_hit)
1736{
1634 int maxdam=0, ndam=0, attacktype=1, magic=(type & AT_MAGIC); 1737 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC);
1635 int maxattacktype, attacknum; 1738 int maxattacktype, attacknum;
1636 int body_attack = op && op->head; /* Did we hit op's head? */ 1739 int body_attack = op && op->head; /* Did we hit op's head? */
1637 int simple_attack; 1740 int simple_attack;
1638 tag_t op_tag, hitter_tag;
1639 int rtn_kill = 0; 1741 int rtn_kill = 0;
1640 int friendlyfire; 1742 int friendlyfire;
1641 1743
1642 if (get_attack_mode (&op, &hitter, &simple_attack)) 1744 if (get_attack_mode (&op, &hitter, &simple_attack))
1745 return 0;
1746
1747 /* very simple: if our target has no_damage 1 set or is wiz, we can't hurt him */
1748 if (QUERY_FLAG (op, FLAG_WIZ) || QUERY_FLAG (op, FLAG_NO_DAMAGE))
1749 return 0;
1750
1751#ifdef PROHIBIT_PLAYERKILL
1752 if (op->type == PLAYER)
1753 {
1754 object *owner = get_owner (hitter);
1755
1756 if (!owner)
1757 owner = hitter;
1758
1759 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner)
1643 return 0; 1760 return 0;
1761 }
1762#endif
1644 1763
1645 /* very simple: if our target has no_damage 1 set or is wiz, we can't hurt him */ 1764 if (body_attack)
1646 if (QUERY_FLAG (op, FLAG_WIZ) || QUERY_FLAG (op, FLAG_NO_DAMAGE)) 1765 {
1766 /* slow and paralyze must hit the head. But we don't want to just
1767 * return - we still need to process other attacks the spell still
1768 * might have. So just remove the paralyze and slow attacktypes,
1769 * and keep on processing if we have other attacktypes.
1770 * return if only magic or nothing is left - under normal code
1771 * we don't attack with pure magic if there is another attacktype.
1772 * Only do processing if the initial attacktype includes one of those
1773 * attack so we don't cancel out things like magic bullet.
1774 */
1775 if (type & (AT_PARALYZE | AT_SLOW))
1776 {
1777 type &= ~(AT_PARALYZE | AT_SLOW);
1778
1779 if (!type || type == AT_MAGIC)
1647 return 0; 1780 return 0;
1781 }
1782 }
1648 1783
1649#ifdef PROHIBIT_PLAYERKILL 1784 if (!simple_attack && op->type == DOOR)
1650 if (op->type == PLAYER) { 1785 {
1651 object *owner = get_owner (hitter); 1786 object *tmp;
1652 if (!owner) owner = hitter; 1787
1653 if (owner->type == PLAYER 1788 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1654 && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) 1789 if (tmp->type == RUNE || tmp->type == TRAP)
1655 && op != owner) { 1790 {
1791 spring_trap (tmp, hitter);
1792 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
1656 return 0; 1793 return 0;
1794 break;
1657 } 1795 }
1796 }
1797
1798 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0)
1658 } 1799 {
1800 /* FIXME: If a player is killed by a rune in a door, the
1801 * destroyed() check above doesn't return, and might get here.
1802 */
1803 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name);
1804 return 0;
1805 }
1806
1807#ifdef ATTACK_DEBUG
1808 LOG (llevDebug, "hit player: attacktype %d, dam %d\n", type, dam);
1659#endif 1809#endif
1660 1810
1661 op_tag = op->count;
1662 hitter_tag = hitter->count;
1663
1664 if (body_attack) {
1665 /* slow and paralyze must hit the head. But we don't want to just
1666 * return - we still need to process other attacks the spell still
1667 * might have. So just remove the paralyze and slow attacktypes,
1668 * and keep on processing if we have other attacktypes.
1669 * return if only magic or nothing is left - under normal code
1670 * we don't attack with pure magic if there is another attacktype.
1671 * Only do processing if the initial attacktype includes one of those
1672 * attack so we don't cancel out things like magic bullet.
1673 */
1674 if (type & (AT_PARALYZE | AT_SLOW)) {
1675 type &= ~(AT_PARALYZE | AT_SLOW);
1676 if (!type || type==AT_MAGIC) return 0;
1677 }
1678 }
1679
1680 if ( ! simple_attack && op->type == DOOR) {
1681 object *tmp;
1682 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1683 if (tmp->type == RUNE || tmp->type == TRAP) {
1684 spring_trap (tmp, hitter);
1685 if (was_destroyed (hitter, hitter_tag)
1686 || was_destroyed (op, op_tag)
1687 || abort_attack (op, hitter, simple_attack))
1688 return 0;
1689 break;
1690 }
1691 }
1692
1693 if ( ! QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0) {
1694 /* FIXME: If a player is killed by a rune in a door, the
1695 * was_destroyed() check above doesn't return, and might get here.
1696 */
1697 LOG (llevDebug, "victim (arch %s, name %s) already dead in "
1698 "hit_player()\n", op->arch->name, op->name);
1699 return 0;
1700 }
1701
1702#ifdef ATTACK_DEBUG
1703 LOG(llevDebug,"hit player: attacktype %d, dam %d\n", type, dam);
1704#endif
1705
1706 if (magic) { 1811 if (magic)
1812 {
1707 /* basically: dam = dam*(100-op->resist[attacknum])/100; 1813 /* basically: dam = dam*(100-op->resist[attacknum])/100;
1708 * in case 0>dam>1, we try to "simulate" a float value-effect */ 1814 * in case 0>dam>1, we try to "simulate" a float value-effect */
1709 dam = dam*(100-op->resist[ATNR_MAGIC]); 1815 dam = dam * (100 - op->resist[ATNR_MAGIC]);
1710 if (dam >= 100) 1816 if (dam >= 100)
1711 dam /= 100; 1817 dam /= 100;
1712 else 1818 else
1713 dam = (dam > (rndm(0, 99))) ? 1 : 0; 1819 dam = (dam > (rndm (0, 99))) ? 1 : 0;
1714 } 1820 }
1715 1821
1716 /* AT_CHAOS here is a weapon or monster. Spells are handled by hit_map 1822 /* AT_CHAOS here is a weapon or monster. Spells are handled by hit_map
1717 * If the attacktype still has chaos, shuffle it, then clear the Chaos bit 1823 * If the attacktype still has chaos, shuffle it, then clear the Chaos bit
1718 */ 1824 */
1719 if(type & AT_CHAOS){ 1825 if (type & AT_CHAOS)
1826 {
1720 shuffle_attack(op,0); /*0 flag tells it to not change the face */ 1827 shuffle_attack (op, 0); /*0 flag tells it to not change the face */
1721 update_object(op,UP_OBJ_FACE); 1828 update_object (op, UP_OBJ_FACE);
1722 type &= ~AT_CHAOS; 1829 type &= ~AT_CHAOS;
1723 } 1830 }
1724 1831
1725 /* Holyword is really an attacktype modifier (like magic is). If 1832 /* Holyword is really an attacktype modifier (like magic is). If
1726 * holyword is part of an attacktype, then make sure the creature is 1833 * holyword is part of an attacktype, then make sure the creature is
1727 * a proper match, otherwise no damage. 1834 * a proper match, otherwise no damage.
1728 */ 1835 */
1729 if (type & AT_HOLYWORD) { 1836 if (type & AT_HOLYWORD)
1837 {
1730 object *god; 1838 object *god;
1839
1731 if ((!hitter->slaying || 1840 if ((!hitter->slaying ||
1732 (!(op->race && strstr(hitter->slaying,op->race)) && 1841 (!(op->race && strstr (hitter->slaying, op->race)) &&
1733 !(op->name && strstr(hitter->slaying,op->name)))) && 1842 !(op->name && strstr (hitter->slaying, op->name)))) &&
1734 (!QUERY_FLAG(op,FLAG_UNDEAD) || 1843 (!QUERY_FLAG (op, FLAG_UNDEAD) ||
1735 (hitter->title != NULL 1844 (hitter->title != NULL
1736 && (god = find_god(determine_god(hitter))) != NULL 1845 && (god = find_god (determine_god (hitter))) != NULL && god->race != NULL && strstr (god->race, undead_name) != NULL)))
1737 && god->race != NULL
1738 && strstr(god->race,undead_name) != NULL)))
1739 return 0; 1846 return 0;
1740 } 1847 }
1741 1848
1742 maxattacktype = type; /* initialize this to something */ 1849 maxattacktype = type; /* initialize this to something */
1743 for (attacknum=0; attacknum<NROFATTACKS; attacknum++, attacktype=1<<attacknum) { 1850 for (attacknum = 0; attacknum < NROFATTACKS; attacknum++, attacktype = 1 << attacknum)
1851 {
1744 /* Magic isn't really a true attack type - it gets combined with other 1852 /* Magic isn't really a true attack type - it gets combined with other
1745 * attack types. As such, skip it over. However, if magic is 1853 * attack types. As such, skip it over. However, if magic is
1746 * the only attacktype in the group, then still attack with it 1854 * the only attacktype in the group, then still attack with it
1747 */ 1855 */
1748 if ((attacktype==AT_MAGIC) && (type & ~AT_MAGIC)) continue; 1856 if ((attacktype == AT_MAGIC) && (type & ~AT_MAGIC))
1857 continue;
1749 1858
1750 /* Go through and hit the player with each attacktype, one by one. 1859 /* Go through and hit the player with each attacktype, one by one.
1751 * hit_player_attacktype only figures out the damage, doesn't inflict 1860 * hit_player_attacktype only figures out the damage, doesn't inflict
1752 * it. It will do the appropriate action for attacktypes with 1861 * it. It will do the appropriate action for attacktypes with
1753 * effects (slow, paralization, etc. 1862 * effects (slow, paralization, etc.
1754 */ 1863 */
1755 if (type & attacktype) { 1864 if (type & attacktype)
1865 {
1756 ndam=hit_player_attacktype(op,hitter,dam,attacknum,magic); 1866 ndam = hit_player_attacktype (op, hitter, dam, attacknum, magic);
1757 /* the >= causes us to prefer messages from special attacks, if 1867 /* the >= causes us to prefer messages from special attacks, if
1758 * the damage is equal. 1868 * the damage is equal.
1759 */ 1869 */
1760 if (ndam >= maxdam) { 1870 if (ndam >= maxdam)
1871 {
1761 maxdam = ndam; 1872 maxdam = ndam;
1762 maxattacktype = 1<<attacknum; 1873 maxattacktype = 1 << attacknum;
1874 }
1875 }
1763 } 1876 }
1764 } 1877
1765 }
1766
1767 /* if this is friendly fire then do a set % of damage only 1878 /* if this is friendly fire then do a set % of damage only
1768 * Note - put a check in to make sure this attack is actually 1879 * Note - put a check in to make sure this attack is actually
1769 * doing damage - otherwise, the +1 in the code below will make 1880 * doing damage - otherwise, the +1 in the code below will make
1770 * an attack do damage before when it otherwise didn't 1881 * an attack do damage before when it otherwise didn't
1771 */ 1882 */
1772 friendlyfire = friendly_fire(op, hitter); 1883 friendlyfire = friendly_fire (op, hitter);
1773 if (friendlyfire && maxdam){ 1884 if (friendlyfire && maxdam)
1885 {
1774 maxdam = ((dam * settings.set_friendly_fire) / 100); 1886 maxdam = ((dam * settings.set_friendly_fire) / 100);
1775#ifndef COZY_SERVER 1887#ifndef COZY_SERVER
1888 maxdam++;
1889#endif
1890
1891#ifdef ATTACK_DEBUG
1892 LOG (llevDebug, "Friendly fire (type:%d setting: %d%) did %d damage dropped to %d\n",
1893 friendlyfire, settings.set_friendly_fire, dam, maxdam);
1894#endif
1895 }
1896
1897 if (!full_hit)
1898 {
1899 archetype *at;
1900 int area;
1901 int remainder;
1902
1903 area = 0;
1904 for (at = op->arch; at != NULL; at = at->more)
1905 area++;
1906 assert (area > 0);
1907
1908 /* basically: maxdam /= area; we try to "simulate" a float
1909 value-effect */
1910 remainder = 100 * (maxdam % area) / area;
1911 maxdam /= area;
1912 if (RANDOM () % 100 < remainder)
1776 maxdam++; 1913 maxdam++;
1914 }
1915
1916#ifdef ATTACK_DEBUG
1917 LOG (llevDebug, "Attacktype %d did %d damage\n", type, maxdam);
1777#endif 1918#endif
1778
1779#ifdef ATTACK_DEBUG
1780 LOG(llevDebug,"Friendly fire (type:%d setting: %d%) did %d damage dropped to %d\n",
1781 friendlyfire, settings.set_friendly_fire, dam, maxdam);
1782#endif
1783 }
1784 1919
1785 if (!full_hit) {
1786 archetype *at;
1787 int area;
1788 int remainder;
1789
1790 area = 0;
1791 for(at = op->arch; at != NULL; at = at->more)
1792 area++;
1793 assert(area > 0);
1794
1795 /* basically: maxdam /= area; we try to "simulate" a float
1796 value-effect */
1797 remainder = 100*(maxdam%area)/area;
1798 maxdam /= area;
1799 if (RANDOM()%100 < remainder)
1800 maxdam++;
1801 }
1802
1803#ifdef ATTACK_DEBUG
1804 LOG(llevDebug,"Attacktype %d did %d damage\n", type, maxdam);
1805#endif
1806
1807 if(get_owner(hitter)) 1920 if (get_owner (hitter))
1808 op->enemy=hitter->owner; 1921 op->enemy = hitter->owner;
1809 else if (QUERY_FLAG(hitter,FLAG_ALIVE)) 1922 else if (QUERY_FLAG (hitter, FLAG_ALIVE))
1810 op->enemy=hitter; 1923 op->enemy = hitter;
1811 1924
1812 if(QUERY_FLAG(op,FLAG_UNAGGRESSIVE) && op->type != PLAYER) { 1925 if (QUERY_FLAG (op, FLAG_UNAGGRESSIVE) && op->type != PLAYER)
1926 {
1813 /* The unaggressives look after themselves 8) */ 1927 /* The unaggressives look after themselves 8) */
1814 CLEAR_FLAG(op, FLAG_UNAGGRESSIVE); 1928 CLEAR_FLAG (op, FLAG_UNAGGRESSIVE);
1815 npc_call_help(op); 1929 npc_call_help (op);
1816 } 1930 }
1817 1931
1818 if (magic && did_make_save(op, op->level, 0)) 1932 if (magic && did_make_save (op, op->level, 0))
1819 maxdam=maxdam/2; 1933 maxdam = maxdam / 2;
1820 1934
1821 attack_message(maxdam, maxattacktype, op, hitter); 1935 attack_message (maxdam, maxattacktype, op, hitter);
1822 1936
1823 op->stats.hp-=maxdam; 1937 op->stats.hp -= maxdam;
1824 1938
1825 /* Eneq(@csd.uu.se): Check to see if monster runs away. */ 1939 /* Eneq(@csd.uu.se): Check to see if monster runs away. */
1826 if ((op->stats.hp>=0) && 1940 if ((op->stats.hp >= 0) &&
1827 (QUERY_FLAG(op, FLAG_MONSTER) || op->type == PLAYER) && 1941 (QUERY_FLAG (op, FLAG_MONSTER) || op->type == PLAYER) &&
1828 op->stats.hp<(signed short)(((float)op->run_away/(float)100)* 1942 op->stats.hp < (signed short) (((float) op->run_away / (float) 100) * (float) op->stats.maxhp))
1829 (float)op->stats.maxhp)) { 1943 {
1830 1944
1831 if (QUERY_FLAG(op, FLAG_MONSTER)) 1945 if (QUERY_FLAG (op, FLAG_MONSTER))
1832 SET_FLAG(op, FLAG_RUN_AWAY); 1946 SET_FLAG (op, FLAG_RUN_AWAY);
1833 else 1947 else
1834 scare_creature(op, hitter); 1948 scare_creature (op, hitter);
1835 } 1949 }
1836 1950
1837 if(QUERY_FLAG(op,FLAG_TEAR_DOWN)) { 1951 if (QUERY_FLAG (op, FLAG_TEAR_DOWN))
1952 {
1838 if (maxdam) 1953 if (maxdam)
1839 tear_down_wall(op); 1954 tear_down_wall (op);
1840 return maxdam; /* nothing more to do for wall */ 1955 return maxdam; /* nothing more to do for wall */
1841 } 1956 }
1842 1957
1843 /* See if the creature has been killed */ 1958 /* See if the creature has been killed */
1844 rtn_kill = kill_object(op, maxdam, hitter, type); 1959 rtn_kill = kill_object (op, maxdam, hitter, type);
1845 if (rtn_kill != -1) 1960 if (rtn_kill != -1)
1846 return rtn_kill; 1961 return rtn_kill;
1847 1962
1848 1963
1849 /* Used to be ghosthit removal - we now use the ONE_HIT flag. Note 1964 /* Used to be ghosthit removal - we now use the ONE_HIT flag. Note
1850 * that before if the player was immune to ghosthit, the monster 1965 * that before if the player was immune to ghosthit, the monster
1851 * remained - that is no longer the case. 1966 * remained - that is no longer the case.
1852 */ 1967 */
1853 if(QUERY_FLAG(hitter, FLAG_ONE_HIT)) { 1968 if (QUERY_FLAG (hitter, FLAG_ONE_HIT))
1969 {
1854 if(QUERY_FLAG(hitter,FLAG_FRIENDLY)) 1970 if (QUERY_FLAG (hitter, FLAG_FRIENDLY))
1855 remove_friendly_object(hitter); 1971 remove_friendly_object (hitter);
1856 remove_ob(hitter); 1972 remove_ob (hitter);
1857 free_object(hitter); 1973 free_object (hitter);
1858 } 1974 }
1859 /* Lets handle creatures that are splitting now */ 1975 /* Lets handle creatures that are splitting now */
1860 else if(type&AT_PHYSICAL&&!QUERY_FLAG(op, FLAG_FREED)&&QUERY_FLAG(op,FLAG_SPLITTING)) { 1976 else if (type & AT_PHYSICAL && !QUERY_FLAG (op, FLAG_FREED) && QUERY_FLAG (op, FLAG_SPLITTING))
1861 int i; 1977 {
1978 int i;
1862 int friendly = QUERY_FLAG(op,FLAG_FRIENDLY); 1979 int friendly = QUERY_FLAG (op, FLAG_FRIENDLY);
1863 int unaggressive = QUERY_FLAG(op, FLAG_UNAGGRESSIVE); 1980 int unaggressive = QUERY_FLAG (op, FLAG_UNAGGRESSIVE);
1864 object *owner = get_owner(op); 1981 object *owner = get_owner (op);
1865 1982
1866 if(!op->other_arch) { 1983 if (!op->other_arch)
1984 {
1867 LOG(llevError,"SPLITTING without other_arch error.\n"); 1985 LOG (llevError, "SPLITTING without other_arch error.\n");
1868 return maxdam; 1986 return maxdam;
1869 } 1987 }
1870 remove_ob(op); 1988 remove_ob (op);
1871 for(i=0;i<NROFNEWOBJS(op);i++) { /* This doesn't handle op->more yet */ 1989 for (i = 0; i < NROFNEWOBJS (op); i++)
1990 { /* This doesn't handle op->more yet */
1872 object *tmp=arch_to_object(op->other_arch); 1991 object *tmp = arch_to_object (op->other_arch);
1873 int j; 1992 int j;
1874 1993
1875 tmp->stats.hp=op->stats.hp; 1994 tmp->stats.hp = op->stats.hp;
1876 if (friendly) { 1995 if (friendly)
1996 {
1877 SET_FLAG(tmp, FLAG_FRIENDLY); 1997 SET_FLAG (tmp, FLAG_FRIENDLY);
1878 add_friendly_object(tmp); 1998 add_friendly_object (tmp);
1879 tmp->attack_movement = PETMOVE; 1999 tmp->attack_movement = PETMOVE;
1880 if (owner!=NULL) 2000 if (owner != NULL)
1881 set_owner(tmp,owner); 2001 set_owner (tmp, owner);
1882 } 2002 }
1883 if (unaggressive) 2003 if (unaggressive)
1884 SET_FLAG(tmp, FLAG_UNAGGRESSIVE); 2004 SET_FLAG (tmp, FLAG_UNAGGRESSIVE);
1885 j=find_first_free_spot(tmp,op->map,op->x,op->y); 2005 j = find_first_free_spot (tmp, op->map, op->x, op->y);
1886 if (j==-1) /* No spot to put this monster */ 2006 if (j == -1) /* No spot to put this monster */
1887 free_object(tmp); 2007 free_object (tmp);
1888 else { 2008 else
2009 {
1889 tmp->x=op->x+freearr_x[j],tmp->y=op->y+freearr_y[j]; 2010 tmp->x = op->x + freearr_x[j], tmp->y = op->y + freearr_y[j];
1890 insert_ob_in_map(tmp,op->map,NULL,0); 2011 insert_ob_in_map (tmp, op->map, NULL, 0);
1891 } 2012 }
1892 } 2013 }
1893 if(friendly) 2014 if (friendly)
1894 remove_friendly_object(op); 2015 remove_friendly_object (op);
1895 free_object(op); 2016 free_object (op);
1896 } 2017 }
1897 else if(type & AT_DRAIN && hitter->type==GRIMREAPER&&hitter->value++>10) { 2018 else if (type & AT_DRAIN && hitter->type == GRIMREAPER && hitter->value++ > 10)
2019 {
1898 remove_ob(hitter); 2020 remove_ob (hitter);
1899 free_object(hitter); 2021 free_object (hitter);
1900 } 2022 }
1901 return maxdam; 2023 return maxdam;
1902} 2024}
1903 2025
1904 2026
2027void
1905void poison_player(object *op, object *hitter, int dam) 2028poison_player (object *op, object *hitter, int dam)
1906{ 2029{
1907 archetype *at = find_archetype("poisoning"); 2030 archetype *at = archetype::find ("poisoning");
1908 object *tmp=present_arch_in_ob(at,op); 2031 object *tmp = present_arch_in_ob (at, op);
1909 2032
1910 if(tmp==NULL) { 2033 if (tmp == NULL)
2034 {
1911 if((tmp=arch_to_object(at))==NULL) 2035 if ((tmp = arch_to_object (at)) == NULL)
1912 LOG(llevError,"Failed to clone arch poisoning.\n"); 2036 LOG (llevError, "Failed to clone arch poisoning.\n");
1913 else { 2037 else
2038 {
1914 tmp = insert_ob_in_ob(tmp,op); 2039 tmp = insert_ob_in_ob (tmp, op);
1915 /* peterm: give poisoning some teeth. It should 2040 /* peterm: give poisoning some teeth. It should
1916 * be able to kill things better than it does: 2041 * be able to kill things better than it does:
1917 * damage should be dependent something--I choose to 2042 * damage should be dependent something--I choose to
1918 * do this: if it's a monster, the damage from the 2043 * do this: if it's a monster, the damage from the
1919 * poisoning goes as the level of the monster/2. 2044 * poisoning goes as the level of the monster/2.
1920 * If anything else, goes as damage. 2045 * If anything else, goes as damage.
1921 */ 2046 */
1922 2047
1923 if(QUERY_FLAG(hitter,FLAG_ALIVE)) 2048 if (QUERY_FLAG (hitter, FLAG_ALIVE))
1924 tmp->stats.dam += hitter->level/2; 2049 tmp->stats.dam += hitter->level / 2;
1925 else 2050 else
1926 tmp->stats.dam = dam; 2051 tmp->stats.dam = dam;
1927 2052
1928 copy_owner(tmp,hitter); /* so we get credit for poisoning kills */ 2053 copy_owner (tmp, hitter); /* so we get credit for poisoning kills */
1929 if(hitter->skill && hitter->skill != tmp->skill) { 2054 if (hitter->skill && hitter->skill != tmp->skill)
1930 if (tmp->skill) free_string(tmp->skill); 2055 {
1931 tmp->skill = add_refcount(hitter->skill); 2056 tmp->skill = hitter->skill;
1932 } 2057 }
1933 2058
1934 tmp->stats.food+=dam; /* more damage, longer poisoning */ 2059 tmp->stats.food += dam; /* more damage, longer poisoning */
1935 2060
1936 if(op->type==PLAYER) { 2061 if (op->type == PLAYER)
2062 {
1937 /* player looses stats, maximum is -10 of each */ 2063 /* player looses stats, maximum is -10 of each */
1938 tmp->stats.Con= MAX(-(dam/4+1), -10); 2064 tmp->stats.Con = MAX (-(dam / 4 + 1), -10);
1939 tmp->stats.Str= MAX(-(dam/3+2), -10); 2065 tmp->stats.Str = MAX (-(dam / 3 + 2), -10);
1940 tmp->stats.Dex= MAX(-(dam/6+1), -10); 2066 tmp->stats.Dex = MAX (-(dam / 6 + 1), -10);
1941 tmp->stats.Int= MAX(-dam/7, -10); 2067 tmp->stats.Int = MAX (-dam / 7, -10);
1942 SET_FLAG(tmp,FLAG_APPLIED); 2068 SET_FLAG (tmp, FLAG_APPLIED);
1943 fix_player(op); 2069 fix_player (op);
1944 new_draw_info(NDI_UNIQUE, 0,op,"You suddenly feel very ill."); 2070 new_draw_info (NDI_UNIQUE, 0, op, "You suddenly feel very ill.");
1945 } 2071 }
1946 if (hitter->type == PLAYER) 2072 if (hitter->type == PLAYER)
1947 new_draw_info_format(NDI_UNIQUE, 0, hitter, "You poison %s.", 2073 new_draw_info_format (NDI_UNIQUE, 0, hitter, "You poison %s.", &op->name);
1948 op->name);
1949 else if (get_owner(hitter) != NULL && hitter->owner->type == PLAYER) 2074 else if (get_owner (hitter) != NULL && hitter->owner->type == PLAYER)
1950 new_draw_info_format(NDI_UNIQUE, 0, hitter->owner, 2075 new_draw_info_format (NDI_UNIQUE, 0, hitter->owner, "Your %s poisons %s.", &hitter->name, &op->name);
1951 "Your %s poisons %s.", hitter->name, op->name); 2076 }
1952 }
1953 tmp->speed_left=0; 2077 tmp->speed_left = 0;
1954 } 2078 }
1955 else 2079 else
1956 tmp->stats.food++; 2080 tmp->stats.food++;
1957} 2081}
1958 2082
2083void
1959void slow_player(object *op,object *hitter,int dam) 2084slow_player (object *op, object *hitter, int dam)
2085{
1960{ archetype *at = find_archetype("slowness"); 2086 archetype *at = archetype::find ("slowness");
1961 object *tmp; 2087 object *tmp;
2088
1962 if(at == NULL) { 2089 if (at == NULL)
2090 {
1963 LOG(llevError,"Can't find slowness archetype.\n"); 2091 LOG (llevError, "Can't find slowness archetype.\n");
1964 } 2092 }
1965 if((tmp=present_arch_in_ob(at,op)) == NULL) { 2093 if ((tmp = present_arch_in_ob (at, op)) == NULL)
2094 {
1966 tmp = arch_to_object(at); 2095 tmp = arch_to_object (at);
1967 tmp = insert_ob_in_ob(tmp,op); 2096 tmp = insert_ob_in_ob (tmp, op);
1968 new_draw_info(NDI_UNIQUE, 0,op,"The world suddenly moves very fast!"); 2097 new_draw_info (NDI_UNIQUE, 0, op, "The world suddenly moves very fast!");
2098 }
1969 } else 2099 else
1970 tmp->stats.food++; 2100 tmp->stats.food++;
1971 SET_FLAG(tmp, FLAG_APPLIED); 2101 SET_FLAG (tmp, FLAG_APPLIED);
1972 tmp->speed_left=0; 2102 tmp->speed_left = 0;
1973 fix_player(op); 2103 fix_player (op);
1974} 2104}
1975 2105
2106void
1976void confuse_player(object *op, object *hitter, int dam) 2107confuse_player (object *op, object *hitter, int dam)
1977{ 2108{
1978 object *tmp; 2109 object *tmp;
1979 int maxduration; 2110 int maxduration;
1980 2111
1981 tmp = present_in_ob_by_name(FORCE,"confusion", op); 2112 tmp = present_in_ob_by_name (FORCE, "confusion", op);
1982 if(!tmp) { 2113 if (!tmp)
1983 tmp = get_archetype(FORCE_NAME);
1984 tmp = insert_ob_in_ob(tmp,op);
1985 }
1986 2114 {
2115 tmp = get_archetype (FORCE_NAME);
2116 tmp = insert_ob_in_ob (tmp, op);
2117 }
2118
1987 /* Duration added per hit and max. duration of confusion both depend 2119 /* Duration added per hit and max. duration of confusion both depend
1988 * on the player's resistance 2120 * on the player's resistance
1989 */ 2121 */
1990 tmp->speed = 0.05; 2122 tmp->speed = 0.05;
1991 tmp->subtype = FORCE_CONFUSION; 2123 tmp->subtype = FORCE_CONFUSION;
1992 tmp->duration = 8 + MAX(1, 5*(100-op->resist[ATNR_CONFUSION])/100); 2124 tmp->duration = 8 + MAX (1, 5 * (100 - op->resist[ATNR_CONFUSION]) / 100);
1993 if (tmp->name) free_string(tmp->name);
1994 tmp->name = add_string("confusion"); 2125 tmp->name = "confusion";
1995 maxduration = MAX(2, 30*(100-op->resist[ATNR_CONFUSION])/100); 2126 maxduration = MAX (2, 30 * (100 - op->resist[ATNR_CONFUSION]) / 100);
1996 if( tmp->duration > maxduration) 2127 if (tmp->duration > maxduration)
1997 tmp->duration = maxduration; 2128 tmp->duration = maxduration;
1998 2129
1999 if(op->type == PLAYER && !QUERY_FLAG(op,FLAG_CONFUSED)) 2130 if (op->type == PLAYER && !QUERY_FLAG (op, FLAG_CONFUSED))
2000 new_draw_info(NDI_UNIQUE, 0,op,"You suddenly feel very confused!"); 2131 new_draw_info (NDI_UNIQUE, 0, op, "You suddenly feel very confused!");
2001 SET_FLAG(op, FLAG_CONFUSED); 2132 SET_FLAG (op, FLAG_CONFUSED);
2002} 2133}
2003 2134
2135void
2004void blind_player(object *op, object *hitter, int dam) 2136blind_player (object *op, object *hitter, int dam)
2005{ 2137{
2006 object *tmp,*owner; 2138 object *tmp, *owner;
2007 2139
2008 /* Save some work if we know it isn't going to affect the player */ 2140 /* Save some work if we know it isn't going to affect the player */
2009 if (op->resist[ATNR_BLIND]==100) return; 2141 if (op->resist[ATNR_BLIND] == 100)
2142 return;
2010 2143
2011 tmp = present_in_ob(BLINDNESS,op); 2144 tmp = present_in_ob (BLINDNESS, op);
2012 if(!tmp) { 2145 if (!tmp)
2146 {
2013 tmp = get_archetype("blindness"); 2147 tmp = get_archetype ("blindness");
2014 SET_FLAG(tmp, FLAG_BLIND); 2148 SET_FLAG (tmp, FLAG_BLIND);
2015 SET_FLAG(tmp, FLAG_APPLIED); 2149 SET_FLAG (tmp, FLAG_APPLIED);
2016 /* use floats so we don't lose too much precision due to rounding errors. 2150 /* use floats so we don't lose too much precision due to rounding errors.
2017 * speed is a float anyways. 2151 * speed is a float anyways.
2018 */ 2152 */
2019 tmp->speed = tmp->speed * (100.0 - (float)op->resist[ATNR_BLIND]) / 100; 2153 tmp->speed = tmp->speed * (100.0 - (float) op->resist[ATNR_BLIND]) / 100;
2020 2154
2021 tmp = insert_ob_in_ob(tmp,op); 2155 tmp = insert_ob_in_ob (tmp, op);
2022 change_abil(op,tmp); /* Mostly to display any messages */ 2156 change_abil (op, tmp); /* Mostly to display any messages */
2023 fix_player(op); /* This takes care of some other stuff */ 2157 fix_player (op); /* This takes care of some other stuff */
2024 2158
2159 if (hitter->owner)
2025 if(hitter->owner) owner = get_owner(hitter); 2160 owner = get_owner (hitter);
2161 else
2026 else owner = hitter; 2162 owner = hitter;
2027 2163
2028 new_draw_info_format(NDI_UNIQUE,0,owner, 2164 new_draw_info_format (NDI_UNIQUE, 0, owner, "Your attack blinds %s!", query_name (op));
2029 "Your attack blinds %s!",query_name(op));
2030 } 2165 }
2031 tmp->stats.food += dam; 2166 tmp->stats.food += dam;
2032 if(tmp->stats.food > 10) tmp->stats.food = 10; 2167 if (tmp->stats.food > 10)
2168 tmp->stats.food = 10;
2033} 2169}
2034 2170
2171void
2035void paralyze_player(object *op, object *hitter, int dam) 2172paralyze_player (object *op, object *hitter, int dam)
2036{ 2173{
2037 float effect,max; 2174 float effect, max;
2175
2038 /* object *tmp; */ 2176 /* object *tmp; */
2039 2177
2040 /* This is strange stuff... someone knows for what this is 2178 /* This is strange stuff... someone knows for what this is
2041 * written? Well, i think this can and should be removed 2179 * written? Well, i think this can and should be removed
2042 */ 2180 */
2043 2181
2044 /* 2182 /*
2045 if((tmp=present(PARAIMAGE,op->map,op->x,op->y))==NULL) { 2183 if((tmp=present(PARAIMAGE,op->map,op->x,op->y))==NULL) {
2046 tmp=clone_arch(PARAIMAGE); 2184 tmp=clone_arch(PARAIMAGE);
2047 tmp->x=op->x,tmp->y=op->y; 2185 tmp->x=op->x,tmp->y=op->y;
2048 insert_ob_in_map(tmp,op->map,tmp,INS_NO_MERGE | INS_NO_WALK_ON); 2186 insert_ob_in_map(tmp,op->map,tmp,INS_NO_MERGE | INS_NO_WALK_ON);
2049 } 2187 }
2050 */ 2188 */
2051 2189
2052 /* Do this as a float - otherwise, rounding might very well reduce this to 0 */ 2190 /* Do this as a float - otherwise, rounding might very well reduce this to 0 */
2053 effect = (float)dam * 3.0 * (100.0 - op->resist[ATNR_PARALYZE]) / 100; 2191 effect = (float) dam *3.0 * (100.0 - op->resist[ATNR_PARALYZE]) / 100;
2054 2192
2055 if (effect==0) return; 2193 if (effect == 0)
2194 return;
2056 2195
2057 op->speed_left-=FABS(op->speed)*effect; 2196 op->speed_left -= FABS (op->speed) * effect;
2058 /* tmp->stats.food+=(signed short) effect/op->speed; */ 2197 /* tmp->stats.food+=(signed short) effect/op->speed; */
2059 2198
2060 /* max number of ticks to be affected for. */ 2199 /* max number of ticks to be affected for. */
2061 max = (100 - op->resist[ATNR_PARALYZE])/ 2; 2200 max = (100 - op->resist[ATNR_PARALYZE]) / 2;
2062 if (op->speed_left< -(FABS(op->speed)*max)) 2201 if (op->speed_left < -(FABS (op->speed) * max))
2063 op->speed_left = (float) -(FABS(op->speed)*max); 2202 op->speed_left = (float) -(FABS (op->speed) * max);
2064 2203
2065/* tmp->stats.food = (signed short) (max/FABS(op->speed)); */ 2204/* tmp->stats.food = (signed short) (max/FABS(op->speed)); */
2066} 2205}
2067 2206
2068 2207
2069/* Attempts to kill 'op'. hitter is the attack object, dam is 2208/* Attempts to kill 'op'. hitter is the attack object, dam is
2070 * the computed damaged. 2209 * the computed damaged.
2071 */ 2210 */
2211void
2072void deathstrike_player(object *op, object *hitter, int *dam) 2212deathstrike_player (object *op, object *hitter, int *dam)
2073{ 2213{
2074 /* The intention of a death attack is to kill outright things 2214 /* The intention of a death attack is to kill outright things
2075 ** that are a lot weaker than the attacker, have a chance of killing 2215 ** that are a lot weaker than the attacker, have a chance of killing
2076 ** things somewhat weaker than the caster, and no chance of 2216 ** things somewhat weaker than the caster, and no chance of
2077 ** killing something equal or stronger than the attacker. 2217 ** killing something equal or stronger than the attacker.
2078 ** Also, if a deathstrike attack has a slaying, any monster 2218 ** Also, if a deathstrike attack has a slaying, any monster
2079 ** whose name or race matches a comma-delimited list in the slaying 2219 ** whose name or race matches a comma-delimited list in the slaying
2080 ** field of the deathstriking object */ 2220 ** field of the deathstriking object */
2081 2221
2082 int atk_lev, def_lev, kill_lev; 2222 int atk_lev, def_lev, kill_lev;
2083 2223
2084 if(hitter->slaying) 2224 if (hitter->slaying)
2085 if(!( (QUERY_FLAG(op,FLAG_UNDEAD)&&strstr(hitter->slaying,undead_name)) || 2225 if (!((QUERY_FLAG (op, FLAG_UNDEAD) && strstr (hitter->slaying, undead_name)) || (op->race && strstr (hitter->slaying, op->race))))
2086 (op->race&&strstr(hitter->slaying,op->race)))) return; 2226 return;
2087 2227
2088 def_lev = op->level; 2228 def_lev = op->level;
2089 if (def_lev < 1) { 2229 if (def_lev < 1)
2230 {
2090 LOG (llevError, "BUG: arch %s, name %s with level < 1\n", 2231 LOG (llevError, "BUG: arch %s, name %s with level < 1\n", &op->arch->name, &op->name);
2091 op->arch->name, op->name);
2092 def_lev = 1; 2232 def_lev = 1;
2093 } 2233 }
2094 atk_lev = (hitter->chosen_skill?hitter->chosen_skill->level:hitter->level) / 2; 2234 atk_lev = (hitter->chosen_skill ? hitter->chosen_skill->level : hitter->level) / 2;
2095 /* LOG(llevDebug,"Deathstrike - attack level %d, defender level %d\n", 2235 /* LOG(llevDebug,"Deathstrike - attack level %d, defender level %d\n",
2096 atk_lev, def_lev); */ 2236 atk_lev, def_lev); */
2097 2237
2098 if(atk_lev >= def_lev ){ 2238 if (atk_lev >= def_lev)
2239 {
2099 kill_lev = random_roll(0, atk_lev-1, hitter, PREFER_HIGH); 2240 kill_lev = random_roll (0, atk_lev - 1, hitter, PREFER_HIGH);
2100 2241
2101 /* Note that the below effectively means the ratio of the atk vs 2242 /* Note that the below effectively means the ratio of the atk vs
2102 * defener level is important - if level 52 character has very little 2243 * defener level is important - if level 52 character has very little
2103 * chance of killing a level 50 monster. This should probably be 2244 * chance of killing a level 50 monster. This should probably be
2104 * redone. 2245 * redone.
2105 */ 2246 */
2106 if(kill_lev >= def_lev) { 2247 if (kill_lev >= def_lev)
2248 {
2107 *dam = op->stats.hp+10; /* take all hp. they can still save for 1/2 */ 2249 *dam = op->stats.hp + 10; /* take all hp. they can still save for 1/2 */
2108 /* I think this doesn't really do much. Because of 2250 /* I think this doesn't really do much. Because of
2109 * integer rounding, this only makes any difference if the 2251 * integer rounding, this only makes any difference if the
2110 * attack level is double the defender level. 2252 * attack level is double the defender level.
2111 */ 2253 */
2112 *dam *= kill_lev / def_lev; 2254 *dam *= kill_lev / def_lev;
2113 } 2255 }
2114 } else { 2256 }
2257 else
2258 {
2115 *dam = 0; /* no harm done */ 2259 *dam = 0; /* no harm done */
2116 } 2260 }
2117} 2261}
2118 2262
2119/* thrown_item_effect() - handles any special effects of thrown 2263/* thrown_item_effect() - handles any special effects of thrown
2120 * items (like attacking living creatures--a potion thrown at a 2264 * items (like attacking living creatures--a potion thrown at a
2121 * monster). 2265 * monster).
2122 */ 2266 */
2267static void
2123static void thrown_item_effect (object *hitter, object *victim) 2268thrown_item_effect (object *hitter, object *victim)
2124{ 2269{
2125 if(!QUERY_FLAG(hitter,FLAG_ALIVE)) { 2270 if (!QUERY_FLAG (hitter, FLAG_ALIVE))
2271 {
2126 /* May not need a switch for just 2 types, but this makes it 2272 /* May not need a switch for just 2 types, but this makes it
2127 * easier for expansion. 2273 * easier for expansion.
2128 */ 2274 */
2129 switch (hitter->type) { 2275 switch (hitter->type)
2276 {
2130 case POTION: 2277 case POTION:
2131 /* should player get a save throw instead of checking magic protection? */ 2278 /* should player get a save throw instead of checking magic protection? */
2132 if(QUERY_FLAG(victim,FLAG_ALIVE)&&!QUERY_FLAG(victim,FLAG_UNDEAD) 2279 if (QUERY_FLAG (victim, FLAG_ALIVE) && !QUERY_FLAG (victim, FLAG_UNDEAD) && (victim->resist[ATNR_MAGIC] < 60))
2133 &&(victim->resist[ATNR_MAGIC]<60)) (void) apply_potion(victim,hitter); 2280 (void) apply_potion (victim, hitter);
2134 break; 2281 break;
2135 2282
2136 case POISON: /* poison drinks */ 2283 case POISON: /* poison drinks */
2137 /* As with potions, should monster get a save? */ 2284 /* As with potions, should monster get a save? */
2138 if(QUERY_FLAG(victim,FLAG_ALIVE)&&!QUERY_FLAG(victim,FLAG_UNDEAD) 2285 if (QUERY_FLAG (victim, FLAG_ALIVE) && !QUERY_FLAG (victim, FLAG_UNDEAD) && (victim->resist[ATNR_POISON] < 60))
2139 &&(victim->resist[ATNR_POISON]<60)) apply_poison(victim,hitter); 2286 apply_poison (victim, hitter);
2140 break; 2287 break;
2141 2288
2142 /* Removed case statements that did nothing. 2289 /* Removed case statements that did nothing.
2143 * food may be poisonous, but monster must be willing to eat it, 2290 * food may be poisonous, but monster must be willing to eat it,
2144 * so we don't handle it here. 2291 * so we don't handle it here.
2145 * Containers should perhaps break open, but that code was disabled. 2292 * Containers should perhaps break open, but that code was disabled.
2146 */ 2293 */
2147 } 2294 }
2148 } 2295 }
2149} 2296}
2150 2297
2151/* adj_attackroll() - adjustments to attacks by various conditions */ 2298/* adj_attackroll() - adjustments to attacks by various conditions */
2152 2299
2300int
2153int adj_attackroll (object *hitter, object *target) { 2301adj_attackroll (object *hitter, object *target)
2302{
2154 object *attacker = hitter; 2303 object *attacker = hitter;
2155 int adjust=0; 2304 int adjust = 0;
2156 2305
2157 /* safety */ 2306 /* safety */
2158 if(!target||!hitter||!hitter->map||!target->map||!on_same_map(hitter,target)) { 2307 if (!target || !hitter || !hitter->map || !target->map || !on_same_map (hitter, target))
2308 {
2159 LOG (llevError, "BUG: adj_attackroll(): hitter and target not on same " 2309 LOG (llevError, "BUG: adj_attackroll(): hitter and target not on same " "map\n");
2160 "map\n"); 2310 return 0;
2311 }
2312
2313 /* aimed missiles use the owning object's sight */
2314 if (is_aimed_missile (hitter))
2315 {
2316 if ((attacker = get_owner (hitter)) == NULL)
2317 attacker = hitter;
2318 /* A player who saves but hasn't quit still could have objects
2319 * owned by him - need to handle that case to avoid crashes.
2320 */
2321 if (QUERY_FLAG (attacker, FLAG_REMOVED))
2322 attacker = hitter;
2323 }
2324 else if (!QUERY_FLAG (hitter, FLAG_ALIVE))
2161 return 0; 2325 return 0;
2162 }
2163 2326
2164 /* aimed missiles use the owning object's sight */
2165 if(is_aimed_missile(hitter)) {
2166 if ((attacker = get_owner(hitter))==NULL) attacker = hitter;
2167 /* A player who saves but hasn't quit still could have objects
2168 * owned by him - need to handle that case to avoid crashes.
2169 */
2170 if (QUERY_FLAG(attacker, FLAG_REMOVED)) attacker = hitter;
2171 }
2172 else if(!QUERY_FLAG(hitter,FLAG_ALIVE))
2173 return 0;
2174
2175 /* determine the condtions under which we make an attack. 2327 /* determine the condtions under which we make an attack.
2176 * Add more cases, as the need occurs. */ 2328 * Add more cases, as the need occurs. */
2177 2329
2178 if(!can_see_enemy(attacker,target)) { 2330 if (!can_see_enemy (attacker, target))
2331 {
2179 /* target is unseen */ 2332 /* target is unseen */
2180 if(target->invisible || QUERY_FLAG(attacker,FLAG_BLIND)) 2333 if (target->invisible || QUERY_FLAG (attacker, FLAG_BLIND))
2181 adjust -= 10; 2334 adjust -= 10;
2182 /* dark map penalty for the hitter (lacks infravision if we got here). */ 2335 /* dark map penalty for the hitter (lacks infravision if we got here). */
2183 else if(target->map&&target->map->darkness>0&&!stand_in_light(target)) 2336 else if (target->map && target->map->darkness > 0 && !stand_in_light (target))
2184 adjust -= target->map->darkness; 2337 adjust -= target->map->darkness;
2185 } 2338 }
2186 2339
2187 if(QUERY_FLAG(attacker,FLAG_SCARED)) 2340 if (QUERY_FLAG (attacker, FLAG_SCARED))
2188 adjust -= 3; 2341 adjust -= 3;
2189 2342
2190 if(QUERY_FLAG(target,FLAG_UNAGGRESSIVE)) 2343 if (QUERY_FLAG (target, FLAG_UNAGGRESSIVE))
2191 adjust += 1; 2344 adjust += 1;
2192 2345
2193 if(QUERY_FLAG(target,FLAG_SCARED)) 2346 if (QUERY_FLAG (target, FLAG_SCARED))
2194 adjust += 1; 2347 adjust += 1;
2195 2348
2196 if(QUERY_FLAG(attacker,FLAG_CONFUSED)) 2349 if (QUERY_FLAG (attacker, FLAG_CONFUSED))
2197 adjust -= 3; 2350 adjust -= 3;
2198 2351
2199 /* if we attack at a different 'altitude' its harder */ 2352 /* if we attack at a different 'altitude' its harder */
2200 if((attacker->move_type & target->move_type)==0) 2353 if ((attacker->move_type & target->move_type) == 0)
2201 adjust -= 2; 2354 adjust -= 2;
2202 2355
2203#if 0 2356#if 0
2204 /* slower attacks are less likely to succeed. We should use a 2357 /* slower attacks are less likely to succeed. We should use a
2205 * comparison between attacker/target speeds BUT, players have 2358 * comparison between attacker/target speeds BUT, players have
2206 * a generally faster speed, so this will wind up being a HUGE 2359 * a generally faster speed, so this will wind up being a HUGE
2207 * disadantage for the monsters! Too bad, because missiles which 2360 * disadantage for the monsters! Too bad, because missiles which
2208 * fly fast should have a better chance of hitting a slower target. 2361 * fly fast should have a better chance of hitting a slower target.
2209 */ 2362 */
2210 if(hitter->speed<target->speed) 2363 if (hitter->speed < target->speed)
2211 adjust += ((float) hitter->speed-target->speed); 2364 adjust += ((float) hitter->speed - target->speed);
2212#endif 2365#endif
2213 2366
2214#if 0 2367#if 0
2215 LOG(llevDebug,"adj_attackroll() returns %d (%d)\n",adjust,attacker->count); 2368 LOG (llevDebug, "adj_attackroll() returns %d (%d)\n", adjust, attacker->count);
2216#endif 2369#endif
2217 2370
2218 return adjust; 2371 return adjust;
2219} 2372}
2220 2373
2221 2374
2222/* determine if the object is an 'aimed' missile */ 2375/* determine if the object is an 'aimed' missile */
2376int
2223int is_aimed_missile ( object *op) { 2377is_aimed_missile (object *op)
2378{
2224 2379
2225 /* I broke what used to be one big if into a few nested 2380 /* I broke what used to be one big if into a few nested
2226 * ones so that figuring out the logic is at least possible. 2381 * ones so that figuring out the logic is at least possible.
2227 */ 2382 */
2228 if (op && (op->move_type & MOVE_FLYING)) { 2383 if (op && (op->move_type & MOVE_FLYING))
2384 {
2229 if (op->type==ARROW || op->type==THROWN_OBJ) 2385 if (op->type == ARROW || op->type == THROWN_OBJ)
2230 return 1; 2386 return 1;
2231 else if (op->type==SPELL_EFFECT && (op->subtype == SP_BULLET || 2387 else if (op->type == SPELL_EFFECT && (op->subtype == SP_BULLET || op->subtype == SP_EXPLOSION))
2232 op->subtype == SP_EXPLOSION))
2233 return 1; 2388 return 1;
2234 } 2389 }
2235 return 0; 2390 return 0;
2236} 2391}
2237

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines