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.10 by root, Mon Sep 11 11:46:52 2006 UTC vs.
Revision 1.37 by root, Fri Jan 5 22:47:18 2007 UTC

1
2/*
3 * static char *rcsid_attack_c =
4 * "$Id: attack.C,v 1.10 2006/09/11 11:46:52 root Exp $";
5 */
6
7/* 1/*
8 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
9 3
10 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
22 16
23 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
24 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 20
27 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>
28*/ 22*/
29#include <assert.h> 23#include <assert.h>
30#include <global.h> 24#include <global.h>
31#include <living.h> 25#include <living.h>
32#include <material.h> 26#include <material.h>
78 esrv_send_item (op->env, op); 72 esrv_send_item (op->env, op);
79 } 73 }
80 } 74 }
81} 75}
82 76
83
84
85/* did_make_save_item just checks to make sure the item actually 77/* did_make_save_item just checks to make sure the item actually
86 * made its saving throw based on the tables. It does not take 78 * made its saving throw based on the tables. It does not take
87 * any further action (like destroying the item). 79 * any further action (like destroying the item).
88 */ 80 */
89
90int 81int
91did_make_save_item (object *op, int type, object *originator) 82did_make_save_item (object *op, int type, object *originator)
92{ 83{
93 int i, roll, saves = 0, attacks = 0, number; 84 int i, roll, saves = 0, attacks = 0, number;
94 materialtype_t *mt; 85 materialtype_t *mt;
95 86
96 if (op->materialname == NULL) 87 if (op->materialname == NULL)
97 { 88 {
98 for (mt = materialt; mt != NULL && mt->next != NULL; mt = mt->next) 89 for (mt = materialt; mt != NULL && mt->next != NULL; mt = mt->next)
99 {
100 if (op->material & mt->material) 90 if (op->material & mt->material)
101 break; 91 break;
102 }
103 } 92 }
104 else 93 else
105 mt = name_to_material (op->materialname); 94 mt = name_to_material (op->materialname);
106 if (mt == NULL) 95 if (mt == NULL)
107 return TRUE; 96 return TRUE;
158{ 147{
159 if (!did_make_save_item (op, type, originator)) 148 if (!did_make_save_item (op, type, originator))
160 { 149 {
161 object *env = op->env; 150 object *env = op->env;
162 int x = op->x, y = op->y; 151 int x = op->x, y = op->y;
163 mapstruct *m = op->map; 152 maptile *m = op->map;
164 153
165 op = stop_item (op); 154 op = stop_item (op);
166 if (op == NULL) 155 if (op == NULL)
167 return; 156 return;
168 157
177 if (type & (AT_FIRE | AT_ELECTRICITY) && op->other_arch && QUERY_FLAG (op, FLAG_IS_LIGHTABLE)) 166 if (type & (AT_FIRE | AT_ELECTRICITY) && op->other_arch && QUERY_FLAG (op, FLAG_IS_LIGHTABLE))
178 { 167 {
179 const char *arch = op->other_arch->name; 168 const char *arch = op->other_arch->name;
180 169
181 op = decrease_ob_nr (op, 1); 170 op = decrease_ob_nr (op, 1);
171
182 if (op) 172 if (op)
183 fix_stopped_item (op, m, originator); 173 fix_stopped_item (op, m, originator);
174
184 if ((op = get_archetype (arch)) != NULL) 175 if ((op = get_archetype (arch)) != NULL)
185 { 176 {
186 if (env) 177 if (env)
187 { 178 {
188 op->x = env->x, op->y = env->y; 179 op->x = env->x, op->y = env->y;
194 { 185 {
195 op->x = x, op->y = y; 186 op->x = x, op->y = y;
196 insert_ob_in_map (op, m, originator, 0); 187 insert_ob_in_map (op, m, originator, 0);
197 } 188 }
198 } 189 }
190
199 return; 191 return;
200 } 192 }
193
201 if (type & AT_CANCELLATION) 194 if (type & AT_CANCELLATION)
202 { /* Cancellation. */ 195 { /* Cancellation. */
203 cancellation (op); 196 cancellation (op);
204 fix_stopped_item (op, m, originator); 197 fix_stopped_item (op, m, originator);
205 return; 198 return;
206 } 199 }
200
207 if (op->nrof > 1) 201 if (op->nrof > 1)
208 { 202 {
209 op = decrease_ob_nr (op, rndm (0, op->nrof - 1)); 203 op = decrease_ob_nr (op, rndm (0, op->nrof - 1));
204
210 if (op) 205 if (op)
211 fix_stopped_item (op, m, originator); 206 fix_stopped_item (op, m, originator);
212 } 207 }
213 else 208 else
214 { 209 {
215 if (op->env) 210 if (op->env)
216 { 211 {
217 object *tmp = is_player_inv (op->env); 212 object *tmp = op->in_player ();
218 213
219 if (tmp) 214 if (tmp)
220 {
221 esrv_del_item (tmp->contr, op->count); 215 esrv_del_item (tmp->contr, op->count);
222 }
223 } 216 }
224 if (!QUERY_FLAG (op, FLAG_REMOVED)) 217
225 remove_ob (op); 218 op->destroy ();
226 free_object (op);
227 } 219 }
220
228 if (type & (AT_FIRE | AT_ELECTRICITY)) 221 if (type & (AT_FIRE | AT_ELECTRICITY))
229 {
230 if (env) 222 if (env)
231 { 223 {
232 op = get_archetype ("burnout"); 224 op = get_archetype ("burnout");
233 op->x = env->x, op->y = env->y; 225 op->x = env->x, op->y = env->y;
234 insert_ob_in_ob (op, env); 226 insert_ob_in_ob (op, env);
235 } 227 }
236 else 228 else
237 {
238 replace_insert_ob_in_map ("burnout", originator); 229 replace_insert_ob_in_map ("burnout", originator);
239 } 230
240 }
241 return; 231 return;
242 } 232 }
233
243 /* The value of 50 is arbitrary. */ 234 /* The value of 50 is arbitrary. */
244 if (type & AT_COLD && (op->resist[ATNR_COLD] < 50) && !QUERY_FLAG (op, FLAG_NO_PICK) && (RANDOM () & 2)) 235 if (type & AT_COLD && (op->resist[ATNR_COLD] < 50) && !QUERY_FLAG (op, FLAG_NO_PICK) && (RANDOM () & 2))
245 { 236 {
246 object *tmp; 237 object *tmp;
247 archetype *at = find_archetype ("icecube"); 238 archetype *at = archetype::find ("icecube");
248 239
249 if (at == NULL) 240 if (at == NULL)
250 return; 241 return;
242
251 op = stop_item (op); 243 op = stop_item (op);
252 if (op == NULL) 244 if (op == NULL)
253 return; 245 return;
246
254 if ((tmp = present_arch (at, op->map, op->x, op->y)) == NULL) 247 if ((tmp = present_arch (at, op->map, op->x, op->y)) == NULL)
255 { 248 {
256 tmp = arch_to_object (at); 249 tmp = arch_to_object (at);
257 tmp->x = op->x, tmp->y = op->y; 250 tmp->x = op->x, tmp->y = op->y;
258 /* This was in the old (pre new movement code) - 251 /* This was in the old (pre new movement code) -
261 */ 254 */
262 tmp->move_slow_penalty = 0; 255 tmp->move_slow_penalty = 0;
263 tmp->move_slow = 0; 256 tmp->move_slow = 0;
264 insert_ob_in_map (tmp, op->map, originator, 0); 257 insert_ob_in_map (tmp, op->map, originator, 0);
265 } 258 }
259
266 if (!QUERY_FLAG (op, FLAG_REMOVED)) 260 if (!QUERY_FLAG (op, FLAG_REMOVED))
267 remove_ob (op); 261 op->remove ();
262
268 (void) insert_ob_in_ob (op, tmp); 263 insert_ob_in_ob (op, tmp);
269 return; 264 return;
270 } 265 }
271} 266}
272 267
273/* Object op is hitting the map. 268/* Object op is hitting the map.
278 */ 273 */
279 274
280int 275int
281hit_map (object *op, int dir, int type, int full_hit) 276hit_map (object *op, int dir, int type, int full_hit)
282{ 277{
283 object *tmp, *next;
284 mapstruct *map; 278 maptile *map;
285 sint16 x, y; 279 sint16 x, y;
286 int retflag = 0; /* added this flag.. will return 1 if it hits a monster */ 280 int retflag = 0; /* added this flag.. will return 1 if it hits a monster */
287 281
288 tag_t op_tag, next_tag = 0;
289
290 if (QUERY_FLAG (op, FLAG_FREED)) 282 if (QUERY_FLAG (op, FLAG_FREED))
291 { 283 {
292 LOG (llevError, "BUG: hit_map(): free object\n"); 284 LOG (llevError, "BUG: hit_map(): free object\n");
293 return 0; 285 return 0;
294 } 286 }
305 return 0; 297 return 0;
306 } 298 }
307 299
308 if (op->head) 300 if (op->head)
309 op = op->head; 301 op = op->head;
310
311 op_tag = op->count;
312 302
313 map = op->map; 303 map = op->map;
314 x = op->x + freearr_x[dir]; 304 x = op->x + freearr_x[dir];
315 y = op->y + freearr_y[dir]; 305 y = op->y + freearr_y[dir];
316 306
317 int mflags = get_map_flags (map, &map, x, y, &x, &y); 307 int mflags = get_map_flags (map, &map, x, y, &x, &y);
318 308
319 // elmex: a safe map tile can't be hit! 309 // elmex: a safe map tile can't be hit!
320 // this should prevent most harmful effects on items and players there. 310 // this should prevent most harmful effects on items and players there.
321 if ((mflags & P_OUT_OF_MAP) || (mflags & P_SAFE)) 311 if (mflags & (P_OUT_OF_MAP | P_SAFE))
322 return 0; 312 return 0;
323 313
324 /* peterm: a few special cases for special attacktypes --counterspell 314 /* peterm: a few special cases for special attacktypes --counterspell
325 * must be out here because it strikes things which are not alive 315 * must be out here because it strikes things which are not alive
326 */ 316 */
331 321
332 /* If the only attacktype is counterspell or magic, don't need 322 /* If the only attacktype is counterspell or magic, don't need
333 * to do any further processing. 323 * to do any further processing.
334 */ 324 */
335 if (!(type & ~(AT_COUNTERSPELL | AT_MAGIC))) 325 if (!(type & ~(AT_COUNTERSPELL | AT_MAGIC)))
336 {
337 return 0; 326 return 0;
338 } 327
339 type &= ~AT_COUNTERSPELL; 328 type &= ~AT_COUNTERSPELL;
340 } 329 }
341 330
342 if (type & AT_CHAOS) 331 if (type & AT_CHAOS)
343 { 332 {
344 shuffle_attack (op, 1); /*1 flag tells it to change the face */ 333 shuffle_attack (op, 1); /*1 flag tells it to change the face */
345 update_object (op, UP_OBJ_FACE); 334 update_object (op, UP_OBJ_FACE);
346 type &= ~AT_CHAOS; 335 type &= ~AT_CHAOS;
347 } 336 }
348 337
349 next = get_map_ob (map, x, y);
350 if (next)
351 next_tag = next->count;
352
353 while (next)
354 {
355 if (was_destroyed (next, next_tag))
356 {
357 /* There may still be objects that were above 'next', but there is no 338 /* There may still be objects that were above 'next', but there is no
358 * simple way to find out short of copying all object references and 339 * simple way to find out short of copying all object references and
359 * tags into a temporary array before we start processing the first 340 * tags into a temporary array before we start processing the first
360 * object. That's why we just abort. 341 * object. That's why we just abort on destroy.
361 * 342 *
362 * This happens whenever attack spells (like fire) hit a pile 343 * This happens whenever attack spells (like fire) hit a pile
363 * of objects. This is not a bug - nor an error. The errormessage 344 * of objects. This is not a bug - nor an error.
364 * below was spamming the logs for absolutely no reason. 345 */
365 */ 346 for (object *next = map->at (x, y).bot; next && !next->destroyed (); )
366 /* LOG (llevDebug, "hit_map(): next object destroyed\n"); */ 347 {
367 break;
368 }
369 tmp = next; 348 object *tmp = next;
370 next = tmp->above; 349 next = tmp->above;
371 if (next)
372 next_tag = next->count;
373
374 if (QUERY_FLAG (tmp, FLAG_FREED))
375 {
376 LOG (llevError, "BUG: hit_map(): found freed object\n");
377 break;
378 }
379 350
380 /* Something could have happened to 'tmp' while 'tmp->below' was processed. 351 /* Something could have happened to 'tmp' while 'tmp->below' was processed.
381 * For example, 'tmp' was put in an icecube. 352 * For example, 'tmp' was put in an icecube.
382 * This is one of the few cases where on_same_map should not be used. 353 * This is one of the few cases where on_same_map should not be used.
383 */ 354 */
386 357
387 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 358 if (QUERY_FLAG (tmp, FLAG_ALIVE))
388 { 359 {
389 hit_player (tmp, op->stats.dam, op, type, full_hit); 360 hit_player (tmp, op->stats.dam, op, type, full_hit);
390 retflag |= 1; 361 retflag |= 1;
391 if (was_destroyed (op, op_tag)) 362 if (op->destroyed ())
392 break; 363 break;
393 } 364 }
394 /* Here we are potentially destroying an object. If the object has 365 /* Here we are potentially destroying an object. If the object has
395 * NO_PASS set, it is also immune - you can't destroy walls. Note 366 * NO_PASS set, it is also immune - you can't destroy walls. Note
396 * that weak walls have is_alive set, which prevent objects from 367 * that weak walls have is_alive set, which prevent objects from
399 * destroyed right now. 370 * destroyed right now.
400 */ 371 */
401 else if ((tmp->material || tmp->materialname) && op->stats.dam > 0 && !tmp->move_block) 372 else if ((tmp->material || tmp->materialname) && op->stats.dam > 0 && !tmp->move_block)
402 { 373 {
403 save_throw_object (tmp, type, op); 374 save_throw_object (tmp, type, op);
375
404 if (was_destroyed (op, op_tag)) 376 if (op->destroyed ())
405 break; 377 break;
406 } 378 }
407 } 379 }
380
408 return 0; 381 return 0;
409} 382}
410 383
411void 384void
412attack_message (int dam, int type, object *op, object *hitter) 385attack_message (int dam, int type, object *op, object *hitter)
413{ 386{
414 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF]; 387 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF];
415 int i, found = 0; 388 int i, found = 0;
416 mapstruct *map; 389 maptile *map;
417 object *next, *tmp; 390 object *next, *tmp;
418 391
419 /* put in a few special messages for some of the common attacktypes 392 /* put in a few special messages for some of the common attacktypes
420 * a player might have. For example, fire, electric, cold, etc 393 * a player might have. For example, fire, electric, cold, etc
421 * [garbled 20010919] 394 * [garbled 20010919]
438 sprintf (buf1, "missed %s", &op->name); 411 sprintf (buf1, "missed %s", &op->name);
439 sprintf (buf2, " misses"); 412 sprintf (buf2, " misses");
440 found++; 413 found++;
441 } 414 }
442 else if ((hitter->type == DISEASE || hitter->type == SYMPTOM || 415 else if ((hitter->type == DISEASE || hitter->type == SYMPTOM ||
443 hitter->type == POISONING || (type & AT_POISON && IS_LIVE (op))) && !found) 416 hitter->type == POISONING || (type & AT_POISON && op->is_alive ())) && !found)
444 { 417 {
445 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_SUFFER][i].level != -1; i++) 418 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_SUFFER][i].level != -1; i++)
446 if (dam < attack_mess[ATM_SUFFER][i].level || attack_mess[ATM_SUFFER][i + 1].level == -1) 419 if (dam < attack_mess[ATM_SUFFER][i].level || attack_mess[ATM_SUFFER][i + 1].level == -1)
447 { 420 {
448 sprintf (buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1, &op->name, attack_mess[ATM_SUFFER][i].buf2); 421 sprintf (buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1, &op->name, attack_mess[ATM_SUFFER][i].buf2);
460 strcpy (buf2, attack_mess[ATM_DOOR][i].buf3); 433 strcpy (buf2, attack_mess[ATM_DOOR][i].buf3);
461 found++; 434 found++;
462 break; 435 break;
463 } 436 }
464 } 437 }
465 else if (hitter->type == PLAYER && IS_LIVE (op)) 438 else if (hitter->type == PLAYER && op->is_alive ())
466 { 439 {
467 if (USING_SKILL (hitter, SK_KARATE)) 440 if (USING_SKILL (hitter, SK_KARATE))
468 { 441 {
469 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_KARATE][i].level != -1; i++) 442 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_KARATE][i].level != -1; i++)
470 if (dam < attack_mess[ATM_KARATE][i].level || attack_mess[ATM_KARATE][i + 1].level == -1) 443 if (dam < attack_mess[ATM_KARATE][i].level || attack_mess[ATM_KARATE][i + 1].level == -1)
496 found++; 469 found++;
497 break; 470 break;
498 } 471 }
499 } 472 }
500 } 473 }
474
501 if (found) 475 if (found)
502 { 476 {
503 /* done */ 477 /* done */
504 } 478 }
505 else if (IS_ARROW (hitter) && (type == AT_PHYSICAL || type == AT_MAGIC)) 479 else if (hitter->is_arrow () && (type == AT_PHYSICAL || type == AT_MAGIC))
506 { 480 {
507 sprintf (buf1, "hit"); /* just in case */ 481 sprintf (buf1, "hit"); /* just in case */
508 for (i = 0; i < MAXATTACKMESS; i++) 482 for (i = 0; i < MAXATTACKMESS; i++)
509 if (dam < attack_mess[ATM_ARROW][i].level || attack_mess[ATM_ARROW][i + 1].level == -1) 483 if (dam < attack_mess[ATM_ARROW][i].level || attack_mess[ATM_ARROW][i + 1].level == -1)
510 { 484 {
511 strcpy (buf2, attack_mess[ATM_ARROW][i].buf3); 485 strcpy (buf2, attack_mess[ATM_ARROW][i].buf3);
512 found++; 486 found++;
513 break; 487 break;
514 } 488 }
515 } 489 }
516 else if (type & AT_DRAIN && IS_LIVE (op)) 490 else if (type & AT_DRAIN && op->is_alive ())
517 { 491 {
518 /* drain is first, because some items have multiple attypes */ 492 /* drain is first, because some items have multiple attypes */
519 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_DRAIN][i].level != -1; i++) 493 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_DRAIN][i].level != -1; i++)
520 if (dam < attack_mess[ATM_DRAIN][i].level || attack_mess[ATM_DRAIN][i + 1].level == -1) 494 if (dam < attack_mess[ATM_DRAIN][i].level || attack_mess[ATM_DRAIN][i + 1].level == -1)
521 { 495 {
523 strcpy (buf2, attack_mess[ATM_DRAIN][i].buf3); 497 strcpy (buf2, attack_mess[ATM_DRAIN][i].buf3);
524 found++; 498 found++;
525 break; 499 break;
526 } 500 }
527 } 501 }
528 else if (type & AT_ELECTRICITY && IS_LIVE (op)) 502 else if (type & AT_ELECTRICITY && op->is_alive ())
529 { 503 {
530 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_ELEC][i].level != -1; i++) 504 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_ELEC][i].level != -1; i++)
531 if (dam < attack_mess[ATM_ELEC][i].level || attack_mess[ATM_ELEC][i + 1].level == -1) 505 if (dam < attack_mess[ATM_ELEC][i].level || attack_mess[ATM_ELEC][i + 1].level == -1)
532 { 506 {
533 sprintf (buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1, &op->name, attack_mess[ATM_ELEC][i].buf2); 507 sprintf (buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1, &op->name, attack_mess[ATM_ELEC][i].buf2);
534 strcpy (buf2, attack_mess[ATM_ELEC][i].buf3); 508 strcpy (buf2, attack_mess[ATM_ELEC][i].buf3);
535 found++; 509 found++;
536 break; 510 break;
537 } 511 }
538 } 512 }
539 else if (type & AT_COLD && IS_LIVE (op)) 513 else if (type & AT_COLD && op->is_alive ())
540 { 514 {
541 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_COLD][i].level != -1; i++) 515 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_COLD][i].level != -1; i++)
542 if (dam < attack_mess[ATM_COLD][i].level || attack_mess[ATM_COLD][i + 1].level == -1) 516 if (dam < attack_mess[ATM_COLD][i].level || attack_mess[ATM_COLD][i + 1].level == -1)
543 { 517 {
544 sprintf (buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1, &op->name, attack_mess[ATM_COLD][i].buf2); 518 sprintf (buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1, &op->name, attack_mess[ATM_COLD][i].buf2);
621 strcpy (buf1, "hit"); 595 strcpy (buf1, "hit");
622 strcpy (buf2, " hits"); 596 strcpy (buf2, " hits");
623 } 597 }
624 598
625 /* bail out if a monster is casting spells */ 599 /* bail out if a monster is casting spells */
626 if (!(hitter->type == PLAYER || (get_owner (hitter) != NULL && hitter->owner->type == PLAYER))) 600 if (!(hitter->type == PLAYER || (hitter->owner != NULL && hitter->owner->type == PLAYER)))
627 return; 601 return;
628 602
629 /* scale down magic considerably. */ 603 /* scale down magic considerably. */
630 if (type & AT_MAGIC && rndm (0, 5)) 604 if (type & AT_MAGIC && rndm (0, 5))
631 return; 605 return;
632 606
633 /* Did a player hurt another player? Inform both! */ 607 /* Did a player hurt another player? Inform both! */
634 if (op->type == PLAYER && (get_owner (hitter) == NULL ? hitter->type : hitter->owner->type) == PLAYER) 608 if (op->type == PLAYER && (hitter->owner == NULL ? hitter->type : hitter->owner->type) == PLAYER)
635 { 609 {
636 if (get_owner (hitter) != NULL) 610 if (hitter->owner != NULL)
637 sprintf (buf, "%s's %s%s you.", &hitter->owner->name, &hitter->name, buf2); 611 sprintf (buf, "%s's %s%s you.", &hitter->owner->name, &hitter->name, buf2);
638 else 612 else
639 { 613 {
640 sprintf (buf, "%s%s you.", &hitter->name, buf2); 614 sprintf (buf, "%s%s you.", &hitter->name, buf2);
641 if (dam != 0) 615 if (dam != 0)
663 else 637 else
664 play_sound_player_only (hitter->contr, SOUND_PLAYER_HITS3, 0, 0); 638 play_sound_player_only (hitter->contr, SOUND_PLAYER_HITS3, 0, 0);
665 } 639 }
666 new_draw_info (NDI_BLACK, 0, hitter, buf); 640 new_draw_info (NDI_BLACK, 0, hitter, buf);
667 } 641 }
668 else if (get_owner (hitter) != NULL && hitter->owner->type == PLAYER) 642 else if (hitter->owner != NULL && hitter->owner->type == PLAYER)
669 { 643 {
670 /* look for stacked spells and start reducing the message chances */ 644 /* look for stacked spells and start reducing the message chances */
671 if (hitter->type == SPELL_EFFECT && (hitter->subtype == SP_EXPLOSION || hitter->subtype == SP_BULLET || hitter->subtype == SP_CONE)) 645 if (hitter->type == SPELL_EFFECT && (hitter->subtype == SP_EXPLOSION || hitter->subtype == SP_BULLET || hitter->subtype == SP_CONE))
672 { 646 {
673 i = 4; 647 i = 4;
674 map = hitter->map; 648 map = hitter->map;
675 if (out_of_map (map, hitter->x, hitter->y)) 649 if (out_of_map (map, hitter->x, hitter->y))
676 return; 650 return;
677 next = get_map_ob (map, hitter->x, hitter->y); 651 next = GET_MAP_OB (map, hitter->x, hitter->y);
678 if (next) 652 if (next)
679 while (next) 653 while (next)
680 { 654 {
681 if (next->type == SPELL_EFFECT && (next->subtype == SP_EXPLOSION || next->subtype == SP_BULLET || next->subtype == SP_CONE)) 655 if (next->type == SPELL_EFFECT && (next->subtype == SP_EXPLOSION || next->subtype == SP_BULLET || next->subtype == SP_CONE))
682 i *= 3; 656 i *= 3;
748attack_ob_simple (object *op, object *hitter, int base_dam, int base_wc) 722attack_ob_simple (object *op, object *hitter, int base_dam, int base_wc)
749{ 723{
750 int simple_attack, roll, dam = 0; 724 int simple_attack, roll, dam = 0;
751 uint32 type; 725 uint32 type;
752 shstr op_name; 726 shstr op_name;
753 tag_t op_tag, hitter_tag;
754 727
755 if (get_attack_mode (&op, &hitter, &simple_attack)) 728 if (get_attack_mode (&op, &hitter, &simple_attack))
756 goto error; 729 goto error;
757 730
758 if (hitter->current_weapon) 731 if (hitter->current_weapon)
759 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op))) 732 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op)))
760 return RESULT_INT (0); 733 return RESULT_INT (0);
761 734
762 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter))) 735 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter)))
763 return RESULT_INT (0); 736 return RESULT_INT (0);
764
765 op_tag = op->count;
766 hitter_tag = hitter->count;
767 737
768 /* 738 /*
769 * A little check to make it more difficult to dance forward and back 739 * A little check to make it more difficult to dance forward and back
770 * to avoid ever being hit by monsters. 740 * to avoid ever being hit by monsters.
771 */ 741 */
776 * which then gets here again. By decreasing the speed before 746 * which then gets here again. By decreasing the speed before
777 * we call process_object, the 'if' statement above will fail. 747 * we call process_object, the 'if' statement above will fail.
778 */ 748 */
779 op->speed_left--; 749 op->speed_left--;
780 process_object (op); 750 process_object (op);
751
781 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 752 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
782 goto error; 753 goto error;
783 } 754 }
784 755
785 op_name = op->name; 756 op_name = op->name;
786 757
820 if (QUERY_FLAG (op, FLAG_SLEEP)) 791 if (QUERY_FLAG (op, FLAG_SLEEP))
821 CLEAR_FLAG (op, FLAG_SLEEP); 792 CLEAR_FLAG (op, FLAG_SLEEP);
822 793
823 /* If the victim can't see the attacker, it may alert others 794 /* If the victim can't see the attacker, it may alert others
824 * for help. */ 795 * for help. */
825 if (op->type != PLAYER && !can_see_enemy (op, hitter) && !get_owner (op) && rndm (0, op->stats.Int)) 796 if (op->type != PLAYER && !can_see_enemy (op, hitter) && !op->owner && rndm (0, op->stats.Int))
826 npc_call_help (op); 797 npc_call_help (op);
827 798
828 /* if you were hidden and hit by a creature, you are discovered */ 799 /* if you were hidden and hit by a creature, you are discovered */
829 if (op->hide && QUERY_FLAG (hitter, FLAG_ALIVE)) 800 if (op->hide && QUERY_FLAG (hitter, FLAG_ALIVE))
830 { 801 {
837 * when they hit the victim. For things like thrown daggers, 808 * when they hit the victim. For things like thrown daggers,
838 * this sets 'hitter' to the actual dagger, and not the 809 * this sets 'hitter' to the actual dagger, and not the
839 * wrapper object. 810 * wrapper object.
840 */ 811 */
841 thrown_item_effect (hitter, op); 812 thrown_item_effect (hitter, op);
813
842 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack)) 814 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
843 goto leave; 815 goto leave;
844 } 816 }
845 817
846 /* Need to do at least 1 damage, otherwise there is no point 818 /* Need to do at least 1 damage, otherwise there is no point
847 * to go further and it will cause FPE's below. 819 * to go further and it will cause FPE's below.
848 */ 820 */
849 if (hitdam <= 0) 821 if (hitdam <= 0)
850 hitdam = 1; 822 hitdam = 1;
851 823
852 type = hitter->attacktype; 824 type = hitter->attacktype;
825
853 if (!type) 826 if (!type)
854 type = AT_PHYSICAL; 827 type = AT_PHYSICAL;
828
855 /* Handle monsters that hit back */ 829 /* Handle monsters that hit back */
856 if (!simple_attack && QUERY_FLAG (op, FLAG_HITBACK) && QUERY_FLAG (hitter, FLAG_ALIVE)) 830 if (!simple_attack && QUERY_FLAG (op, FLAG_HITBACK) && QUERY_FLAG (hitter, FLAG_ALIVE))
857 { 831 {
858 if (op->attacktype & AT_ACID && hitter->type == PLAYER) 832 if (op->attacktype & AT_ACID && hitter->type == PLAYER)
859 new_draw_info (NDI_UNIQUE, 0, hitter, "You are splashed by acid!\n"); 833 new_draw_info (NDI_UNIQUE, 0, hitter, "You are splashed by acid!\n");
834
860 hit_player (hitter, random_roll (0, (op->stats.dam), hitter, PREFER_LOW), op, op->attacktype, 1); 835 hit_player (hitter, random_roll (0, (op->stats.dam), hitter, PREFER_LOW), op, op->attacktype, 1);
836
861 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 837 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
862 goto leave; 838 goto leave;
863 } 839 }
864 840
865 /* In the new attack code, it should handle multiple attack 841 /* In the new attack code, it should handle multiple attack
866 * types in its area, so remove it from here. 842 * types in its area, so remove it from here.
867 */ 843 */
868 dam = hit_player (op, random_roll (1, hitdam, hitter, PREFER_HIGH), hitter, type, 1); 844 dam = hit_player (op, random_roll (1, hitdam, hitter, PREFER_HIGH), hitter, type, 1);
845
869 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 846 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
870 goto leave; 847 goto leave;
871 } /* end of if hitter hit op */ 848 } /* end of if hitter hit op */
872 /* if we missed, dam=0 */ 849 /* if we missed, dam=0 */
873 850
874 /*attack_message(dam, type, op, hitter); */ 851 /*attack_message(dam, type, op, hitter); */
908 if (op->weight <= 5000 && tmp->stats.hp >= 0) 885 if (op->weight <= 5000 && tmp->stats.hp >= 0)
909 { 886 {
910 if (tmp->head != NULL) 887 if (tmp->head != NULL)
911 tmp = tmp->head; 888 tmp = tmp->head;
912 889
913 remove_ob (op); 890 op->remove ();
914 op = insert_ob_in_ob (op, tmp); 891 op = insert_ob_in_ob (op, tmp);
915 892
916 if (tmp->type == PLAYER) 893 if (tmp->type == PLAYER)
917 esrv_send_item (tmp, op); 894 esrv_send_item (tmp, op);
918 895
931object * 908object *
932hit_with_arrow (object *op, object *victim) 909hit_with_arrow (object *op, object *victim)
933{ 910{
934 object *container, *hitter; 911 object *container, *hitter;
935 int hit_something = 0; 912 int hit_something = 0;
936 tag_t victim_tag, hitter_tag;
937 sint16 victim_x, victim_y;
938 913
939 /* Disassemble missile */ 914 /* Disassemble missile */
940 if (op->inv) 915 if (op->inv)
941 { 916 {
942 container = op; 917 container = op;
943 hitter = op->inv; 918 hitter = op->inv;
944 remove_ob (hitter); 919 hitter->remove ();
945 insert_ob_in_map (hitter, container->map, hitter, INS_NO_MERGE | INS_NO_WALK_ON); 920 insert_ob_in_map (hitter, container->map, hitter, INS_NO_MERGE | INS_NO_WALK_ON);
946 /* Note that we now have an empty THROWN_OBJ on the map. Code that 921 /* Note that we now have an empty THROWN_OBJ on the map. Code that
947 * might be called until this THROWN_OBJ is either reassembled or 922 * might be called until this THROWN_OBJ is either reassembled or
948 * removed at the end of this function must be able to deal with empty 923 * removed at the end of this function must be able to deal with empty
949 * THROWN_OBJs. */ 924 * THROWN_OBJs. */
950 } 925 }
951 else 926 else
952 { 927 {
953 container = NULL; 928 container = 0;
954 hitter = op; 929 hitter = op;
955 } 930 }
956 931
957 /* Try to hit victim */ 932 /* Try to hit victim */
958 victim_x = victim->x;
959 victim_y = victim->y;
960 victim_tag = victim->count;
961 hitter_tag = hitter->count;
962
963 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc); 933 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc);
964 934
965 /* Arrow attacks door, rune of summoning is triggered, demon is put on 935 /* Arrow attacks door, rune of summoning is triggered, demon is put on
966 * arrow, move_apply() calls this function, arrow sticks in demon, 936 * arrow, move_apply() calls this function, arrow sticks in demon,
967 * attack_ob_simple() returns, and we've got an arrow that still exists 937 * attack_ob_simple() returns, and we've got an arrow that still exists
968 * but is no longer on the map. Ugh. (Beware: Such things can happen at 938 * but is no longer on the map. Ugh. (Beware: Such things can happen at
969 * other places as well!) 939 * other places as well!)
970 */ 940 */
971 if (was_destroyed (hitter, hitter_tag) || hitter->env != NULL) 941 if (hitter->destroyed () || hitter->env != NULL)
972 { 942 {
973 if (container) 943 if (container)
974 { 944 {
975 remove_ob (container); 945 container->remove ();
976 free_object (container); 946 container->destroy ();
977 } 947 }
948
978 return NULL; 949 return 0;
979 } 950 }
980 951
981 /* Missile hit victim */ 952 /* Missile hit victim */
982 /* if the speed is > 10, then this is a fast moving arrow, we go straight 953 /* if the speed is > 10, then this is a fast moving arrow, we go straight
983 * through the target 954 * through the target
984 */ 955 */
985 if (hit_something && op->speed <= 10.0) 956 if (hit_something && op->speed <= 10.0)
986 { 957 {
987 /* Stop arrow */ 958 /* Stop arrow */
988 if (container == NULL) 959 if (!container)
989 { 960 {
990 hitter = fix_stopped_arrow (hitter); 961 hitter = fix_stopped_arrow (hitter);
991 if (hitter == NULL) 962 if (!hitter)
992 return NULL; 963 return 0;
993 } 964 }
994 else 965 else
995 { 966 container->destroy ();
996 remove_ob (container);
997 free_object (container);
998 }
999 967
1000 /* Try to stick arrow into victim */ 968 /* Try to stick arrow into victim */
1001 if (!was_destroyed (victim, victim_tag) && stick_arrow (hitter, victim)) 969 if (!victim->destroyed () && stick_arrow (hitter, victim))
1002 return NULL; 970 return 0;
1003 971
1004 /* Else try to put arrow on victim's map square 972 /* Else try to put arrow on victim's map square
1005 * remove check for P_WALL here. If the arrow got to this 973 * remove check for P_WALL here. If the arrow got to this
1006 * space, that is good enough - with the new movement code, 974 * space, that is good enough - with the new movement code,
1007 * there is now the potential for lots of spaces where something 975 * there is now the potential for lots of spaces where something
1008 * can fly over but not otherwise move over. What is the correct 976 * can fly over but not otherwise move over. What is the correct
1009 * way to handle those otherwise? 977 * way to handle those otherwise?
1010 */ 978 */
1011 if (victim_x != hitter->x || victim_y != hitter->y) 979 if (victim->x != hitter->x || victim->y != hitter->y)
1012 { 980 {
1013 remove_ob (hitter); 981 hitter->remove ();
1014 hitter->x = victim_x; 982 hitter->x = victim->x;
1015 hitter->y = victim_y; 983 hitter->y = victim->y;
1016 insert_ob_in_map (hitter, victim->map, hitter, 0); 984 insert_ob_in_map (hitter, victim->map, hitter, 0);
1017 } 985 }
1018 else 986 else
1019 {
1020 /* Else leave arrow where it is */ 987 /* Else leave arrow where it is */
1021 merge_ob (hitter, NULL); 988 merge_ob (hitter, NULL);
1022 } 989
1023 return NULL; 990 return 0;
1024 } 991 }
1025 992
1026 if (hit_something && op->speed >= 10.0) 993 if (hit_something && op->speed >= 10.0)
1027 op->speed -= 1.0; 994 op->speed -= 1.0;
1028 995
1029 /* Missile missed victim - reassemble missile */ 996 /* Missile missed victim - reassemble missile */
1030 if (container) 997 if (container)
1031 { 998 {
1032 remove_ob (hitter); 999 hitter->remove ();
1033 insert_ob_in_ob (hitter, container); 1000 insert_ob_in_ob (hitter, container);
1034 } 1001 }
1002
1035 return op; 1003 return op;
1036} 1004}
1037 1005
1038 1006
1039void 1007void
1048 } 1016 }
1049 else if (!GET_ANIM_ID (op)) 1017 else if (!GET_ANIM_ID (op))
1050 { 1018 {
1051 /* Object has been called - no animations, so remove it */ 1019 /* Object has been called - no animations, so remove it */
1052 if (op->stats.hp < 0) 1020 if (op->stats.hp < 0)
1021 op->destroy ();
1053 { 1022
1054 remove_ob (op); /* Should update LOS */
1055 free_object (op);
1056 /* Don't know why this is here - remove_ob should do it for us */
1057 /*update_position(m, x, y); */
1058 }
1059 return; /* no animations, so nothing more to do */ 1023 return; /* no animations, so nothing more to do */
1060 } 1024 }
1025
1061 perc = NUM_ANIMATIONS (op) - ((int) NUM_ANIMATIONS (op) * op->stats.hp) / op->stats.maxhp; 1026 perc = NUM_ANIMATIONS (op) - ((int) NUM_ANIMATIONS (op) * op->stats.hp) / op->stats.maxhp;
1027
1062 if (perc >= (int) NUM_ANIMATIONS (op)) 1028 if (perc >= (int) NUM_ANIMATIONS (op))
1063 perc = NUM_ANIMATIONS (op) - 1; 1029 perc = NUM_ANIMATIONS (op) - 1;
1064 else if (perc < 1) 1030 else if (perc < 1)
1065 perc = 1; 1031 perc = 1;
1032
1066 SET_ANIMATION (op, perc); 1033 SET_ANIMATION (op, perc);
1067 update_object (op, UP_OBJ_FACE); 1034 update_object (op, UP_OBJ_FACE);
1035
1068 if (perc == NUM_ANIMATIONS (op) - 1) 1036 if (perc == NUM_ANIMATIONS (op) - 1)
1069 { /* Reached the last animation */ 1037 { /* Reached the last animation */
1070 if (op->face == blank_face) 1038 if (op->face == blank_face)
1071 {
1072 /* If the last face is blank, remove the ob */ 1039 /* If the last face is blank, remove the ob */
1073 remove_ob (op); /* Should update LOS */ 1040 op->destroy ();
1074 free_object (op);
1075
1076 /* remove_ob should call update_position for us */
1077 /*update_position(m, x, y); */
1078
1079 }
1080 else 1041 else
1081 { /* The last face was not blank, leave an image */ 1042 { /* The last face was not blank, leave an image */
1082 CLEAR_FLAG (op, FLAG_BLOCKSVIEW); 1043 CLEAR_FLAG (op, FLAG_BLOCKSVIEW);
1083 update_all_los (op->map, op->x, op->y); 1044 update_all_los (op->map, op->x, op->y);
1084 op->move_block = 0; 1045 op->move_block = 0;
1088} 1049}
1089 1050
1090void 1051void
1091scare_creature (object *target, object *hitter) 1052scare_creature (object *target, object *hitter)
1092{ 1053{
1093 object *owner = get_owner (hitter); 1054 object *owner = hitter->owner;
1094 1055
1095 if (!owner) 1056 if (!owner)
1096 owner = hitter; 1057 owner = hitter;
1097 1058
1098 SET_FLAG (target, FLAG_SCARED); 1059 SET_FLAG (target, FLAG_SCARED);
1213 else if (attacknum == ATNR_FEAR) 1174 else if (attacknum == ATNR_FEAR)
1214 scare_creature (op, hitter); 1175 scare_creature (op, hitter);
1215 else if (attacknum == ATNR_CANCELLATION) 1176 else if (attacknum == ATNR_CANCELLATION)
1216 cancellation (op); 1177 cancellation (op);
1217 else if (attacknum == ATNR_DEPLETE) 1178 else if (attacknum == ATNR_DEPLETE)
1218 drain_stat (op); 1179 op->drain_stat ();
1219 else if (attacknum == ATNR_BLIND && !QUERY_FLAG (op, FLAG_UNDEAD) && !QUERY_FLAG (op, FLAG_GENERATOR)) 1180 else if (attacknum == ATNR_BLIND && !QUERY_FLAG (op, FLAG_UNDEAD) && !QUERY_FLAG (op, FLAG_GENERATOR))
1220 blind_player (op, hitter, dam); 1181 blind_player (op, hitter, dam);
1221 } 1182 }
1222 dam = 0; /* These are all effects and don't do real damage */ 1183 dam = 0; /* These are all effects and don't do real damage */
1223 } 1184 }
1262 if (op->type == PLAYER) 1223 if (op->type == PLAYER)
1263 esrv_send_item (op, tmp); 1224 esrv_send_item (op, tmp);
1264 } 1225 }
1265 } 1226 }
1266 if (flag) 1227 if (flag)
1267 fix_player (op); /* Something was corroded */ 1228 op->update_stats (); /* Something was corroded */
1268 } 1229 }
1269 } 1230 }
1270 break; 1231 break;
1271 case ATNR_DRAIN: 1232 case ATNR_DRAIN:
1272 { 1233 {
1302 * Try to credit the owner. We try to display player -> player drain 1263 * Try to credit the owner. We try to display player -> player drain
1303 * attacks, hence all the != PLAYER checks. 1264 * attacks, hence all the != PLAYER checks.
1304 */ 1265 */
1305 if (!op_on_battleground (hitter, NULL, NULL) && !QUERY_FLAG (op, FLAG_WAS_WIZ)) 1266 if (!op_on_battleground (hitter, NULL, NULL) && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1306 { 1267 {
1307 object *owner = get_owner (hitter); 1268 object *owner = hitter->owner;
1308 1269
1309 if (owner && owner != hitter) 1270 if (owner && owner != hitter)
1310 { 1271 {
1311 if (op->type != PLAYER || owner->type != PLAYER) 1272 if (op->type != PLAYER || owner->type != PLAYER)
1312 change_exp (owner, op->stats.exp / (rate * 2), 1273 change_exp (owner, op->stats.exp / (rate * 2),
1328 break; 1289 break;
1329 case ATNR_TURN_UNDEAD: 1290 case ATNR_TURN_UNDEAD:
1330 { 1291 {
1331 if (QUERY_FLAG (op, FLAG_UNDEAD)) 1292 if (QUERY_FLAG (op, FLAG_UNDEAD))
1332 { 1293 {
1333 object *owner = get_owner (hitter) == NULL ? hitter : get_owner (hitter); 1294 object *owner = hitter->owner ? (object *)hitter->owner : hitter;
1334 object *god = find_god (determine_god (owner)); 1295 object *god = find_god (determine_god (owner));
1335 int div = 1; 1296 int div = 1;
1336 1297
1337 /* if undead are not an enemy of your god, you turn them 1298 /* if undead are not an enemy of your god, you turn them
1338 * at half strength */ 1299 * at half strength */
1364 break; 1325 break;
1365 case ATNR_HOLYWORD: 1326 case ATNR_HOLYWORD:
1366 { 1327 {
1367 /* This has already been handled by hit_player, 1328 /* This has already been handled by hit_player,
1368 * no need to check twice -- DAMN */ 1329 * no need to check twice -- DAMN */
1369 1330 object *owner = hitter->owner ? (object *)hitter->owner : hitter;
1370 object *owner = get_owner (hitter) == NULL ? hitter : get_owner (hitter);
1371 1331
1372 /* As with turn undead above, give a bonus on the saving throw */ 1332 /* As with turn undead above, give a bonus on the saving throw */
1373 if ((op->level + (op->resist[ATNR_HOLYWORD] / 100)) < owner->level + turn_bonus[owner->stats.Wis]) 1333 if ((op->level + (op->resist[ATNR_HOLYWORD] / 100)) < owner->level + turn_bonus[owner->stats.Wis])
1374 scare_creature (op, owner); 1334 scare_creature (op, owner);
1375 } 1335 }
1450 if (QUERY_FLAG (op, FLAG_BLOCKSVIEW)) 1410 if (QUERY_FLAG (op, FLAG_BLOCKSVIEW))
1451 update_all_los (op->map, op->x, op->y); /* makes sure los will be recalculated */ 1411 update_all_los (op->map, op->x, op->y); /* makes sure los will be recalculated */
1452 1412
1453 if (op->type == DOOR) 1413 if (op->type == DOOR)
1454 { 1414 {
1455 op->speed = 0.1; 1415 op->set_speed (0.1);
1456 update_ob_speed (op);
1457 op->speed_left = -0.05; 1416 op->speed_left = -0.05;
1458 return maxdam; 1417 return maxdam;
1459 } 1418 }
1419
1460 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER) 1420 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER)
1461 { 1421 {
1462 remove_friendly_object (op); 1422 remove_friendly_object (op);
1423
1463 if (get_owner (op) != NULL && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op) 1424 if (op->owner && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op)
1464 {
1465 op->owner->contr->ranges[range_golem] = NULL; 1425 op->owner->contr->ranges[range_golem] = 0;
1466 op->owner->contr->golem_count = 0;
1467 }
1468 1426
1469 remove_ob (op); 1427 op->destroy ();
1470 free_object (op);
1471 return maxdam; 1428 return maxdam;
1472 } 1429 }
1473 1430
1474 /* Now lets start dealing with experience we get for killing something */ 1431 /* Now lets start dealing with experience we get for killing something */
1475 1432
1476 owner = get_owner (hitter); 1433 owner = hitter->owner;
1477 if (owner == NULL) 1434 if (!owner)
1478 owner = hitter; 1435 owner = hitter;
1479 1436
1480 /* is the victim (op) standing on battleground? */ 1437 /* is the victim (op) standing on battleground? */
1481 if (op_on_battleground (op, NULL, NULL)) 1438 if (op_on_battleground (op, NULL, NULL))
1482 battleg = 1; 1439 battleg = 1;
1502 char buf[256]; 1459 char buf[256];
1503 1460
1504 tmv = localtime (&t); 1461 tmv = localtime (&t);
1505 strftime (buf, 256, "%a %b %d %H:%M:%S %Y", tmv); 1462 strftime (buf, 256, "%a %b %d %H:%M:%S %Y", tmv);
1506 1463
1507 LOG (llevInfo, "%s PLAYER_KILL_PLAYER: %s (%s) killed %s\n", buf, &owner->name, owner->contr->socket.host, query_name (op)); 1464 LOG (llevInfo, "%s PLAYER_KILL_PLAYER: %s (%s) killed %s\n", buf, &owner->name, owner->contr->ns->host, query_name (op));
1508 } 1465 }
1509 1466
1510 /* try to filter some things out - basically, if you are 1467 /* try to filter some things out - basically, if you are
1511 * killing a level 1 creature and your level 20, you 1468 * killing a level 1 creature and your level 20, you
1512 * probably don't want to see that. 1469 * probably don't want to see that.
1513 */ 1470 */
1514 if (owner->level < op->level * 2 || op->stats.exp > 1000) 1471 if (owner->level < op->level * 2 || op->stats.exp > 1000)
1515 { 1472 {
1516 if (owner != hitter) 1473 if (owner != hitter)
1517 {
1518 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter)); 1474 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter));
1519 }
1520 else 1475 else
1521 {
1522 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op)); 1476 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op));
1523 } 1477
1524 /* Only play sounds for melee kills */ 1478 /* Only play sounds for melee kills */
1525 if (hitter->type == PLAYER) 1479 if (hitter->type == PLAYER)
1526 play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS); 1480 play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS);
1527 } 1481 }
1528 1482
1533 * player that the object belonged to - so if you killed another player 1487 * player that the object belonged to - so if you killed another player
1534 * with spells, pets, whatever, there was no penalty. 1488 * with spells, pets, whatever, there was no penalty.
1535 * Changed to make luck penalty configurable in settings. 1489 * Changed to make luck penalty configurable in settings.
1536 */ 1490 */
1537 if (op->type == PLAYER && owner != op && !battleg) 1491 if (op->type == PLAYER && owner != op && !battleg)
1538 change_luck (owner, -settings.pk_luck_penalty); 1492 owner->change_luck (-settings.pk_luck_penalty);
1539 1493
1540 /* This code below deals with finding the appropriate skill 1494 /* This code below deals with finding the appropriate skill
1541 * to credit exp to. This is a bit problematic - we should 1495 * to credit exp to. This is a bit problematic - we should
1542 * probably never really have to look at current_weapon->skill 1496 * probably never really have to look at current_weapon->skill
1543 */ 1497 */
1544 skill = NULL; 1498 skill = 0;
1499
1545 if (hitter->skill && hitter->type != PLAYER) 1500 if (hitter->skill && hitter->type != PLAYER)
1546 skill = hitter->skill; 1501 skill = hitter->skill;
1547 else if (owner->chosen_skill) 1502 else if (owner->chosen_skill)
1548 { 1503 {
1549 skill = owner->chosen_skill->skill; 1504 skill = owner->chosen_skill->skill;
1568 break; 1523 break;
1569 } 1524 }
1570 } 1525 }
1571 } /* Was it a player that hit somethign */ 1526 } /* Was it a player that hit somethign */
1572 else 1527 else
1573 {
1574 skill = NULL; 1528 skill = 0;
1575 }
1576 1529
1577 /* Pet (or spell) killed something. */ 1530 /* Pet (or spell) killed something. */
1578 if (owner != hitter) 1531 if (owner != hitter)
1579 {
1580 (void) sprintf (buf, "%s killed %s with %s%s%s.", &owner->name, 1532 sprintf (buf, "%s killed %s with %s%s%s.", &owner->name,
1581 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : ""); 1533 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : "");
1582 }
1583 else 1534 else
1584 {
1585 (void) sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name, 1535 sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name,
1586 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ? 1536 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ?
1587 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : ""); 1537 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : "");
1588 } 1538
1589 /* These may have been set in the player code section above */ 1539 /* These may have been set in the player code section above */
1590 if (!skop) 1540 if (!skop)
1591 skop = hitter->chosen_skill; 1541 skop = hitter->chosen_skill;
1542
1592 if (!skill && skop) 1543 if (!skill && skop)
1593 skill = skop->skill; 1544 skill = skop->skill;
1594 1545
1595 new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf); 1546 new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf);
1596 1547
1597
1598 /* If you didn't kill yourself, and your not the wizard */ 1548 /* If you didn't kill yourself, and your not the wizard */
1599 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ)) 1549 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1600 { 1550 {
1601 int exp; 1551 int exp;
1602 1552
1603 /* Really don't give much experience for killing other players */ 1553 /* Really don't give much experience for killing other players */
1604 // schmorp: temporary? reduce the amount of exp gained for pking enourmously 1554 // schmorp: temporarily? reduce the amount of exp gained for pking enourmously
1605 if (op->type == PLAYER) 1555 if (op->type == PLAYER)
1606 { 1556 {
1607 if (battleg) 1557 if (battleg)
1608 { 1558 {
1609 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!"); 1559 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!");
1627 1577
1628 if (!settings.simple_exp) 1578 if (!settings.simple_exp)
1629 exp = exp / 2; 1579 exp = exp / 2;
1630 1580
1631 if (owner->type != PLAYER || owner->contr->party == NULL) 1581 if (owner->type != PLAYER || owner->contr->party == NULL)
1632 {
1633 change_exp (owner, exp, skill, 0); 1582 change_exp (owner, exp, skill, 0);
1634 }
1635 else 1583 else
1636 { 1584 {
1637 int shares = 0, count = 0; 1585 int shares = 0, count = 0;
1638
1639 player *pl; 1586 player *pl;
1640
1641 partylist *party = owner->contr->party; 1587 partylist *party = owner->contr->party;
1642 1588
1643#ifdef PARTY_KILL_LOG
1644 add_kill_to_party (party, query_name (owner), query_name (op), exp); 1589 add_kill_to_party (party, query_name (owner), query_name (op), exp);
1645#endif 1590
1646 for (pl = first_player; pl != NULL; pl = pl->next) 1591 for_all_players (pl)
1647 {
1648 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) 1592 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1649 { 1593 {
1650 count++; 1594 count++;
1651 shares += (pl->ob->level + 4); 1595 shares += (pl->ob->level + 4);
1652 } 1596 }
1653 } 1597
1654 if (count == 1 || shares > exp) 1598 if (count == 1 || shares > exp || !shares)
1655 change_exp (owner, exp, skill, SK_EXP_TOTAL); 1599 change_exp (owner, exp, skill, SK_EXP_TOTAL);
1656 else 1600 else
1657 { 1601 {
1658 int share = exp / shares, given = 0, nexp; 1602 int share = exp / shares, given = 0, nexp;
1659 1603
1660 for (pl = first_player; pl != NULL; pl = pl->next) 1604 for_all_players (pl)
1661 {
1662 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) 1605 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1663 { 1606 {
1664 nexp = (pl->ob->level + 4) * share; 1607 nexp = (pl->ob->level + 4) * share;
1665 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL); 1608 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL);
1666 given += nexp; 1609 given += nexp;
1667 } 1610 }
1668 } 1611
1669 exp -= given; 1612 exp -= given;
1670 /* give any remainder to the player */ 1613 /* give any remainder to the player */
1671 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL); 1614 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL);
1672 } 1615 }
1673 } /* else part of a party */ 1616 } /* else part of a party */
1674
1675 } /* end if person didn't kill himself */ 1617 } /* end if person didn't kill himself */
1676 1618
1677 if (op->type != PLAYER) 1619 if (op->type != PLAYER)
1678 { 1620 {
1679 if (QUERY_FLAG (op, FLAG_FRIENDLY)) 1621 if (QUERY_FLAG (op, FLAG_FRIENDLY))
1680 { 1622 {
1681 object *owner1 = get_owner (op); 1623 object *owner1 = op->owner;
1682 1624
1683 if (owner1 != NULL && owner1->type == PLAYER) 1625 if (owner1 && owner1->type == PLAYER)
1684 { 1626 {
1685 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0); 1627 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0);
1686 /* Maybe we should include the owner that killed this, maybe not */ 1628 /* Maybe we should include the owner that killed this, maybe not */
1687 new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name); 1629 new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name);
1688 } 1630 }
1631
1689 remove_friendly_object (op); 1632 remove_friendly_object (op);
1690 } 1633 }
1691 remove_ob (op); 1634
1692 free_object (op); 1635 op->destroy ();
1693 } 1636 }
1694 /* Player has been killed! */
1695 else 1637 else
1696 { 1638 {
1639 /* Player has been killed! */
1697 if (owner->type == PLAYER) 1640 if (owner->type == PLAYER)
1698 {
1699 snprintf (op->contr->killer, BIG_NAME, "%s the %s", &owner->name, owner->contr->title); 1641 snprintf (op->contr->killer, sizeof (op->contr->killer), "%s the %s", &owner->name, owner->contr->title);
1700 }
1701 else 1642 else
1702 {
1703 strncpy (op->contr->killer, hitter->name, BIG_NAME); 1643 assign (op->contr->killer, hitter->name);
1704 op->contr->killer[BIG_NAME - 1] = '\0';
1705 }
1706 } 1644 }
1645
1707 /* This was return -1 - that doesn't seem correct - if we return -1, process 1646 /* This was return -1 - that doesn't seem correct - if we return -1, process
1708 * continues in the calling function. 1647 * continues in the calling function.
1709 */ 1648 */
1710 return maxdam; 1649 return maxdam;
1711} 1650}
1731 return 0; 1670 return 0;
1732 1671
1733 if (hitter->type == PLAYER && hitter->contr->peaceful == 1) 1672 if (hitter->type == PLAYER && hitter->contr->peaceful == 1)
1734 return 1; 1673 return 1;
1735 1674
1736 if ((owner = get_owner (hitter)) != NULL) 1675 if ((owner = hitter->owner) != NULL)
1737 { 1676 {
1738 if (owner->type == PLAYER && owner->contr->peaceful == 1) 1677 if (owner->type == PLAYER && owner->contr->peaceful == 1)
1739 friendlyfire = 2; 1678 friendlyfire = 2;
1740 } 1679 }
1741 1680
1762{ 1701{
1763 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC); 1702 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC);
1764 int maxattacktype, attacknum; 1703 int maxattacktype, attacknum;
1765 int body_attack = op && op->head; /* Did we hit op's head? */ 1704 int body_attack = op && op->head; /* Did we hit op's head? */
1766 int simple_attack; 1705 int simple_attack;
1767 tag_t op_tag, hitter_tag;
1768 int rtn_kill = 0; 1706 int rtn_kill = 0;
1769 int friendlyfire; 1707 int friendlyfire;
1770 1708
1771 if (get_attack_mode (&op, &hitter, &simple_attack)) 1709 if (get_attack_mode (&op, &hitter, &simple_attack))
1772 return 0; 1710 return 0;
1776 return 0; 1714 return 0;
1777 1715
1778#ifdef PROHIBIT_PLAYERKILL 1716#ifdef PROHIBIT_PLAYERKILL
1779 if (op->type == PLAYER) 1717 if (op->type == PLAYER)
1780 { 1718 {
1781 object *owner = get_owner (hitter); 1719 object *owner = hitter->owner;
1782 1720
1783 if (!owner) 1721 if (!owner)
1784 owner = hitter; 1722 owner = hitter;
1723
1785 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner) 1724 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner)
1786 {
1787 return 0; 1725 return 0;
1788 }
1789 } 1726 }
1790#endif 1727#endif
1791
1792 op_tag = op->count;
1793 hitter_tag = hitter->count;
1794 1728
1795 if (body_attack) 1729 if (body_attack)
1796 { 1730 {
1797 /* slow and paralyze must hit the head. But we don't want to just 1731 /* slow and paralyze must hit the head. But we don't want to just
1798 * return - we still need to process other attacks the spell still 1732 * return - we still need to process other attacks the spell still
1804 * attack so we don't cancel out things like magic bullet. 1738 * attack so we don't cancel out things like magic bullet.
1805 */ 1739 */
1806 if (type & (AT_PARALYZE | AT_SLOW)) 1740 if (type & (AT_PARALYZE | AT_SLOW))
1807 { 1741 {
1808 type &= ~(AT_PARALYZE | AT_SLOW); 1742 type &= ~(AT_PARALYZE | AT_SLOW);
1743
1809 if (!type || type == AT_MAGIC) 1744 if (!type || type == AT_MAGIC)
1810 return 0; 1745 return 0;
1811 } 1746 }
1812 } 1747 }
1813 1748
1817 1752
1818 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) 1753 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1819 if (tmp->type == RUNE || tmp->type == TRAP) 1754 if (tmp->type == RUNE || tmp->type == TRAP)
1820 { 1755 {
1821 spring_trap (tmp, hitter); 1756 spring_trap (tmp, hitter);
1757
1822 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack)) 1758 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
1823 return 0; 1759 return 0;
1760
1824 break; 1761 break;
1825 } 1762 }
1826 } 1763 }
1827 1764
1828 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0) 1765 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0)
1829 { 1766 {
1830 /* FIXME: If a player is killed by a rune in a door, the 1767 /* FIXME: If a player is killed by a rune in a door, the
1831 * was_destroyed() check above doesn't return, and might get here. 1768 * destroyed() check above doesn't return, and might get here.
1832 */ 1769 */
1833 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name); 1770 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name);
1834 return 0; 1771 return 0;
1835 } 1772 }
1836 1773
1874 (hitter->title != NULL 1811 (hitter->title != NULL
1875 && (god = find_god (determine_god (hitter))) != NULL && god->race != NULL && strstr (god->race, undead_name) != NULL))) 1812 && (god = find_god (determine_god (hitter))) != NULL && god->race != NULL && strstr (god->race, undead_name) != NULL)))
1876 return 0; 1813 return 0;
1877 } 1814 }
1878 1815
1879 maxattacktype = type; /* initialize this to something */ 1816 maxattacktype = type; /* initialise this to something */
1880 for (attacknum = 0; attacknum < NROFATTACKS; attacknum++, attacktype = 1 << attacknum) 1817 for (attacknum = 0; attacknum < NROFATTACKS; attacknum++, attacktype = 1 << attacknum)
1881 { 1818 {
1882 /* Magic isn't really a true attack type - it gets combined with other 1819 /* Magic isn't really a true attack type - it gets combined with other
1883 * attack types. As such, skip it over. However, if magic is 1820 * attack types. As such, skip it over. However, if magic is
1884 * the only attacktype in the group, then still attack with it 1821 * the only attacktype in the group, then still attack with it
1945 1882
1946#ifdef ATTACK_DEBUG 1883#ifdef ATTACK_DEBUG
1947 LOG (llevDebug, "Attacktype %d did %d damage\n", type, maxdam); 1884 LOG (llevDebug, "Attacktype %d did %d damage\n", type, maxdam);
1948#endif 1885#endif
1949 1886
1950 if (get_owner (hitter)) 1887 if (hitter->owner)
1951 op->enemy = hitter->owner; 1888 op->enemy = hitter->owner;
1952 else if (QUERY_FLAG (hitter, FLAG_ALIVE)) 1889 else if (QUERY_FLAG (hitter, FLAG_ALIVE))
1953 op->enemy = hitter; 1890 op->enemy = hitter;
1954 1891
1955 if (QUERY_FLAG (op, FLAG_UNAGGRESSIVE) && op->type != PLAYER) 1892 if (QUERY_FLAG (op, FLAG_UNAGGRESSIVE) && op->type != PLAYER)
1980 1917
1981 if (QUERY_FLAG (op, FLAG_TEAR_DOWN)) 1918 if (QUERY_FLAG (op, FLAG_TEAR_DOWN))
1982 { 1919 {
1983 if (maxdam) 1920 if (maxdam)
1984 tear_down_wall (op); 1921 tear_down_wall (op);
1922
1985 return maxdam; /* nothing more to do for wall */ 1923 return maxdam; /* nothing more to do for wall */
1986 } 1924 }
1987 1925
1988 /* See if the creature has been killed */ 1926 /* See if the creature has been killed */
1989 rtn_kill = kill_object (op, maxdam, hitter, type); 1927 rtn_kill = kill_object (op, maxdam, hitter, type);
1997 */ 1935 */
1998 if (QUERY_FLAG (hitter, FLAG_ONE_HIT)) 1936 if (QUERY_FLAG (hitter, FLAG_ONE_HIT))
1999 { 1937 {
2000 if (QUERY_FLAG (hitter, FLAG_FRIENDLY)) 1938 if (QUERY_FLAG (hitter, FLAG_FRIENDLY))
2001 remove_friendly_object (hitter); 1939 remove_friendly_object (hitter);
2002 remove_ob (hitter); 1940
2003 free_object (hitter); 1941 hitter->destroy ();
2004 } 1942 }
2005 /* Lets handle creatures that are splitting now */ 1943 /* Lets handle creatures that are splitting now */
2006 else if (type & AT_PHYSICAL && !QUERY_FLAG (op, FLAG_FREED) && QUERY_FLAG (op, FLAG_SPLITTING)) 1944 else if (type & AT_PHYSICAL && !QUERY_FLAG (op, FLAG_FREED) && QUERY_FLAG (op, FLAG_SPLITTING))
2007 { 1945 {
2008 int i; 1946 int i;
2009 int friendly = QUERY_FLAG (op, FLAG_FRIENDLY); 1947 int friendly = QUERY_FLAG (op, FLAG_FRIENDLY);
2010 int unaggressive = QUERY_FLAG (op, FLAG_UNAGGRESSIVE); 1948 int unaggressive = QUERY_FLAG (op, FLAG_UNAGGRESSIVE);
2011 object *owner = get_owner (op); 1949 object *owner = op->owner;
2012 1950
2013 if (!op->other_arch) 1951 if (!op->other_arch)
2014 { 1952 {
2015 LOG (llevError, "SPLITTING without other_arch error.\n"); 1953 LOG (llevError, "SPLITTING without other_arch error.\n");
2016 return maxdam; 1954 return maxdam;
2017 } 1955 }
1956
2018 remove_ob (op); 1957 op->remove ();
1958
2019 for (i = 0; i < NROFNEWOBJS (op); i++) 1959 for (i = 0; i < NROFNEWOBJS (op); i++)
2020 { /* This doesn't handle op->more yet */ 1960 { /* This doesn't handle op->more yet */
2021 object *tmp = arch_to_object (op->other_arch); 1961 object *tmp = arch_to_object (op->other_arch);
2022 int j; 1962 int j;
2023 1963
2024 tmp->stats.hp = op->stats.hp; 1964 tmp->stats.hp = op->stats.hp;
1965
2025 if (friendly) 1966 if (friendly)
2026 { 1967 {
2027 SET_FLAG (tmp, FLAG_FRIENDLY); 1968 SET_FLAG (tmp, FLAG_FRIENDLY);
2028 add_friendly_object (tmp); 1969 add_friendly_object (tmp);
2029 tmp->attack_movement = PETMOVE; 1970 tmp->attack_movement = PETMOVE;
2030 if (owner != NULL) 1971 if (owner != NULL)
2031 set_owner (tmp, owner); 1972 tmp->set_owner (owner);
2032 } 1973 }
1974
2033 if (unaggressive) 1975 if (unaggressive)
2034 SET_FLAG (tmp, FLAG_UNAGGRESSIVE); 1976 SET_FLAG (tmp, FLAG_UNAGGRESSIVE);
1977
2035 j = find_first_free_spot (tmp, op->map, op->x, op->y); 1978 j = find_first_free_spot (tmp, op->map, op->x, op->y);
1979
2036 if (j == -1) /* No spot to put this monster */ 1980 if (j == -1) /* No spot to put this monster */
2037 free_object (tmp); 1981 tmp->destroy ();
2038 else 1982 else
2039 { 1983 {
2040 tmp->x = op->x + freearr_x[j], tmp->y = op->y + freearr_y[j]; 1984 tmp->x = op->x + freearr_x[j], tmp->y = op->y + freearr_y[j];
2041 insert_ob_in_map (tmp, op->map, NULL, 0); 1985 insert_ob_in_map (tmp, op->map, NULL, 0);
2042 } 1986 }
2043 } 1987 }
2044 if (friendly) 1988
2045 remove_friendly_object (op); 1989 op->destroy ();
2046 free_object (op);
2047 } 1990 }
2048 else if (type & AT_DRAIN && hitter->type == GRIMREAPER && hitter->value++ > 10) 1991 else if (type & AT_DRAIN && hitter->type == GRIMREAPER && hitter->value++ > 10)
2049 { 1992 hitter->destroy ();
2050 remove_ob (hitter); 1993
2051 free_object (hitter);
2052 }
2053 return maxdam; 1994 return maxdam;
2054} 1995}
2055 1996
2056 1997
2057void 1998void
2058poison_player (object *op, object *hitter, int dam) 1999poison_player (object *op, object *hitter, int dam)
2059{ 2000{
2060 archetype *at = find_archetype ("poisoning"); 2001 archetype *at = archetype::find ("poisoning");
2061 object *tmp = present_arch_in_ob (at, op); 2002 object *tmp = present_arch_in_ob (at, op);
2062 2003
2063 if (tmp == NULL) 2004 if (tmp == NULL)
2064 { 2005 {
2065 if ((tmp = arch_to_object (at)) == NULL) 2006 if ((tmp = arch_to_object (at)) == NULL)
2078 if (QUERY_FLAG (hitter, FLAG_ALIVE)) 2019 if (QUERY_FLAG (hitter, FLAG_ALIVE))
2079 tmp->stats.dam += hitter->level / 2; 2020 tmp->stats.dam += hitter->level / 2;
2080 else 2021 else
2081 tmp->stats.dam = dam; 2022 tmp->stats.dam = dam;
2082 2023
2083 copy_owner (tmp, hitter); /* so we get credit for poisoning kills */ 2024 tmp->set_owner (hitter); /* so we get credit for poisoning kills */
2084 if (hitter->skill && hitter->skill != tmp->skill) 2025 if (hitter->skill && hitter->skill != tmp->skill)
2085 { 2026 {
2086 tmp->skill = hitter->skill; 2027 tmp->skill = hitter->skill;
2087 } 2028 }
2088 2029
2094 tmp->stats.Con = MAX (-(dam / 4 + 1), -10); 2035 tmp->stats.Con = MAX (-(dam / 4 + 1), -10);
2095 tmp->stats.Str = MAX (-(dam / 3 + 2), -10); 2036 tmp->stats.Str = MAX (-(dam / 3 + 2), -10);
2096 tmp->stats.Dex = MAX (-(dam / 6 + 1), -10); 2037 tmp->stats.Dex = MAX (-(dam / 6 + 1), -10);
2097 tmp->stats.Int = MAX (-dam / 7, -10); 2038 tmp->stats.Int = MAX (-dam / 7, -10);
2098 SET_FLAG (tmp, FLAG_APPLIED); 2039 SET_FLAG (tmp, FLAG_APPLIED);
2099 fix_player (op); 2040 op->update_stats ();
2100 new_draw_info (NDI_UNIQUE, 0, op, "You suddenly feel very ill."); 2041 new_draw_info (NDI_UNIQUE, 0, op, "You suddenly feel very ill.");
2101 } 2042 }
2102 if (hitter->type == PLAYER) 2043 if (hitter->type == PLAYER)
2103 new_draw_info_format (NDI_UNIQUE, 0, hitter, "You poison %s.", &op->name); 2044 new_draw_info_format (NDI_UNIQUE, 0, hitter, "You poison %s.", &op->name);
2104 else if (get_owner (hitter) != NULL && hitter->owner->type == PLAYER) 2045 else if (hitter->owner != NULL && hitter->owner->type == PLAYER)
2105 new_draw_info_format (NDI_UNIQUE, 0, hitter->owner, "Your %s poisons %s.", &hitter->name, &op->name); 2046 new_draw_info_format (NDI_UNIQUE, 0, hitter->owner, "Your %s poisons %s.", &hitter->name, &op->name);
2106 } 2047 }
2107 tmp->speed_left = 0; 2048 tmp->speed_left = 0;
2108 } 2049 }
2109 else 2050 else
2111} 2052}
2112 2053
2113void 2054void
2114slow_player (object *op, object *hitter, int dam) 2055slow_player (object *op, object *hitter, int dam)
2115{ 2056{
2116 archetype *at = find_archetype ("slowness"); 2057 archetype *at = archetype::find ("slowness");
2117 object *tmp; 2058 object *tmp;
2118 2059
2119 if (at == NULL) 2060 if (at == NULL)
2120 { 2061 {
2121 LOG (llevError, "Can't find slowness archetype.\n"); 2062 LOG (llevError, "Can't find slowness archetype.\n");
2128 } 2069 }
2129 else 2070 else
2130 tmp->stats.food++; 2071 tmp->stats.food++;
2131 SET_FLAG (tmp, FLAG_APPLIED); 2072 SET_FLAG (tmp, FLAG_APPLIED);
2132 tmp->speed_left = 0; 2073 tmp->speed_left = 0;
2133 fix_player (op); 2074 op->update_stats ();
2134} 2075}
2135 2076
2136void 2077void
2137confuse_player (object *op, object *hitter, int dam) 2078confuse_player (object *op, object *hitter, int dam)
2138{ 2079{
2182 */ 2123 */
2183 tmp->speed = tmp->speed * (100.0 - (float) op->resist[ATNR_BLIND]) / 100; 2124 tmp->speed = tmp->speed * (100.0 - (float) op->resist[ATNR_BLIND]) / 100;
2184 2125
2185 tmp = insert_ob_in_ob (tmp, op); 2126 tmp = insert_ob_in_ob (tmp, op);
2186 change_abil (op, tmp); /* Mostly to display any messages */ 2127 change_abil (op, tmp); /* Mostly to display any messages */
2187 fix_player (op); /* This takes care of some other stuff */ 2128 op->update_stats (); /* This takes care of some other stuff */
2188 2129
2189 if (hitter->owner) 2130 if (hitter->owner)
2190 owner = get_owner (hitter); 2131 owner = hitter->owner;
2191 else 2132 else
2192 owner = hitter; 2133 owner = hitter;
2193 2134
2194 new_draw_info_format (NDI_UNIQUE, 0, owner, "Your attack blinds %s!", query_name (op)); 2135 new_draw_info_format (NDI_UNIQUE, 0, owner, "Your attack blinds %s!", query_name (op));
2195 } 2136 }
2341 } 2282 }
2342 2283
2343 /* aimed missiles use the owning object's sight */ 2284 /* aimed missiles use the owning object's sight */
2344 if (is_aimed_missile (hitter)) 2285 if (is_aimed_missile (hitter))
2345 { 2286 {
2346 if ((attacker = get_owner (hitter)) == NULL) 2287 if ((attacker = hitter->owner) == NULL)
2347 attacker = hitter; 2288 attacker = hitter;
2348 /* A player who saves but hasn't quit still could have objects 2289 /* A player who saves but hasn't quit still could have objects
2349 * owned by him - need to handle that case to avoid crashes. 2290 * owned by him - need to handle that case to avoid crashes.
2350 */ 2291 */
2351 if (QUERY_FLAG (attacker, FLAG_REMOVED)) 2292 if (QUERY_FLAG (attacker, FLAG_REMOVED))

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines