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.15 by root, Thu Sep 14 20:46:10 2006 UTC vs.
Revision 1.31 by root, Thu Dec 21 23:37:05 2006 UTC

1
2/*
3 * static char *rcsid_attack_c =
4 * "$Id: attack.C,v 1.15 2006/09/14 20:46:10 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
218 } 207 }
219 else 208 else
220 { 209 {
221 if (op->env) 210 if (op->env)
222 { 211 {
223 object *tmp = is_player_inv (op->env); 212 object *tmp = op->in_player ();
224 213
225 if (tmp) 214 if (tmp)
226 esrv_del_item (tmp->contr, op->count); 215 esrv_del_item (tmp->contr, op->count);
227 } 216 }
228 217
229 if (!QUERY_FLAG (op, FLAG_REMOVED)) 218 op->destroy ();
230 remove_ob (op);
231
232 free_object (op);
233 } 219 }
234 220
235 if (type & (AT_FIRE | AT_ELECTRICITY)) 221 if (type & (AT_FIRE | AT_ELECTRICITY))
236 if (env) 222 if (env)
237 { 223 {
247 233
248 /* The value of 50 is arbitrary. */ 234 /* The value of 50 is arbitrary. */
249 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))
250 { 236 {
251 object *tmp; 237 object *tmp;
252 archetype *at = find_archetype ("icecube"); 238 archetype *at = archetype::find ("icecube");
253 239
254 if (at == NULL) 240 if (at == NULL)
255 return; 241 return;
256 242
257 op = stop_item (op); 243 op = stop_item (op);
270 tmp->move_slow = 0; 256 tmp->move_slow = 0;
271 insert_ob_in_map (tmp, op->map, originator, 0); 257 insert_ob_in_map (tmp, op->map, originator, 0);
272 } 258 }
273 259
274 if (!QUERY_FLAG (op, FLAG_REMOVED)) 260 if (!QUERY_FLAG (op, FLAG_REMOVED))
275 remove_ob (op); 261 op->remove ();
276 262
277 insert_ob_in_ob (op, tmp); 263 insert_ob_in_ob (op, tmp);
278 return; 264 return;
279 } 265 }
280} 266}
288 274
289int 275int
290hit_map (object *op, int dir, int type, int full_hit) 276hit_map (object *op, int dir, int type, int full_hit)
291{ 277{
292 object *tmp, *next; 278 object *tmp, *next;
293 mapstruct *map; 279 maptile *map;
294 sint16 x, y; 280 sint16 x, y;
295 int retflag = 0; /* added this flag.. will return 1 if it hits a monster */ 281 int retflag = 0; /* added this flag.. will return 1 if it hits a monster */
296 282
297 tag_t op_tag, next_tag = 0;
298
299 if (QUERY_FLAG (op, FLAG_FREED)) 283 if (QUERY_FLAG (op, FLAG_FREED))
300 { 284 {
301 LOG (llevError, "BUG: hit_map(): free object\n"); 285 LOG (llevError, "BUG: hit_map(): free object\n");
302 return 0; 286 return 0;
303 } 287 }
314 return 0; 298 return 0;
315 } 299 }
316 300
317 if (op->head) 301 if (op->head)
318 op = op->head; 302 op = op->head;
319
320 op_tag = op->count;
321 303
322 map = op->map; 304 map = op->map;
323 x = op->x + freearr_x[dir]; 305 x = op->x + freearr_x[dir];
324 y = op->y + freearr_y[dir]; 306 y = op->y + freearr_y[dir];
325 307
352 shuffle_attack (op, 1); /*1 flag tells it to change the face */ 334 shuffle_attack (op, 1); /*1 flag tells it to change the face */
353 update_object (op, UP_OBJ_FACE); 335 update_object (op, UP_OBJ_FACE);
354 type &= ~AT_CHAOS; 336 type &= ~AT_CHAOS;
355 } 337 }
356 338
357 next = get_map_ob (map, x, y); 339 next = GET_MAP_OB (map, x, y);
358 if (next)
359 next_tag = next->count;
360 340
361 while (next) 341 while (next)
362 { 342 {
363 if (was_destroyed (next, next_tag)) 343 if (next->destroyed ())
364 { 344 {
365 /* There may still be objects that were above 'next', but there is no 345 /* There may still be objects that were above 'next', but there is no
366 * simple way to find out short of copying all object references and 346 * simple way to find out short of copying all object references and
367 * tags into a temporary array before we start processing the first 347 * tags into a temporary array before we start processing the first
368 * object. That's why we just abort. 348 * object. That's why we just abort.
376 } 356 }
377 357
378 tmp = next; 358 tmp = next;
379 next = tmp->above; 359 next = tmp->above;
380 360
381 if (next) 361 if (tmp->destroyed ())
382 next_tag = next->count;
383
384 if (QUERY_FLAG (tmp, FLAG_FREED))
385 { 362 {
386 LOG (llevError, "BUG: hit_map(): found freed object\n"); 363 LOG (llevError, "BUG: hit_map(): found freed object\n");
387 break; 364 break;
388 } 365 }
389 366
396 373
397 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 374 if (QUERY_FLAG (tmp, FLAG_ALIVE))
398 { 375 {
399 hit_player (tmp, op->stats.dam, op, type, full_hit); 376 hit_player (tmp, op->stats.dam, op, type, full_hit);
400 retflag |= 1; 377 retflag |= 1;
401 if (was_destroyed (op, op_tag)) 378 if (op->destroyed ())
402 break; 379 break;
403 } 380 }
404 381
405 /* Here we are potentially destroying an object. If the object has 382 /* Here we are potentially destroying an object. If the object has
406 * NO_PASS set, it is also immune - you can't destroy walls. Note 383 * NO_PASS set, it is also immune - you can't destroy walls. Note
410 * destroyed right now. 387 * destroyed right now.
411 */ 388 */
412 else if ((tmp->material || tmp->materialname) && op->stats.dam > 0 && !tmp->move_block) 389 else if ((tmp->material || tmp->materialname) && op->stats.dam > 0 && !tmp->move_block)
413 { 390 {
414 save_throw_object (tmp, type, op); 391 save_throw_object (tmp, type, op);
415 if (was_destroyed (op, op_tag)) 392 if (op->destroyed ())
416 break; 393 break;
417 } 394 }
418 } 395 }
419 396
420 return 0; 397 return 0;
423void 400void
424attack_message (int dam, int type, object *op, object *hitter) 401attack_message (int dam, int type, object *op, object *hitter)
425{ 402{
426 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF]; 403 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF];
427 int i, found = 0; 404 int i, found = 0;
428 mapstruct *map; 405 maptile *map;
429 object *next, *tmp; 406 object *next, *tmp;
430 407
431 /* put in a few special messages for some of the common attacktypes 408 /* put in a few special messages for some of the common attacktypes
432 * a player might have. For example, fire, electric, cold, etc 409 * a player might have. For example, fire, electric, cold, etc
433 * [garbled 20010919] 410 * [garbled 20010919]
450 sprintf (buf1, "missed %s", &op->name); 427 sprintf (buf1, "missed %s", &op->name);
451 sprintf (buf2, " misses"); 428 sprintf (buf2, " misses");
452 found++; 429 found++;
453 } 430 }
454 else if ((hitter->type == DISEASE || hitter->type == SYMPTOM || 431 else if ((hitter->type == DISEASE || hitter->type == SYMPTOM ||
455 hitter->type == POISONING || (type & AT_POISON && IS_LIVE (op))) && !found) 432 hitter->type == POISONING || (type & AT_POISON && op->is_alive ())) && !found)
456 { 433 {
457 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_SUFFER][i].level != -1; i++) 434 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_SUFFER][i].level != -1; i++)
458 if (dam < attack_mess[ATM_SUFFER][i].level || attack_mess[ATM_SUFFER][i + 1].level == -1) 435 if (dam < attack_mess[ATM_SUFFER][i].level || attack_mess[ATM_SUFFER][i + 1].level == -1)
459 { 436 {
460 sprintf (buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1, &op->name, attack_mess[ATM_SUFFER][i].buf2); 437 sprintf (buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1, &op->name, attack_mess[ATM_SUFFER][i].buf2);
472 strcpy (buf2, attack_mess[ATM_DOOR][i].buf3); 449 strcpy (buf2, attack_mess[ATM_DOOR][i].buf3);
473 found++; 450 found++;
474 break; 451 break;
475 } 452 }
476 } 453 }
477 else if (hitter->type == PLAYER && IS_LIVE (op)) 454 else if (hitter->type == PLAYER && op->is_alive ())
478 { 455 {
479 if (USING_SKILL (hitter, SK_KARATE)) 456 if (USING_SKILL (hitter, SK_KARATE))
480 { 457 {
481 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_KARATE][i].level != -1; i++) 458 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_KARATE][i].level != -1; i++)
482 if (dam < attack_mess[ATM_KARATE][i].level || attack_mess[ATM_KARATE][i + 1].level == -1) 459 if (dam < attack_mess[ATM_KARATE][i].level || attack_mess[ATM_KARATE][i + 1].level == -1)
508 found++; 485 found++;
509 break; 486 break;
510 } 487 }
511 } 488 }
512 } 489 }
490
513 if (found) 491 if (found)
514 { 492 {
515 /* done */ 493 /* done */
516 } 494 }
517 else if (IS_ARROW (hitter) && (type == AT_PHYSICAL || type == AT_MAGIC)) 495 else if (hitter->is_arrow () && (type == AT_PHYSICAL || type == AT_MAGIC))
518 { 496 {
519 sprintf (buf1, "hit"); /* just in case */ 497 sprintf (buf1, "hit"); /* just in case */
520 for (i = 0; i < MAXATTACKMESS; i++) 498 for (i = 0; i < MAXATTACKMESS; i++)
521 if (dam < attack_mess[ATM_ARROW][i].level || attack_mess[ATM_ARROW][i + 1].level == -1) 499 if (dam < attack_mess[ATM_ARROW][i].level || attack_mess[ATM_ARROW][i + 1].level == -1)
522 { 500 {
523 strcpy (buf2, attack_mess[ATM_ARROW][i].buf3); 501 strcpy (buf2, attack_mess[ATM_ARROW][i].buf3);
524 found++; 502 found++;
525 break; 503 break;
526 } 504 }
527 } 505 }
528 else if (type & AT_DRAIN && IS_LIVE (op)) 506 else if (type & AT_DRAIN && op->is_alive ())
529 { 507 {
530 /* drain is first, because some items have multiple attypes */ 508 /* drain is first, because some items have multiple attypes */
531 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_DRAIN][i].level != -1; i++) 509 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_DRAIN][i].level != -1; i++)
532 if (dam < attack_mess[ATM_DRAIN][i].level || attack_mess[ATM_DRAIN][i + 1].level == -1) 510 if (dam < attack_mess[ATM_DRAIN][i].level || attack_mess[ATM_DRAIN][i + 1].level == -1)
533 { 511 {
535 strcpy (buf2, attack_mess[ATM_DRAIN][i].buf3); 513 strcpy (buf2, attack_mess[ATM_DRAIN][i].buf3);
536 found++; 514 found++;
537 break; 515 break;
538 } 516 }
539 } 517 }
540 else if (type & AT_ELECTRICITY && IS_LIVE (op)) 518 else if (type & AT_ELECTRICITY && op->is_alive ())
541 { 519 {
542 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_ELEC][i].level != -1; i++) 520 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_ELEC][i].level != -1; i++)
543 if (dam < attack_mess[ATM_ELEC][i].level || attack_mess[ATM_ELEC][i + 1].level == -1) 521 if (dam < attack_mess[ATM_ELEC][i].level || attack_mess[ATM_ELEC][i + 1].level == -1)
544 { 522 {
545 sprintf (buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1, &op->name, attack_mess[ATM_ELEC][i].buf2); 523 sprintf (buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1, &op->name, attack_mess[ATM_ELEC][i].buf2);
546 strcpy (buf2, attack_mess[ATM_ELEC][i].buf3); 524 strcpy (buf2, attack_mess[ATM_ELEC][i].buf3);
547 found++; 525 found++;
548 break; 526 break;
549 } 527 }
550 } 528 }
551 else if (type & AT_COLD && IS_LIVE (op)) 529 else if (type & AT_COLD && op->is_alive ())
552 { 530 {
553 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_COLD][i].level != -1; i++) 531 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_COLD][i].level != -1; i++)
554 if (dam < attack_mess[ATM_COLD][i].level || attack_mess[ATM_COLD][i + 1].level == -1) 532 if (dam < attack_mess[ATM_COLD][i].level || attack_mess[ATM_COLD][i + 1].level == -1)
555 { 533 {
556 sprintf (buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1, &op->name, attack_mess[ATM_COLD][i].buf2); 534 sprintf (buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1, &op->name, attack_mess[ATM_COLD][i].buf2);
633 strcpy (buf1, "hit"); 611 strcpy (buf1, "hit");
634 strcpy (buf2, " hits"); 612 strcpy (buf2, " hits");
635 } 613 }
636 614
637 /* bail out if a monster is casting spells */ 615 /* bail out if a monster is casting spells */
638 if (!(hitter->type == PLAYER || (get_owner (hitter) != NULL && hitter->owner->type == PLAYER))) 616 if (!(hitter->type == PLAYER || (hitter->owner != NULL && hitter->owner->type == PLAYER)))
639 return; 617 return;
640 618
641 /* scale down magic considerably. */ 619 /* scale down magic considerably. */
642 if (type & AT_MAGIC && rndm (0, 5)) 620 if (type & AT_MAGIC && rndm (0, 5))
643 return; 621 return;
644 622
645 /* Did a player hurt another player? Inform both! */ 623 /* Did a player hurt another player? Inform both! */
646 if (op->type == PLAYER && (get_owner (hitter) == NULL ? hitter->type : hitter->owner->type) == PLAYER) 624 if (op->type == PLAYER && (hitter->owner == NULL ? hitter->type : hitter->owner->type) == PLAYER)
647 { 625 {
648 if (get_owner (hitter) != NULL) 626 if (hitter->owner != NULL)
649 sprintf (buf, "%s's %s%s you.", &hitter->owner->name, &hitter->name, buf2); 627 sprintf (buf, "%s's %s%s you.", &hitter->owner->name, &hitter->name, buf2);
650 else 628 else
651 { 629 {
652 sprintf (buf, "%s%s you.", &hitter->name, buf2); 630 sprintf (buf, "%s%s you.", &hitter->name, buf2);
653 if (dam != 0) 631 if (dam != 0)
675 else 653 else
676 play_sound_player_only (hitter->contr, SOUND_PLAYER_HITS3, 0, 0); 654 play_sound_player_only (hitter->contr, SOUND_PLAYER_HITS3, 0, 0);
677 } 655 }
678 new_draw_info (NDI_BLACK, 0, hitter, buf); 656 new_draw_info (NDI_BLACK, 0, hitter, buf);
679 } 657 }
680 else if (get_owner (hitter) != NULL && hitter->owner->type == PLAYER) 658 else if (hitter->owner != NULL && hitter->owner->type == PLAYER)
681 { 659 {
682 /* look for stacked spells and start reducing the message chances */ 660 /* look for stacked spells and start reducing the message chances */
683 if (hitter->type == SPELL_EFFECT && (hitter->subtype == SP_EXPLOSION || hitter->subtype == SP_BULLET || hitter->subtype == SP_CONE)) 661 if (hitter->type == SPELL_EFFECT && (hitter->subtype == SP_EXPLOSION || hitter->subtype == SP_BULLET || hitter->subtype == SP_CONE))
684 { 662 {
685 i = 4; 663 i = 4;
686 map = hitter->map; 664 map = hitter->map;
687 if (out_of_map (map, hitter->x, hitter->y)) 665 if (out_of_map (map, hitter->x, hitter->y))
688 return; 666 return;
689 next = get_map_ob (map, hitter->x, hitter->y); 667 next = GET_MAP_OB (map, hitter->x, hitter->y);
690 if (next) 668 if (next)
691 while (next) 669 while (next)
692 { 670 {
693 if (next->type == SPELL_EFFECT && (next->subtype == SP_EXPLOSION || next->subtype == SP_BULLET || next->subtype == SP_CONE)) 671 if (next->type == SPELL_EFFECT && (next->subtype == SP_EXPLOSION || next->subtype == SP_BULLET || next->subtype == SP_CONE))
694 i *= 3; 672 i *= 3;
760attack_ob_simple (object *op, object *hitter, int base_dam, int base_wc) 738attack_ob_simple (object *op, object *hitter, int base_dam, int base_wc)
761{ 739{
762 int simple_attack, roll, dam = 0; 740 int simple_attack, roll, dam = 0;
763 uint32 type; 741 uint32 type;
764 shstr op_name; 742 shstr op_name;
765 tag_t op_tag, hitter_tag;
766 743
767 if (get_attack_mode (&op, &hitter, &simple_attack)) 744 if (get_attack_mode (&op, &hitter, &simple_attack))
768 goto error; 745 goto error;
769 746
770 if (hitter->current_weapon) 747 if (hitter->current_weapon)
771 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op))) 748 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op)))
772 return RESULT_INT (0); 749 return RESULT_INT (0);
773 750
774 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter))) 751 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter)))
775 return RESULT_INT (0); 752 return RESULT_INT (0);
776
777 op_tag = op->count;
778 hitter_tag = hitter->count;
779 753
780 /* 754 /*
781 * A little check to make it more difficult to dance forward and back 755 * A little check to make it more difficult to dance forward and back
782 * to avoid ever being hit by monsters. 756 * to avoid ever being hit by monsters.
783 */ 757 */
788 * which then gets here again. By decreasing the speed before 762 * which then gets here again. By decreasing the speed before
789 * we call process_object, the 'if' statement above will fail. 763 * we call process_object, the 'if' statement above will fail.
790 */ 764 */
791 op->speed_left--; 765 op->speed_left--;
792 process_object (op); 766 process_object (op);
767
793 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 768 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
794 goto error; 769 goto error;
795 } 770 }
796 771
797 op_name = op->name; 772 op_name = op->name;
798 773
832 if (QUERY_FLAG (op, FLAG_SLEEP)) 807 if (QUERY_FLAG (op, FLAG_SLEEP))
833 CLEAR_FLAG (op, FLAG_SLEEP); 808 CLEAR_FLAG (op, FLAG_SLEEP);
834 809
835 /* If the victim can't see the attacker, it may alert others 810 /* If the victim can't see the attacker, it may alert others
836 * for help. */ 811 * for help. */
837 if (op->type != PLAYER && !can_see_enemy (op, hitter) && !get_owner (op) && rndm (0, op->stats.Int)) 812 if (op->type != PLAYER && !can_see_enemy (op, hitter) && !op->owner && rndm (0, op->stats.Int))
838 npc_call_help (op); 813 npc_call_help (op);
839 814
840 /* if you were hidden and hit by a creature, you are discovered */ 815 /* if you were hidden and hit by a creature, you are discovered */
841 if (op->hide && QUERY_FLAG (hitter, FLAG_ALIVE)) 816 if (op->hide && QUERY_FLAG (hitter, FLAG_ALIVE))
842 { 817 {
849 * when they hit the victim. For things like thrown daggers, 824 * when they hit the victim. For things like thrown daggers,
850 * this sets 'hitter' to the actual dagger, and not the 825 * this sets 'hitter' to the actual dagger, and not the
851 * wrapper object. 826 * wrapper object.
852 */ 827 */
853 thrown_item_effect (hitter, op); 828 thrown_item_effect (hitter, op);
829
854 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack)) 830 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
855 goto leave; 831 goto leave;
856 } 832 }
857 833
858 /* Need to do at least 1 damage, otherwise there is no point 834 /* Need to do at least 1 damage, otherwise there is no point
859 * to go further and it will cause FPE's below. 835 * to go further and it will cause FPE's below.
860 */ 836 */
861 if (hitdam <= 0) 837 if (hitdam <= 0)
862 hitdam = 1; 838 hitdam = 1;
863 839
864 type = hitter->attacktype; 840 type = hitter->attacktype;
841
865 if (!type) 842 if (!type)
866 type = AT_PHYSICAL; 843 type = AT_PHYSICAL;
844
867 /* Handle monsters that hit back */ 845 /* Handle monsters that hit back */
868 if (!simple_attack && QUERY_FLAG (op, FLAG_HITBACK) && QUERY_FLAG (hitter, FLAG_ALIVE)) 846 if (!simple_attack && QUERY_FLAG (op, FLAG_HITBACK) && QUERY_FLAG (hitter, FLAG_ALIVE))
869 { 847 {
870 if (op->attacktype & AT_ACID && hitter->type == PLAYER) 848 if (op->attacktype & AT_ACID && hitter->type == PLAYER)
871 new_draw_info (NDI_UNIQUE, 0, hitter, "You are splashed by acid!\n"); 849 new_draw_info (NDI_UNIQUE, 0, hitter, "You are splashed by acid!\n");
850
872 hit_player (hitter, random_roll (0, (op->stats.dam), hitter, PREFER_LOW), op, op->attacktype, 1); 851 hit_player (hitter, random_roll (0, (op->stats.dam), hitter, PREFER_LOW), op, op->attacktype, 1);
852
873 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 853 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
874 goto leave; 854 goto leave;
875 } 855 }
876 856
877 /* In the new attack code, it should handle multiple attack 857 /* In the new attack code, it should handle multiple attack
878 * types in its area, so remove it from here. 858 * types in its area, so remove it from here.
879 */ 859 */
880 dam = hit_player (op, random_roll (1, hitdam, hitter, PREFER_HIGH), hitter, type, 1); 860 dam = hit_player (op, random_roll (1, hitdam, hitter, PREFER_HIGH), hitter, type, 1);
861
881 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 862 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
882 goto leave; 863 goto leave;
883 } /* end of if hitter hit op */ 864 } /* end of if hitter hit op */
884 /* if we missed, dam=0 */ 865 /* if we missed, dam=0 */
885 866
886 /*attack_message(dam, type, op, hitter); */ 867 /*attack_message(dam, type, op, hitter); */
920 if (op->weight <= 5000 && tmp->stats.hp >= 0) 901 if (op->weight <= 5000 && tmp->stats.hp >= 0)
921 { 902 {
922 if (tmp->head != NULL) 903 if (tmp->head != NULL)
923 tmp = tmp->head; 904 tmp = tmp->head;
924 905
925 remove_ob (op); 906 op->remove ();
926 op = insert_ob_in_ob (op, tmp); 907 op = insert_ob_in_ob (op, tmp);
927 908
928 if (tmp->type == PLAYER) 909 if (tmp->type == PLAYER)
929 esrv_send_item (tmp, op); 910 esrv_send_item (tmp, op);
930 911
943object * 924object *
944hit_with_arrow (object *op, object *victim) 925hit_with_arrow (object *op, object *victim)
945{ 926{
946 object *container, *hitter; 927 object *container, *hitter;
947 int hit_something = 0; 928 int hit_something = 0;
948 tag_t victim_tag, hitter_tag;
949 sint16 victim_x, victim_y;
950 929
951 /* Disassemble missile */ 930 /* Disassemble missile */
952 if (op->inv) 931 if (op->inv)
953 { 932 {
954 container = op; 933 container = op;
955 hitter = op->inv; 934 hitter = op->inv;
956 remove_ob (hitter); 935 hitter->remove ();
957 insert_ob_in_map (hitter, container->map, hitter, INS_NO_MERGE | INS_NO_WALK_ON); 936 insert_ob_in_map (hitter, container->map, hitter, INS_NO_MERGE | INS_NO_WALK_ON);
958 /* Note that we now have an empty THROWN_OBJ on the map. Code that 937 /* Note that we now have an empty THROWN_OBJ on the map. Code that
959 * might be called until this THROWN_OBJ is either reassembled or 938 * might be called until this THROWN_OBJ is either reassembled or
960 * removed at the end of this function must be able to deal with empty 939 * removed at the end of this function must be able to deal with empty
961 * THROWN_OBJs. */ 940 * THROWN_OBJs. */
962 } 941 }
963 else 942 else
964 { 943 {
965 container = NULL; 944 container = 0;
966 hitter = op; 945 hitter = op;
967 } 946 }
968 947
969 /* Try to hit victim */ 948 /* Try to hit victim */
970 victim_x = victim->x;
971 victim_y = victim->y;
972 victim_tag = victim->count;
973 hitter_tag = hitter->count;
974
975 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc); 949 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc);
976 950
977 /* Arrow attacks door, rune of summoning is triggered, demon is put on 951 /* Arrow attacks door, rune of summoning is triggered, demon is put on
978 * arrow, move_apply() calls this function, arrow sticks in demon, 952 * arrow, move_apply() calls this function, arrow sticks in demon,
979 * attack_ob_simple() returns, and we've got an arrow that still exists 953 * attack_ob_simple() returns, and we've got an arrow that still exists
980 * but is no longer on the map. Ugh. (Beware: Such things can happen at 954 * but is no longer on the map. Ugh. (Beware: Such things can happen at
981 * other places as well!) 955 * other places as well!)
982 */ 956 */
983 if (was_destroyed (hitter, hitter_tag) || hitter->env != NULL) 957 if (hitter->destroyed () || hitter->env != NULL)
984 { 958 {
985 if (container) 959 if (container)
986 { 960 {
987 remove_ob (container); 961 container->remove ();
988 free_object (container); 962 container->destroy ();
989 } 963 }
964
990 return NULL; 965 return 0;
991 } 966 }
992 967
993 /* Missile hit victim */ 968 /* Missile hit victim */
994 /* if the speed is > 10, then this is a fast moving arrow, we go straight 969 /* if the speed is > 10, then this is a fast moving arrow, we go straight
995 * through the target 970 * through the target
996 */ 971 */
997 if (hit_something && op->speed <= 10.0) 972 if (hit_something && op->speed <= 10.0)
998 { 973 {
999 /* Stop arrow */ 974 /* Stop arrow */
1000 if (container == NULL) 975 if (!container)
1001 { 976 {
1002 hitter = fix_stopped_arrow (hitter); 977 hitter = fix_stopped_arrow (hitter);
1003 if (hitter == NULL) 978 if (!hitter)
1004 return NULL; 979 return 0;
1005 } 980 }
1006 else 981 else
1007 { 982 container->destroy ();
1008 remove_ob (container);
1009 free_object (container);
1010 }
1011 983
1012 /* Try to stick arrow into victim */ 984 /* Try to stick arrow into victim */
1013 if (!was_destroyed (victim, victim_tag) && stick_arrow (hitter, victim)) 985 if (!victim->destroyed () && stick_arrow (hitter, victim))
1014 return NULL; 986 return 0;
1015 987
1016 /* Else try to put arrow on victim's map square 988 /* Else try to put arrow on victim's map square
1017 * remove check for P_WALL here. If the arrow got to this 989 * remove check for P_WALL here. If the arrow got to this
1018 * space, that is good enough - with the new movement code, 990 * space, that is good enough - with the new movement code,
1019 * there is now the potential for lots of spaces where something 991 * there is now the potential for lots of spaces where something
1020 * can fly over but not otherwise move over. What is the correct 992 * can fly over but not otherwise move over. What is the correct
1021 * way to handle those otherwise? 993 * way to handle those otherwise?
1022 */ 994 */
1023 if (victim_x != hitter->x || victim_y != hitter->y) 995 if (victim->x != hitter->x || victim->y != hitter->y)
1024 { 996 {
1025 remove_ob (hitter); 997 hitter->remove ();
1026 hitter->x = victim_x; 998 hitter->x = victim->x;
1027 hitter->y = victim_y; 999 hitter->y = victim->y;
1028 insert_ob_in_map (hitter, victim->map, hitter, 0); 1000 insert_ob_in_map (hitter, victim->map, hitter, 0);
1029 } 1001 }
1030 else 1002 else
1031 {
1032 /* Else leave arrow where it is */ 1003 /* Else leave arrow where it is */
1033 merge_ob (hitter, NULL); 1004 merge_ob (hitter, NULL);
1034 } 1005
1035 return NULL; 1006 return 0;
1036 } 1007 }
1037 1008
1038 if (hit_something && op->speed >= 10.0) 1009 if (hit_something && op->speed >= 10.0)
1039 op->speed -= 1.0; 1010 op->speed -= 1.0;
1040 1011
1041 /* Missile missed victim - reassemble missile */ 1012 /* Missile missed victim - reassemble missile */
1042 if (container) 1013 if (container)
1043 { 1014 {
1044 remove_ob (hitter); 1015 hitter->remove ();
1045 insert_ob_in_ob (hitter, container); 1016 insert_ob_in_ob (hitter, container);
1046 } 1017 }
1018
1047 return op; 1019 return op;
1048} 1020}
1049 1021
1050 1022
1051void 1023void
1060 } 1032 }
1061 else if (!GET_ANIM_ID (op)) 1033 else if (!GET_ANIM_ID (op))
1062 { 1034 {
1063 /* Object has been called - no animations, so remove it */ 1035 /* Object has been called - no animations, so remove it */
1064 if (op->stats.hp < 0) 1036 if (op->stats.hp < 0)
1037 op->destroy ();
1065 { 1038
1066 remove_ob (op); /* Should update LOS */
1067 free_object (op);
1068 /* Don't know why this is here - remove_ob should do it for us */
1069 /*update_position(m, x, y); */
1070 }
1071 return; /* no animations, so nothing more to do */ 1039 return; /* no animations, so nothing more to do */
1072 } 1040 }
1041
1073 perc = NUM_ANIMATIONS (op) - ((int) NUM_ANIMATIONS (op) * op->stats.hp) / op->stats.maxhp; 1042 perc = NUM_ANIMATIONS (op) - ((int) NUM_ANIMATIONS (op) * op->stats.hp) / op->stats.maxhp;
1043
1074 if (perc >= (int) NUM_ANIMATIONS (op)) 1044 if (perc >= (int) NUM_ANIMATIONS (op))
1075 perc = NUM_ANIMATIONS (op) - 1; 1045 perc = NUM_ANIMATIONS (op) - 1;
1076 else if (perc < 1) 1046 else if (perc < 1)
1077 perc = 1; 1047 perc = 1;
1048
1078 SET_ANIMATION (op, perc); 1049 SET_ANIMATION (op, perc);
1079 update_object (op, UP_OBJ_FACE); 1050 update_object (op, UP_OBJ_FACE);
1051
1080 if (perc == NUM_ANIMATIONS (op) - 1) 1052 if (perc == NUM_ANIMATIONS (op) - 1)
1081 { /* Reached the last animation */ 1053 { /* Reached the last animation */
1082 if (op->face == blank_face) 1054 if (op->face == blank_face)
1083 {
1084 /* If the last face is blank, remove the ob */ 1055 /* If the last face is blank, remove the ob */
1085 remove_ob (op); /* Should update LOS */ 1056 op->destroy ();
1086 free_object (op);
1087
1088 /* remove_ob should call update_position for us */
1089 /*update_position(m, x, y); */
1090
1091 }
1092 else 1057 else
1093 { /* The last face was not blank, leave an image */ 1058 { /* The last face was not blank, leave an image */
1094 CLEAR_FLAG (op, FLAG_BLOCKSVIEW); 1059 CLEAR_FLAG (op, FLAG_BLOCKSVIEW);
1095 update_all_los (op->map, op->x, op->y); 1060 update_all_los (op->map, op->x, op->y);
1096 op->move_block = 0; 1061 op->move_block = 0;
1100} 1065}
1101 1066
1102void 1067void
1103scare_creature (object *target, object *hitter) 1068scare_creature (object *target, object *hitter)
1104{ 1069{
1105 object *owner = get_owner (hitter); 1070 object *owner = hitter->owner;
1106 1071
1107 if (!owner) 1072 if (!owner)
1108 owner = hitter; 1073 owner = hitter;
1109 1074
1110 SET_FLAG (target, FLAG_SCARED); 1075 SET_FLAG (target, FLAG_SCARED);
1314 * Try to credit the owner. We try to display player -> player drain 1279 * Try to credit the owner. We try to display player -> player drain
1315 * attacks, hence all the != PLAYER checks. 1280 * attacks, hence all the != PLAYER checks.
1316 */ 1281 */
1317 if (!op_on_battleground (hitter, NULL, NULL) && !QUERY_FLAG (op, FLAG_WAS_WIZ)) 1282 if (!op_on_battleground (hitter, NULL, NULL) && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1318 { 1283 {
1319 object *owner = get_owner (hitter); 1284 object *owner = hitter->owner;
1320 1285
1321 if (owner && owner != hitter) 1286 if (owner && owner != hitter)
1322 { 1287 {
1323 if (op->type != PLAYER || owner->type != PLAYER) 1288 if (op->type != PLAYER || owner->type != PLAYER)
1324 change_exp (owner, op->stats.exp / (rate * 2), 1289 change_exp (owner, op->stats.exp / (rate * 2),
1466 op->speed = 0.1; 1431 op->speed = 0.1;
1467 update_ob_speed (op); 1432 update_ob_speed (op);
1468 op->speed_left = -0.05; 1433 op->speed_left = -0.05;
1469 return maxdam; 1434 return maxdam;
1470 } 1435 }
1436
1471 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER) 1437 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER)
1472 { 1438 {
1473 remove_friendly_object (op); 1439 remove_friendly_object (op);
1440
1474 if (get_owner (op) != NULL && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op) 1441 if (op->owner && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op)
1475 {
1476 op->owner->contr->ranges[range_golem] = NULL; 1442 op->owner->contr->ranges[range_golem] = 0;
1477 op->owner->contr->golem_count = 0;
1478 }
1479 1443
1480 remove_ob (op); 1444 op->destroy ();
1481 free_object (op);
1482 return maxdam; 1445 return maxdam;
1483 } 1446 }
1484 1447
1485 /* Now lets start dealing with experience we get for killing something */ 1448 /* Now lets start dealing with experience we get for killing something */
1486 1449
1487 owner = get_owner (hitter); 1450 owner = hitter->owner;
1488 if (owner == NULL) 1451 if (!owner)
1489 owner = hitter; 1452 owner = hitter;
1490 1453
1491 /* is the victim (op) standing on battleground? */ 1454 /* is the victim (op) standing on battleground? */
1492 if (op_on_battleground (op, NULL, NULL)) 1455 if (op_on_battleground (op, NULL, NULL))
1493 battleg = 1; 1456 battleg = 1;
1513 char buf[256]; 1476 char buf[256];
1514 1477
1515 tmv = localtime (&t); 1478 tmv = localtime (&t);
1516 strftime (buf, 256, "%a %b %d %H:%M:%S %Y", tmv); 1479 strftime (buf, 256, "%a %b %d %H:%M:%S %Y", tmv);
1517 1480
1518 LOG (llevInfo, "%s PLAYER_KILL_PLAYER: %s (%s) killed %s\n", buf, &owner->name, owner->contr->socket.host, query_name (op)); 1481 LOG (llevInfo, "%s PLAYER_KILL_PLAYER: %s (%s) killed %s\n", buf, &owner->name, owner->contr->ns->host, query_name (op));
1519 } 1482 }
1520 1483
1521 /* try to filter some things out - basically, if you are 1484 /* try to filter some things out - basically, if you are
1522 * killing a level 1 creature and your level 20, you 1485 * killing a level 1 creature and your level 20, you
1523 * probably don't want to see that. 1486 * probably don't want to see that.
1524 */ 1487 */
1525 if (owner->level < op->level * 2 || op->stats.exp > 1000) 1488 if (owner->level < op->level * 2 || op->stats.exp > 1000)
1526 { 1489 {
1527 if (owner != hitter) 1490 if (owner != hitter)
1528 {
1529 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter)); 1491 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter));
1530 }
1531 else 1492 else
1532 {
1533 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op)); 1493 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op));
1534 } 1494
1535 /* Only play sounds for melee kills */ 1495 /* Only play sounds for melee kills */
1536 if (hitter->type == PLAYER) 1496 if (hitter->type == PLAYER)
1537 play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS); 1497 play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS);
1538 } 1498 }
1539 1499
1550 1510
1551 /* This code below deals with finding the appropriate skill 1511 /* This code below deals with finding the appropriate skill
1552 * to credit exp to. This is a bit problematic - we should 1512 * to credit exp to. This is a bit problematic - we should
1553 * probably never really have to look at current_weapon->skill 1513 * probably never really have to look at current_weapon->skill
1554 */ 1514 */
1555 skill = NULL; 1515 skill = 0;
1516
1556 if (hitter->skill && hitter->type != PLAYER) 1517 if (hitter->skill && hitter->type != PLAYER)
1557 skill = hitter->skill; 1518 skill = hitter->skill;
1558 else if (owner->chosen_skill) 1519 else if (owner->chosen_skill)
1559 { 1520 {
1560 skill = owner->chosen_skill->skill; 1521 skill = owner->chosen_skill->skill;
1579 break; 1540 break;
1580 } 1541 }
1581 } 1542 }
1582 } /* Was it a player that hit somethign */ 1543 } /* Was it a player that hit somethign */
1583 else 1544 else
1584 {
1585 skill = NULL; 1545 skill = 0;
1586 }
1587 1546
1588 /* Pet (or spell) killed something. */ 1547 /* Pet (or spell) killed something. */
1589 if (owner != hitter) 1548 if (owner != hitter)
1590 {
1591 (void) sprintf (buf, "%s killed %s with %s%s%s.", &owner->name, 1549 sprintf (buf, "%s killed %s with %s%s%s.", &owner->name,
1592 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : ""); 1550 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : "");
1593 }
1594 else 1551 else
1595 {
1596 (void) sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name, 1552 sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name,
1597 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ? 1553 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ?
1598 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : ""); 1554 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : "");
1599 } 1555
1600 /* These may have been set in the player code section above */ 1556 /* These may have been set in the player code section above */
1601 if (!skop) 1557 if (!skop)
1602 skop = hitter->chosen_skill; 1558 skop = hitter->chosen_skill;
1559
1603 if (!skill && skop) 1560 if (!skill && skop)
1604 skill = skop->skill; 1561 skill = skop->skill;
1605 1562
1606 new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf); 1563 new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf);
1607 1564
1608
1609 /* If you didn't kill yourself, and your not the wizard */ 1565 /* If you didn't kill yourself, and your not the wizard */
1610 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ)) 1566 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1611 { 1567 {
1612 int exp; 1568 int exp;
1613 1569
1614 /* Really don't give much experience for killing other players */ 1570 /* Really don't give much experience for killing other players */
1615 // schmorp: temporary? reduce the amount of exp gained for pking enourmously 1571 // schmorp: temporarily? reduce the amount of exp gained for pking enourmously
1616 if (op->type == PLAYER) 1572 if (op->type == PLAYER)
1617 { 1573 {
1618 if (battleg) 1574 if (battleg)
1619 { 1575 {
1620 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!"); 1576 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!");
1638 1594
1639 if (!settings.simple_exp) 1595 if (!settings.simple_exp)
1640 exp = exp / 2; 1596 exp = exp / 2;
1641 1597
1642 if (owner->type != PLAYER || owner->contr->party == NULL) 1598 if (owner->type != PLAYER || owner->contr->party == NULL)
1643 {
1644 change_exp (owner, exp, skill, 0); 1599 change_exp (owner, exp, skill, 0);
1645 }
1646 else 1600 else
1647 { 1601 {
1648 int shares = 0, count = 0; 1602 int shares = 0, count = 0;
1649
1650 player *pl; 1603 player *pl;
1651
1652 partylist *party = owner->contr->party; 1604 partylist *party = owner->contr->party;
1653 1605
1654#ifdef PARTY_KILL_LOG 1606#ifdef PARTY_KILL_LOG
1655 add_kill_to_party (party, query_name (owner), query_name (op), exp); 1607 add_kill_to_party (party, query_name (owner), query_name (op), exp);
1656#endif 1608#endif
1657 for (pl = first_player; pl != NULL; pl = pl->next) 1609 for (pl = first_player; pl != NULL; pl = pl->next)
1658 {
1659 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) 1610 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1660 { 1611 {
1661 count++; 1612 count++;
1662 shares += (pl->ob->level + 4); 1613 shares += (pl->ob->level + 4);
1663 } 1614 }
1664 } 1615
1665 if (count == 1 || shares > exp) 1616 if (count == 1 || shares > exp || !shares)
1666 change_exp (owner, exp, skill, SK_EXP_TOTAL); 1617 change_exp (owner, exp, skill, SK_EXP_TOTAL);
1667 else 1618 else
1668 { 1619 {
1669 int share = exp / shares, given = 0, nexp; 1620 int share = exp / shares, given = 0, nexp;
1670 1621
1671 for (pl = first_player; pl != NULL; pl = pl->next) 1622 for (pl = first_player; pl != NULL; pl = pl->next)
1672 {
1673 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) 1623 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1674 { 1624 {
1675 nexp = (pl->ob->level + 4) * share; 1625 nexp = (pl->ob->level + 4) * share;
1676 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL); 1626 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL);
1677 given += nexp; 1627 given += nexp;
1678 } 1628 }
1679 } 1629
1680 exp -= given; 1630 exp -= given;
1681 /* give any remainder to the player */ 1631 /* give any remainder to the player */
1682 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL); 1632 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL);
1683 } 1633 }
1684 } /* else part of a party */ 1634 } /* else part of a party */
1685
1686 } /* end if person didn't kill himself */ 1635 } /* end if person didn't kill himself */
1687 1636
1688 if (op->type != PLAYER) 1637 if (op->type != PLAYER)
1689 { 1638 {
1690 if (QUERY_FLAG (op, FLAG_FRIENDLY)) 1639 if (QUERY_FLAG (op, FLAG_FRIENDLY))
1691 { 1640 {
1692 object *owner1 = get_owner (op); 1641 object *owner1 = op->owner;
1693 1642
1694 if (owner1 != NULL && owner1->type == PLAYER) 1643 if (owner1 && owner1->type == PLAYER)
1695 { 1644 {
1696 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0); 1645 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0);
1697 /* Maybe we should include the owner that killed this, maybe not */ 1646 /* Maybe we should include the owner that killed this, maybe not */
1698 new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name); 1647 new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name);
1699 } 1648 }
1700 1649
1701 remove_friendly_object (op); 1650 remove_friendly_object (op);
1702 } 1651 }
1703 1652
1704 remove_ob (op); 1653 op->destroy ();
1705 free_object (op);
1706 } 1654 }
1707 /* Player has been killed! */
1708 else 1655 else
1709 { 1656 {
1657 /* Player has been killed! */
1710 if (owner->type == PLAYER) 1658 if (owner->type == PLAYER)
1711 {
1712 snprintf (op->contr->killer, BIG_NAME, "%s the %s", &owner->name, owner->contr->title); 1659 snprintf (op->contr->killer, sizeof (op->contr->killer), "%s the %s", &owner->name, owner->contr->title);
1713 }
1714 else 1660 else
1715 assign (op->contr->killer, hitter->name); 1661 assign (op->contr->killer, hitter->name);
1716 } 1662 }
1717 1663
1718 /* This was return -1 - that doesn't seem correct - if we return -1, process 1664 /* This was return -1 - that doesn't seem correct - if we return -1, process
1742 return 0; 1688 return 0;
1743 1689
1744 if (hitter->type == PLAYER && hitter->contr->peaceful == 1) 1690 if (hitter->type == PLAYER && hitter->contr->peaceful == 1)
1745 return 1; 1691 return 1;
1746 1692
1747 if ((owner = get_owner (hitter)) != NULL) 1693 if ((owner = hitter->owner) != NULL)
1748 { 1694 {
1749 if (owner->type == PLAYER && owner->contr->peaceful == 1) 1695 if (owner->type == PLAYER && owner->contr->peaceful == 1)
1750 friendlyfire = 2; 1696 friendlyfire = 2;
1751 } 1697 }
1752 1698
1773{ 1719{
1774 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC); 1720 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC);
1775 int maxattacktype, attacknum; 1721 int maxattacktype, attacknum;
1776 int body_attack = op && op->head; /* Did we hit op's head? */ 1722 int body_attack = op && op->head; /* Did we hit op's head? */
1777 int simple_attack; 1723 int simple_attack;
1778 tag_t op_tag, hitter_tag;
1779 int rtn_kill = 0; 1724 int rtn_kill = 0;
1780 int friendlyfire; 1725 int friendlyfire;
1781 1726
1782 if (get_attack_mode (&op, &hitter, &simple_attack)) 1727 if (get_attack_mode (&op, &hitter, &simple_attack))
1783 return 0; 1728 return 0;
1787 return 0; 1732 return 0;
1788 1733
1789#ifdef PROHIBIT_PLAYERKILL 1734#ifdef PROHIBIT_PLAYERKILL
1790 if (op->type == PLAYER) 1735 if (op->type == PLAYER)
1791 { 1736 {
1792 object *owner = get_owner (hitter); 1737 object *owner = hitter->owner;
1793 1738
1794 if (!owner) 1739 if (!owner)
1795 owner = hitter; 1740 owner = hitter;
1741
1796 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner) 1742 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner)
1797 {
1798 return 0; 1743 return 0;
1799 }
1800 } 1744 }
1801#endif 1745#endif
1802
1803 op_tag = op->count;
1804 hitter_tag = hitter->count;
1805 1746
1806 if (body_attack) 1747 if (body_attack)
1807 { 1748 {
1808 /* slow and paralyze must hit the head. But we don't want to just 1749 /* slow and paralyze must hit the head. But we don't want to just
1809 * return - we still need to process other attacks the spell still 1750 * return - we still need to process other attacks the spell still
1815 * attack so we don't cancel out things like magic bullet. 1756 * attack so we don't cancel out things like magic bullet.
1816 */ 1757 */
1817 if (type & (AT_PARALYZE | AT_SLOW)) 1758 if (type & (AT_PARALYZE | AT_SLOW))
1818 { 1759 {
1819 type &= ~(AT_PARALYZE | AT_SLOW); 1760 type &= ~(AT_PARALYZE | AT_SLOW);
1761
1820 if (!type || type == AT_MAGIC) 1762 if (!type || type == AT_MAGIC)
1821 return 0; 1763 return 0;
1822 } 1764 }
1823 } 1765 }
1824 1766
1828 1770
1829 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) 1771 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1830 if (tmp->type == RUNE || tmp->type == TRAP) 1772 if (tmp->type == RUNE || tmp->type == TRAP)
1831 { 1773 {
1832 spring_trap (tmp, hitter); 1774 spring_trap (tmp, hitter);
1775
1833 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack)) 1776 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
1834 return 0; 1777 return 0;
1778
1835 break; 1779 break;
1836 } 1780 }
1837 } 1781 }
1838 1782
1839 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0) 1783 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0)
1840 { 1784 {
1841 /* FIXME: If a player is killed by a rune in a door, the 1785 /* FIXME: If a player is killed by a rune in a door, the
1842 * was_destroyed() check above doesn't return, and might get here. 1786 * destroyed() check above doesn't return, and might get here.
1843 */ 1787 */
1844 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name); 1788 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name);
1845 return 0; 1789 return 0;
1846 } 1790 }
1847 1791
1956 1900
1957#ifdef ATTACK_DEBUG 1901#ifdef ATTACK_DEBUG
1958 LOG (llevDebug, "Attacktype %d did %d damage\n", type, maxdam); 1902 LOG (llevDebug, "Attacktype %d did %d damage\n", type, maxdam);
1959#endif 1903#endif
1960 1904
1961 if (get_owner (hitter)) 1905 if (hitter->owner)
1962 op->enemy = hitter->owner; 1906 op->enemy = hitter->owner;
1963 else if (QUERY_FLAG (hitter, FLAG_ALIVE)) 1907 else if (QUERY_FLAG (hitter, FLAG_ALIVE))
1964 op->enemy = hitter; 1908 op->enemy = hitter;
1965 1909
1966 if (QUERY_FLAG (op, FLAG_UNAGGRESSIVE) && op->type != PLAYER) 1910 if (QUERY_FLAG (op, FLAG_UNAGGRESSIVE) && op->type != PLAYER)
1991 1935
1992 if (QUERY_FLAG (op, FLAG_TEAR_DOWN)) 1936 if (QUERY_FLAG (op, FLAG_TEAR_DOWN))
1993 { 1937 {
1994 if (maxdam) 1938 if (maxdam)
1995 tear_down_wall (op); 1939 tear_down_wall (op);
1940
1996 return maxdam; /* nothing more to do for wall */ 1941 return maxdam; /* nothing more to do for wall */
1997 } 1942 }
1998 1943
1999 /* See if the creature has been killed */ 1944 /* See if the creature has been killed */
2000 rtn_kill = kill_object (op, maxdam, hitter, type); 1945 rtn_kill = kill_object (op, maxdam, hitter, type);
2008 */ 1953 */
2009 if (QUERY_FLAG (hitter, FLAG_ONE_HIT)) 1954 if (QUERY_FLAG (hitter, FLAG_ONE_HIT))
2010 { 1955 {
2011 if (QUERY_FLAG (hitter, FLAG_FRIENDLY)) 1956 if (QUERY_FLAG (hitter, FLAG_FRIENDLY))
2012 remove_friendly_object (hitter); 1957 remove_friendly_object (hitter);
2013 remove_ob (hitter); 1958
2014 free_object (hitter); 1959 hitter->destroy ();
2015 } 1960 }
2016 /* Lets handle creatures that are splitting now */ 1961 /* Lets handle creatures that are splitting now */
2017 else if (type & AT_PHYSICAL && !QUERY_FLAG (op, FLAG_FREED) && QUERY_FLAG (op, FLAG_SPLITTING)) 1962 else if (type & AT_PHYSICAL && !QUERY_FLAG (op, FLAG_FREED) && QUERY_FLAG (op, FLAG_SPLITTING))
2018 { 1963 {
2019 int i; 1964 int i;
2020 int friendly = QUERY_FLAG (op, FLAG_FRIENDLY); 1965 int friendly = QUERY_FLAG (op, FLAG_FRIENDLY);
2021 int unaggressive = QUERY_FLAG (op, FLAG_UNAGGRESSIVE); 1966 int unaggressive = QUERY_FLAG (op, FLAG_UNAGGRESSIVE);
2022 object *owner = get_owner (op); 1967 object *owner = op->owner;
2023 1968
2024 if (!op->other_arch) 1969 if (!op->other_arch)
2025 { 1970 {
2026 LOG (llevError, "SPLITTING without other_arch error.\n"); 1971 LOG (llevError, "SPLITTING without other_arch error.\n");
2027 return maxdam; 1972 return maxdam;
2028 } 1973 }
1974
2029 remove_ob (op); 1975 op->remove ();
1976
2030 for (i = 0; i < NROFNEWOBJS (op); i++) 1977 for (i = 0; i < NROFNEWOBJS (op); i++)
2031 { /* This doesn't handle op->more yet */ 1978 { /* This doesn't handle op->more yet */
2032 object *tmp = arch_to_object (op->other_arch); 1979 object *tmp = arch_to_object (op->other_arch);
2033 int j; 1980 int j;
2034 1981
2035 tmp->stats.hp = op->stats.hp; 1982 tmp->stats.hp = op->stats.hp;
1983
2036 if (friendly) 1984 if (friendly)
2037 { 1985 {
2038 SET_FLAG (tmp, FLAG_FRIENDLY); 1986 SET_FLAG (tmp, FLAG_FRIENDLY);
2039 add_friendly_object (tmp); 1987 add_friendly_object (tmp);
2040 tmp->attack_movement = PETMOVE; 1988 tmp->attack_movement = PETMOVE;
2041 if (owner != NULL) 1989 if (owner != NULL)
2042 set_owner (tmp, owner); 1990 tmp->set_owner (owner);
2043 } 1991 }
1992
2044 if (unaggressive) 1993 if (unaggressive)
2045 SET_FLAG (tmp, FLAG_UNAGGRESSIVE); 1994 SET_FLAG (tmp, FLAG_UNAGGRESSIVE);
1995
2046 j = find_first_free_spot (tmp, op->map, op->x, op->y); 1996 j = find_first_free_spot (tmp, op->map, op->x, op->y);
1997
2047 if (j == -1) /* No spot to put this monster */ 1998 if (j == -1) /* No spot to put this monster */
2048 free_object (tmp); 1999 tmp->destroy ();
2049 else 2000 else
2050 { 2001 {
2051 tmp->x = op->x + freearr_x[j], tmp->y = op->y + freearr_y[j]; 2002 tmp->x = op->x + freearr_x[j], tmp->y = op->y + freearr_y[j];
2052 insert_ob_in_map (tmp, op->map, NULL, 0); 2003 insert_ob_in_map (tmp, op->map, NULL, 0);
2053 } 2004 }
2054 } 2005 }
2055 if (friendly) 2006
2056 remove_friendly_object (op); 2007 op->destroy ();
2057 free_object (op);
2058 } 2008 }
2059 else if (type & AT_DRAIN && hitter->type == GRIMREAPER && hitter->value++ > 10) 2009 else if (type & AT_DRAIN && hitter->type == GRIMREAPER && hitter->value++ > 10)
2060 { 2010 hitter->destroy ();
2061 remove_ob (hitter); 2011
2062 free_object (hitter);
2063 }
2064 return maxdam; 2012 return maxdam;
2065} 2013}
2066 2014
2067 2015
2068void 2016void
2069poison_player (object *op, object *hitter, int dam) 2017poison_player (object *op, object *hitter, int dam)
2070{ 2018{
2071 archetype *at = find_archetype ("poisoning"); 2019 archetype *at = archetype::find ("poisoning");
2072 object *tmp = present_arch_in_ob (at, op); 2020 object *tmp = present_arch_in_ob (at, op);
2073 2021
2074 if (tmp == NULL) 2022 if (tmp == NULL)
2075 { 2023 {
2076 if ((tmp = arch_to_object (at)) == NULL) 2024 if ((tmp = arch_to_object (at)) == NULL)
2089 if (QUERY_FLAG (hitter, FLAG_ALIVE)) 2037 if (QUERY_FLAG (hitter, FLAG_ALIVE))
2090 tmp->stats.dam += hitter->level / 2; 2038 tmp->stats.dam += hitter->level / 2;
2091 else 2039 else
2092 tmp->stats.dam = dam; 2040 tmp->stats.dam = dam;
2093 2041
2094 copy_owner (tmp, hitter); /* so we get credit for poisoning kills */ 2042 tmp->set_owner (hitter); /* so we get credit for poisoning kills */
2095 if (hitter->skill && hitter->skill != tmp->skill) 2043 if (hitter->skill && hitter->skill != tmp->skill)
2096 { 2044 {
2097 tmp->skill = hitter->skill; 2045 tmp->skill = hitter->skill;
2098 } 2046 }
2099 2047
2110 fix_player (op); 2058 fix_player (op);
2111 new_draw_info (NDI_UNIQUE, 0, op, "You suddenly feel very ill."); 2059 new_draw_info (NDI_UNIQUE, 0, op, "You suddenly feel very ill.");
2112 } 2060 }
2113 if (hitter->type == PLAYER) 2061 if (hitter->type == PLAYER)
2114 new_draw_info_format (NDI_UNIQUE, 0, hitter, "You poison %s.", &op->name); 2062 new_draw_info_format (NDI_UNIQUE, 0, hitter, "You poison %s.", &op->name);
2115 else if (get_owner (hitter) != NULL && hitter->owner->type == PLAYER) 2063 else if (hitter->owner != NULL && hitter->owner->type == PLAYER)
2116 new_draw_info_format (NDI_UNIQUE, 0, hitter->owner, "Your %s poisons %s.", &hitter->name, &op->name); 2064 new_draw_info_format (NDI_UNIQUE, 0, hitter->owner, "Your %s poisons %s.", &hitter->name, &op->name);
2117 } 2065 }
2118 tmp->speed_left = 0; 2066 tmp->speed_left = 0;
2119 } 2067 }
2120 else 2068 else
2122} 2070}
2123 2071
2124void 2072void
2125slow_player (object *op, object *hitter, int dam) 2073slow_player (object *op, object *hitter, int dam)
2126{ 2074{
2127 archetype *at = find_archetype ("slowness"); 2075 archetype *at = archetype::find ("slowness");
2128 object *tmp; 2076 object *tmp;
2129 2077
2130 if (at == NULL) 2078 if (at == NULL)
2131 { 2079 {
2132 LOG (llevError, "Can't find slowness archetype.\n"); 2080 LOG (llevError, "Can't find slowness archetype.\n");
2196 tmp = insert_ob_in_ob (tmp, op); 2144 tmp = insert_ob_in_ob (tmp, op);
2197 change_abil (op, tmp); /* Mostly to display any messages */ 2145 change_abil (op, tmp); /* Mostly to display any messages */
2198 fix_player (op); /* This takes care of some other stuff */ 2146 fix_player (op); /* This takes care of some other stuff */
2199 2147
2200 if (hitter->owner) 2148 if (hitter->owner)
2201 owner = get_owner (hitter); 2149 owner = hitter->owner;
2202 else 2150 else
2203 owner = hitter; 2151 owner = hitter;
2204 2152
2205 new_draw_info_format (NDI_UNIQUE, 0, owner, "Your attack blinds %s!", query_name (op)); 2153 new_draw_info_format (NDI_UNIQUE, 0, owner, "Your attack blinds %s!", query_name (op));
2206 } 2154 }
2352 } 2300 }
2353 2301
2354 /* aimed missiles use the owning object's sight */ 2302 /* aimed missiles use the owning object's sight */
2355 if (is_aimed_missile (hitter)) 2303 if (is_aimed_missile (hitter))
2356 { 2304 {
2357 if ((attacker = get_owner (hitter)) == NULL) 2305 if ((attacker = hitter->owner) == NULL)
2358 attacker = hitter; 2306 attacker = hitter;
2359 /* A player who saves but hasn't quit still could have objects 2307 /* A player who saves but hasn't quit still could have objects
2360 * owned by him - need to handle that case to avoid crashes. 2308 * owned by him - need to handle that case to avoid crashes.
2361 */ 2309 */
2362 if (QUERY_FLAG (attacker, FLAG_REMOVED)) 2310 if (QUERY_FLAG (attacker, FLAG_REMOVED))

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines