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.11 by root, Mon Sep 11 20:26:41 2006 UTC vs.
Revision 1.24 by root, Sat Dec 9 16:11:09 2006 UTC

1
2/*
3 * static char *rcsid_attack_c =
4 * "$Id: attack.C,v 1.11 2006/09/11 20:26:41 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
177 if (type & (AT_FIRE | AT_ELECTRICITY) && op->other_arch && QUERY_FLAG (op, FLAG_IS_LIGHTABLE)) 171 if (type & (AT_FIRE | AT_ELECTRICITY) && op->other_arch && QUERY_FLAG (op, FLAG_IS_LIGHTABLE))
178 { 172 {
179 const char *arch = op->other_arch->name; 173 const char *arch = op->other_arch->name;
180 174
181 op = decrease_ob_nr (op, 1); 175 op = decrease_ob_nr (op, 1);
176
182 if (op) 177 if (op)
183 fix_stopped_item (op, m, originator); 178 fix_stopped_item (op, m, originator);
179
184 if ((op = get_archetype (arch)) != NULL) 180 if ((op = get_archetype (arch)) != NULL)
185 { 181 {
186 if (env) 182 if (env)
187 { 183 {
188 op->x = env->x, op->y = env->y; 184 op->x = env->x, op->y = env->y;
194 { 190 {
195 op->x = x, op->y = y; 191 op->x = x, op->y = y;
196 insert_ob_in_map (op, m, originator, 0); 192 insert_ob_in_map (op, m, originator, 0);
197 } 193 }
198 } 194 }
195
199 return; 196 return;
200 } 197 }
198
201 if (type & AT_CANCELLATION) 199 if (type & AT_CANCELLATION)
202 { /* Cancellation. */ 200 { /* Cancellation. */
203 cancellation (op); 201 cancellation (op);
204 fix_stopped_item (op, m, originator); 202 fix_stopped_item (op, m, originator);
205 return; 203 return;
206 } 204 }
205
207 if (op->nrof > 1) 206 if (op->nrof > 1)
208 { 207 {
209 op = decrease_ob_nr (op, rndm (0, op->nrof - 1)); 208 op = decrease_ob_nr (op, rndm (0, op->nrof - 1));
209
210 if (op) 210 if (op)
211 fix_stopped_item (op, m, originator); 211 fix_stopped_item (op, m, originator);
212 } 212 }
213 else 213 else
214 { 214 {
215 if (op->env) 215 if (op->env)
216 { 216 {
217 object *tmp = is_player_inv (op->env); 217 object *tmp = is_player_inv (op->env);
218 218
219 if (tmp) 219 if (tmp)
220 {
221 esrv_del_item (tmp->contr, op->count); 220 esrv_del_item (tmp->contr, op->count);
222 }
223 } 221 }
222
224 if (!QUERY_FLAG (op, FLAG_REMOVED)) 223 if (!QUERY_FLAG (op, FLAG_REMOVED))
225 remove_ob (op); 224 remove_ob (op);
225
226 free_object (op); 226 free_object (op);
227 } 227 }
228
228 if (type & (AT_FIRE | AT_ELECTRICITY)) 229 if (type & (AT_FIRE | AT_ELECTRICITY))
229 {
230 if (env) 230 if (env)
231 { 231 {
232 op = get_archetype ("burnout"); 232 op = get_archetype ("burnout");
233 op->x = env->x, op->y = env->y; 233 op->x = env->x, op->y = env->y;
234 insert_ob_in_ob (op, env); 234 insert_ob_in_ob (op, env);
235 } 235 }
236 else 236 else
237 {
238 replace_insert_ob_in_map ("burnout", originator); 237 replace_insert_ob_in_map ("burnout", originator);
239 } 238
240 }
241 return; 239 return;
242 } 240 }
241
243 /* The value of 50 is arbitrary. */ 242 /* The value of 50 is arbitrary. */
244 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))
245 { 244 {
246 object *tmp; 245 object *tmp;
247 archetype *at = find_archetype ("icecube"); 246 archetype *at = archetype::find ("icecube");
248 247
249 if (at == NULL) 248 if (at == NULL)
250 return; 249 return;
250
251 op = stop_item (op); 251 op = stop_item (op);
252 if (op == NULL) 252 if (op == NULL)
253 return; 253 return;
254
254 if ((tmp = present_arch (at, op->map, op->x, op->y)) == NULL) 255 if ((tmp = present_arch (at, op->map, op->x, op->y)) == NULL)
255 { 256 {
256 tmp = arch_to_object (at); 257 tmp = arch_to_object (at);
257 tmp->x = op->x, tmp->y = op->y; 258 tmp->x = op->x, tmp->y = op->y;
258 /* This was in the old (pre new movement code) - 259 /* This was in the old (pre new movement code) -
261 */ 262 */
262 tmp->move_slow_penalty = 0; 263 tmp->move_slow_penalty = 0;
263 tmp->move_slow = 0; 264 tmp->move_slow = 0;
264 insert_ob_in_map (tmp, op->map, originator, 0); 265 insert_ob_in_map (tmp, op->map, originator, 0);
265 } 266 }
267
266 if (!QUERY_FLAG (op, FLAG_REMOVED)) 268 if (!QUERY_FLAG (op, FLAG_REMOVED))
267 remove_ob (op); 269 remove_ob (op);
270
268 (void) insert_ob_in_ob (op, tmp); 271 insert_ob_in_ob (op, tmp);
269 return; 272 return;
270 } 273 }
271} 274}
272 275
273/* Object op is hitting the map. 276/* Object op is hitting the map.
279 282
280int 283int
281hit_map (object *op, int dir, int type, int full_hit) 284hit_map (object *op, int dir, int type, int full_hit)
282{ 285{
283 object *tmp, *next; 286 object *tmp, *next;
284 mapstruct *map; 287 maptile *map;
285 sint16 x, y; 288 sint16 x, y;
286 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 */
287 290
288 tag_t op_tag, next_tag = 0;
289
290 if (QUERY_FLAG (op, FLAG_FREED)) 291 if (QUERY_FLAG (op, FLAG_FREED))
291 { 292 {
292 LOG (llevError, "BUG: hit_map(): free object\n"); 293 LOG (llevError, "BUG: hit_map(): free object\n");
293 return 0; 294 return 0;
294 } 295 }
305 return 0; 306 return 0;
306 } 307 }
307 308
308 if (op->head) 309 if (op->head)
309 op = op->head; 310 op = op->head;
310
311 op_tag = op->count;
312 311
313 map = op->map; 312 map = op->map;
314 x = op->x + freearr_x[dir]; 313 x = op->x + freearr_x[dir];
315 y = op->y + freearr_y[dir]; 314 y = op->y + freearr_y[dir];
316 315
344 update_object (op, UP_OBJ_FACE); 343 update_object (op, UP_OBJ_FACE);
345 type &= ~AT_CHAOS; 344 type &= ~AT_CHAOS;
346 } 345 }
347 346
348 next = get_map_ob (map, x, y); 347 next = get_map_ob (map, x, y);
349 if (next)
350 next_tag = next->count;
351 348
352 while (next) 349 while (next)
353 { 350 {
354 if (was_destroyed (next, next_tag)) 351 if (next->destroyed ())
355 { 352 {
356 /* 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
357 * 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
358 * tags into a temporary array before we start processing the first 355 * tags into a temporary array before we start processing the first
359 * object. That's why we just abort. 356 * object. That's why we just abort.
367 } 364 }
368 365
369 tmp = next; 366 tmp = next;
370 next = tmp->above; 367 next = tmp->above;
371 368
372 if (next) 369 if (tmp->destroyed ())
373 next_tag = next->count;
374
375 if (QUERY_FLAG (tmp, FLAG_FREED))
376 { 370 {
377 LOG (llevError, "BUG: hit_map(): found freed object\n"); 371 LOG (llevError, "BUG: hit_map(): found freed object\n");
378 break; 372 break;
379 } 373 }
380 374
387 381
388 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 382 if (QUERY_FLAG (tmp, FLAG_ALIVE))
389 { 383 {
390 hit_player (tmp, op->stats.dam, op, type, full_hit); 384 hit_player (tmp, op->stats.dam, op, type, full_hit);
391 retflag |= 1; 385 retflag |= 1;
392 if (was_destroyed (op, op_tag)) 386 if (op->destroyed ())
393 break; 387 break;
394 } 388 }
395 389
396 /* Here we are potentially destroying an object. If the object has 390 /* Here we are potentially destroying an object. If the object has
397 * 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
401 * destroyed right now. 395 * destroyed right now.
402 */ 396 */
403 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)
404 { 398 {
405 save_throw_object (tmp, type, op); 399 save_throw_object (tmp, type, op);
406 if (was_destroyed (op, op_tag)) 400 if (op->destroyed ())
407 break; 401 break;
408 } 402 }
409 } 403 }
410 404
411 return 0; 405 return 0;
414void 408void
415attack_message (int dam, int type, object *op, object *hitter) 409attack_message (int dam, int type, object *op, object *hitter)
416{ 410{
417 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF]; 411 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF];
418 int i, found = 0; 412 int i, found = 0;
419 mapstruct *map; 413 maptile *map;
420 object *next, *tmp; 414 object *next, *tmp;
421 415
422 /* 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
423 * a player might have. For example, fire, electric, cold, etc 417 * a player might have. For example, fire, electric, cold, etc
424 * [garbled 20010919] 418 * [garbled 20010919]
751attack_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)
752{ 746{
753 int simple_attack, roll, dam = 0; 747 int simple_attack, roll, dam = 0;
754 uint32 type; 748 uint32 type;
755 shstr op_name; 749 shstr op_name;
756 tag_t op_tag, hitter_tag;
757 750
758 if (get_attack_mode (&op, &hitter, &simple_attack)) 751 if (get_attack_mode (&op, &hitter, &simple_attack))
759 goto error; 752 goto error;
760 753
761 if (hitter->current_weapon) 754 if (hitter->current_weapon)
762 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)))
763 return RESULT_INT (0); 756 return RESULT_INT (0);
764 757
765 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter))) 758 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter)))
766 return RESULT_INT (0); 759 return RESULT_INT (0);
767
768 op_tag = op->count;
769 hitter_tag = hitter->count;
770 760
771 /* 761 /*
772 * 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
773 * to avoid ever being hit by monsters. 763 * to avoid ever being hit by monsters.
774 */ 764 */
779 * which then gets here again. By decreasing the speed before 769 * which then gets here again. By decreasing the speed before
780 * we call process_object, the 'if' statement above will fail. 770 * we call process_object, the 'if' statement above will fail.
781 */ 771 */
782 op->speed_left--; 772 op->speed_left--;
783 process_object (op); 773 process_object (op);
784 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))
785 goto error; 775 goto error;
786 } 776 }
787 777
788 op_name = op->name; 778 op_name = op->name;
789 779
840 * when they hit the victim. For things like thrown daggers, 830 * when they hit the victim. For things like thrown daggers,
841 * this sets 'hitter' to the actual dagger, and not the 831 * this sets 'hitter' to the actual dagger, and not the
842 * wrapper object. 832 * wrapper object.
843 */ 833 */
844 thrown_item_effect (hitter, op); 834 thrown_item_effect (hitter, op);
845 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))
846 goto leave; 836 goto leave;
847 } 837 }
848 838
849 /* 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
850 * to go further and it will cause FPE's below. 840 * to go further and it will cause FPE's below.
851 */ 841 */
852 if (hitdam <= 0) 842 if (hitdam <= 0)
853 hitdam = 1; 843 hitdam = 1;
854 844
855 type = hitter->attacktype; 845 type = hitter->attacktype;
846
856 if (!type) 847 if (!type)
857 type = AT_PHYSICAL; 848 type = AT_PHYSICAL;
849
858 /* Handle monsters that hit back */ 850 /* Handle monsters that hit back */
859 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))
860 { 852 {
861 if (op->attacktype & AT_ACID && hitter->type == PLAYER) 853 if (op->attacktype & AT_ACID && hitter->type == PLAYER)
862 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
863 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
864 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))
865 goto leave; 859 goto leave;
866 } 860 }
867 861
868 /* In the new attack code, it should handle multiple attack 862 /* In the new attack code, it should handle multiple attack
869 * types in its area, so remove it from here. 863 * types in its area, so remove it from here.
870 */ 864 */
871 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
872 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))
873 goto leave; 868 goto leave;
874 } /* end of if hitter hit op */ 869 } /* end of if hitter hit op */
875 /* if we missed, dam=0 */ 870 /* if we missed, dam=0 */
876 871
877 /*attack_message(dam, type, op, hitter); */ 872 /*attack_message(dam, type, op, hitter); */
934object * 929object *
935hit_with_arrow (object *op, object *victim) 930hit_with_arrow (object *op, object *victim)
936{ 931{
937 object *container, *hitter; 932 object *container, *hitter;
938 int hit_something = 0; 933 int hit_something = 0;
939 tag_t victim_tag, hitter_tag;
940 sint16 victim_x, victim_y;
941 934
942 /* Disassemble missile */ 935 /* Disassemble missile */
943 if (op->inv) 936 if (op->inv)
944 { 937 {
945 container = op; 938 container = op;
951 * removed at the end of this function must be able to deal with empty 944 * removed at the end of this function must be able to deal with empty
952 * THROWN_OBJs. */ 945 * THROWN_OBJs. */
953 } 946 }
954 else 947 else
955 { 948 {
956 container = NULL; 949 container = 0;
957 hitter = op; 950 hitter = op;
958 } 951 }
959 952
960 /* Try to hit victim */ 953 /* Try to hit victim */
961 victim_x = victim->x;
962 victim_y = victim->y;
963 victim_tag = victim->count;
964 hitter_tag = hitter->count;
965
966 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc); 954 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc);
967 955
968 /* Arrow attacks door, rune of summoning is triggered, demon is put on 956 /* Arrow attacks door, rune of summoning is triggered, demon is put on
969 * arrow, move_apply() calls this function, arrow sticks in demon, 957 * arrow, move_apply() calls this function, arrow sticks in demon,
970 * attack_ob_simple() returns, and we've got an arrow that still exists 958 * attack_ob_simple() returns, and we've got an arrow that still exists
971 * but is no longer on the map. Ugh. (Beware: Such things can happen at 959 * but is no longer on the map. Ugh. (Beware: Such things can happen at
972 * other places as well!) 960 * other places as well!)
973 */ 961 */
974 if (was_destroyed (hitter, hitter_tag) || hitter->env != NULL) 962 if (hitter->destroyed () || hitter->env != NULL)
975 { 963 {
976 if (container) 964 if (container)
977 { 965 {
978 remove_ob (container); 966 remove_ob (container);
979 free_object (container); 967 free_object (container);
980 } 968 }
969
981 return NULL; 970 return 0;
982 } 971 }
983 972
984 /* Missile hit victim */ 973 /* Missile hit victim */
985 /* if the speed is > 10, then this is a fast moving arrow, we go straight 974 /* if the speed is > 10, then this is a fast moving arrow, we go straight
986 * through the target 975 * through the target
987 */ 976 */
988 if (hit_something && op->speed <= 10.0) 977 if (hit_something && op->speed <= 10.0)
989 { 978 {
990 /* Stop arrow */ 979 /* Stop arrow */
991 if (container == NULL) 980 if (!container)
992 { 981 {
993 hitter = fix_stopped_arrow (hitter); 982 hitter = fix_stopped_arrow (hitter);
994 if (hitter == NULL) 983 if (!hitter)
995 return NULL; 984 return 0;
996 } 985 }
997 else 986 else
998 { 987 {
999 remove_ob (container); 988 remove_ob (container);
1000 free_object (container); 989 free_object (container);
1001 } 990 }
1002 991
1003 /* Try to stick arrow into victim */ 992 /* Try to stick arrow into victim */
1004 if (!was_destroyed (victim, victim_tag) && stick_arrow (hitter, victim)) 993 if (!victim->destroyed () && stick_arrow (hitter, victim))
1005 return NULL; 994 return 0;
1006 995
1007 /* Else try to put arrow on victim's map square 996 /* Else try to put arrow on victim's map square
1008 * remove check for P_WALL here. If the arrow got to this 997 * remove check for P_WALL here. If the arrow got to this
1009 * space, that is good enough - with the new movement code, 998 * space, that is good enough - with the new movement code,
1010 * there is now the potential for lots of spaces where something 999 * there is now the potential for lots of spaces where something
1011 * can fly over but not otherwise move over. What is the correct 1000 * can fly over but not otherwise move over. What is the correct
1012 * way to handle those otherwise? 1001 * way to handle those otherwise?
1013 */ 1002 */
1014 if (victim_x != hitter->x || victim_y != hitter->y) 1003 if (victim->x != hitter->x || victim->y != hitter->y)
1015 { 1004 {
1016 remove_ob (hitter); 1005 remove_ob (hitter);
1017 hitter->x = victim_x; 1006 hitter->x = victim->x;
1018 hitter->y = victim_y; 1007 hitter->y = victim->y;
1019 insert_ob_in_map (hitter, victim->map, hitter, 0); 1008 insert_ob_in_map (hitter, victim->map, hitter, 0);
1020 } 1009 }
1021 else 1010 else
1022 {
1023 /* Else leave arrow where it is */ 1011 /* Else leave arrow where it is */
1024 merge_ob (hitter, NULL); 1012 merge_ob (hitter, NULL);
1025 } 1013
1026 return NULL; 1014 return 0;
1027 } 1015 }
1028 1016
1029 if (hit_something && op->speed >= 10.0) 1017 if (hit_something && op->speed >= 10.0)
1030 op->speed -= 1.0; 1018 op->speed -= 1.0;
1031 1019
1033 if (container) 1021 if (container)
1034 { 1022 {
1035 remove_ob (hitter); 1023 remove_ob (hitter);
1036 insert_ob_in_ob (hitter, container); 1024 insert_ob_in_ob (hitter, container);
1037 } 1025 }
1026
1038 return op; 1027 return op;
1039} 1028}
1040 1029
1041 1030
1042void 1031void
1331 break; 1320 break;
1332 case ATNR_TURN_UNDEAD: 1321 case ATNR_TURN_UNDEAD:
1333 { 1322 {
1334 if (QUERY_FLAG (op, FLAG_UNDEAD)) 1323 if (QUERY_FLAG (op, FLAG_UNDEAD))
1335 { 1324 {
1336 object *owner = get_owner (hitter) == NULL ? hitter : get_owner (hitter); 1325 object *owner = hitter->owner ? (object *)hitter->owner : hitter;
1337 object *god = find_god (determine_god (owner)); 1326 object *god = find_god (determine_god (owner));
1338 int div = 1; 1327 int div = 1;
1339 1328
1340 /* if undead are not an enemy of your god, you turn them 1329 /* if undead are not an enemy of your god, you turn them
1341 * at half strength */ 1330 * at half strength */
1367 break; 1356 break;
1368 case ATNR_HOLYWORD: 1357 case ATNR_HOLYWORD:
1369 { 1358 {
1370 /* This has already been handled by hit_player, 1359 /* This has already been handled by hit_player,
1371 * no need to check twice -- DAMN */ 1360 * no need to check twice -- DAMN */
1372 1361 object *owner = hitter->owner ? (object *)hitter->owner : hitter;
1373 object *owner = get_owner (hitter) == NULL ? hitter : get_owner (hitter);
1374 1362
1375 /* As with turn undead above, give a bonus on the saving throw */ 1363 /* As with turn undead above, give a bonus on the saving throw */
1376 if ((op->level + (op->resist[ATNR_HOLYWORD] / 100)) < owner->level + turn_bonus[owner->stats.Wis]) 1364 if ((op->level + (op->resist[ATNR_HOLYWORD] / 100)) < owner->level + turn_bonus[owner->stats.Wis])
1377 scare_creature (op, owner); 1365 scare_creature (op, owner);
1378 } 1366 }
1458 op->speed = 0.1; 1446 op->speed = 0.1;
1459 update_ob_speed (op); 1447 update_ob_speed (op);
1460 op->speed_left = -0.05; 1448 op->speed_left = -0.05;
1461 return maxdam; 1449 return maxdam;
1462 } 1450 }
1451
1463 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER) 1452 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER)
1464 { 1453 {
1465 remove_friendly_object (op); 1454 remove_friendly_object (op);
1455
1466 if (get_owner (op) != NULL && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op) 1456 if (get_owner (op) && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op)
1467 {
1468 op->owner->contr->ranges[range_golem] = NULL; 1457 op->owner->contr->ranges[range_golem] = 0;
1469 op->owner->contr->golem_count = 0;
1470 }
1471 1458
1472 remove_ob (op); 1459 remove_ob (op);
1473 free_object (op); 1460 free_object (op);
1474 return maxdam; 1461 return maxdam;
1475 } 1462 }
1476 1463
1477 /* Now lets start dealing with experience we get for killing something */ 1464 /* Now lets start dealing with experience we get for killing something */
1478 1465
1479 owner = get_owner (hitter); 1466 owner = get_owner (hitter);
1480 if (owner == NULL) 1467 if (!owner)
1481 owner = hitter; 1468 owner = hitter;
1482 1469
1483 /* is the victim (op) standing on battleground? */ 1470 /* is the victim (op) standing on battleground? */
1484 if (op_on_battleground (op, NULL, NULL)) 1471 if (op_on_battleground (op, NULL, NULL))
1485 battleg = 1; 1472 battleg = 1;
1515 * probably don't want to see that. 1502 * probably don't want to see that.
1516 */ 1503 */
1517 if (owner->level < op->level * 2 || op->stats.exp > 1000) 1504 if (owner->level < op->level * 2 || op->stats.exp > 1000)
1518 { 1505 {
1519 if (owner != hitter) 1506 if (owner != hitter)
1520 {
1521 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter)); 1507 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter));
1522 }
1523 else 1508 else
1524 {
1525 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op)); 1509 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op));
1526 } 1510
1527 /* Only play sounds for melee kills */ 1511 /* Only play sounds for melee kills */
1528 if (hitter->type == PLAYER) 1512 if (hitter->type == PLAYER)
1529 play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS); 1513 play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS);
1530 } 1514 }
1531 1515
1542 1526
1543 /* This code below deals with finding the appropriate skill 1527 /* This code below deals with finding the appropriate skill
1544 * to credit exp to. This is a bit problematic - we should 1528 * to credit exp to. This is a bit problematic - we should
1545 * probably never really have to look at current_weapon->skill 1529 * probably never really have to look at current_weapon->skill
1546 */ 1530 */
1547 skill = NULL; 1531 skill = 0;
1532
1548 if (hitter->skill && hitter->type != PLAYER) 1533 if (hitter->skill && hitter->type != PLAYER)
1549 skill = hitter->skill; 1534 skill = hitter->skill;
1550 else if (owner->chosen_skill) 1535 else if (owner->chosen_skill)
1551 { 1536 {
1552 skill = owner->chosen_skill->skill; 1537 skill = owner->chosen_skill->skill;
1571 break; 1556 break;
1572 } 1557 }
1573 } 1558 }
1574 } /* Was it a player that hit somethign */ 1559 } /* Was it a player that hit somethign */
1575 else 1560 else
1576 {
1577 skill = NULL; 1561 skill = 0;
1578 }
1579 1562
1580 /* Pet (or spell) killed something. */ 1563 /* Pet (or spell) killed something. */
1581 if (owner != hitter) 1564 if (owner != hitter)
1582 {
1583 (void) sprintf (buf, "%s killed %s with %s%s%s.", &owner->name, 1565 sprintf (buf, "%s killed %s with %s%s%s.", &owner->name,
1584 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : ""); 1566 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : "");
1585 }
1586 else 1567 else
1587 {
1588 (void) sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name, 1568 sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name,
1589 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ? 1569 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ?
1590 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : ""); 1570 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : "");
1591 } 1571
1592 /* These may have been set in the player code section above */ 1572 /* These may have been set in the player code section above */
1593 if (!skop) 1573 if (!skop)
1594 skop = hitter->chosen_skill; 1574 skop = hitter->chosen_skill;
1575
1595 if (!skill && skop) 1576 if (!skill && skop)
1596 skill = skop->skill; 1577 skill = skop->skill;
1597 1578
1598 new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf); 1579 new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf);
1599 1580
1600
1601 /* If you didn't kill yourself, and your not the wizard */ 1581 /* If you didn't kill yourself, and your not the wizard */
1602 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ)) 1582 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1603 { 1583 {
1604 int exp; 1584 int exp;
1605 1585
1606 /* Really don't give much experience for killing other players */ 1586 /* Really don't give much experience for killing other players */
1607 // schmorp: temporary? reduce the amount of exp gained for pking enourmously 1587 // schmorp: temporarily? reduce the amount of exp gained for pking enourmously
1608 if (op->type == PLAYER) 1588 if (op->type == PLAYER)
1609 { 1589 {
1610 if (battleg) 1590 if (battleg)
1611 { 1591 {
1612 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!"); 1592 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!");
1630 1610
1631 if (!settings.simple_exp) 1611 if (!settings.simple_exp)
1632 exp = exp / 2; 1612 exp = exp / 2;
1633 1613
1634 if (owner->type != PLAYER || owner->contr->party == NULL) 1614 if (owner->type != PLAYER || owner->contr->party == NULL)
1635 {
1636 change_exp (owner, exp, skill, 0); 1615 change_exp (owner, exp, skill, 0);
1637 }
1638 else 1616 else
1639 { 1617 {
1640 int shares = 0, count = 0; 1618 int shares = 0, count = 0;
1641
1642 player *pl; 1619 player *pl;
1643
1644 partylist *party = owner->contr->party; 1620 partylist *party = owner->contr->party;
1645 1621
1646#ifdef PARTY_KILL_LOG 1622#ifdef PARTY_KILL_LOG
1647 add_kill_to_party (party, query_name (owner), query_name (op), exp); 1623 add_kill_to_party (party, query_name (owner), query_name (op), exp);
1648#endif 1624#endif
1649 for (pl = first_player; pl != NULL; pl = pl->next) 1625 for (pl = first_player; pl != NULL; pl = pl->next)
1650 {
1651 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) 1626 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1652 { 1627 {
1653 count++; 1628 count++;
1654 shares += (pl->ob->level + 4); 1629 shares += (pl->ob->level + 4);
1655 } 1630 }
1656 } 1631
1657 if (count == 1 || shares > exp) 1632 if (count == 1 || shares > exp || !shares)
1658 change_exp (owner, exp, skill, SK_EXP_TOTAL); 1633 change_exp (owner, exp, skill, SK_EXP_TOTAL);
1659 else 1634 else
1660 { 1635 {
1661 int share = exp / shares, given = 0, nexp; 1636 int share = exp / shares, given = 0, nexp;
1662 1637
1663 for (pl = first_player; pl != NULL; pl = pl->next) 1638 for (pl = first_player; pl != NULL; pl = pl->next)
1664 {
1665 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) 1639 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1666 { 1640 {
1667 nexp = (pl->ob->level + 4) * share; 1641 nexp = (pl->ob->level + 4) * share;
1668 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL); 1642 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL);
1669 given += nexp; 1643 given += nexp;
1670 } 1644 }
1671 } 1645
1672 exp -= given; 1646 exp -= given;
1673 /* give any remainder to the player */ 1647 /* give any remainder to the player */
1674 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL); 1648 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL);
1675 } 1649 }
1676 } /* else part of a party */ 1650 } /* else part of a party */
1677
1678 } /* end if person didn't kill himself */ 1651 } /* end if person didn't kill himself */
1679 1652
1680 if (op->type != PLAYER) 1653 if (op->type != PLAYER)
1681 { 1654 {
1682 if (QUERY_FLAG (op, FLAG_FRIENDLY)) 1655 if (QUERY_FLAG (op, FLAG_FRIENDLY))
1683 { 1656 {
1684 object *owner1 = get_owner (op); 1657 object *owner1 = get_owner (op);
1685 1658
1686 if (owner1 != NULL && owner1->type == PLAYER) 1659 if (owner1 && owner1->type == PLAYER)
1687 { 1660 {
1688 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0); 1661 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0);
1689 /* Maybe we should include the owner that killed this, maybe not */ 1662 /* Maybe we should include the owner that killed this, maybe not */
1690 new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name); 1663 new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name);
1691 } 1664 }
1665
1692 remove_friendly_object (op); 1666 remove_friendly_object (op);
1693 } 1667 }
1668
1694 remove_ob (op); 1669 remove_ob (op);
1695 free_object (op); 1670 free_object (op);
1696 } 1671 }
1697 /* Player has been killed! */
1698 else 1672 else
1699 { 1673 {
1674 /* Player has been killed! */
1700 if (owner->type == PLAYER) 1675 if (owner->type == PLAYER)
1701 {
1702 snprintf (op->contr->killer, BIG_NAME, "%s the %s", &owner->name, owner->contr->title); 1676 snprintf (op->contr->killer, sizeof (op->contr->killer), "%s the %s", &owner->name, owner->contr->title);
1703 }
1704 else 1677 else
1705 {
1706 strncpy (op->contr->killer, hitter->name, BIG_NAME); 1678 assign (op->contr->killer, hitter->name);
1707 op->contr->killer[BIG_NAME - 1] = '\0';
1708 }
1709 } 1679 }
1680
1710 /* This was return -1 - that doesn't seem correct - if we return -1, process 1681 /* This was return -1 - that doesn't seem correct - if we return -1, process
1711 * continues in the calling function. 1682 * continues in the calling function.
1712 */ 1683 */
1713 return maxdam; 1684 return maxdam;
1714} 1685}
1765{ 1736{
1766 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC); 1737 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC);
1767 int maxattacktype, attacknum; 1738 int maxattacktype, attacknum;
1768 int body_attack = op && op->head; /* Did we hit op's head? */ 1739 int body_attack = op && op->head; /* Did we hit op's head? */
1769 int simple_attack; 1740 int simple_attack;
1770 tag_t op_tag, hitter_tag;
1771 int rtn_kill = 0; 1741 int rtn_kill = 0;
1772 int friendlyfire; 1742 int friendlyfire;
1773 1743
1774 if (get_attack_mode (&op, &hitter, &simple_attack)) 1744 if (get_attack_mode (&op, &hitter, &simple_attack))
1775 return 0; 1745 return 0;
1783 { 1753 {
1784 object *owner = get_owner (hitter); 1754 object *owner = get_owner (hitter);
1785 1755
1786 if (!owner) 1756 if (!owner)
1787 owner = hitter; 1757 owner = hitter;
1758
1788 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner) 1759 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner)
1789 {
1790 return 0; 1760 return 0;
1791 }
1792 } 1761 }
1793#endif 1762#endif
1794
1795 op_tag = op->count;
1796 hitter_tag = hitter->count;
1797 1763
1798 if (body_attack) 1764 if (body_attack)
1799 { 1765 {
1800 /* slow and paralyze must hit the head. But we don't want to just 1766 /* slow and paralyze must hit the head. But we don't want to just
1801 * return - we still need to process other attacks the spell still 1767 * return - we still need to process other attacks the spell still
1807 * attack so we don't cancel out things like magic bullet. 1773 * attack so we don't cancel out things like magic bullet.
1808 */ 1774 */
1809 if (type & (AT_PARALYZE | AT_SLOW)) 1775 if (type & (AT_PARALYZE | AT_SLOW))
1810 { 1776 {
1811 type &= ~(AT_PARALYZE | AT_SLOW); 1777 type &= ~(AT_PARALYZE | AT_SLOW);
1778
1812 if (!type || type == AT_MAGIC) 1779 if (!type || type == AT_MAGIC)
1813 return 0; 1780 return 0;
1814 } 1781 }
1815 } 1782 }
1816 1783
1820 1787
1821 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) 1788 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1822 if (tmp->type == RUNE || tmp->type == TRAP) 1789 if (tmp->type == RUNE || tmp->type == TRAP)
1823 { 1790 {
1824 spring_trap (tmp, hitter); 1791 spring_trap (tmp, hitter);
1825 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack)) 1792 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
1826 return 0; 1793 return 0;
1827 break; 1794 break;
1828 } 1795 }
1829 } 1796 }
1830 1797
1831 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0) 1798 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0)
1832 { 1799 {
1833 /* FIXME: If a player is killed by a rune in a door, the 1800 /* FIXME: If a player is killed by a rune in a door, the
1834 * was_destroyed() check above doesn't return, and might get here. 1801 * destroyed() check above doesn't return, and might get here.
1835 */ 1802 */
1836 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name); 1803 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name);
1837 return 0; 1804 return 0;
1838 } 1805 }
1839 1806
2058 2025
2059 2026
2060void 2027void
2061poison_player (object *op, object *hitter, int dam) 2028poison_player (object *op, object *hitter, int dam)
2062{ 2029{
2063 archetype *at = find_archetype ("poisoning"); 2030 archetype *at = archetype::find ("poisoning");
2064 object *tmp = present_arch_in_ob (at, op); 2031 object *tmp = present_arch_in_ob (at, op);
2065 2032
2066 if (tmp == NULL) 2033 if (tmp == NULL)
2067 { 2034 {
2068 if ((tmp = arch_to_object (at)) == NULL) 2035 if ((tmp = arch_to_object (at)) == NULL)
2114} 2081}
2115 2082
2116void 2083void
2117slow_player (object *op, object *hitter, int dam) 2084slow_player (object *op, object *hitter, int dam)
2118{ 2085{
2119 archetype *at = find_archetype ("slowness"); 2086 archetype *at = archetype::find ("slowness");
2120 object *tmp; 2087 object *tmp;
2121 2088
2122 if (at == NULL) 2089 if (at == NULL)
2123 { 2090 {
2124 LOG (llevError, "Can't find slowness archetype.\n"); 2091 LOG (llevError, "Can't find slowness archetype.\n");

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines