1 | /* |
1 | /* |
2 | * static char *rcsid_attack_c = |
2 | * static char *rcsid_attack_c = |
3 | * "$Id: attack.c,v 1.10 2006/03/31 17:33:40 root Exp $"; |
3 | * "$Id: attack.c,v 1.14 2006/05/12 11:33:36 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 |
… | |
… | |
403 | i++) |
403 | i++) |
404 | 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) { |
405 | || attack_mess[ATM_SUFFER][i+1].level == -1) { |
406 | sprintf(buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1, |
406 | sprintf(buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1, |
407 | op->name, attack_mess[ATM_SUFFER][i].buf2); |
407 | op->name, attack_mess[ATM_SUFFER][i].buf2); |
408 | sprintf(buf2, "%s", attack_mess[ATM_SUFFER][i].buf3); |
408 | strcpy (buf2, attack_mess[ATM_SUFFER][i].buf3); |
409 | found++; |
409 | found++; |
410 | break; |
410 | break; |
411 | } |
411 | } |
412 | } else if (op->type == DOOR && !found) { |
412 | } else if (op->type == DOOR && !found) { |
413 | 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; |
414 | i++) |
414 | i++) |
415 | 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) { |
416 | || attack_mess[ATM_DOOR][i+1].level == -1) { |
417 | sprintf(buf1, "%s %s%s", attack_mess[ATM_DOOR][i].buf1, |
417 | sprintf(buf1, "%s %s%s", attack_mess[ATM_DOOR][i].buf1, |
418 | op->name, attack_mess[ATM_DOOR][i].buf2); |
418 | op->name, attack_mess[ATM_DOOR][i].buf2); |
419 | sprintf(buf2, "%s", attack_mess[ATM_DOOR][i].buf3); |
419 | strcpy (buf2, attack_mess[ATM_DOOR][i].buf3); |
420 | found++; |
420 | found++; |
421 | break; |
421 | break; |
422 | } |
422 | } |
423 | } else if (hitter->type == PLAYER && IS_LIVE(op)) { |
423 | } else if (hitter->type == PLAYER && IS_LIVE(op)) { |
424 | if (USING_SKILL(hitter, SK_KARATE)) { |
424 | if (USING_SKILL(hitter, SK_KARATE)) { |
… | |
… | |
426 | i++) |
426 | i++) |
427 | 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) { |
428 | || attack_mess[ATM_KARATE][i+1].level == -1) { |
429 | sprintf(buf1, "%s %s%s", attack_mess[ATM_KARATE][i].buf1, |
429 | sprintf(buf1, "%s %s%s", attack_mess[ATM_KARATE][i].buf1, |
430 | op->name, attack_mess[ATM_KARATE][i].buf2); |
430 | op->name, attack_mess[ATM_KARATE][i].buf2); |
431 | sprintf(buf2, "%s", attack_mess[ATM_KARATE][i].buf3); |
431 | strcpy (buf2, attack_mess[ATM_KARATE][i].buf3); |
432 | found++; |
432 | found++; |
433 | break; |
433 | break; |
434 | } |
434 | } |
435 | } else if (USING_SKILL(hitter, SK_CLAWING)) { |
435 | } else if (USING_SKILL(hitter, SK_CLAWING)) { |
436 | 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; |
437 | i++) |
437 | i++) |
438 | 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) { |
439 | || attack_mess[ATM_CLAW][i+1].level == -1) { |
440 | sprintf(buf1, "%s %s%s", attack_mess[ATM_CLAW][i].buf1, |
440 | sprintf(buf1, "%s %s%s", attack_mess[ATM_CLAW][i].buf1, |
441 | op->name, attack_mess[ATM_CLAW][i].buf2); |
441 | op->name, attack_mess[ATM_CLAW][i].buf2); |
442 | sprintf(buf2, "%s", attack_mess[ATM_CLAW][i].buf3); |
442 | strcpy (buf2, attack_mess[ATM_CLAW][i].buf3); |
443 | found++; |
443 | found++; |
444 | break; |
444 | break; |
445 | } |
445 | } |
446 | } else if (USING_SKILL(hitter, SK_PUNCHING)) { |
446 | } else if (USING_SKILL(hitter, SK_PUNCHING)) { |
447 | 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; |
448 | i++) |
448 | i++) |
449 | 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) { |
450 | || attack_mess[ATM_PUNCH][i+1].level == -1) { |
451 | sprintf(buf1, "%s %s%s", attack_mess[ATM_PUNCH][i].buf1, |
451 | sprintf(buf1, "%s %s%s", attack_mess[ATM_PUNCH][i].buf1, |
452 | op->name, attack_mess[ATM_PUNCH][i].buf2); |
452 | op->name, attack_mess[ATM_PUNCH][i].buf2); |
453 | sprintf(buf2, "%s", attack_mess[ATM_PUNCH][i].buf3); |
453 | strcpy (buf2, attack_mess[ATM_PUNCH][i].buf3); |
454 | found++; |
454 | found++; |
455 | break; |
455 | break; |
456 | } |
456 | } |
457 | } |
457 | } |
458 | } |
458 | } |
… | |
… | |
461 | } else if (IS_ARROW(hitter) && (type == AT_PHYSICAL || type == AT_MAGIC)) { |
461 | } else if (IS_ARROW(hitter) && (type == AT_PHYSICAL || type == AT_MAGIC)) { |
462 | sprintf(buf1, "hit"); /* just in case */ |
462 | sprintf(buf1, "hit"); /* just in case */ |
463 | for (i=0; i < MAXATTACKMESS; i++) |
463 | for (i=0; i < MAXATTACKMESS; i++) |
464 | 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) { |
465 | || attack_mess[ATM_ARROW][i+1].level == -1) { |
466 | sprintf(buf2, "%s", attack_mess[ATM_ARROW][i].buf3); |
466 | strcpy (buf2, attack_mess[ATM_ARROW][i].buf3); |
467 | found++; |
467 | found++; |
468 | break; |
468 | break; |
469 | } |
469 | } |
470 | } else if (type & AT_DRAIN && IS_LIVE(op)) { |
470 | } else if (type & AT_DRAIN && IS_LIVE(op)) { |
471 | /* drain is first, because some items have multiple attypes */ |
471 | /* drain is first, because some items have multiple attypes */ |
… | |
… | |
473 | i++) |
473 | i++) |
474 | 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) { |
475 | || attack_mess[ATM_DRAIN][i+1].level == -1) { |
476 | sprintf(buf1, "%s %s%s", attack_mess[ATM_DRAIN][i].buf1, |
476 | sprintf(buf1, "%s %s%s", attack_mess[ATM_DRAIN][i].buf1, |
477 | op->name, attack_mess[ATM_DRAIN][i].buf2); |
477 | op->name, attack_mess[ATM_DRAIN][i].buf2); |
478 | sprintf(buf2, "%s", attack_mess[ATM_DRAIN][i].buf3); |
478 | strcpy (buf2, attack_mess[ATM_DRAIN][i].buf3); |
479 | found++; |
479 | found++; |
480 | break; |
480 | break; |
481 | } |
481 | } |
482 | } else if (type & AT_ELECTRICITY && IS_LIVE(op)) { |
482 | } else if (type & AT_ELECTRICITY && IS_LIVE(op)) { |
483 | 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; |
484 | i++) |
484 | i++) |
485 | 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) { |
486 | || attack_mess[ATM_ELEC][i+1].level == -1) { |
487 | sprintf(buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1, |
487 | sprintf(buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1, |
488 | op->name, attack_mess[ATM_ELEC][i].buf2); |
488 | op->name, attack_mess[ATM_ELEC][i].buf2); |
489 | sprintf(buf2, "%s", attack_mess[ATM_ELEC][i].buf3); |
489 | strcpy (buf2, attack_mess[ATM_ELEC][i].buf3); |
490 | found++; |
490 | found++; |
491 | break; |
491 | break; |
492 | } |
492 | } |
493 | } else if (type & AT_COLD && IS_LIVE(op)) { |
493 | } else if (type & AT_COLD && IS_LIVE(op)) { |
494 | 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; |
495 | i++) |
495 | i++) |
496 | 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) { |
497 | || attack_mess[ATM_COLD][i+1].level == -1) { |
498 | sprintf(buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1, |
498 | sprintf(buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1, |
499 | op->name, attack_mess[ATM_COLD][i].buf2); |
499 | op->name, attack_mess[ATM_COLD][i].buf2); |
500 | sprintf(buf2, "%s", attack_mess[ATM_COLD][i].buf3); |
500 | strcpy (buf2, attack_mess[ATM_COLD][i].buf3); |
501 | found++; |
501 | found++; |
502 | break; |
502 | break; |
503 | } |
503 | } |
504 | } else if (type & AT_FIRE) { |
504 | } else if (type & AT_FIRE) { |
505 | 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; |
506 | i++) |
506 | i++) |
507 | 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) { |
508 | || attack_mess[ATM_FIRE][i+1].level == -1) { |
509 | sprintf(buf1, "%s %s%s", attack_mess[ATM_FIRE][i].buf1, |
509 | sprintf(buf1, "%s %s%s", attack_mess[ATM_FIRE][i].buf1, |
510 | op->name, attack_mess[ATM_FIRE][i].buf2); |
510 | op->name, attack_mess[ATM_FIRE][i].buf2); |
511 | sprintf(buf2, "%s", attack_mess[ATM_FIRE][i].buf3); |
511 | strcpy (buf2, attack_mess[ATM_FIRE][i].buf3); |
512 | found++; |
512 | found++; |
513 | break; |
513 | break; |
514 | } |
514 | } |
515 | } else if (hitter->current_weapon != NULL) { |
515 | } else if (hitter->current_weapon != NULL) { |
516 | int mtype; |
516 | int mtype; |
… | |
… | |
530 | i++) |
530 | i++) |
531 | if (dam < attack_mess[mtype][i].level |
531 | if (dam < attack_mess[mtype][i].level |
532 | || attack_mess[mtype][i+1].level == -1) { |
532 | || attack_mess[mtype][i+1].level == -1) { |
533 | sprintf(buf1, "%s %s%s", attack_mess[mtype][i].buf1, |
533 | sprintf(buf1, "%s %s%s", attack_mess[mtype][i].buf1, |
534 | op->name, attack_mess[mtype][i].buf2); |
534 | op->name, attack_mess[mtype][i].buf2); |
535 | sprintf(buf2, "%s", attack_mess[mtype][i].buf3); |
535 | strcpy (buf2, attack_mess[mtype][i].buf3); |
536 | found++; |
536 | found++; |
537 | break; |
537 | break; |
538 | } |
538 | } |
539 | } else { |
539 | } else { |
540 | 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; |
541 | i++) |
541 | i++) |
542 | 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) { |
543 | || attack_mess[ATM_BASIC][i+1].level == -1) { |
544 | sprintf(buf1, "%s %s%s", attack_mess[ATM_BASIC][i].buf1, |
544 | sprintf(buf1, "%s %s%s", attack_mess[ATM_BASIC][i].buf1, |
545 | op->name, attack_mess[ATM_BASIC][i].buf2); |
545 | op->name, attack_mess[ATM_BASIC][i].buf2); |
546 | sprintf(buf2, "%s", attack_mess[ATM_BASIC][i].buf3); |
546 | strcpy (buf2, attack_mess[ATM_BASIC][i].buf3); |
547 | found++; |
547 | found++; |
548 | break; |
548 | break; |
549 | } |
549 | } |
550 | } |
550 | } |
551 | |
551 | |
552 | if (!found) { |
552 | if (!found) { |
553 | sprintf(buf1, "hit"); |
553 | strcpy (buf1, "hit"); |
554 | sprintf(buf2, "hits"); |
554 | strcpy (buf2, " hits"); |
555 | } |
555 | } |
556 | |
556 | |
557 | /* bail out if a monster is casting spells */ |
557 | /* bail out if a monster is casting spells */ |
558 | if (!(hitter->type == PLAYER || |
558 | if (!(hitter->type == PLAYER || |
559 | (get_owner(hitter) != NULL && hitter->owner->type == PLAYER))) |
559 | (get_owner(hitter) != NULL && hitter->owner->type == PLAYER))) |
… | |
… | |
562 | /* scale down magic considerably. */ |
562 | /* scale down magic considerably. */ |
563 | if (type & AT_MAGIC && rndm(0, 5)) |
563 | if (type & AT_MAGIC && rndm(0, 5)) |
564 | return; |
564 | return; |
565 | |
565 | |
566 | /* Did a player hurt another player? Inform both! */ |
566 | /* Did a player hurt another player? Inform both! */ |
567 | /* only show half the player->player combat messages */ |
|
|
568 | if(op->type==PLAYER && rndm(0, 1) && |
567 | if(op->type==PLAYER && |
569 | (get_owner(hitter)==NULL?hitter->type:hitter->owner->type)==PLAYER) { |
568 | (get_owner(hitter)==NULL?hitter->type:hitter->owner->type)==PLAYER) { |
570 | if(get_owner(hitter)!=NULL) |
569 | if(get_owner(hitter)!=NULL) |
571 | sprintf(buf,"%s's %s %s you.", |
570 | sprintf(buf,"%s's %s%s you.", |
572 | hitter->owner->name, hitter->name, buf2); |
571 | hitter->owner->name, hitter->name, buf2); |
573 | else { |
572 | else { |
574 | sprintf(buf,"%s%s you.",hitter->name, buf2); |
573 | sprintf(buf,"%s%s you.",hitter->name, buf2); |
575 | if (dam != 0) { |
574 | if (dam != 0) { |
576 | if (dam < 10) |
575 | if (dam < 10) |
… | |
… | |
582 | } |
581 | } |
583 | } |
582 | } |
584 | new_draw_info(NDI_BLACK, 0,op,buf); |
583 | new_draw_info(NDI_BLACK, 0,op,buf); |
585 | } /* end of player hitting player */ |
584 | } /* end of player hitting player */ |
586 | |
585 | |
587 | /* scale down these messages too */ |
|
|
588 | if(hitter->type==PLAYER && rndm(0, 2) == 0) { |
586 | if(hitter->type==PLAYER) { |
589 | sprintf(buf,"You %s.",buf1); |
587 | sprintf(buf,"You %s.",buf1); |
590 | if (dam != 0) { |
588 | if (dam != 0) { |
591 | if (dam < 10) |
589 | if (dam < 10) |
592 | play_sound_player_only(hitter->contr, SOUND_PLAYER_HITS1,0,0); |
590 | play_sound_player_only(hitter->contr, SOUND_PLAYER_HITS1,0,0); |
593 | else if (dam < 20) |
591 | else if (dam < 20) |
… | |
… | |
873 | * isn't available anymore. |
871 | * isn't available anymore. |
874 | */ |
872 | */ |
875 | object *hit_with_arrow (object *op, object *victim) |
873 | object *hit_with_arrow (object *op, object *victim) |
876 | { |
874 | { |
877 | object *container, *hitter; |
875 | object *container, *hitter; |
878 | int hit_something; |
876 | int hit_something = 0; |
879 | tag_t victim_tag, hitter_tag; |
877 | tag_t victim_tag, hitter_tag; |
880 | sint16 victim_x, victim_y; |
878 | sint16 victim_x, victim_y; |
881 | |
879 | |
882 | /* Disassemble missile */ |
880 | /* Disassemble missile */ |
883 | if (op->inv) { |
881 | if (op->inv) { |
… | |
… | |
1373 | if (get_owner (op) != NULL && op->owner->type == PLAYER && |
1371 | if (get_owner (op) != NULL && op->owner->type == PLAYER && |
1374 | op->owner->contr->ranges[range_golem] == op) { |
1372 | op->owner->contr->ranges[range_golem] == op) { |
1375 | op->owner->contr->ranges[range_golem]=NULL; |
1373 | op->owner->contr->ranges[range_golem]=NULL; |
1376 | op->owner->contr->golem_count=0; |
1374 | op->owner->contr->golem_count=0; |
1377 | } |
1375 | } |
1378 | else |
|
|
1379 | LOG (llevError, "BUG: hit_player(): Encountered golem without owner.\n"); |
|
|
1380 | |
1376 | |
1381 | remove_ob(op); |
1377 | remove_ob(op); |
1382 | free_object(op); |
1378 | free_object(op); |
1383 | return maxdam; |
1379 | return maxdam; |
1384 | } |
1380 | } |