1 | /* |
1 | /* |
2 | * static char *rcsid_attack_c = |
2 | * static char *rcsid_attack_c = |
3 | * "$Id: attack.C,v 1.6 2006/08/29 11:58:02 elmex Exp $"; |
3 | * "$Id: attack.C,v 1.8 2006/09/03 00:18:42 root Exp $"; |
4 | */ |
4 | */ |
5 | /* |
5 | /* |
6 | CrossFire, A Multiplayer game for X-windows |
6 | CrossFire, A Multiplayer game for X-windows |
7 | |
7 | |
8 | Copyright (C) 2002 Mark Wedel & Crossfire Development Team |
8 | Copyright (C) 2002 Mark Wedel & Crossfire Development Team |
… | |
… | |
261 | return 0; |
261 | return 0; |
262 | } |
262 | } |
263 | |
263 | |
264 | if (QUERY_FLAG (op, FLAG_REMOVED) || op->env != NULL) { |
264 | if (QUERY_FLAG (op, FLAG_REMOVED) || op->env != NULL) { |
265 | LOG (llevError, "BUG: hit_map(): hitter (arch %s, name %s) not on a map\n", |
265 | LOG (llevError, "BUG: hit_map(): hitter (arch %s, name %s) not on a map\n", |
266 | op->arch->name, op->name); |
266 | &op->arch->name, &op->name); |
267 | return 0; |
267 | return 0; |
268 | } |
268 | } |
269 | |
269 | |
270 | if ( ! op->map) { |
270 | if ( ! op->map) { |
271 | LOG (llevError,"BUG: hit_map(): %s has no map\n", op->name); |
271 | LOG (llevError,"BUG: hit_map(): %s has no map\n", &op->name); |
272 | return 0; |
272 | return 0; |
273 | } |
273 | } |
274 | |
274 | |
275 | if (op->head) op=op->head; |
275 | if (op->head) op=op->head; |
276 | |
276 | |
… | |
… | |
376 | * a player might have. For example, fire, electric, cold, etc |
376 | * a player might have. For example, fire, electric, cold, etc |
377 | * [garbled 20010919] |
377 | * [garbled 20010919] |
378 | */ |
378 | */ |
379 | |
379 | |
380 | if (dam == 9998 && op->type == DOOR) { |
380 | if (dam == 9998 && op->type == DOOR) { |
381 | sprintf(buf1, "unlock %s", op->name); |
381 | sprintf(buf1, "unlock %s", &op->name); |
382 | sprintf(buf2, " unlocks"); |
382 | sprintf(buf2, " unlocks"); |
383 | found++; |
383 | found++; |
384 | } |
384 | } |
385 | if(dam<0) { |
385 | if(dam<0) { |
386 | sprintf(buf1, "hit %s", op->name); |
386 | sprintf(buf1, "hit %s", &op->name); |
387 | sprintf(buf2, " hits"); |
387 | sprintf(buf2, " hits"); |
388 | found++; |
388 | found++; |
389 | } else if(dam==0) { |
389 | } else if(dam==0) { |
390 | sprintf(buf1, "missed %s", op->name); |
390 | sprintf(buf1, "missed %s", &op->name); |
391 | sprintf(buf2, " misses"); |
391 | sprintf(buf2, " misses"); |
392 | found++; |
392 | found++; |
393 | } else if ((hitter->type == DISEASE || hitter->type == SYMPTOM || |
393 | } else if ((hitter->type == DISEASE || hitter->type == SYMPTOM || |
394 | hitter->type == POISONING || |
394 | hitter->type == POISONING || |
395 | (type & AT_POISON && IS_LIVE(op))) && !found) { |
395 | (type & AT_POISON && IS_LIVE(op))) && !found) { |
396 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_SUFFER][i].level != -1; |
396 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_SUFFER][i].level != -1; |
397 | i++) |
397 | i++) |
398 | if (dam < attack_mess[ATM_SUFFER][i].level |
398 | if (dam < attack_mess[ATM_SUFFER][i].level |
399 | || attack_mess[ATM_SUFFER][i+1].level == -1) { |
399 | || attack_mess[ATM_SUFFER][i+1].level == -1) { |
400 | sprintf(buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1, |
400 | sprintf(buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1, |
401 | op->name, attack_mess[ATM_SUFFER][i].buf2); |
401 | &op->name, attack_mess[ATM_SUFFER][i].buf2); |
402 | strcpy (buf2, attack_mess[ATM_SUFFER][i].buf3); |
402 | strcpy (buf2, attack_mess[ATM_SUFFER][i].buf3); |
403 | found++; |
403 | found++; |
404 | break; |
404 | break; |
405 | } |
405 | } |
406 | } else if (op->type == DOOR && !found) { |
406 | } else if (op->type == DOOR && !found) { |
407 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_DOOR][i].level != -1; |
407 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_DOOR][i].level != -1; |
408 | i++) |
408 | i++) |
409 | if (dam < attack_mess[ATM_DOOR][i].level |
409 | if (dam < attack_mess[ATM_DOOR][i].level |
410 | || attack_mess[ATM_DOOR][i+1].level == -1) { |
410 | || attack_mess[ATM_DOOR][i+1].level == -1) { |
411 | sprintf(buf1, "%s %s%s", attack_mess[ATM_DOOR][i].buf1, |
411 | sprintf(buf1, "%s %s%s", attack_mess[ATM_DOOR][i].buf1, |
412 | op->name, attack_mess[ATM_DOOR][i].buf2); |
412 | &op->name, attack_mess[ATM_DOOR][i].buf2); |
413 | strcpy (buf2, attack_mess[ATM_DOOR][i].buf3); |
413 | strcpy (buf2, attack_mess[ATM_DOOR][i].buf3); |
414 | found++; |
414 | found++; |
415 | break; |
415 | break; |
416 | } |
416 | } |
417 | } else if (hitter->type == PLAYER && IS_LIVE(op)) { |
417 | } else if (hitter->type == PLAYER && IS_LIVE(op)) { |
… | |
… | |
419 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_KARATE][i].level != -1; |
419 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_KARATE][i].level != -1; |
420 | i++) |
420 | i++) |
421 | if (dam < attack_mess[ATM_KARATE][i].level |
421 | if (dam < attack_mess[ATM_KARATE][i].level |
422 | || attack_mess[ATM_KARATE][i+1].level == -1) { |
422 | || attack_mess[ATM_KARATE][i+1].level == -1) { |
423 | sprintf(buf1, "%s %s%s", attack_mess[ATM_KARATE][i].buf1, |
423 | sprintf(buf1, "%s %s%s", attack_mess[ATM_KARATE][i].buf1, |
424 | op->name, attack_mess[ATM_KARATE][i].buf2); |
424 | &op->name, attack_mess[ATM_KARATE][i].buf2); |
425 | strcpy (buf2, attack_mess[ATM_KARATE][i].buf3); |
425 | strcpy (buf2, attack_mess[ATM_KARATE][i].buf3); |
426 | found++; |
426 | found++; |
427 | break; |
427 | break; |
428 | } |
428 | } |
429 | } else if (USING_SKILL(hitter, SK_CLAWING)) { |
429 | } else if (USING_SKILL(hitter, SK_CLAWING)) { |
430 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_CLAW][i].level != -1; |
430 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_CLAW][i].level != -1; |
431 | i++) |
431 | i++) |
432 | if (dam < attack_mess[ATM_CLAW][i].level |
432 | if (dam < attack_mess[ATM_CLAW][i].level |
433 | || attack_mess[ATM_CLAW][i+1].level == -1) { |
433 | || attack_mess[ATM_CLAW][i+1].level == -1) { |
434 | sprintf(buf1, "%s %s%s", attack_mess[ATM_CLAW][i].buf1, |
434 | sprintf(buf1, "%s %s%s", attack_mess[ATM_CLAW][i].buf1, |
435 | op->name, attack_mess[ATM_CLAW][i].buf2); |
435 | &op->name, attack_mess[ATM_CLAW][i].buf2); |
436 | strcpy (buf2, attack_mess[ATM_CLAW][i].buf3); |
436 | strcpy (buf2, attack_mess[ATM_CLAW][i].buf3); |
437 | found++; |
437 | found++; |
438 | break; |
438 | break; |
439 | } |
439 | } |
440 | } else if (USING_SKILL(hitter, SK_PUNCHING)) { |
440 | } else if (USING_SKILL(hitter, SK_PUNCHING)) { |
441 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_PUNCH][i].level != -1; |
441 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_PUNCH][i].level != -1; |
442 | i++) |
442 | i++) |
443 | if (dam < attack_mess[ATM_PUNCH][i].level |
443 | if (dam < attack_mess[ATM_PUNCH][i].level |
444 | || attack_mess[ATM_PUNCH][i+1].level == -1) { |
444 | || attack_mess[ATM_PUNCH][i+1].level == -1) { |
445 | sprintf(buf1, "%s %s%s", attack_mess[ATM_PUNCH][i].buf1, |
445 | sprintf(buf1, "%s %s%s", attack_mess[ATM_PUNCH][i].buf1, |
446 | op->name, attack_mess[ATM_PUNCH][i].buf2); |
446 | &op->name, attack_mess[ATM_PUNCH][i].buf2); |
447 | strcpy (buf2, attack_mess[ATM_PUNCH][i].buf3); |
447 | strcpy (buf2, attack_mess[ATM_PUNCH][i].buf3); |
448 | found++; |
448 | found++; |
449 | break; |
449 | break; |
450 | } |
450 | } |
451 | } |
451 | } |
… | |
… | |
466 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_DRAIN][i].level != -1; |
466 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_DRAIN][i].level != -1; |
467 | i++) |
467 | i++) |
468 | if (dam < attack_mess[ATM_DRAIN][i].level |
468 | if (dam < attack_mess[ATM_DRAIN][i].level |
469 | || attack_mess[ATM_DRAIN][i+1].level == -1) { |
469 | || attack_mess[ATM_DRAIN][i+1].level == -1) { |
470 | sprintf(buf1, "%s %s%s", attack_mess[ATM_DRAIN][i].buf1, |
470 | sprintf(buf1, "%s %s%s", attack_mess[ATM_DRAIN][i].buf1, |
471 | op->name, attack_mess[ATM_DRAIN][i].buf2); |
471 | &op->name, attack_mess[ATM_DRAIN][i].buf2); |
472 | strcpy (buf2, attack_mess[ATM_DRAIN][i].buf3); |
472 | strcpy (buf2, attack_mess[ATM_DRAIN][i].buf3); |
473 | found++; |
473 | found++; |
474 | break; |
474 | break; |
475 | } |
475 | } |
476 | } else if (type & AT_ELECTRICITY && IS_LIVE(op)) { |
476 | } else if (type & AT_ELECTRICITY && IS_LIVE(op)) { |
477 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_ELEC][i].level != -1; |
477 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_ELEC][i].level != -1; |
478 | i++) |
478 | i++) |
479 | if (dam < attack_mess[ATM_ELEC][i].level |
479 | if (dam < attack_mess[ATM_ELEC][i].level |
480 | || attack_mess[ATM_ELEC][i+1].level == -1) { |
480 | || attack_mess[ATM_ELEC][i+1].level == -1) { |
481 | sprintf(buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1, |
481 | sprintf(buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1, |
482 | op->name, attack_mess[ATM_ELEC][i].buf2); |
482 | &op->name, attack_mess[ATM_ELEC][i].buf2); |
483 | strcpy (buf2, attack_mess[ATM_ELEC][i].buf3); |
483 | strcpy (buf2, attack_mess[ATM_ELEC][i].buf3); |
484 | found++; |
484 | found++; |
485 | break; |
485 | break; |
486 | } |
486 | } |
487 | } else if (type & AT_COLD && IS_LIVE(op)) { |
487 | } else if (type & AT_COLD && IS_LIVE(op)) { |
488 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_COLD][i].level != -1; |
488 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_COLD][i].level != -1; |
489 | i++) |
489 | i++) |
490 | if (dam < attack_mess[ATM_COLD][i].level |
490 | if (dam < attack_mess[ATM_COLD][i].level |
491 | || attack_mess[ATM_COLD][i+1].level == -1) { |
491 | || attack_mess[ATM_COLD][i+1].level == -1) { |
492 | sprintf(buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1, |
492 | sprintf(buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1, |
493 | op->name, attack_mess[ATM_COLD][i].buf2); |
493 | &op->name, attack_mess[ATM_COLD][i].buf2); |
494 | strcpy (buf2, attack_mess[ATM_COLD][i].buf3); |
494 | strcpy (buf2, attack_mess[ATM_COLD][i].buf3); |
495 | found++; |
495 | found++; |
496 | break; |
496 | break; |
497 | } |
497 | } |
498 | } else if (type & AT_FIRE) { |
498 | } else if (type & AT_FIRE) { |
499 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_FIRE][i].level != -1; |
499 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_FIRE][i].level != -1; |
500 | i++) |
500 | i++) |
501 | if (dam < attack_mess[ATM_FIRE][i].level |
501 | if (dam < attack_mess[ATM_FIRE][i].level |
502 | || attack_mess[ATM_FIRE][i+1].level == -1) { |
502 | || attack_mess[ATM_FIRE][i+1].level == -1) { |
503 | sprintf(buf1, "%s %s%s", attack_mess[ATM_FIRE][i].buf1, |
503 | sprintf(buf1, "%s %s%s", attack_mess[ATM_FIRE][i].buf1, |
504 | op->name, attack_mess[ATM_FIRE][i].buf2); |
504 | &op->name, attack_mess[ATM_FIRE][i].buf2); |
505 | strcpy (buf2, attack_mess[ATM_FIRE][i].buf3); |
505 | strcpy (buf2, attack_mess[ATM_FIRE][i].buf3); |
506 | found++; |
506 | found++; |
507 | break; |
507 | break; |
508 | } |
508 | } |
509 | } else if (hitter->current_weapon != NULL) { |
509 | } else if (hitter->current_weapon != NULL) { |
… | |
… | |
523 | for (i=0; i < MAXATTACKMESS && attack_mess[mtype][i].level != -1; |
523 | for (i=0; i < MAXATTACKMESS && attack_mess[mtype][i].level != -1; |
524 | i++) |
524 | i++) |
525 | if (dam < attack_mess[mtype][i].level |
525 | if (dam < attack_mess[mtype][i].level |
526 | || attack_mess[mtype][i+1].level == -1) { |
526 | || attack_mess[mtype][i+1].level == -1) { |
527 | sprintf(buf1, "%s %s%s", attack_mess[mtype][i].buf1, |
527 | sprintf(buf1, "%s %s%s", attack_mess[mtype][i].buf1, |
528 | op->name, attack_mess[mtype][i].buf2); |
528 | &op->name, attack_mess[mtype][i].buf2); |
529 | strcpy (buf2, attack_mess[mtype][i].buf3); |
529 | strcpy (buf2, attack_mess[mtype][i].buf3); |
530 | found++; |
530 | found++; |
531 | break; |
531 | break; |
532 | } |
532 | } |
533 | } else { |
533 | } else { |
534 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_BASIC][i].level != -1; |
534 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_BASIC][i].level != -1; |
535 | i++) |
535 | i++) |
536 | if (dam < attack_mess[ATM_BASIC][i].level |
536 | if (dam < attack_mess[ATM_BASIC][i].level |
537 | || attack_mess[ATM_BASIC][i+1].level == -1) { |
537 | || attack_mess[ATM_BASIC][i+1].level == -1) { |
538 | sprintf(buf1, "%s %s%s", attack_mess[ATM_BASIC][i].buf1, |
538 | sprintf(buf1, "%s %s%s", attack_mess[ATM_BASIC][i].buf1, |
539 | op->name, attack_mess[ATM_BASIC][i].buf2); |
539 | &op->name, attack_mess[ATM_BASIC][i].buf2); |
540 | strcpy (buf2, attack_mess[ATM_BASIC][i].buf3); |
540 | strcpy (buf2, attack_mess[ATM_BASIC][i].buf3); |
541 | found++; |
541 | found++; |
542 | break; |
542 | break; |
543 | } |
543 | } |
544 | } |
544 | } |
… | |
… | |
560 | /* Did a player hurt another player? Inform both! */ |
560 | /* Did a player hurt another player? Inform both! */ |
561 | if(op->type==PLAYER && |
561 | if(op->type==PLAYER && |
562 | (get_owner(hitter)==NULL?hitter->type:hitter->owner->type)==PLAYER) { |
562 | (get_owner(hitter)==NULL?hitter->type:hitter->owner->type)==PLAYER) { |
563 | if(get_owner(hitter)!=NULL) |
563 | if(get_owner(hitter)!=NULL) |
564 | sprintf(buf,"%s's %s%s you.", |
564 | sprintf(buf,"%s's %s%s you.", |
565 | hitter->owner->name, hitter->name, buf2); |
565 | &hitter->owner->name, &hitter->name, buf2); |
566 | else { |
566 | else { |
567 | sprintf(buf,"%s%s you.",hitter->name, buf2); |
567 | sprintf(buf,"%s%s you.", &hitter->name, buf2); |
568 | if (dam != 0) { |
568 | if (dam != 0) { |
569 | if (dam < 10) |
569 | if (dam < 10) |
570 | play_sound_player_only(op->contr, SOUND_PLAYER_IS_HIT1,0,0); |
570 | play_sound_player_only(op->contr, SOUND_PLAYER_IS_HIT1,0,0); |
571 | else if (dam < 20) |
571 | else if (dam < 20) |
572 | play_sound_player_only(op->contr, SOUND_PLAYER_IS_HIT2,0,0); |
572 | play_sound_player_only(op->contr, SOUND_PLAYER_IS_HIT2,0,0); |
… | |
… | |
612 | return; |
612 | return; |
613 | if (rndm(0, i) != 0) |
613 | if (rndm(0, i) != 0) |
614 | return; |
614 | return; |
615 | } else if (rndm(0, 5) != 0) |
615 | } else if (rndm(0, 5) != 0) |
616 | return; |
616 | return; |
617 | sprintf(buf,"Your %s%s %s.", hitter->name, buf2, op->name); |
617 | sprintf(buf,"Your %s%s %s.", &hitter->name, buf2, &op->name); |
618 | play_sound_map(op->map, op->x, op->y, SOUND_PLAYER_HITS4); |
618 | play_sound_map(op->map, op->x, op->y, SOUND_PLAYER_HITS4); |
619 | new_draw_info(NDI_BLACK, 0, hitter->owner, buf); |
619 | new_draw_info(NDI_BLACK, 0, hitter->owner, buf); |
620 | } |
620 | } |
621 | } |
621 | } |
622 | |
622 | |
… | |
… | |
639 | if (QUERY_FLAG (*target, FLAG_REMOVED) |
639 | if (QUERY_FLAG (*target, FLAG_REMOVED) |
640 | || QUERY_FLAG (*hitter, FLAG_REMOVED) |
640 | || QUERY_FLAG (*hitter, FLAG_REMOVED) |
641 | || (*hitter)->map == NULL || !on_same_map((*hitter), (*target))) |
641 | || (*hitter)->map == NULL || !on_same_map((*hitter), (*target))) |
642 | { |
642 | { |
643 | LOG (llevError, "BUG: hitter (arch %s, name %s) with no relation to " |
643 | LOG (llevError, "BUG: hitter (arch %s, name %s) with no relation to " |
644 | "target\n", (*hitter)->arch->name, (*hitter)->name); |
644 | "target\n", &(*hitter)->arch->name, &(*hitter)->name); |
645 | return 1; |
645 | return 1; |
646 | } |
646 | } |
647 | *simple_attack = 0; |
647 | *simple_attack = 0; |
648 | return 0; |
648 | return 0; |
649 | } |
649 | } |
… | |
… | |
671 | static int attack_ob_simple (object *op, object *hitter, int base_dam, |
671 | static int attack_ob_simple (object *op, object *hitter, int base_dam, |
672 | int base_wc) |
672 | int base_wc) |
673 | { |
673 | { |
674 | int simple_attack, roll, dam=0; |
674 | int simple_attack, roll, dam=0; |
675 | uint32 type; |
675 | uint32 type; |
676 | const char *op_name = NULL; |
676 | shstr op_name; |
677 | tag_t op_tag, hitter_tag; |
677 | tag_t op_tag, hitter_tag; |
678 | |
678 | |
679 | if (get_attack_mode (&op, &hitter, &simple_attack)) |
679 | if (get_attack_mode (&op, &hitter, &simple_attack)) |
680 | goto error; |
680 | goto error; |
681 | |
681 | |
682 | if (hitter->current_weapon) |
682 | if (hitter->current_weapon) |
683 | if (INVOKE_OBJECT (ATTACKS, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op))) |
683 | if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op))) |
684 | return RESULT_INT (0); |
684 | return RESULT_INT (0); |
685 | |
685 | |
686 | if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter))) |
686 | if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter))) |
687 | return RESULT_INT (0); |
687 | return RESULT_INT (0); |
688 | |
688 | |
… | |
… | |
706 | if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) |
706 | if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) |
707 | || abort_attack (op, hitter, simple_attack)) |
707 | || abort_attack (op, hitter, simple_attack)) |
708 | goto error; |
708 | goto error; |
709 | } |
709 | } |
710 | |
710 | |
711 | add_refcount(op_name = op->name); |
711 | op_name = op->name; |
712 | |
712 | |
713 | roll=random_roll(1, 20, hitter, PREFER_HIGH); |
713 | roll=random_roll(1, 20, hitter, PREFER_HIGH); |
714 | |
714 | |
715 | /* Adjust roll for various situations. */ |
715 | /* Adjust roll for various situations. */ |
716 | if ( ! simple_attack) |
716 | if ( ! simple_attack) |
… | |
… | |
730 | if (op->type == PLAYER) { |
730 | if (op->type == PLAYER) { |
731 | new_draw_info(NDI_UNIQUE, 0,op,"You were hit and lost " |
731 | new_draw_info(NDI_UNIQUE, 0,op,"You were hit and lost " |
732 | "your spell!"); |
732 | "your spell!"); |
733 | new_draw_info_format(NDI_ALL|NDI_UNIQUE,5,NULL, |
733 | new_draw_info_format(NDI_ALL|NDI_UNIQUE,5,NULL, |
734 | "%s was hit by %s and lost a spell.", |
734 | "%s was hit by %s and lost a spell.", |
735 | op_name,hitter->name); |
735 | &op_name,&hitter->name); |
736 | } |
736 | } |
737 | } |
737 | } |
738 | } |
738 | } |
739 | if ( ! simple_attack) |
739 | if ( ! simple_attack) |
740 | { |
740 | { |
… | |
… | |
809 | |
809 | |
810 | error: |
810 | error: |
811 | dam = 1; |
811 | dam = 1; |
812 | |
812 | |
813 | leave: |
813 | leave: |
814 | if (op_name) |
|
|
815 | free_string (op_name); |
|
|
816 | |
814 | |
817 | return dam; |
815 | return dam; |
818 | } |
816 | } |
819 | |
817 | |
820 | int attack_ob (object *op, object *hitter) |
818 | int attack_ob (object *op, object *hitter) |
… | |
… | |
954 | void tear_down_wall(object *op) |
952 | void tear_down_wall(object *op) |
955 | { |
953 | { |
956 | int perc=0; |
954 | int perc=0; |
957 | |
955 | |
958 | if (!op->stats.maxhp) { |
956 | if (!op->stats.maxhp) { |
959 | LOG(llevError, "TEAR_DOWN wall %s had no maxhp.\n", op->name); |
957 | LOG(llevError, "TEAR_DOWN wall %s had no maxhp.\n", &op->name); |
960 | perc = 1; |
958 | perc = 1; |
961 | } else if(!GET_ANIM_ID(op)) { |
959 | } else if(!GET_ANIM_ID(op)) { |
962 | /* Object has been called - no animations, so remove it */ |
960 | /* Object has been called - no animations, so remove it */ |
963 | if(op->stats.hp<0) { |
961 | if(op->stats.hp<0) { |
964 | remove_ob(op); /* Should update LOS */ |
962 | remove_ob(op); /* Should update LOS */ |
… | |
… | |
1200 | object *owner = get_owner(hitter); |
1198 | object *owner = get_owner(hitter); |
1201 | |
1199 | |
1202 | if (owner && owner != hitter) { |
1200 | if (owner && owner != hitter) { |
1203 | if (op->type != PLAYER || owner->type != PLAYER) |
1201 | if (op->type != PLAYER || owner->type != PLAYER) |
1204 | change_exp(owner, op->stats.exp/(rate*2), |
1202 | change_exp(owner, op->stats.exp/(rate*2), |
1205 | hitter->chosen_skill? hitter->chosen_skill->skill:NULL, SK_EXP_TOTAL); |
1203 | hitter->chosen_skill ? hitter->chosen_skill->skill : (const char *)0, SK_EXP_TOTAL); |
1206 | } else if (op->type != PLAYER || hitter->type != PLAYER) { |
1204 | } else if (op->type != PLAYER || hitter->type != PLAYER) { |
1207 | change_exp(hitter, op->stats.exp/(rate*2), |
1205 | change_exp(hitter, op->stats.exp/(rate*2), |
1208 | hitter->chosen_skill?hitter->chosen_skill->skill:NULL, 0); |
1206 | hitter->chosen_skill ? hitter->chosen_skill->skill : (const char*)0, 0); |
1209 | } |
1207 | } |
1210 | change_exp(op,-op->stats.exp/rate, NULL, 0); |
1208 | change_exp(op,-op->stats.exp/rate, NULL, 0); |
1211 | } |
1209 | } |
1212 | dam = 1; /* Drain is an effect. Still return 1 - otherwise, if you have pure |
1210 | dam = 1; /* Drain is an effect. Still return 1 - otherwise, if you have pure |
1213 | * drain attack, you won't know that you are actually sucking out EXP, |
1211 | * drain attack, you won't know that you are actually sucking out EXP, |
… | |
… | |
1389 | |
1387 | |
1390 | tmv = localtime(&t); |
1388 | tmv = localtime(&t); |
1391 | strftime(buf, 256,"%a %b %d %H:%M:%S %Y", tmv); |
1389 | strftime(buf, 256,"%a %b %d %H:%M:%S %Y", tmv); |
1392 | |
1390 | |
1393 | LOG(llevInfo,"%s PLAYER_KILL_PLAYER: %s (%s) killed %s\n", |
1391 | LOG(llevInfo,"%s PLAYER_KILL_PLAYER: %s (%s) killed %s\n", |
1394 | buf, owner->name, owner->contr->socket.host, query_name(op)); |
1392 | buf, &owner->name, owner->contr->socket.host, query_name(op)); |
1395 | } |
1393 | } |
1396 | |
1394 | |
1397 | /* try to filter some things out - basically, if you are |
1395 | /* try to filter some things out - basically, if you are |
1398 | * killing a level 1 creature and your level 20, you |
1396 | * killing a level 1 creature and your level 20, you |
1399 | * probably don't want to see that. |
1397 | * probably don't want to see that. |
… | |
… | |
1456 | skill = NULL; |
1454 | skill = NULL; |
1457 | } |
1455 | } |
1458 | |
1456 | |
1459 | /* Pet (or spell) killed something. */ |
1457 | /* Pet (or spell) killed something. */ |
1460 | if(owner != hitter ) { |
1458 | if(owner != hitter ) { |
1461 | (void) sprintf(buf,"%s killed %s with %s%s%s.",owner->name, |
1459 | (void) sprintf(buf,"%s killed %s with %s%s%s.",&owner->name, |
1462 | query_name(op),query_name(hitter), battleg? " (duel)":"", pk? " (pk)":""); |
1460 | query_name(op),query_name(hitter), battleg? " (duel)":"", pk? " (pk)":""); |
1463 | } |
1461 | } |
1464 | else { |
1462 | else { |
1465 | (void) sprintf(buf,"%s killed %s%s%s%s.",hitter->name,op->name, |
1463 | (void) sprintf(buf,"%s killed %s%s%s%s.",&hitter->name,&op->name, |
1466 | (QUERY_FLAG(hitter, FLAG_MONSTER)) || hitter->type == PLAYER ? |
1464 | (QUERY_FLAG(hitter, FLAG_MONSTER)) || hitter->type == PLAYER ? |
1467 | " in hand to hand combat":"", battleg? " (duel)":"", pk? " (pk)":""); |
1465 | " in hand to hand combat":"", battleg? " (duel)":"", pk? " (pk)":""); |
1468 | } |
1466 | } |
1469 | /* These may have been set in the player code section above */ |
1467 | /* These may have been set in the player code section above */ |
1470 | if (!skop) skop = hitter->chosen_skill; |
1468 | if (!skop) skop = hitter->chosen_skill; |
… | |
… | |
1545 | |
1543 | |
1546 | if(owner1!= NULL && owner1->type == PLAYER) { |
1544 | if(owner1!= NULL && owner1->type == PLAYER) { |
1547 | play_sound_player_only(owner1->contr, SOUND_PET_IS_KILLED,0,0); |
1545 | play_sound_player_only(owner1->contr, SOUND_PET_IS_KILLED,0,0); |
1548 | /* Maybe we should include the owner that killed this, maybe not */ |
1546 | /* Maybe we should include the owner that killed this, maybe not */ |
1549 | new_draw_info_format(NDI_UNIQUE, 0,owner1,"Your pet, the %s, is killed by %s.", |
1547 | new_draw_info_format(NDI_UNIQUE, 0,owner1,"Your pet, the %s, is killed by %s.", |
1550 | op->name,hitter->name); |
1548 | &op->name,&hitter->name); |
1551 | } |
1549 | } |
1552 | remove_friendly_object(op); |
1550 | remove_friendly_object(op); |
1553 | } |
1551 | } |
1554 | remove_ob(op); |
1552 | remove_ob(op); |
1555 | free_object(op); |
1553 | free_object(op); |
1556 | } |
1554 | } |
1557 | /* Player has been killed! */ |
1555 | /* Player has been killed! */ |
1558 | else { |
1556 | else { |
1559 | if(owner->type==PLAYER) { |
1557 | if(owner->type==PLAYER) { |
1560 | snprintf(op->contr->killer, BIG_NAME, "%s the %s",owner->name,owner->contr->title); |
1558 | snprintf(op->contr->killer, BIG_NAME, "%s the %s", &owner->name, owner->contr->title); |
1561 | } |
1559 | } |
1562 | else { |
1560 | else { |
1563 | strncpy(op->contr->killer,hitter->name,BIG_NAME); |
1561 | strncpy(op->contr->killer,hitter->name,BIG_NAME); |
1564 | op->contr->killer[BIG_NAME-1]='\0'; |
1562 | op->contr->killer[BIG_NAME-1]='\0'; |
1565 | } |
1563 | } |
… | |
… | |
1676 | if ( ! QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0) { |
1674 | if ( ! QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0) { |
1677 | /* FIXME: If a player is killed by a rune in a door, the |
1675 | /* FIXME: If a player is killed by a rune in a door, the |
1678 | * was_destroyed() check above doesn't return, and might get here. |
1676 | * was_destroyed() check above doesn't return, and might get here. |
1679 | */ |
1677 | */ |
1680 | LOG (llevDebug, "victim (arch %s, name %s) already dead in " |
1678 | LOG (llevDebug, "victim (arch %s, name %s) already dead in " |
1681 | "hit_player()\n", op->arch->name, op->name); |
1679 | "hit_player()\n", &op->arch->name, &op->name); |
1682 | return 0; |
1680 | return 0; |
1683 | } |
1681 | } |
1684 | |
1682 | |
1685 | #ifdef ATTACK_DEBUG |
1683 | #ifdef ATTACK_DEBUG |
1686 | LOG(llevDebug,"hit player: attacktype %d, dam %d\n", type, dam); |
1684 | LOG(llevDebug,"hit player: attacktype %d, dam %d\n", type, dam); |
… | |
… | |
1908 | else |
1906 | else |
1909 | tmp->stats.dam = dam; |
1907 | tmp->stats.dam = dam; |
1910 | |
1908 | |
1911 | copy_owner(tmp,hitter); /* so we get credit for poisoning kills */ |
1909 | copy_owner(tmp,hitter); /* so we get credit for poisoning kills */ |
1912 | if(hitter->skill && hitter->skill != tmp->skill) { |
1910 | if(hitter->skill && hitter->skill != tmp->skill) { |
1913 | if (tmp->skill) free_string(tmp->skill); |
|
|
1914 | tmp->skill = add_refcount(hitter->skill); |
1911 | tmp->skill = hitter->skill; |
1915 | } |
1912 | } |
1916 | |
1913 | |
1917 | tmp->stats.food+=dam; /* more damage, longer poisoning */ |
1914 | tmp->stats.food+=dam; /* more damage, longer poisoning */ |
1918 | |
1915 | |
1919 | if(op->type==PLAYER) { |
1916 | if(op->type==PLAYER) { |
… | |
… | |
1925 | SET_FLAG(tmp,FLAG_APPLIED); |
1922 | SET_FLAG(tmp,FLAG_APPLIED); |
1926 | fix_player(op); |
1923 | fix_player(op); |
1927 | new_draw_info(NDI_UNIQUE, 0,op,"You suddenly feel very ill."); |
1924 | new_draw_info(NDI_UNIQUE, 0,op,"You suddenly feel very ill."); |
1928 | } |
1925 | } |
1929 | if (hitter->type == PLAYER) |
1926 | if (hitter->type == PLAYER) |
1930 | new_draw_info_format(NDI_UNIQUE, 0, hitter, "You poison %s.", |
1927 | new_draw_info_format(NDI_UNIQUE, 0, hitter, "You poison %s.", &op->name); |
1931 | op->name); |
|
|
1932 | else if (get_owner(hitter) != NULL && hitter->owner->type == PLAYER) |
1928 | else if (get_owner(hitter) != NULL && hitter->owner->type == PLAYER) |
1933 | new_draw_info_format(NDI_UNIQUE, 0, hitter->owner, |
1929 | new_draw_info_format(NDI_UNIQUE, 0, hitter->owner, |
1934 | "Your %s poisons %s.", hitter->name, op->name); |
1930 | "Your %s poisons %s.", &hitter->name, &op->name); |
1935 | } |
1931 | } |
1936 | tmp->speed_left=0; |
1932 | tmp->speed_left=0; |
1937 | } |
1933 | } |
1938 | else |
1934 | else |
1939 | tmp->stats.food++; |
1935 | tmp->stats.food++; |
… | |
… | |
1971 | * on the player's resistance |
1967 | * on the player's resistance |
1972 | */ |
1968 | */ |
1973 | tmp->speed = 0.05; |
1969 | tmp->speed = 0.05; |
1974 | tmp->subtype = FORCE_CONFUSION; |
1970 | tmp->subtype = FORCE_CONFUSION; |
1975 | tmp->duration = 8 + MAX(1, 5*(100-op->resist[ATNR_CONFUSION])/100); |
1971 | tmp->duration = 8 + MAX(1, 5*(100-op->resist[ATNR_CONFUSION])/100); |
1976 | if (tmp->name) free_string(tmp->name); |
|
|
1977 | tmp->name = add_string("confusion"); |
1972 | tmp->name = "confusion"; |
1978 | maxduration = MAX(2, 30*(100-op->resist[ATNR_CONFUSION])/100); |
1973 | maxduration = MAX(2, 30*(100-op->resist[ATNR_CONFUSION])/100); |
1979 | if( tmp->duration > maxduration) |
1974 | if( tmp->duration > maxduration) |
1980 | tmp->duration = maxduration; |
1975 | tmp->duration = maxduration; |
1981 | |
1976 | |
1982 | if(op->type == PLAYER && !QUERY_FLAG(op,FLAG_CONFUSED)) |
1977 | if(op->type == PLAYER && !QUERY_FLAG(op,FLAG_CONFUSED)) |
… | |
… | |
2069 | (op->race&&strstr(hitter->slaying,op->race)))) return; |
2064 | (op->race&&strstr(hitter->slaying,op->race)))) return; |
2070 | |
2065 | |
2071 | def_lev = op->level; |
2066 | def_lev = op->level; |
2072 | if (def_lev < 1) { |
2067 | if (def_lev < 1) { |
2073 | LOG (llevError, "BUG: arch %s, name %s with level < 1\n", |
2068 | LOG (llevError, "BUG: arch %s, name %s with level < 1\n", |
2074 | op->arch->name, op->name); |
2069 | &op->arch->name, &op->name); |
2075 | def_lev = 1; |
2070 | def_lev = 1; |
2076 | } |
2071 | } |
2077 | atk_lev = (hitter->chosen_skill?hitter->chosen_skill->level:hitter->level) / 2; |
2072 | atk_lev = (hitter->chosen_skill?hitter->chosen_skill->level:hitter->level) / 2; |
2078 | /* LOG(llevDebug,"Deathstrike - attack level %d, defender level %d\n", |
2073 | /* LOG(llevDebug,"Deathstrike - attack level %d, defender level %d\n", |
2079 | atk_lev, def_lev); */ |
2074 | atk_lev, def_lev); */ |