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.19 by root, Sat Sep 16 22:24:13 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>
158{ 152{
159 if (!did_make_save_item (op, type, originator)) 153 if (!did_make_save_item (op, type, originator))
160 { 154 {
161 object *env = op->env; 155 object *env = op->env;
162 int x = op->x, y = op->y; 156 int x = op->x, y = op->y;
163 mapstruct *m = op->map; 157 maptile *m = op->map;
164 158
165 op = stop_item (op); 159 op = stop_item (op);
166 if (op == NULL) 160 if (op == NULL)
167 return; 161 return;
168 162
247 241
248 /* The value of 50 is arbitrary. */ 242 /* The value of 50 is arbitrary. */
249 if (type & AT_COLD && (op->resist[ATNR_COLD] < 50) && !QUERY_FLAG (op, FLAG_NO_PICK) && (RANDOM () & 2)) 243 if (type & AT_COLD && (op->resist[ATNR_COLD] < 50) && !QUERY_FLAG (op, FLAG_NO_PICK) && (RANDOM () & 2))
250 { 244 {
251 object *tmp; 245 object *tmp;
252 archetype *at = find_archetype ("icecube"); 246 archetype *at = archetype::find ("icecube");
253 247
254 if (at == NULL) 248 if (at == NULL)
255 return; 249 return;
256 250
257 op = stop_item (op); 251 op = stop_item (op);
288 282
289int 283int
290hit_map (object *op, int dir, int type, int full_hit) 284hit_map (object *op, int dir, int type, int full_hit)
291{ 285{
292 object *tmp, *next; 286 object *tmp, *next;
293 mapstruct *map; 287 maptile *map;
294 sint16 x, y; 288 sint16 x, y;
295 int retflag = 0; /* added this flag.. will return 1 if it hits a monster */ 289 int retflag = 0; /* added this flag.. will return 1 if it hits a monster */
296 290
297 tag_t op_tag, next_tag = 0;
298
299 if (QUERY_FLAG (op, FLAG_FREED)) 291 if (QUERY_FLAG (op, FLAG_FREED))
300 { 292 {
301 LOG (llevError, "BUG: hit_map(): free object\n"); 293 LOG (llevError, "BUG: hit_map(): free object\n");
302 return 0; 294 return 0;
303 } 295 }
314 return 0; 306 return 0;
315 } 307 }
316 308
317 if (op->head) 309 if (op->head)
318 op = op->head; 310 op = op->head;
319
320 op_tag = op->count;
321 311
322 map = op->map; 312 map = op->map;
323 x = op->x + freearr_x[dir]; 313 x = op->x + freearr_x[dir];
324 y = op->y + freearr_y[dir]; 314 y = op->y + freearr_y[dir];
325 315
353 update_object (op, UP_OBJ_FACE); 343 update_object (op, UP_OBJ_FACE);
354 type &= ~AT_CHAOS; 344 type &= ~AT_CHAOS;
355 } 345 }
356 346
357 next = get_map_ob (map, x, y); 347 next = get_map_ob (map, x, y);
358 if (next)
359 next_tag = next->count;
360 348
361 while (next) 349 while (next)
362 { 350 {
363 if (was_destroyed (next, next_tag)) 351 if (next->destroyed ())
364 { 352 {
365 /* There may still be objects that were above 'next', but there is no 353 /* 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 354 * simple way to find out short of copying all object references and
367 * tags into a temporary array before we start processing the first 355 * tags into a temporary array before we start processing the first
368 * object. That's why we just abort. 356 * object. That's why we just abort.
376 } 364 }
377 365
378 tmp = next; 366 tmp = next;
379 next = tmp->above; 367 next = tmp->above;
380 368
381 if (next) 369 if (tmp->destroyed ())
382 next_tag = next->count;
383
384 if (QUERY_FLAG (tmp, FLAG_FREED))
385 { 370 {
386 LOG (llevError, "BUG: hit_map(): found freed object\n"); 371 LOG (llevError, "BUG: hit_map(): found freed object\n");
387 break; 372 break;
388 } 373 }
389 374
396 381
397 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 382 if (QUERY_FLAG (tmp, FLAG_ALIVE))
398 { 383 {
399 hit_player (tmp, op->stats.dam, op, type, full_hit); 384 hit_player (tmp, op->stats.dam, op, type, full_hit);
400 retflag |= 1; 385 retflag |= 1;
401 if (was_destroyed (op, op_tag)) 386 if (op->destroyed ())
402 break; 387 break;
403 } 388 }
404 389
405 /* Here we are potentially destroying an object. If the object has 390 /* 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 391 * NO_PASS set, it is also immune - you can't destroy walls. Note
410 * destroyed right now. 395 * destroyed right now.
411 */ 396 */
412 else if ((tmp->material || tmp->materialname) && op->stats.dam > 0 && !tmp->move_block) 397 else if ((tmp->material || tmp->materialname) && op->stats.dam > 0 && !tmp->move_block)
413 { 398 {
414 save_throw_object (tmp, type, op); 399 save_throw_object (tmp, type, op);
415 if (was_destroyed (op, op_tag)) 400 if (op->destroyed ())
416 break; 401 break;
417 } 402 }
418 } 403 }
419 404
420 return 0; 405 return 0;
423void 408void
424attack_message (int dam, int type, object *op, object *hitter) 409attack_message (int dam, int type, object *op, object *hitter)
425{ 410{
426 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF]; 411 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF];
427 int i, found = 0; 412 int i, found = 0;
428 mapstruct *map; 413 maptile *map;
429 object *next, *tmp; 414 object *next, *tmp;
430 415
431 /* put in a few special messages for some of the common attacktypes 416 /* put in a few special messages for some of the common attacktypes
432 * a player might have. For example, fire, electric, cold, etc 417 * a player might have. For example, fire, electric, cold, etc
433 * [garbled 20010919] 418 * [garbled 20010919]
760attack_ob_simple (object *op, object *hitter, int base_dam, int base_wc) 745attack_ob_simple (object *op, object *hitter, int base_dam, int base_wc)
761{ 746{
762 int simple_attack, roll, dam = 0; 747 int simple_attack, roll, dam = 0;
763 uint32 type; 748 uint32 type;
764 shstr op_name; 749 shstr op_name;
765 tag_t op_tag, hitter_tag;
766 750
767 if (get_attack_mode (&op, &hitter, &simple_attack)) 751 if (get_attack_mode (&op, &hitter, &simple_attack))
768 goto error; 752 goto error;
769 753
770 if (hitter->current_weapon) 754 if (hitter->current_weapon)
771 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op))) 755 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op)))
772 return RESULT_INT (0); 756 return RESULT_INT (0);
773 757
774 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter))) 758 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter)))
775 return RESULT_INT (0); 759 return RESULT_INT (0);
776
777 op_tag = op->count;
778 hitter_tag = hitter->count;
779 760
780 /* 761 /*
781 * A little check to make it more difficult to dance forward and back 762 * A little check to make it more difficult to dance forward and back
782 * to avoid ever being hit by monsters. 763 * to avoid ever being hit by monsters.
783 */ 764 */
788 * which then gets here again. By decreasing the speed before 769 * which then gets here again. By decreasing the speed before
789 * we call process_object, the 'if' statement above will fail. 770 * we call process_object, the 'if' statement above will fail.
790 */ 771 */
791 op->speed_left--; 772 op->speed_left--;
792 process_object (op); 773 process_object (op);
793 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 774 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
794 goto error; 775 goto error;
795 } 776 }
796 777
797 op_name = op->name; 778 op_name = op->name;
798 779
849 * when they hit the victim. For things like thrown daggers, 830 * when they hit the victim. For things like thrown daggers,
850 * this sets 'hitter' to the actual dagger, and not the 831 * this sets 'hitter' to the actual dagger, and not the
851 * wrapper object. 832 * wrapper object.
852 */ 833 */
853 thrown_item_effect (hitter, op); 834 thrown_item_effect (hitter, op);
854 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack)) 835 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
855 goto leave; 836 goto leave;
856 } 837 }
857 838
858 /* Need to do at least 1 damage, otherwise there is no point 839 /* Need to do at least 1 damage, otherwise there is no point
859 * to go further and it will cause FPE's below. 840 * to go further and it will cause FPE's below.
860 */ 841 */
861 if (hitdam <= 0) 842 if (hitdam <= 0)
862 hitdam = 1; 843 hitdam = 1;
863 844
864 type = hitter->attacktype; 845 type = hitter->attacktype;
846
865 if (!type) 847 if (!type)
866 type = AT_PHYSICAL; 848 type = AT_PHYSICAL;
849
867 /* Handle monsters that hit back */ 850 /* Handle monsters that hit back */
868 if (!simple_attack && QUERY_FLAG (op, FLAG_HITBACK) && QUERY_FLAG (hitter, FLAG_ALIVE)) 851 if (!simple_attack && QUERY_FLAG (op, FLAG_HITBACK) && QUERY_FLAG (hitter, FLAG_ALIVE))
869 { 852 {
870 if (op->attacktype & AT_ACID && hitter->type == PLAYER) 853 if (op->attacktype & AT_ACID && hitter->type == PLAYER)
871 new_draw_info (NDI_UNIQUE, 0, hitter, "You are splashed by acid!\n"); 854 new_draw_info (NDI_UNIQUE, 0, hitter, "You are splashed by acid!\n");
855
872 hit_player (hitter, random_roll (0, (op->stats.dam), hitter, PREFER_LOW), op, op->attacktype, 1); 856 hit_player (hitter, random_roll (0, (op->stats.dam), hitter, PREFER_LOW), op, op->attacktype, 1);
857
873 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 858 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
874 goto leave; 859 goto leave;
875 } 860 }
876 861
877 /* In the new attack code, it should handle multiple attack 862 /* In the new attack code, it should handle multiple attack
878 * types in its area, so remove it from here. 863 * types in its area, so remove it from here.
879 */ 864 */
880 dam = hit_player (op, random_roll (1, hitdam, hitter, PREFER_HIGH), hitter, type, 1); 865 dam = hit_player (op, random_roll (1, hitdam, hitter, PREFER_HIGH), hitter, type, 1);
866
881 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 867 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
882 goto leave; 868 goto leave;
883 } /* end of if hitter hit op */ 869 } /* end of if hitter hit op */
884 /* if we missed, dam=0 */ 870 /* if we missed, dam=0 */
885 871
886 /*attack_message(dam, type, op, hitter); */ 872 /*attack_message(dam, type, op, hitter); */
943object * 929object *
944hit_with_arrow (object *op, object *victim) 930hit_with_arrow (object *op, object *victim)
945{ 931{
946 object *container, *hitter; 932 object *container, *hitter;
947 int hit_something = 0; 933 int hit_something = 0;
948 tag_t victim_tag, hitter_tag;
949 sint16 victim_x, victim_y; 934 sint16 victim_x, victim_y;
950 935
951 /* Disassemble missile */ 936 /* Disassemble missile */
952 if (op->inv) 937 if (op->inv)
953 { 938 {
967 } 952 }
968 953
969 /* Try to hit victim */ 954 /* Try to hit victim */
970 victim_x = victim->x; 955 victim_x = victim->x;
971 victim_y = victim->y; 956 victim_y = victim->y;
972 victim_tag = victim->count;
973 hitter_tag = hitter->count;
974 957
975 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc); 958 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc);
976 959
977 /* Arrow attacks door, rune of summoning is triggered, demon is put on 960 /* Arrow attacks door, rune of summoning is triggered, demon is put on
978 * arrow, move_apply() calls this function, arrow sticks in demon, 961 * arrow, move_apply() calls this function, arrow sticks in demon,
979 * attack_ob_simple() returns, and we've got an arrow that still exists 962 * 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 963 * but is no longer on the map. Ugh. (Beware: Such things can happen at
981 * other places as well!) 964 * other places as well!)
982 */ 965 */
983 if (was_destroyed (hitter, hitter_tag) || hitter->env != NULL) 966 if (hitter->destroyed () || hitter->env != NULL)
984 { 967 {
985 if (container) 968 if (container)
986 { 969 {
987 remove_ob (container); 970 remove_ob (container);
988 free_object (container); 971 free_object (container);
1008 remove_ob (container); 991 remove_ob (container);
1009 free_object (container); 992 free_object (container);
1010 } 993 }
1011 994
1012 /* Try to stick arrow into victim */ 995 /* Try to stick arrow into victim */
1013 if (!was_destroyed (victim, victim_tag) && stick_arrow (hitter, victim)) 996 if (!victim->destroyed () && stick_arrow (hitter, victim))
1014 return NULL; 997 return NULL;
1015 998
1016 /* Else try to put arrow on victim's map square 999 /* Else try to put arrow on victim's map square
1017 * remove check for P_WALL here. If the arrow got to this 1000 * remove check for P_WALL here. If the arrow got to this
1018 * space, that is good enough - with the new movement code, 1001 * space, that is good enough - with the new movement code,
1773{ 1756{
1774 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC); 1757 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC);
1775 int maxattacktype, attacknum; 1758 int maxattacktype, attacknum;
1776 int body_attack = op && op->head; /* Did we hit op's head? */ 1759 int body_attack = op && op->head; /* Did we hit op's head? */
1777 int simple_attack; 1760 int simple_attack;
1778 tag_t op_tag, hitter_tag;
1779 int rtn_kill = 0; 1761 int rtn_kill = 0;
1780 int friendlyfire; 1762 int friendlyfire;
1781 1763
1782 if (get_attack_mode (&op, &hitter, &simple_attack)) 1764 if (get_attack_mode (&op, &hitter, &simple_attack))
1783 return 0; 1765 return 0;
1791 { 1773 {
1792 object *owner = get_owner (hitter); 1774 object *owner = get_owner (hitter);
1793 1775
1794 if (!owner) 1776 if (!owner)
1795 owner = hitter; 1777 owner = hitter;
1778
1796 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner) 1779 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner)
1797 {
1798 return 0; 1780 return 0;
1799 }
1800 } 1781 }
1801#endif 1782#endif
1802
1803 op_tag = op->count;
1804 hitter_tag = hitter->count;
1805 1783
1806 if (body_attack) 1784 if (body_attack)
1807 { 1785 {
1808 /* slow and paralyze must hit the head. But we don't want to just 1786 /* 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 1787 * return - we still need to process other attacks the spell still
1815 * attack so we don't cancel out things like magic bullet. 1793 * attack so we don't cancel out things like magic bullet.
1816 */ 1794 */
1817 if (type & (AT_PARALYZE | AT_SLOW)) 1795 if (type & (AT_PARALYZE | AT_SLOW))
1818 { 1796 {
1819 type &= ~(AT_PARALYZE | AT_SLOW); 1797 type &= ~(AT_PARALYZE | AT_SLOW);
1798
1820 if (!type || type == AT_MAGIC) 1799 if (!type || type == AT_MAGIC)
1821 return 0; 1800 return 0;
1822 } 1801 }
1823 } 1802 }
1824 1803
1828 1807
1829 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) 1808 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1830 if (tmp->type == RUNE || tmp->type == TRAP) 1809 if (tmp->type == RUNE || tmp->type == TRAP)
1831 { 1810 {
1832 spring_trap (tmp, hitter); 1811 spring_trap (tmp, hitter);
1833 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack)) 1812 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
1834 return 0; 1813 return 0;
1835 break; 1814 break;
1836 } 1815 }
1837 } 1816 }
1838 1817
1839 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0) 1818 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0)
1840 { 1819 {
1841 /* FIXME: If a player is killed by a rune in a door, the 1820 /* 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. 1821 * destroyed() check above doesn't return, and might get here.
1843 */ 1822 */
1844 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name); 1823 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name);
1845 return 0; 1824 return 0;
1846 } 1825 }
1847 1826
2066 2045
2067 2046
2068void 2047void
2069poison_player (object *op, object *hitter, int dam) 2048poison_player (object *op, object *hitter, int dam)
2070{ 2049{
2071 archetype *at = find_archetype ("poisoning"); 2050 archetype *at = archetype::find ("poisoning");
2072 object *tmp = present_arch_in_ob (at, op); 2051 object *tmp = present_arch_in_ob (at, op);
2073 2052
2074 if (tmp == NULL) 2053 if (tmp == NULL)
2075 { 2054 {
2076 if ((tmp = arch_to_object (at)) == NULL) 2055 if ((tmp = arch_to_object (at)) == NULL)
2122} 2101}
2123 2102
2124void 2103void
2125slow_player (object *op, object *hitter, int dam) 2104slow_player (object *op, object *hitter, int dam)
2126{ 2105{
2127 archetype *at = find_archetype ("slowness"); 2106 archetype *at = archetype::find ("slowness");
2128 object *tmp; 2107 object *tmp;
2129 2108
2130 if (at == NULL) 2109 if (at == NULL)
2131 { 2110 {
2132 LOG (llevError, "Can't find slowness archetype.\n"); 2111 LOG (llevError, "Can't find slowness archetype.\n");

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines