Go to the documentation of this file.
42 object *
op,
object *
hitter,
int dam, uint32_t attacknum);
77 if (
op->materialname == NULL) {
80 if (
op->material & (*mt)->material) {
105 int i, roll, saves = 0,
attacks = 0, number;
136 if (
op->resist[number] == 100)
138 else if (roll >= mt->
save[number]-
op->magic-
op->resist[number]/100)
140 else if ((20-mt->
save[number])/3 > originator->
stats.
dam)
167 tmp->move_slow_penalty = 0;
206 object *
env =
op->env;
210 int weight =
op->weight;
220 if (
op->map == NULL) {
221 LOG(
llevError,
"Transport %s not on a map but with an item %s in it?\n",
op->name,
op->inv->name);
228 "You are expelled from the %s during its destruction.",
230 inv->contr->transport = NULL;
245 object *badguy =
blame(originator);
246 if (badguy != NULL) {
263 const char *
arch =
op->other_arch->name;
309 "Despite the flame, you feel nothing.");
311 dam = weight / 1000 * (100 -
env->resist[
ATNR_FIRE]) / 100;
318 env->stats.hp -= dam;
320 if (
env->stats.hp < 0)
367 LOG(
llevError,
"BUG: hit_map(): hitter (arch %s, name %s) not on a map\n",
op->arch->name,
op->name);
443 else if ((
tmp->material ||
tmp->materialname) &&
op->stats.dam > 0 && !
tmp->move_block) {
507 if (
hitter->current_weapon != NULL) {
508 switch (
hitter->current_weapon->weapontype) {
539 snprintf(buf1,
MAX_BUF,
"hit");
540 snprintf(buf2,
MAX_BUF,
"hits");
570 if (dam == 9998 &&
op->type ==
DOOR) {
571 snprintf(buf1,
MAX_BUF,
"unlock %s",
op->name);
572 snprintf(buf2,
MAX_BUF,
" unlocks");
576 snprintf(buf1,
MAX_BUF,
"hit %s",
op->name);
577 snprintf(buf2,
MAX_BUF,
" hits");
581 snprintf(buf1,
MAX_BUF,
"missed %s",
op->name);
582 snprintf(buf2,
MAX_BUF,
" misses");
586 snprintf(buf1,
MAX_BUF,
"hit");
587 snprintf(buf2,
MAX_BUF,
"hits");
634 snprintf(
buf,
sizeof(
buf),
"%s's %s%s you.", owner->
name,
hitter->name, buf2);
636 snprintf(
buf,
sizeof(
buf),
"%s%s you.",
hitter->name, buf2);
644 snprintf(
buf,
sizeof(
buf),
"You %s.", buf1);
647 }
else if (owner != NULL && owner->
type ==
PLAYER) {
668 }
else if (
rndm(0, 5) != 0)
689 int *simple_attack) {
691 LOG(
llevError,
"BUG: get_attack_mode(): freed object\n");
694 *target =
HEAD(*target);
696 if ((*hitter)->env != NULL || (*target)->env != NULL) {
702 || (*hitter)->map == NULL
704 LOG(
llevError,
"BUG: hitter (arch %s, name %s) with no relation to target\n", (*hitter)->arch->name, (*hitter)->name);
735 return new_mode != simple_attack;
768 int simple_attack, roll, dam;
770 tag_t op_tag, hitter_tag;
771 const char *anim_suffix = NULL;
778 if (
hitter->current_weapon != NULL) {
785 if (
hitter->current_weapon) {
786 anim_suffix =
hitter->current_weapon->anim_suffix;
787 }
else if (
hitter->chosen_skill) {
788 anim_suffix =
hitter->chosen_skill->anim_suffix;
792 anim_suffix =
"attack";
798 hitter_tag =
hitter->count;
804 &&
op->speed_left > -(
FABS(
op->speed))*0.3) {
825 if (roll >= 20 ||
op->stats.ac >= wc-roll) {
828 hitter->casting_time = -1;
830 "You attacked and lost your spell!");
832 if (
op->casting_time > -1 && base_dam > 0) {
833 op->casting_time = -1;
836 "You were hit and lost your spell!");
839 "%s was hit by %s and lost a spell.",
844 if (!simple_attack) {
862 "You were hit by a wild attack. You are no longer hidden!");
892 "You are splashed by acid!\n");
915 "The %s arrests you!",
hitter->name);
959 if (
op->weight <= 5000 &&
tmp->stats.hp >= 0) {
980 object *container, *
hitter;
981 int hit_something = 0;
982 tag_t victim_tag, hitter_tag, container_tag;
983 int16_t victim_x, victim_y;
985 const char *old_skill = NULL;
1011 container_tag = container->
count;
1017 victim_map =
victim->map;
1018 victim_tag =
victim->count;
1019 hitter_tag =
hitter->count;
1031 if (container != NULL) {
1032 old_skill =
hitter->skill;
1050 if (container != NULL) {
1052 hitter->skill = old_skill;
1058 if (hit_something &&
op->speed <= 10.0) {
1060 if (container == NULL) {
1097 if (hit_something &&
op->speed >= 10.0)
1117 if (!
op->stats.maxhp) {
1122 if (
op->stats.hp < 0) {
1130 assert(
op->stats.maxhp > 0);
1193 int exp_to_drain =
op->stats.exp/rate;
1199 exp_to_drain =
MIN(exp_to_drain,
1203 if (exp_to_drain <= 1) {
1228 int64_t orig_exp =
op->stats.exp;
1230 exp_to_drain = orig_exp -
op->stats.exp;
1233 if (owner && owner !=
hitter) {
1238 hitter->chosen_skill ?
hitter->chosen_skill->skill : NULL,
1244 hitter->chosen_skill ?
hitter->chosen_skill->skill : NULL,
1271 int doesnt_slay = 1;
1276 LOG(
llevError,
"hit_with_one_attacktype: Invalid attacknumber passed: %u\n", attacknum);
1281 LOG(
llevError,
"hit_with_one_attacktype called with negative damage: %d\n", dam);
1292 if ((
op->race != NULL && strstr(
op->race,
hitter->slaying))
1313 dam *= (100-
op->resist[attacknum]);
1325 if (
op->resist[attacknum] >= 100
1332 switch (attacknum) {
1406 if (
tmp->magic < -4)
1424 "The %s's acid corrodes your %s!",
1425 name_hitter, name_op);
1475 LOG(
llevError,
"%s was hit by %s with non-specific chaos.\n", name_op, name_hitter);
1526 if (dam >
op->stats.hp+1)
1527 dam =
op->stats.hp+1;
1528 new_hp =
hitter->stats.hp+dam;
1529 if (new_hp >
hitter->stats.maxhp)
1530 new_hp =
hitter->stats.maxhp;
1531 if (new_hp >
hitter->stats.hp)
1532 hitter->stats.hp = new_hp;
1539 hitter->stats.food += dam;
1551 #ifdef PARTY_KILL_LOG
1552 void party_add_kill(
partylist *party,
const char *
killer,
const char *dead,
long exp);
1588 object *owner = NULL;
1589 const object *skop = NULL;
1591 if (
op->stats.hp >= 0)
1604 maxdam = dam+
op->stats.hp+1;
1612 op->speed_left = -0.05;
1630 "Your pet, the %s, is killed by %s.",
1666 if (
op->type ==
PLAYER && !battleg) {
1667 time_t
t = time(NULL);
1672 tmv = localtime(&
t);
1673 strftime(
buf,
sizeof(
buf),
"%a %b %d %H:%M:%S %Y", tmv);
1683 if (owner->
level <
op->level*2 ||
op->stats.exp > 1000) {
1690 "You killed %s with %s.",
1713 if (pk == 1 && !battleg)
1729 LOG(
llevError,
"kill_object - unable to find skill that killed monster\n");
1734 if ((!skop || skop->
type !=
SKILL) && skill) {
1745 const char *owner_prefix;
1746 const char *op_prefix;
1748 owner_prefix = !battleg && pk && owner->
contr != NULL && !owner->
contr->
peaceful ?
"hostile " :
"";
1749 op_prefix = !battleg && pk &&
op->contr != NULL && !
op->contr->peaceful ?
"hostile " :
"";
1753 snprintf(kill_message,
sizeof(kill_message),
"%s%s killed %s%s with %s%s.", owner_prefix, owner->
name, op_prefix, name_op, name_hitter, battleg ?
" (duel)" : (pk ?
" (pk)" :
""));
1755 const char *hitter_prefix;
1756 const char *op_prefix;
1758 hitter_prefix = !battleg && pk &&
hitter->contr != NULL && !
hitter->contr->peaceful ?
"hostile " :
"";
1759 op_prefix = !battleg && pk &&
op->contr != NULL && !
op->contr->peaceful ?
"hostile " :
"";
1761 snprintf(kill_message,
sizeof(kill_message),
"%s%s killed %s%s%s%s.", hitter_prefix,
hitter->name, op_prefix,
op->name,
1763 " in hand to hand combat" :
"", battleg ?
" (duel)" : (pk ?
" (pk)" :
""));
1767 skop =
hitter->chosen_skill;
1769 skill = skop->
skill;
1786 "Your foe has fallen!\nVICTORY!!!");
1809 #ifdef PARTY_KILL_LOG
1828 snprintf(
op->contr->killer,
BIG_NAME,
"%s the %.*s", owner->
name,
1829 int(
sizeof(
op->contr->killer) - strlen(owner->
name) - 4), owner->
contr->
title);
1866 if (owner != NULL) {
1877 return friendlyfire;
1905 int maxattacktype, attacknum;
1906 int body_attack =
op->head != NULL;
1908 tag_t op_tag, hitter_tag;
1928 hitter_tag =
hitter->count;
1947 if (!simple_attack &&
op->type ==
DOOR) {
1964 LOG(
llevDebug,
"victim (arch %s, name %s) already dead in hit_player()\n",
op->arch->name,
op->name);
1979 dam = (dam > (
rndm(0, 99))) ? 1 : 0;
1999 && !(
op->name && strstr(
hitter->slaying,
op->name))))
2002 && god->race != NULL
2007 maxattacktype =
type;
2008 for (attacknum = 0; attacknum <
NROFATTACKS; attacknum++) {
2011 attacktype = 1<<attacknum;
2025 if (
type&attacktype) {
2030 if (ndam >= maxdam) {
2032 maxattacktype = 1<<attacknum;
2036 if (attacktype ==
AT_DEATH && ndam > 0)
2054 if (friendlyfire && maxdam) {
2065 unsigned int area = 0;
2066 for (at =
op->arch; at != NULL; at = at->
more)
2071 unsigned int remainder = 100*(maxdam%area)/area;
2073 if (
RANDOM()%100 < remainder)
2082 if (owner != NULL) {
2086 if (
op->enemy == NULL ||
rndm(1, 20) == 0)
2100 op->stats.hp -= maxdam;
2103 if (
op->stats.hp >= 0
2105 &&
op->stats.hp < (int16_t)((int32_t)
op->run_away *
op->stats.maxhp / 100)) {
2179 tmp->stats.dam = dam;
2183 if (!skill &&
hitter->chosen_skill)
2184 skill =
hitter->chosen_skill->name;
2186 if (skill && skill !=
tmp->skill) {
2192 tmp->stats.food += dam;
2196 tmp->stats.Con =
MAX(-(dam/4+1), -10);
2197 tmp->stats.Str =
MAX(-(dam/3+2), -10);
2198 tmp->stats.Dex =
MAX(-(dam/6+1), -10);
2199 tmp->stats.Int =
MAX(-dam/7, -10);
2204 "You suddenly feel very ill.");
2218 "Your %s poisons %s.",
2221 tmp->speed_left = 0;
2236 tmp->stats.exp = -speed_penalty;
2241 else if (
tmp->stats.exp > -speed_penalty) {
2242 tmp->stats.exp = -speed_penalty;
2243 tmp->stats.food -= 3;
2250 tmp->speed_left = 0;
2279 speed_penalty = speed_penalty * (100-
op->resist[
ATNR_SLOW]) / 100;
2281 if (speed_penalty < 1)
2283 else if (speed_penalty > 30)
2289 "The world suddenly moves very fast!");
2294 "The world moves even faster!");
2335 if (
tmp->duration > maxduration)
2336 tmp->duration = maxduration;
2340 "You suddenly feel very confused!");
2355 object *
tmp, *owner;
2382 "Your attack blinds %s!",
2385 tmp->stats.food += dam;
2386 if (
tmp->stats.food > 10)
2387 tmp->stats.food = 10;
2407 op->speed_left -=
FABS(
op->speed)*effect;
2419 "You limbs stop moving!");
2450 int atk_lev, def_lev, kill_lev, lev_mult = 1;
2454 || (
op->race && strstr(
op->race,
hitter->slaying))))
2468 def_lev =
op->level;
2470 LOG(
llevError,
"deathstrike_living: arch %s (%s in %s at %d, %d) has level < 1\n",
op->arch->name,
op->name,
op->map->name,
op->x,
op->y);
2491 kill_lev = (atk_lev - def_lev) * lev_mult * (100 -
op->resist[
ATNR_DEATH]) / 100;
2498 *dam =
op->stats.hp+10;
2503 *dam *= kill_lev/def_lev;
2563 object *attacker =
hitter;
2568 LOG(
llevError,
"BUG: adj_attackroll(): hitter and target not on same map\n");
2575 if (attacker == NULL)
#define object_was_destroyed(op, old_tag)
bool object_value_set(const object *op, const char *const key)
static int did_make_save_item(object *op, int type, object *originator)
static uint8_t get_attack_message_type(int type, const object *op, const object *hitter)
object * object_get_owner(object *op)
static void deathstrike_living(object *op, object *hitter, int *dam)
static void cancellation(object *op)
#define ATNR_CANCELLATION
void remove_friendly_object(object *op)
static int stick_arrow(object *op, object *tmp)
object * find_applied_skill_by_name(const object *op, const char *name)
static int abort_attack(object *target, object *hitter, int simple_attack)
#define MSG_TYPE_ADMIN_PLAYER
void LOG(LogLevel logLevel, const char *format,...)
int monster_stand_in_light(object *op)
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
#define QUERY_FLAG(xyz, p)
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
object * map_find_by_archetype(mapstruct *m, int x, int y, const archetype *at)
object * object_merge(object *op, object *top)
void make_visible(object *op)
int op_on_battleground(object *op, int *x, int *y, archetype **trophy)
#define MSG_TYPE_ATTACK_DID_HIT
void object_set_enemy(object *op, object *enemy)
void spring_trap(object *trap, object *victim)
static void get_attack_message(int dam, int type, const object *op, const object *hitter, char *buf1, char *buf2)
object * arch_present_in_ob(const archetype *at, const object *op)
void object_set_owner(object *op, object *owner)
void object_handle_death_animation(object *op)
#define MSG_TYPE_ATTRIBUTE
#define SET_ANIMATION(ob, newanim)
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
void play_sound_map(int8_t sound_type, object *emitter, int dir, const char *action)
void set_materialname(object *op)
void fix_object(object *op)
void shuffle_attack(object *op)
void confuse_living(object *op, object *hitter, int dam)
int hit_map(object *op, int dir, uint32_t type, int full_hit)
int friendly_fire(object *op, object *hitter)
int rndm(int min, int max)
std::vector< materialtype_t * > materials
int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
materialtype_t * name_to_material(const char *name)
object * object_insert_in_ob(object *op, object *where)
const object * find_god(const char *name)
int attack_ob(object *op, object *hitter)
static int hit_with_one_attacktype(object *op, object *hitter, int dam, uint32_t attacknum)
int64_t pk_max_experience
void blind_living(object *op, object *hitter, int dam)
#define MSG_TYPE_ATTACK_DID_KILL
static event_registration m
void object_free_drop_inventory(object *ob)
void save_throw_object(object *op, uint32_t type, object *originator)
void object_update(object *op, int action)
#define USING_SKILL(op, skill)
object * object_find_by_type2(const object *who, int type1, int type2)
bool is_criminal(object *op)
int pk_max_experience_percent
sstring add_refcount(sstring str)
int free_no_drop(object *op)
static int adj_attackroll(object *hitter, object *target)
const char * determine_god(object *op)
short freearr_y[SIZEOFFREE]
#define MSG_TYPE_ATTRIBUTE_BAD_EFFECT_START
object * object_present_in_ob_by_name(int type, const char *str, const object *op)
#define MSG_TYPE_APPLY_SUCCESS
void query_name(const object *op, char *buf, size_t size)
uint16_t set_friendly_fire
#define FLAG_KNOWN_CURSED
object * ranges[range_size]
void check_physically_infect(object *victim, object *hitter)
int64_t calc_skill_exp(const object *who, const object *op, const object *skill)
sstring add_string(const char *str)
void apply_anim_suffix(object *who, const char *suffix)
#define FOR_OB_AND_BELOW_FINISH()
void commit_crime(object *op, const char *description)
#define MSG_TYPE_ATTACK_PET_DIED
object * hit_with_arrow(object *op, object *victim)
void object_update_speed(object *op)
int slow_living_by(object *op, const int speed_penalty)
void counterspell(object *op, int dir)
void fix_stopped_item(object *op, mapstruct *map, object *originator)
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
object * fix_stopped_arrow(object *op)
#define FLAG_UNAGGRESSIVE
#define ATNR_COUNTERSPELL
#define MSG_TYPE_VICTIM_WAS_HIT
#define FOR_OB_AND_BELOW_PREPARE(op_)
int random_roll(int min, int max, const object *op, int goodbad)
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Chaos_Attacks ATTACKS[22]
static int get_attack_mode(object **target, object **hitter, int *simple_attack)
static std::shared_ptr< inja::Environment > env
object * blame(object *op)
int is_wraith_pl(object *op)
object * create_archetype(const char *name)
object * object_present_in_ob(uint8_t type, const object *op)
void free_string(sstring str)
static void thrown_item_effect(object *, object *)
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
#define FLAG_KNOWN_MAGICAL
int change_abil(object *op, object *tmp)
#define OUT_OF_REAL_MAP(M, X, Y)
attackmess_t attack_mess[NROFATTACKMESS][MAXATTACKMESS]
static void attack_message(int dam, int type, object *op, object *hitter)
object * object_decrease_nrof(object *op, uint32_t i)
int monster_can_see_enemy(object *op, object *enemy)
#define MSG_TYPE_ATTACK_PET_HIT
static void tear_down_wall(object *op)
#define MSG_TYPE_VICTIM_WAS_PUSHED
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
const char *const attacks[NROFATTACKS]
void drain_stat(object *op)
void monster_npc_call_help(object *op)
archetype * find_archetype(const char *name)
static void object_get_materialtype(object *op, materialtype_t **mt)
int get_turn_bonus(int stat)
void change_luck(object *op, int value)
void esrv_update_item(int flags, object *pl, object *op)
int did_make_save(const object *op, int level, int bonus)
static int attack_ob_simple(object *op, object *hitter, int base_dam, int wc)
#define MSG_TYPE_ATTACK_FUMBLE
int on_same_map(const object *op1, const object *op2)
#define CLEAR_FLAG(xyz, p)
method_ret ob_apply(object *op, object *applier, int aflags)
static int hit_with_drain(object *op, object *hitter, int dam)
void paralyze_living(object *op, int dam)
#define NUM_ANIMATIONS(ob)
int player_arrest(object *who)
void share_exp(object *op, int64_t exp, const char *skill, int flag)
object * arch_to_object(archetype *at)
void change_object(object *op)
int64_t check_exp_loss(const object *op, int64_t exp)
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
object * stop_item(object *op)
static void scare_creature(object *target, object *hitter)
void process_object(object *op)
void object_remove(object *op)
int player_can_view(object *pl, object *op)
void update_all_los(const mapstruct *map, int x, int y)
void object_copy_owner(object *op, object *clone)
static void put_in_icecube(object *op, object *originator)
void get_attack_message_for_attack_type(int dam, uint8_t atm_type, const char *victim_name, char *buf1, char *buf2)
short freearr_x[SIZEOFFREE]
#define FLAG_IS_LIGHTABLE
#define FLAG_READY_WEAPON
static int kill_object(object *op, int dam, object *hitter)
#define ATNR_LIFE_STEALING
void kill_player(object *op, const object *killer)
static int is_aimed_missile(object *op)
#define FOR_INV_PREPARE(op_, it_)
static const int32_t MAX_FOOD
static void poison_living(object *op, object *hitter, int dam)
void events_execute_global_event(int eventcode,...)
void object_replace_insert_in_map(const char *arch_string, object *op)
static void slow_living(object *op, object *hitter, int dam)
#define MSG_TYPE_APPLY_UNAPPLY