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

Comparing deliantra/server/server/attack.C (file contents):
Revision 1.10 by root, Mon Sep 11 11:46:52 2006 UTC vs.
Revision 1.20 by root, Tue Sep 19 10:35:22 2006 UTC

1
2/*
3 * static char *rcsid_attack_c =
4 * "$Id: attack.C,v 1.10 2006/09/11 11:46:52 root Exp $";
5 */
6
7/* 1/*
8 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
9 3
10 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
22 16
23 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 20
27 The authors can be reached via e-mail to crossfire-devel@real-time.com 21 The authors can be reached via e-mail to <crossfire@schmorp.de>
28*/ 22*/
29#include <assert.h> 23#include <assert.h>
30#include <global.h> 24#include <global.h>
31#include <living.h> 25#include <living.h>
32#include <material.h> 26#include <material.h>
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
317 int mflags = get_map_flags (map, &map, x, y, &x, &y); 316 int mflags = get_map_flags (map, &map, x, y, &x, &y);
318 317
319 // elmex: a safe map tile can't be hit! 318 // elmex: a safe map tile can't be hit!
320 // this should prevent most harmful effects on items and players there. 319 // this should prevent most harmful effects on items and players there.
321 if ((mflags & P_OUT_OF_MAP) || (mflags & P_SAFE)) 320 if (mflags & (P_OUT_OF_MAP | P_SAFE))
322 return 0; 321 return 0;
323 322
324 /* peterm: a few special cases for special attacktypes --counterspell 323 /* peterm: a few special cases for special attacktypes --counterspell
325 * must be out here because it strikes things which are not alive 324 * must be out here because it strikes things which are not alive
326 */ 325 */
331 330
332 /* If the only attacktype is counterspell or magic, don't need 331 /* If the only attacktype is counterspell or magic, don't need
333 * to do any further processing. 332 * to do any further processing.
334 */ 333 */
335 if (!(type & ~(AT_COUNTERSPELL | AT_MAGIC))) 334 if (!(type & ~(AT_COUNTERSPELL | AT_MAGIC)))
336 {
337 return 0; 335 return 0;
338 } 336
339 type &= ~AT_COUNTERSPELL; 337 type &= ~AT_COUNTERSPELL;
340 } 338 }
341 339
342 if (type & AT_CHAOS) 340 if (type & AT_CHAOS)
343 { 341 {
345 update_object (op, UP_OBJ_FACE); 343 update_object (op, UP_OBJ_FACE);
346 type &= ~AT_CHAOS; 344 type &= ~AT_CHAOS;
347 } 345 }
348 346
349 next = get_map_ob (map, x, y); 347 next = get_map_ob (map, x, y);
350 if (next)
351 next_tag = next->count;
352 348
353 while (next) 349 while (next)
354 { 350 {
355 if (was_destroyed (next, next_tag)) 351 if (next->destroyed ())
356 { 352 {
357 /* 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
358 * 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
359 * tags into a temporary array before we start processing the first 355 * tags into a temporary array before we start processing the first
360 * object. That's why we just abort. 356 * object. That's why we just abort.
364 * below was spamming the logs for absolutely no reason. 360 * below was spamming the logs for absolutely no reason.
365 */ 361 */
366 /* LOG (llevDebug, "hit_map(): next object destroyed\n"); */ 362 /* LOG (llevDebug, "hit_map(): next object destroyed\n"); */
367 break; 363 break;
368 } 364 }
365
369 tmp = next; 366 tmp = next;
370 next = tmp->above; 367 next = tmp->above;
371 if (next)
372 next_tag = next->count;
373 368
374 if (QUERY_FLAG (tmp, FLAG_FREED)) 369 if (tmp->destroyed ())
375 { 370 {
376 LOG (llevError, "BUG: hit_map(): found freed object\n"); 371 LOG (llevError, "BUG: hit_map(): found freed object\n");
377 break; 372 break;
378 } 373 }
379 374
386 381
387 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 382 if (QUERY_FLAG (tmp, FLAG_ALIVE))
388 { 383 {
389 hit_player (tmp, op->stats.dam, op, type, full_hit); 384 hit_player (tmp, op->stats.dam, op, type, full_hit);
390 retflag |= 1; 385 retflag |= 1;
391 if (was_destroyed (op, op_tag)) 386 if (op->destroyed ())
392 break; 387 break;
393 } 388 }
389
394 /* Here we are potentially destroying an object. If the object has 390 /* Here we are potentially destroying an object. If the object has
395 * NO_PASS set, it is also immune - you can't destroy walls. Note 391 * NO_PASS set, it is also immune - you can't destroy walls. Note
396 * that weak walls have is_alive set, which prevent objects from 392 * that weak walls have is_alive set, which prevent objects from
397 * passing over/through them. We don't care what type of movement 393 * passing over/through them. We don't care what type of movement
398 * the wall blocks - if it blocks any type of movement, can't be 394 * the wall blocks - if it blocks any type of movement, can't be
399 * destroyed right now. 395 * destroyed right now.
400 */ 396 */
401 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)
402 { 398 {
403 save_throw_object (tmp, type, op); 399 save_throw_object (tmp, type, op);
404 if (was_destroyed (op, op_tag)) 400 if (op->destroyed ())
405 break; 401 break;
406 } 402 }
407 } 403 }
404
408 return 0; 405 return 0;
409} 406}
410 407
411void 408void
412attack_message (int dam, int type, object *op, object *hitter) 409attack_message (int dam, int type, object *op, object *hitter)
413{ 410{
414 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF]; 411 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF];
415 int i, found = 0; 412 int i, found = 0;
416 mapstruct *map; 413 maptile *map;
417 object *next, *tmp; 414 object *next, *tmp;
418 415
419 /* 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
420 * a player might have. For example, fire, electric, cold, etc 417 * a player might have. For example, fire, electric, cold, etc
421 * [garbled 20010919] 418 * [garbled 20010919]
748attack_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)
749{ 746{
750 int simple_attack, roll, dam = 0; 747 int simple_attack, roll, dam = 0;
751 uint32 type; 748 uint32 type;
752 shstr op_name; 749 shstr op_name;
753 tag_t op_tag, hitter_tag;
754 750
755 if (get_attack_mode (&op, &hitter, &simple_attack)) 751 if (get_attack_mode (&op, &hitter, &simple_attack))
756 goto error; 752 goto error;
757 753
758 if (hitter->current_weapon) 754 if (hitter->current_weapon)
759 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)))
760 return RESULT_INT (0); 756 return RESULT_INT (0);
761 757
762 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter))) 758 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter)))
763 return RESULT_INT (0); 759 return RESULT_INT (0);
764
765 op_tag = op->count;
766 hitter_tag = hitter->count;
767 760
768 /* 761 /*
769 * 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
770 * to avoid ever being hit by monsters. 763 * to avoid ever being hit by monsters.
771 */ 764 */
776 * which then gets here again. By decreasing the speed before 769 * which then gets here again. By decreasing the speed before
777 * we call process_object, the 'if' statement above will fail. 770 * we call process_object, the 'if' statement above will fail.
778 */ 771 */
779 op->speed_left--; 772 op->speed_left--;
780 process_object (op); 773 process_object (op);
781 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))
782 goto error; 775 goto error;
783 } 776 }
784 777
785 op_name = op->name; 778 op_name = op->name;
786 779
837 * when they hit the victim. For things like thrown daggers, 830 * when they hit the victim. For things like thrown daggers,
838 * this sets 'hitter' to the actual dagger, and not the 831 * this sets 'hitter' to the actual dagger, and not the
839 * wrapper object. 832 * wrapper object.
840 */ 833 */
841 thrown_item_effect (hitter, op); 834 thrown_item_effect (hitter, op);
842 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))
843 goto leave; 836 goto leave;
844 } 837 }
845 838
846 /* 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
847 * to go further and it will cause FPE's below. 840 * to go further and it will cause FPE's below.
848 */ 841 */
849 if (hitdam <= 0) 842 if (hitdam <= 0)
850 hitdam = 1; 843 hitdam = 1;
851 844
852 type = hitter->attacktype; 845 type = hitter->attacktype;
846
853 if (!type) 847 if (!type)
854 type = AT_PHYSICAL; 848 type = AT_PHYSICAL;
849
855 /* Handle monsters that hit back */ 850 /* Handle monsters that hit back */
856 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))
857 { 852 {
858 if (op->attacktype & AT_ACID && hitter->type == PLAYER) 853 if (op->attacktype & AT_ACID && hitter->type == PLAYER)
859 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
860 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
861 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))
862 goto leave; 859 goto leave;
863 } 860 }
864 861
865 /* In the new attack code, it should handle multiple attack 862 /* In the new attack code, it should handle multiple attack
866 * types in its area, so remove it from here. 863 * types in its area, so remove it from here.
867 */ 864 */
868 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
869 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))
870 goto leave; 868 goto leave;
871 } /* end of if hitter hit op */ 869 } /* end of if hitter hit op */
872 /* if we missed, dam=0 */ 870 /* if we missed, dam=0 */
873 871
874 /*attack_message(dam, type, op, hitter); */ 872 /*attack_message(dam, type, op, hitter); */
931object * 929object *
932hit_with_arrow (object *op, object *victim) 930hit_with_arrow (object *op, object *victim)
933{ 931{
934 object *container, *hitter; 932 object *container, *hitter;
935 int hit_something = 0; 933 int hit_something = 0;
936 tag_t victim_tag, hitter_tag;
937 sint16 victim_x, victim_y; 934 sint16 victim_x, victim_y;
938 935
939 /* Disassemble missile */ 936 /* Disassemble missile */
940 if (op->inv) 937 if (op->inv)
941 { 938 {
955 } 952 }
956 953
957 /* Try to hit victim */ 954 /* Try to hit victim */
958 victim_x = victim->x; 955 victim_x = victim->x;
959 victim_y = victim->y; 956 victim_y = victim->y;
960 victim_tag = victim->count;
961 hitter_tag = hitter->count;
962 957
963 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);
964 959
965 /* 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
966 * arrow, move_apply() calls this function, arrow sticks in demon, 961 * arrow, move_apply() calls this function, arrow sticks in demon,
967 * 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
968 * 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
969 * other places as well!) 964 * other places as well!)
970 */ 965 */
971 if (was_destroyed (hitter, hitter_tag) || hitter->env != NULL) 966 if (hitter->destroyed () || hitter->env != NULL)
972 { 967 {
973 if (container) 968 if (container)
974 { 969 {
975 remove_ob (container); 970 remove_ob (container);
976 free_object (container); 971 free_object (container);
996 remove_ob (container); 991 remove_ob (container);
997 free_object (container); 992 free_object (container);
998 } 993 }
999 994
1000 /* Try to stick arrow into victim */ 995 /* Try to stick arrow into victim */
1001 if (!was_destroyed (victim, victim_tag) && stick_arrow (hitter, victim)) 996 if (!victim->destroyed () && stick_arrow (hitter, victim))
1002 return NULL; 997 return NULL;
1003 998
1004 /* Else try to put arrow on victim's map square 999 /* Else try to put arrow on victim's map square
1005 * 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
1006 * space, that is good enough - with the new movement code, 1001 * space, that is good enough - with the new movement code,
1328 break; 1323 break;
1329 case ATNR_TURN_UNDEAD: 1324 case ATNR_TURN_UNDEAD:
1330 { 1325 {
1331 if (QUERY_FLAG (op, FLAG_UNDEAD)) 1326 if (QUERY_FLAG (op, FLAG_UNDEAD))
1332 { 1327 {
1333 object *owner = get_owner (hitter) == NULL ? hitter : get_owner (hitter); 1328 object *owner = hitter->owner ? (object *)hitter->owner : hitter;
1334 object *god = find_god (determine_god (owner)); 1329 object *god = find_god (determine_god (owner));
1335 int div = 1; 1330 int div = 1;
1336 1331
1337 /* if undead are not an enemy of your god, you turn them 1332 /* if undead are not an enemy of your god, you turn them
1338 * at half strength */ 1333 * at half strength */
1364 break; 1359 break;
1365 case ATNR_HOLYWORD: 1360 case ATNR_HOLYWORD:
1366 { 1361 {
1367 /* This has already been handled by hit_player, 1362 /* This has already been handled by hit_player,
1368 * no need to check twice -- DAMN */ 1363 * no need to check twice -- DAMN */
1369 1364 object *owner = hitter->owner ? (object *)hitter->owner : hitter;
1370 object *owner = get_owner (hitter) == NULL ? hitter : get_owner (hitter);
1371 1365
1372 /* As with turn undead above, give a bonus on the saving throw */ 1366 /* As with turn undead above, give a bonus on the saving throw */
1373 if ((op->level + (op->resist[ATNR_HOLYWORD] / 100)) < owner->level + turn_bonus[owner->stats.Wis]) 1367 if ((op->level + (op->resist[ATNR_HOLYWORD] / 100)) < owner->level + turn_bonus[owner->stats.Wis])
1374 scare_creature (op, owner); 1368 scare_creature (op, owner);
1375 } 1369 }
1455 op->speed = 0.1; 1449 op->speed = 0.1;
1456 update_ob_speed (op); 1450 update_ob_speed (op);
1457 op->speed_left = -0.05; 1451 op->speed_left = -0.05;
1458 return maxdam; 1452 return maxdam;
1459 } 1453 }
1454
1460 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER) 1455 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER)
1461 { 1456 {
1462 remove_friendly_object (op); 1457 remove_friendly_object (op);
1463 if (get_owner (op) != NULL && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op) 1458 if (get_owner (op) && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op)
1464 { 1459 {
1465 op->owner->contr->ranges[range_golem] = NULL; 1460 op->owner->contr->ranges[range_golem] = 0;
1466 op->owner->contr->golem_count = 0; 1461 op->owner->contr->golem_count = 0;
1467 } 1462 }
1468 1463
1469 remove_ob (op); 1464 remove_ob (op);
1470 free_object (op); 1465 free_object (op);
1472 } 1467 }
1473 1468
1474 /* Now lets start dealing with experience we get for killing something */ 1469 /* Now lets start dealing with experience we get for killing something */
1475 1470
1476 owner = get_owner (hitter); 1471 owner = get_owner (hitter);
1477 if (owner == NULL) 1472 if (!owner)
1478 owner = hitter; 1473 owner = hitter;
1479 1474
1480 /* is the victim (op) standing on battleground? */ 1475 /* is the victim (op) standing on battleground? */
1481 if (op_on_battleground (op, NULL, NULL)) 1476 if (op_on_battleground (op, NULL, NULL))
1482 battleg = 1; 1477 battleg = 1;
1512 * probably don't want to see that. 1507 * probably don't want to see that.
1513 */ 1508 */
1514 if (owner->level < op->level * 2 || op->stats.exp > 1000) 1509 if (owner->level < op->level * 2 || op->stats.exp > 1000)
1515 { 1510 {
1516 if (owner != hitter) 1511 if (owner != hitter)
1517 {
1518 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter)); 1512 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter));
1519 }
1520 else 1513 else
1521 {
1522 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op)); 1514 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op));
1523 } 1515
1524 /* Only play sounds for melee kills */ 1516 /* Only play sounds for melee kills */
1525 if (hitter->type == PLAYER) 1517 if (hitter->type == PLAYER)
1526 play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS); 1518 play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS);
1527 } 1519 }
1528 1520
1539 1531
1540 /* This code below deals with finding the appropriate skill 1532 /* This code below deals with finding the appropriate skill
1541 * to credit exp to. This is a bit problematic - we should 1533 * to credit exp to. This is a bit problematic - we should
1542 * probably never really have to look at current_weapon->skill 1534 * probably never really have to look at current_weapon->skill
1543 */ 1535 */
1544 skill = NULL; 1536 skill = 0;
1537
1545 if (hitter->skill && hitter->type != PLAYER) 1538 if (hitter->skill && hitter->type != PLAYER)
1546 skill = hitter->skill; 1539 skill = hitter->skill;
1547 else if (owner->chosen_skill) 1540 else if (owner->chosen_skill)
1548 { 1541 {
1549 skill = owner->chosen_skill->skill; 1542 skill = owner->chosen_skill->skill;
1568 break; 1561 break;
1569 } 1562 }
1570 } 1563 }
1571 } /* Was it a player that hit somethign */ 1564 } /* Was it a player that hit somethign */
1572 else 1565 else
1573 {
1574 skill = NULL; 1566 skill = 0;
1575 }
1576 1567
1577 /* Pet (or spell) killed something. */ 1568 /* Pet (or spell) killed something. */
1578 if (owner != hitter) 1569 if (owner != hitter)
1579 {
1580 (void) sprintf (buf, "%s killed %s with %s%s%s.", &owner->name, 1570 sprintf (buf, "%s killed %s with %s%s%s.", &owner->name,
1581 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : ""); 1571 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : "");
1582 }
1583 else 1572 else
1584 {
1585 (void) sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name, 1573 sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name,
1586 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ? 1574 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ?
1587 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : ""); 1575 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : "");
1588 } 1576
1589 /* These may have been set in the player code section above */ 1577 /* These may have been set in the player code section above */
1590 if (!skop) 1578 if (!skop)
1591 skop = hitter->chosen_skill; 1579 skop = hitter->chosen_skill;
1580
1592 if (!skill && skop) 1581 if (!skill && skop)
1593 skill = skop->skill; 1582 skill = skop->skill;
1594 1583
1595 new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf); 1584 new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf);
1596 1585
1597
1598 /* If you didn't kill yourself, and your not the wizard */ 1586 /* If you didn't kill yourself, and your not the wizard */
1599 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ)) 1587 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1600 { 1588 {
1601 int exp; 1589 int exp;
1602 1590
1603 /* Really don't give much experience for killing other players */ 1591 /* Really don't give much experience for killing other players */
1604 // schmorp: temporary? reduce the amount of exp gained for pking enourmously 1592 // schmorp: temporarily? reduce the amount of exp gained for pking enourmously
1605 if (op->type == PLAYER) 1593 if (op->type == PLAYER)
1606 { 1594 {
1607 if (battleg) 1595 if (battleg)
1608 { 1596 {
1609 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!"); 1597 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!");
1633 change_exp (owner, exp, skill, 0); 1621 change_exp (owner, exp, skill, 0);
1634 } 1622 }
1635 else 1623 else
1636 { 1624 {
1637 int shares = 0, count = 0; 1625 int shares = 0, count = 0;
1638
1639 player *pl; 1626 player *pl;
1640
1641 partylist *party = owner->contr->party; 1627 partylist *party = owner->contr->party;
1642 1628
1643#ifdef PARTY_KILL_LOG 1629#ifdef PARTY_KILL_LOG
1644 add_kill_to_party (party, query_name (owner), query_name (op), exp); 1630 add_kill_to_party (party, query_name (owner), query_name (op), exp);
1645#endif 1631#endif
1646 for (pl = first_player; pl != NULL; pl = pl->next) 1632 for (pl = first_player; pl != NULL; pl = pl->next)
1647 {
1648 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) 1633 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1649 { 1634 {
1650 count++; 1635 count++;
1651 shares += (pl->ob->level + 4); 1636 shares += (pl->ob->level + 4);
1652 } 1637 }
1653 } 1638
1654 if (count == 1 || shares > exp) 1639 if (count == 1 || shares > exp)
1655 change_exp (owner, exp, skill, SK_EXP_TOTAL); 1640 change_exp (owner, exp, skill, SK_EXP_TOTAL);
1656 else 1641 else
1657 { 1642 {
1658 int share = exp / shares, given = 0, nexp; 1643 int share = exp / shares, given = 0, nexp;
1659 1644
1660 for (pl = first_player; pl != NULL; pl = pl->next) 1645 for (pl = first_player; pl != NULL; pl = pl->next)
1661 {
1662 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) 1646 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1663 { 1647 {
1664 nexp = (pl->ob->level + 4) * share; 1648 nexp = (pl->ob->level + 4) * share;
1665 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL); 1649 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL);
1666 given += nexp; 1650 given += nexp;
1667 } 1651 }
1668 } 1652
1669 exp -= given; 1653 exp -= given;
1670 /* give any remainder to the player */ 1654 /* give any remainder to the player */
1671 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL); 1655 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL);
1672 } 1656 }
1673 } /* else part of a party */ 1657 } /* else part of a party */
1674
1675 } /* end if person didn't kill himself */ 1658 } /* end if person didn't kill himself */
1676 1659
1677 if (op->type != PLAYER) 1660 if (op->type != PLAYER)
1678 { 1661 {
1679 if (QUERY_FLAG (op, FLAG_FRIENDLY)) 1662 if (QUERY_FLAG (op, FLAG_FRIENDLY))
1680 { 1663 {
1681 object *owner1 = get_owner (op); 1664 object *owner1 = get_owner (op);
1682 1665
1683 if (owner1 != NULL && owner1->type == PLAYER) 1666 if (owner1 && owner1->type == PLAYER)
1684 { 1667 {
1685 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0); 1668 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0);
1686 /* Maybe we should include the owner that killed this, maybe not */ 1669 /* Maybe we should include the owner that killed this, maybe not */
1687 new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name); 1670 new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name);
1688 } 1671 }
1672
1689 remove_friendly_object (op); 1673 remove_friendly_object (op);
1690 } 1674 }
1675
1691 remove_ob (op); 1676 remove_ob (op);
1692 free_object (op); 1677 free_object (op);
1693 } 1678 }
1694 /* Player has been killed! */
1695 else 1679 else
1696 { 1680 {
1681 /* Player has been killed! */
1697 if (owner->type == PLAYER) 1682 if (owner->type == PLAYER)
1698 {
1699 snprintf (op->contr->killer, BIG_NAME, "%s the %s", &owner->name, owner->contr->title); 1683 snprintf (op->contr->killer, BIG_NAME, "%s the %s", &owner->name, owner->contr->title);
1700 }
1701 else 1684 else
1702 {
1703 strncpy (op->contr->killer, hitter->name, BIG_NAME); 1685 assign (op->contr->killer, hitter->name);
1704 op->contr->killer[BIG_NAME - 1] = '\0';
1705 }
1706 } 1686 }
1687
1707 /* This was return -1 - that doesn't seem correct - if we return -1, process 1688 /* This was return -1 - that doesn't seem correct - if we return -1, process
1708 * continues in the calling function. 1689 * continues in the calling function.
1709 */ 1690 */
1710 return maxdam; 1691 return maxdam;
1711} 1692}
1762{ 1743{
1763 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC); 1744 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC);
1764 int maxattacktype, attacknum; 1745 int maxattacktype, attacknum;
1765 int body_attack = op && op->head; /* Did we hit op's head? */ 1746 int body_attack = op && op->head; /* Did we hit op's head? */
1766 int simple_attack; 1747 int simple_attack;
1767 tag_t op_tag, hitter_tag;
1768 int rtn_kill = 0; 1748 int rtn_kill = 0;
1769 int friendlyfire; 1749 int friendlyfire;
1770 1750
1771 if (get_attack_mode (&op, &hitter, &simple_attack)) 1751 if (get_attack_mode (&op, &hitter, &simple_attack))
1772 return 0; 1752 return 0;
1780 { 1760 {
1781 object *owner = get_owner (hitter); 1761 object *owner = get_owner (hitter);
1782 1762
1783 if (!owner) 1763 if (!owner)
1784 owner = hitter; 1764 owner = hitter;
1765
1785 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner) 1766 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner)
1786 {
1787 return 0; 1767 return 0;
1788 }
1789 } 1768 }
1790#endif 1769#endif
1791
1792 op_tag = op->count;
1793 hitter_tag = hitter->count;
1794 1770
1795 if (body_attack) 1771 if (body_attack)
1796 { 1772 {
1797 /* slow and paralyze must hit the head. But we don't want to just 1773 /* slow and paralyze must hit the head. But we don't want to just
1798 * return - we still need to process other attacks the spell still 1774 * return - we still need to process other attacks the spell still
1804 * attack so we don't cancel out things like magic bullet. 1780 * attack so we don't cancel out things like magic bullet.
1805 */ 1781 */
1806 if (type & (AT_PARALYZE | AT_SLOW)) 1782 if (type & (AT_PARALYZE | AT_SLOW))
1807 { 1783 {
1808 type &= ~(AT_PARALYZE | AT_SLOW); 1784 type &= ~(AT_PARALYZE | AT_SLOW);
1785
1809 if (!type || type == AT_MAGIC) 1786 if (!type || type == AT_MAGIC)
1810 return 0; 1787 return 0;
1811 } 1788 }
1812 } 1789 }
1813 1790
1817 1794
1818 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) 1795 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1819 if (tmp->type == RUNE || tmp->type == TRAP) 1796 if (tmp->type == RUNE || tmp->type == TRAP)
1820 { 1797 {
1821 spring_trap (tmp, hitter); 1798 spring_trap (tmp, hitter);
1822 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack)) 1799 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
1823 return 0; 1800 return 0;
1824 break; 1801 break;
1825 } 1802 }
1826 } 1803 }
1827 1804
1828 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0) 1805 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0)
1829 { 1806 {
1830 /* FIXME: If a player is killed by a rune in a door, the 1807 /* FIXME: If a player is killed by a rune in a door, the
1831 * was_destroyed() check above doesn't return, and might get here. 1808 * destroyed() check above doesn't return, and might get here.
1832 */ 1809 */
1833 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name); 1810 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name);
1834 return 0; 1811 return 0;
1835 } 1812 }
1836 1813
2055 2032
2056 2033
2057void 2034void
2058poison_player (object *op, object *hitter, int dam) 2035poison_player (object *op, object *hitter, int dam)
2059{ 2036{
2060 archetype *at = find_archetype ("poisoning"); 2037 archetype *at = archetype::find ("poisoning");
2061 object *tmp = present_arch_in_ob (at, op); 2038 object *tmp = present_arch_in_ob (at, op);
2062 2039
2063 if (tmp == NULL) 2040 if (tmp == NULL)
2064 { 2041 {
2065 if ((tmp = arch_to_object (at)) == NULL) 2042 if ((tmp = arch_to_object (at)) == NULL)
2111} 2088}
2112 2089
2113void 2090void
2114slow_player (object *op, object *hitter, int dam) 2091slow_player (object *op, object *hitter, int dam)
2115{ 2092{
2116 archetype *at = find_archetype ("slowness"); 2093 archetype *at = archetype::find ("slowness");
2117 object *tmp; 2094 object *tmp;
2118 2095
2119 if (at == NULL) 2096 if (at == NULL)
2120 { 2097 {
2121 LOG (llevError, "Can't find slowness archetype.\n"); 2098 LOG (llevError, "Can't find slowness archetype.\n");

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines