1 | /* |
1 | /* |
2 | * static char *rcsid_attack_c = |
2 | * static char *rcsid_attack_c = |
3 | * "$Id: attack.c,v 1.1 2006/02/03 07:14:27 root Exp $"; |
3 | * "$Id: attack.c,v 1.6 2006/03/26 08:32:11 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 |
… | |
… | |
337 | * This is one of the few cases where on_same_map should not be used. |
337 | * This is one of the few cases where on_same_map should not be used. |
338 | */ |
338 | */ |
339 | if (tmp->map != map || tmp->x != x || tmp->y != y) |
339 | if (tmp->map != map || tmp->x != x || tmp->y != y) |
340 | continue; |
340 | continue; |
341 | |
341 | |
|
|
342 | /* Need to hit everyone in the transport with this spell */ |
|
|
343 | if (tmp->type == TRANSPORT) { |
|
|
344 | object *pl; |
|
|
345 | |
|
|
346 | for (pl=tmp->inv; pl; pl=pl->below) { |
|
|
347 | if (pl->type == PLAYER) |
|
|
348 | hit_player(pl,op->stats.dam,op,type,full_hit); |
|
|
349 | } |
|
|
350 | } |
|
|
351 | |
342 | if (QUERY_FLAG (tmp, FLAG_ALIVE)) { |
352 | if (QUERY_FLAG (tmp, FLAG_ALIVE)) { |
343 | hit_player(tmp,op->stats.dam,op,type,full_hit); |
353 | hit_player(tmp,op->stats.dam,op,type,full_hit); |
344 | retflag |=1; |
354 | retflag |=1; |
345 | if (was_destroyed (op, op_tag)) |
355 | if (was_destroyed (op, op_tag)) |
346 | break; |
356 | break; |
… | |
… | |
389 | } else if ((hitter->type == DISEASE || hitter->type == SYMPTOM || |
399 | } else if ((hitter->type == DISEASE || hitter->type == SYMPTOM || |
390 | hitter->type == POISONING || |
400 | hitter->type == POISONING || |
391 | (type & AT_POISON && IS_LIVE(op))) && !found) { |
401 | (type & AT_POISON && IS_LIVE(op))) && !found) { |
392 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_SUFFER][i].level != -1; |
402 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_SUFFER][i].level != -1; |
393 | i++) |
403 | i++) |
394 | if (dam < attack_mess[ATM_SUFFER][i].level) { |
404 | if (dam < attack_mess[ATM_SUFFER][i].level |
|
|
405 | || attack_mess[ATM_SUFFER][i+1].level == -1) { |
395 | sprintf(buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1, |
406 | sprintf(buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1, |
396 | op->name, attack_mess[ATM_SUFFER][i].buf2); |
407 | op->name, attack_mess[ATM_SUFFER][i].buf2); |
397 | sprintf(buf2, "%s", attack_mess[ATM_SUFFER][i].buf3); |
408 | sprintf(buf2, "%s", attack_mess[ATM_SUFFER][i].buf3); |
398 | found++; |
409 | found++; |
399 | break; |
410 | break; |
400 | } |
411 | } |
401 | } else if (op->type == DOOR && !found) { |
412 | } else if (op->type == DOOR && !found) { |
402 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_DOOR][i].level != -1; |
413 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_DOOR][i].level != -1; |
403 | i++) |
414 | i++) |
404 | if (dam < attack_mess[ATM_DOOR][i].level) { |
415 | if (dam < attack_mess[ATM_DOOR][i].level |
|
|
416 | || attack_mess[ATM_DOOR][i+1].level == -1) { |
405 | sprintf(buf1, "%s %s%s", attack_mess[ATM_DOOR][i].buf1, |
417 | sprintf(buf1, "%s %s%s", attack_mess[ATM_DOOR][i].buf1, |
406 | op->name, attack_mess[ATM_DOOR][i].buf2); |
418 | op->name, attack_mess[ATM_DOOR][i].buf2); |
407 | sprintf(buf2, "%s", attack_mess[ATM_DOOR][i].buf3); |
419 | sprintf(buf2, "%s", attack_mess[ATM_DOOR][i].buf3); |
408 | found++; |
420 | found++; |
409 | break; |
421 | break; |
410 | } |
422 | } |
411 | } else if (hitter->type == PLAYER && IS_LIVE(op)) { |
423 | } else if (hitter->type == PLAYER && IS_LIVE(op)) { |
412 | if (USING_SKILL(hitter, SK_KARATE)) { |
424 | if (USING_SKILL(hitter, SK_KARATE)) { |
413 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_KARATE][i].level != -1; |
425 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_KARATE][i].level != -1; |
414 | i++) |
426 | i++) |
415 | if (dam < attack_mess[ATM_KARATE][i].level) { |
427 | if (dam < attack_mess[ATM_KARATE][i].level |
|
|
428 | || attack_mess[ATM_KARATE][i+1].level == -1) { |
416 | sprintf(buf1, "%s %s%s", attack_mess[ATM_KARATE][i].buf1, |
429 | sprintf(buf1, "%s %s%s", attack_mess[ATM_KARATE][i].buf1, |
417 | op->name, attack_mess[ATM_KARATE][i].buf2); |
430 | op->name, attack_mess[ATM_KARATE][i].buf2); |
418 | sprintf(buf2, "%s", attack_mess[ATM_KARATE][i].buf3); |
431 | sprintf(buf2, "%s", attack_mess[ATM_KARATE][i].buf3); |
419 | found++; |
432 | found++; |
420 | break; |
433 | break; |
421 | } |
434 | } |
422 | } else if (USING_SKILL(hitter, SK_CLAWING)) { |
435 | } else if (USING_SKILL(hitter, SK_CLAWING)) { |
423 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_CLAW][i].level != -1; |
436 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_CLAW][i].level != -1; |
424 | i++) |
437 | i++) |
425 | if (dam < attack_mess[ATM_CLAW][i].level) { |
438 | if (dam < attack_mess[ATM_CLAW][i].level |
|
|
439 | || attack_mess[ATM_CLAW][i+1].level == -1) { |
426 | sprintf(buf1, "%s %s%s", attack_mess[ATM_CLAW][i].buf1, |
440 | sprintf(buf1, "%s %s%s", attack_mess[ATM_CLAW][i].buf1, |
427 | op->name, attack_mess[ATM_CLAW][i].buf2); |
441 | op->name, attack_mess[ATM_CLAW][i].buf2); |
428 | sprintf(buf2, "%s", attack_mess[ATM_CLAW][i].buf3); |
442 | sprintf(buf2, "%s", attack_mess[ATM_CLAW][i].buf3); |
429 | found++; |
443 | found++; |
430 | break; |
444 | break; |
431 | } |
445 | } |
432 | } else if (USING_SKILL(hitter, SK_PUNCHING)) { |
446 | } else if (USING_SKILL(hitter, SK_PUNCHING)) { |
433 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_PUNCH][i].level != -1; |
447 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_PUNCH][i].level != -1; |
434 | i++) |
448 | i++) |
435 | if (dam < attack_mess[ATM_PUNCH][i].level) { |
449 | if (dam < attack_mess[ATM_PUNCH][i].level |
|
|
450 | || attack_mess[ATM_PUNCH][i+1].level == -1) { |
436 | sprintf(buf1, "%s %s%s", attack_mess[ATM_PUNCH][i].buf1, |
451 | sprintf(buf1, "%s %s%s", attack_mess[ATM_PUNCH][i].buf1, |
437 | op->name, attack_mess[ATM_PUNCH][i].buf2); |
452 | op->name, attack_mess[ATM_PUNCH][i].buf2); |
438 | sprintf(buf2, "%s", attack_mess[ATM_PUNCH][i].buf3); |
453 | sprintf(buf2, "%s", attack_mess[ATM_PUNCH][i].buf3); |
439 | found++; |
454 | found++; |
440 | break; |
455 | break; |
441 | } |
456 | } |
442 | } |
457 | } |
443 | } |
458 | } |
|
|
459 | if (found) { |
|
|
460 | /* done */ |
444 | if (IS_ARROW(hitter) && (type == AT_PHYSICAL || type == AT_MAGIC) && |
461 | } else if (IS_ARROW(hitter) && (type == AT_PHYSICAL || type == AT_MAGIC)) { |
445 | !found) { |
|
|
446 | sprintf(buf1, "hit"); /* just in case */ |
462 | sprintf(buf1, "hit"); /* just in case */ |
447 | for (i=0; i < MAXATTACKMESS; i++) |
463 | for (i=0; i < MAXATTACKMESS; i++) |
448 | if (dam < attack_mess[ATM_ARROW][i].level) { |
464 | if (dam < attack_mess[ATM_ARROW][i].level |
|
|
465 | || attack_mess[ATM_ARROW][i+1].level == -1) { |
449 | sprintf(buf2, "%s", attack_mess[ATM_ARROW][i].buf3); |
466 | sprintf(buf2, "%s", attack_mess[ATM_ARROW][i].buf3); |
|
|
467 | found++; |
450 | break; |
468 | break; |
451 | } |
469 | } |
452 | } else if (type & AT_DRAIN && IS_LIVE(op) && !found) { |
470 | } else if (type & AT_DRAIN && IS_LIVE(op)) { |
453 | /* drain is first, because some items have multiple attypes */ |
471 | /* drain is first, because some items have multiple attypes */ |
454 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_DRAIN][i].level != -1; |
472 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_DRAIN][i].level != -1; |
455 | i++) |
473 | i++) |
456 | if (dam < attack_mess[ATM_DRAIN][i].level) { |
474 | if (dam < attack_mess[ATM_DRAIN][i].level |
|
|
475 | || attack_mess[ATM_DRAIN][i+1].level == -1) { |
457 | sprintf(buf1, "%s %s%s", attack_mess[ATM_DRAIN][i].buf1, |
476 | sprintf(buf1, "%s %s%s", attack_mess[ATM_DRAIN][i].buf1, |
458 | op->name, attack_mess[ATM_DRAIN][i].buf2); |
477 | op->name, attack_mess[ATM_DRAIN][i].buf2); |
459 | sprintf(buf2, "%s", attack_mess[ATM_DRAIN][i].buf3); |
478 | sprintf(buf2, "%s", attack_mess[ATM_DRAIN][i].buf3); |
|
|
479 | found++; |
460 | break; |
480 | break; |
461 | } |
481 | } |
462 | } else if (type & AT_ELECTRICITY && IS_LIVE(op) && !found) { |
482 | } else if (type & AT_ELECTRICITY && IS_LIVE(op)) { |
463 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_ELEC][i].level != -1; |
483 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_ELEC][i].level != -1; |
464 | i++) |
484 | i++) |
465 | if (dam < attack_mess[ATM_ELEC][i].level) { |
485 | if (dam < attack_mess[ATM_ELEC][i].level |
|
|
486 | || attack_mess[ATM_ELEC][i+1].level == -1) { |
466 | sprintf(buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1, |
487 | sprintf(buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1, |
467 | op->name, attack_mess[ATM_ELEC][i].buf2); |
488 | op->name, attack_mess[ATM_ELEC][i].buf2); |
468 | sprintf(buf2, "%s", attack_mess[ATM_ELEC][i].buf3); |
489 | sprintf(buf2, "%s", attack_mess[ATM_ELEC][i].buf3); |
|
|
490 | found++; |
469 | break; |
491 | break; |
470 | } |
492 | } |
471 | } else if (type & AT_COLD && IS_LIVE(op) && !found) { |
493 | } else if (type & AT_COLD && IS_LIVE(op)) { |
472 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_COLD][i].level != -1; |
494 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_COLD][i].level != -1; |
473 | i++) |
495 | i++) |
474 | if (dam < attack_mess[ATM_COLD][i].level) { |
496 | if (dam < attack_mess[ATM_COLD][i].level |
|
|
497 | || attack_mess[ATM_COLD][i+1].level == -1) { |
475 | sprintf(buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1, |
498 | sprintf(buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1, |
476 | op->name, attack_mess[ATM_COLD][i].buf2); |
499 | op->name, attack_mess[ATM_COLD][i].buf2); |
477 | sprintf(buf2, "%s", attack_mess[ATM_COLD][i].buf3); |
500 | sprintf(buf2, "%s", attack_mess[ATM_COLD][i].buf3); |
|
|
501 | found++; |
478 | break; |
502 | break; |
479 | } |
503 | } |
480 | } else if (type & AT_FIRE && !found) { |
504 | } else if (type & AT_FIRE) { |
481 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_FIRE][i].level != -1; |
505 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_FIRE][i].level != -1; |
482 | i++) |
506 | i++) |
483 | if (dam < attack_mess[ATM_FIRE][i].level) { |
507 | if (dam < attack_mess[ATM_FIRE][i].level |
|
|
508 | || attack_mess[ATM_FIRE][i+1].level == -1) { |
484 | sprintf(buf1, "%s %s%s", attack_mess[ATM_FIRE][i].buf1, |
509 | sprintf(buf1, "%s %s%s", attack_mess[ATM_FIRE][i].buf1, |
485 | op->name, attack_mess[ATM_FIRE][i].buf2); |
510 | op->name, attack_mess[ATM_FIRE][i].buf2); |
486 | sprintf(buf2, "%s", attack_mess[ATM_FIRE][i].buf3); |
511 | sprintf(buf2, "%s", attack_mess[ATM_FIRE][i].buf3); |
|
|
512 | found++; |
487 | break; |
513 | break; |
488 | } |
514 | } |
489 | } else if (hitter->current_weapon != NULL && !found) { |
515 | } else if (hitter->current_weapon != NULL) { |
490 | int mtype; |
516 | int mtype; |
491 | switch (hitter->current_weapon->weapontype) { |
517 | switch (hitter->current_weapon->weapontype) { |
492 | case WEAP_HIT: mtype = ATM_BASIC; break; |
518 | case WEAP_HIT: mtype = ATM_BASIC; break; |
493 | case WEAP_SLASH: mtype = ATM_SLASH; break; |
519 | case WEAP_SLASH: mtype = ATM_SLASH; break; |
494 | case WEAP_PIERCE: mtype = ATM_PIERCE; break; |
520 | case WEAP_PIERCE: mtype = ATM_PIERCE; break; |
… | |
… | |
500 | case WEAP_BLUD: mtype = ATM_BLUD; break; |
526 | case WEAP_BLUD: mtype = ATM_BLUD; break; |
501 | default: mtype = ATM_BASIC; break; |
527 | default: mtype = ATM_BASIC; break; |
502 | } |
528 | } |
503 | for (i=0; i < MAXATTACKMESS && attack_mess[mtype][i].level != -1; |
529 | for (i=0; i < MAXATTACKMESS && attack_mess[mtype][i].level != -1; |
504 | i++) |
530 | i++) |
505 | if (dam < attack_mess[mtype][i].level) { |
531 | if (dam < attack_mess[mtype][i].level |
|
|
532 | || attack_mess[mtype][i+1].level == -1) { |
506 | sprintf(buf1, "%s %s%s", attack_mess[mtype][i].buf1, |
533 | sprintf(buf1, "%s %s%s", attack_mess[mtype][i].buf1, |
507 | op->name, attack_mess[mtype][i].buf2); |
534 | op->name, attack_mess[mtype][i].buf2); |
508 | sprintf(buf2, "%s", attack_mess[mtype][i].buf3); |
535 | sprintf(buf2, "%s", attack_mess[mtype][i].buf3); |
|
|
536 | found++; |
509 | break; |
537 | break; |
510 | } |
538 | } |
511 | } else if (!found){ |
539 | } else { |
512 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_BASIC][i].level != -1; |
540 | for (i=0; i < MAXATTACKMESS && attack_mess[ATM_BASIC][i].level != -1; |
513 | i++) |
541 | i++) |
514 | if (dam < attack_mess[ATM_BASIC][i].level) { |
542 | if (dam < attack_mess[ATM_BASIC][i].level |
|
|
543 | || attack_mess[ATM_BASIC][i+1].level == -1) { |
515 | sprintf(buf1, "%s %s%s", attack_mess[ATM_BASIC][i].buf1, |
544 | sprintf(buf1, "%s %s%s", attack_mess[ATM_BASIC][i].buf1, |
516 | op->name, attack_mess[ATM_BASIC][i].buf2); |
545 | op->name, attack_mess[ATM_BASIC][i].buf2); |
517 | sprintf(buf2, "%s", attack_mess[ATM_BASIC][i].buf3); |
546 | sprintf(buf2, "%s", attack_mess[ATM_BASIC][i].buf3); |
|
|
547 | found++; |
518 | break; |
548 | break; |
519 | } |
549 | } |
|
|
550 | } |
|
|
551 | |
|
|
552 | if (!found) { |
|
|
553 | sprintf(buf1, "hit"); |
|
|
554 | sprintf(buf2, "hits"); |
520 | } |
555 | } |
521 | |
556 | |
522 | /* bail out if a monster is casting spells */ |
557 | /* bail out if a monster is casting spells */ |
523 | if (!(hitter->type == PLAYER || |
558 | if (!(hitter->type == PLAYER || |
524 | (get_owner(hitter) != NULL && hitter->owner->type == PLAYER))) |
559 | (get_owner(hitter) != NULL && hitter->owner->type == PLAYER))) |
… | |
… | |
1618 | |
1653 | |
1619 | /* very simple: if our target has no_damage 1 set or is wiz, we can't hurt him */ |
1654 | /* very simple: if our target has no_damage 1 set or is wiz, we can't hurt him */ |
1620 | if (QUERY_FLAG (op, FLAG_WIZ) || QUERY_FLAG (op, FLAG_NO_DAMAGE)) |
1655 | if (QUERY_FLAG (op, FLAG_WIZ) || QUERY_FLAG (op, FLAG_NO_DAMAGE)) |
1621 | return 0; |
1656 | return 0; |
1622 | |
1657 | |
|
|
1658 | #ifdef PROHIBIT_PLAYERKILL |
|
|
1659 | if (op->type == PLAYER) { |
|
|
1660 | object *owner = get_owner (hitter); |
|
|
1661 | if (!owner) owner = hitter; |
|
|
1662 | if (owner->type == PLAYER |
|
|
1663 | && !op_on_battleground (op, 0, 0) |
|
|
1664 | && op != owner) { |
|
|
1665 | return 0; |
|
|
1666 | } |
|
|
1667 | } |
|
|
1668 | #endif |
|
|
1669 | |
1623 | op_tag = op->count; |
1670 | op_tag = op->count; |
1624 | hitter_tag = hitter->count; |
1671 | hitter_tag = hitter->count; |
1625 | |
1672 | |
1626 | if (body_attack) { |
1673 | if (body_attack) { |
1627 | /* slow and paralyze must hit the head. But we don't want to just |
1674 | /* slow and paralyze must hit the head. But we don't want to just |
… | |
… | |
1731 | * doing damage - otherwise, the +1 in the coe below will make |
1778 | * doing damage - otherwise, the +1 in the coe below will make |
1732 | * an attack do damage before when it otherwise didn't |
1779 | * an attack do damage before when it otherwise didn't |
1733 | */ |
1780 | */ |
1734 | friendlyfire = friendly_fire(op, hitter); |
1781 | friendlyfire = friendly_fire(op, hitter); |
1735 | if (friendlyfire && maxdam){ |
1782 | if (friendlyfire && maxdam){ |
1736 | maxdam = ((dam * settings.set_friendly_fire) / 100)+1; |
1783 | maxdam = ((dam * settings.set_friendly_fire) / 100); |
1737 | |
1784 | #ifndef COZY_SERVER |
|
|
1785 | maxdam++; |
|
|
1786 | #endif |
|
|
1787 | |
1738 | #ifdef ATTACK_DEBUG |
1788 | #ifdef ATTACK_DEBUG |
1739 | LOG(llevDebug,"Friendly fire (type:%d setting: %d%) did %d damage dropped to %d\n", |
1789 | LOG(llevDebug,"Friendly fire (type:%d setting: %d%) did %d damage dropped to %d\n", |
1740 | friendlyfire, settings.set_friendly_fire, dam, maxdam); |
1790 | friendlyfire, settings.set_friendly_fire, dam, maxdam); |
1741 | #endif |
1791 | #endif |
1742 | } |
1792 | } |