… | |
… | |
929 | object * |
929 | object * |
930 | hit_with_arrow (object *op, object *victim) |
930 | hit_with_arrow (object *op, object *victim) |
931 | { |
931 | { |
932 | object *container, *hitter; |
932 | object *container, *hitter; |
933 | int hit_something = 0; |
933 | int hit_something = 0; |
934 | sint16 victim_x, victim_y; |
|
|
935 | |
934 | |
936 | /* Disassemble missile */ |
935 | /* Disassemble missile */ |
937 | if (op->inv) |
936 | if (op->inv) |
938 | { |
937 | { |
939 | container = op; |
938 | container = op; |
… | |
… | |
945 | * removed at the end of this function must be able to deal with empty |
944 | * removed at the end of this function must be able to deal with empty |
946 | * THROWN_OBJs. */ |
945 | * THROWN_OBJs. */ |
947 | } |
946 | } |
948 | else |
947 | else |
949 | { |
948 | { |
950 | container = NULL; |
949 | container = 0; |
951 | hitter = op; |
950 | hitter = op; |
952 | } |
951 | } |
953 | |
952 | |
954 | /* Try to hit victim */ |
953 | /* Try to hit victim */ |
955 | victim_x = victim->x; |
|
|
956 | victim_y = victim->y; |
|
|
957 | |
|
|
958 | hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc); |
954 | hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc); |
959 | |
955 | |
960 | /* Arrow attacks door, rune of summoning is triggered, demon is put on |
956 | /* Arrow attacks door, rune of summoning is triggered, demon is put on |
961 | * arrow, move_apply() calls this function, arrow sticks in demon, |
957 | * arrow, move_apply() calls this function, arrow sticks in demon, |
962 | * attack_ob_simple() returns, and we've got an arrow that still exists |
958 | * attack_ob_simple() returns, and we've got an arrow that still exists |
… | |
… | |
968 | if (container) |
964 | if (container) |
969 | { |
965 | { |
970 | remove_ob (container); |
966 | remove_ob (container); |
971 | free_object (container); |
967 | free_object (container); |
972 | } |
968 | } |
|
|
969 | |
973 | return NULL; |
970 | return 0; |
974 | } |
971 | } |
975 | |
972 | |
976 | /* Missile hit victim */ |
973 | /* Missile hit victim */ |
977 | /* if the speed is > 10, then this is a fast moving arrow, we go straight |
974 | /* if the speed is > 10, then this is a fast moving arrow, we go straight |
978 | * through the target |
975 | * through the target |
979 | */ |
976 | */ |
980 | if (hit_something && op->speed <= 10.0) |
977 | if (hit_something && op->speed <= 10.0) |
981 | { |
978 | { |
982 | /* Stop arrow */ |
979 | /* Stop arrow */ |
983 | if (container == NULL) |
980 | if (!container) |
984 | { |
981 | { |
985 | hitter = fix_stopped_arrow (hitter); |
982 | hitter = fix_stopped_arrow (hitter); |
986 | if (hitter == NULL) |
983 | if (!hitter) |
987 | return NULL; |
984 | return 0; |
988 | } |
985 | } |
989 | else |
986 | else |
990 | { |
987 | { |
991 | remove_ob (container); |
988 | remove_ob (container); |
992 | free_object (container); |
989 | free_object (container); |
993 | } |
990 | } |
994 | |
991 | |
995 | /* Try to stick arrow into victim */ |
992 | /* Try to stick arrow into victim */ |
996 | if (!victim->destroyed () && stick_arrow (hitter, victim)) |
993 | if (!victim->destroyed () && stick_arrow (hitter, victim)) |
997 | return NULL; |
994 | return 0; |
998 | |
995 | |
999 | /* Else try to put arrow on victim's map square |
996 | /* Else try to put arrow on victim's map square |
1000 | * remove check for P_WALL here. If the arrow got to this |
997 | * remove check for P_WALL here. If the arrow got to this |
1001 | * space, that is good enough - with the new movement code, |
998 | * space, that is good enough - with the new movement code, |
1002 | * there is now the potential for lots of spaces where something |
999 | * there is now the potential for lots of spaces where something |
1003 | * can fly over but not otherwise move over. What is the correct |
1000 | * can fly over but not otherwise move over. What is the correct |
1004 | * way to handle those otherwise? |
1001 | * way to handle those otherwise? |
1005 | */ |
1002 | */ |
1006 | if (victim_x != hitter->x || victim_y != hitter->y) |
1003 | if (victim->x != hitter->x || victim->y != hitter->y) |
1007 | { |
1004 | { |
1008 | remove_ob (hitter); |
1005 | remove_ob (hitter); |
1009 | hitter->x = victim_x; |
1006 | hitter->x = victim->x; |
1010 | hitter->y = victim_y; |
1007 | hitter->y = victim->y; |
1011 | insert_ob_in_map (hitter, victim->map, hitter, 0); |
1008 | insert_ob_in_map (hitter, victim->map, hitter, 0); |
1012 | } |
1009 | } |
1013 | else |
1010 | else |
1014 | { |
|
|
1015 | /* Else leave arrow where it is */ |
1011 | /* Else leave arrow where it is */ |
1016 | merge_ob (hitter, NULL); |
1012 | merge_ob (hitter, NULL); |
1017 | } |
1013 | |
1018 | return NULL; |
1014 | return 0; |
1019 | } |
1015 | } |
1020 | |
1016 | |
1021 | if (hit_something && op->speed >= 10.0) |
1017 | if (hit_something && op->speed >= 10.0) |
1022 | op->speed -= 1.0; |
1018 | op->speed -= 1.0; |
1023 | |
1019 | |
… | |
… | |
1025 | if (container) |
1021 | if (container) |
1026 | { |
1022 | { |
1027 | remove_ob (hitter); |
1023 | remove_ob (hitter); |
1028 | insert_ob_in_ob (hitter, container); |
1024 | insert_ob_in_ob (hitter, container); |
1029 | } |
1025 | } |
|
|
1026 | |
1030 | return op; |
1027 | return op; |
1031 | } |
1028 | } |
1032 | |
1029 | |
1033 | |
1030 | |
1034 | void |
1031 | void |
… | |
… | |
1449 | op->speed = 0.1; |
1446 | op->speed = 0.1; |
1450 | update_ob_speed (op); |
1447 | update_ob_speed (op); |
1451 | op->speed_left = -0.05; |
1448 | op->speed_left = -0.05; |
1452 | return maxdam; |
1449 | return maxdam; |
1453 | } |
1450 | } |
|
|
1451 | |
1454 | if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER) |
1452 | if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER) |
1455 | { |
1453 | { |
1456 | remove_friendly_object (op); |
1454 | remove_friendly_object (op); |
|
|
1455 | |
1457 | if (get_owner (op) != NULL && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op) |
1456 | if (get_owner (op) && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op) |
1458 | { |
|
|
1459 | op->owner->contr->ranges[range_golem] = NULL; |
1457 | op->owner->contr->ranges[range_golem] = 0; |
1460 | op->owner->contr->golem_count = 0; |
|
|
1461 | } |
|
|
1462 | |
1458 | |
1463 | remove_ob (op); |
1459 | remove_ob (op); |
1464 | free_object (op); |
1460 | free_object (op); |
1465 | return maxdam; |
1461 | return maxdam; |
1466 | } |
1462 | } |
1467 | |
1463 | |
1468 | /* Now lets start dealing with experience we get for killing something */ |
1464 | /* Now lets start dealing with experience we get for killing something */ |
1469 | |
1465 | |
1470 | owner = get_owner (hitter); |
1466 | owner = get_owner (hitter); |
1471 | if (owner == NULL) |
1467 | if (!owner) |
1472 | owner = hitter; |
1468 | owner = hitter; |
1473 | |
1469 | |
1474 | /* is the victim (op) standing on battleground? */ |
1470 | /* is the victim (op) standing on battleground? */ |
1475 | if (op_on_battleground (op, NULL, NULL)) |
1471 | if (op_on_battleground (op, NULL, NULL)) |
1476 | battleg = 1; |
1472 | battleg = 1; |
… | |
… | |
1506 | * probably don't want to see that. |
1502 | * probably don't want to see that. |
1507 | */ |
1503 | */ |
1508 | if (owner->level < op->level * 2 || op->stats.exp > 1000) |
1504 | if (owner->level < op->level * 2 || op->stats.exp > 1000) |
1509 | { |
1505 | { |
1510 | if (owner != hitter) |
1506 | if (owner != hitter) |
1511 | { |
|
|
1512 | new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter)); |
1507 | new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter)); |
1513 | } |
|
|
1514 | else |
1508 | else |
1515 | { |
|
|
1516 | new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op)); |
1509 | new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op)); |
1517 | } |
1510 | |
1518 | /* Only play sounds for melee kills */ |
1511 | /* Only play sounds for melee kills */ |
1519 | if (hitter->type == PLAYER) |
1512 | if (hitter->type == PLAYER) |
1520 | play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS); |
1513 | play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS); |
1521 | } |
1514 | } |
1522 | |
1515 | |
… | |
… | |
1533 | |
1526 | |
1534 | /* This code below deals with finding the appropriate skill |
1527 | /* This code below deals with finding the appropriate skill |
1535 | * to credit exp to. This is a bit problematic - we should |
1528 | * to credit exp to. This is a bit problematic - we should |
1536 | * probably never really have to look at current_weapon->skill |
1529 | * probably never really have to look at current_weapon->skill |
1537 | */ |
1530 | */ |
1538 | skill = NULL; |
1531 | skill = 0; |
|
|
1532 | |
1539 | if (hitter->skill && hitter->type != PLAYER) |
1533 | if (hitter->skill && hitter->type != PLAYER) |
1540 | skill = hitter->skill; |
1534 | skill = hitter->skill; |
1541 | else if (owner->chosen_skill) |
1535 | else if (owner->chosen_skill) |
1542 | { |
1536 | { |
1543 | skill = owner->chosen_skill->skill; |
1537 | skill = owner->chosen_skill->skill; |
… | |
… | |
1562 | break; |
1556 | break; |
1563 | } |
1557 | } |
1564 | } |
1558 | } |
1565 | } /* Was it a player that hit somethign */ |
1559 | } /* Was it a player that hit somethign */ |
1566 | else |
1560 | else |
1567 | { |
|
|
1568 | skill = NULL; |
1561 | skill = 0; |
1569 | } |
|
|
1570 | |
1562 | |
1571 | /* Pet (or spell) killed something. */ |
1563 | /* Pet (or spell) killed something. */ |
1572 | if (owner != hitter) |
1564 | if (owner != hitter) |
1573 | { |
|
|
1574 | (void) sprintf (buf, "%s killed %s with %s%s%s.", &owner->name, |
1565 | sprintf (buf, "%s killed %s with %s%s%s.", &owner->name, |
1575 | query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : ""); |
1566 | query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : ""); |
1576 | } |
|
|
1577 | else |
1567 | else |
1578 | { |
|
|
1579 | (void) sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name, |
1568 | sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name, |
1580 | (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ? |
1569 | (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ? |
1581 | " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : ""); |
1570 | " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : ""); |
1582 | } |
1571 | |
1583 | /* These may have been set in the player code section above */ |
1572 | /* These may have been set in the player code section above */ |
1584 | if (!skop) |
1573 | if (!skop) |
1585 | skop = hitter->chosen_skill; |
1574 | skop = hitter->chosen_skill; |
|
|
1575 | |
1586 | if (!skill && skop) |
1576 | if (!skill && skop) |
1587 | skill = skop->skill; |
1577 | skill = skop->skill; |
1588 | |
1578 | |
1589 | new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf); |
1579 | new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf); |
1590 | |
1580 | |
1591 | |
|
|
1592 | /* If you didn't kill yourself, and your not the wizard */ |
1581 | /* If you didn't kill yourself, and your not the wizard */ |
1593 | if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ)) |
1582 | if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ)) |
1594 | { |
1583 | { |
1595 | int exp; |
1584 | int exp; |
1596 | |
1585 | |
1597 | /* Really don't give much experience for killing other players */ |
1586 | /* Really don't give much experience for killing other players */ |
1598 | // schmorp: temporary? reduce the amount of exp gained for pking enourmously |
1587 | // schmorp: temporarily? reduce the amount of exp gained for pking enourmously |
1599 | if (op->type == PLAYER) |
1588 | if (op->type == PLAYER) |
1600 | { |
1589 | { |
1601 | if (battleg) |
1590 | if (battleg) |
1602 | { |
1591 | { |
1603 | new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!"); |
1592 | new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!"); |
… | |
… | |
1621 | |
1610 | |
1622 | if (!settings.simple_exp) |
1611 | if (!settings.simple_exp) |
1623 | exp = exp / 2; |
1612 | exp = exp / 2; |
1624 | |
1613 | |
1625 | if (owner->type != PLAYER || owner->contr->party == NULL) |
1614 | if (owner->type != PLAYER || owner->contr->party == NULL) |
1626 | { |
|
|
1627 | change_exp (owner, exp, skill, 0); |
1615 | change_exp (owner, exp, skill, 0); |
1628 | } |
|
|
1629 | else |
1616 | else |
1630 | { |
1617 | { |
1631 | int shares = 0, count = 0; |
1618 | int shares = 0, count = 0; |
1632 | |
|
|
1633 | player *pl; |
1619 | player *pl; |
1634 | |
|
|
1635 | partylist *party = owner->contr->party; |
1620 | partylist *party = owner->contr->party; |
1636 | |
1621 | |
1637 | #ifdef PARTY_KILL_LOG |
1622 | #ifdef PARTY_KILL_LOG |
1638 | add_kill_to_party (party, query_name (owner), query_name (op), exp); |
1623 | add_kill_to_party (party, query_name (owner), query_name (op), exp); |
1639 | #endif |
1624 | #endif |
1640 | for (pl = first_player; pl != NULL; pl = pl->next) |
1625 | for (pl = first_player; pl != NULL; pl = pl->next) |
1641 | { |
|
|
1642 | if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) |
1626 | if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) |
1643 | { |
1627 | { |
1644 | count++; |
1628 | count++; |
1645 | shares += (pl->ob->level + 4); |
1629 | shares += (pl->ob->level + 4); |
1646 | } |
1630 | } |
1647 | } |
1631 | |
1648 | if (count == 1 || shares > exp) |
1632 | if (count == 1 || shares > exp || !shares) |
1649 | change_exp (owner, exp, skill, SK_EXP_TOTAL); |
1633 | change_exp (owner, exp, skill, SK_EXP_TOTAL); |
1650 | else |
1634 | else |
1651 | { |
1635 | { |
1652 | int share = exp / shares, given = 0, nexp; |
1636 | int share = exp / shares, given = 0, nexp; |
1653 | |
1637 | |
1654 | for (pl = first_player; pl != NULL; pl = pl->next) |
1638 | for (pl = first_player; pl != NULL; pl = pl->next) |
1655 | { |
|
|
1656 | if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) |
1639 | if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) |
1657 | { |
1640 | { |
1658 | nexp = (pl->ob->level + 4) * share; |
1641 | nexp = (pl->ob->level + 4) * share; |
1659 | change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL); |
1642 | change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL); |
1660 | given += nexp; |
1643 | given += nexp; |
1661 | } |
1644 | } |
1662 | } |
1645 | |
1663 | exp -= given; |
1646 | exp -= given; |
1664 | /* give any remainder to the player */ |
1647 | /* give any remainder to the player */ |
1665 | change_exp (owner, exp, skill, SK_EXP_ADD_SKILL); |
1648 | change_exp (owner, exp, skill, SK_EXP_ADD_SKILL); |
1666 | } |
1649 | } |
1667 | } /* else part of a party */ |
1650 | } /* else part of a party */ |
1668 | |
|
|
1669 | } /* end if person didn't kill himself */ |
1651 | } /* end if person didn't kill himself */ |
1670 | |
1652 | |
1671 | if (op->type != PLAYER) |
1653 | if (op->type != PLAYER) |
1672 | { |
1654 | { |
1673 | if (QUERY_FLAG (op, FLAG_FRIENDLY)) |
1655 | if (QUERY_FLAG (op, FLAG_FRIENDLY)) |
1674 | { |
1656 | { |
1675 | object *owner1 = get_owner (op); |
1657 | object *owner1 = get_owner (op); |
1676 | |
1658 | |
1677 | if (owner1 != NULL && owner1->type == PLAYER) |
1659 | if (owner1 && owner1->type == PLAYER) |
1678 | { |
1660 | { |
1679 | play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0); |
1661 | play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0); |
1680 | /* Maybe we should include the owner that killed this, maybe not */ |
1662 | /* Maybe we should include the owner that killed this, maybe not */ |
1681 | new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name); |
1663 | new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name); |
1682 | } |
1664 | } |
… | |
… | |
1685 | } |
1667 | } |
1686 | |
1668 | |
1687 | remove_ob (op); |
1669 | remove_ob (op); |
1688 | free_object (op); |
1670 | free_object (op); |
1689 | } |
1671 | } |
1690 | /* Player has been killed! */ |
|
|
1691 | else |
1672 | else |
1692 | { |
1673 | { |
|
|
1674 | /* Player has been killed! */ |
1693 | if (owner->type == PLAYER) |
1675 | if (owner->type == PLAYER) |
1694 | { |
|
|
1695 | snprintf (op->contr->killer, BIG_NAME, "%s the %s", &owner->name, owner->contr->title); |
1676 | snprintf (op->contr->killer, sizeof (op->contr->killer), "%s the %s", &owner->name, owner->contr->title); |
1696 | } |
|
|
1697 | else |
1677 | else |
1698 | assign (op->contr->killer, hitter->name); |
1678 | assign (op->contr->killer, hitter->name); |
1699 | } |
1679 | } |
1700 | |
1680 | |
1701 | /* This was return -1 - that doesn't seem correct - if we return -1, process |
1681 | /* This was return -1 - that doesn't seem correct - if we return -1, process |