Go to the documentation of this file.
74 if (
op->materialname == NULL) {
76 if (
op->material & (*mt)->material)
99 int i, roll, saves = 0,
attacks = 0, number;
130 if (
op->resist[number] == 100)
132 else if (roll >= mt->
save[number]-
op->magic-
op->resist[number]/100)
134 else if ((20-mt->
save[number])/3 > originator->
stats.
dam)
161 tmp->move_slow_penalty = 0;
200 object *
env =
op->env;
204 int weight =
op->weight;
214 if (
op->map == NULL) {
215 LOG(
llevError,
"Transport %s not on a map but with an item %s in it?\n",
op->name,
op->inv->name);
222 "You are expelled from the %s during its destruction.",
224 inv->contr->transport = NULL;
239 object *badguy =
blame(originator);
240 if (badguy != NULL) {
257 const char *
arch =
op->other_arch->name;
303 "Despite the flame, you feel nothing.");
305 dam = weight / 1000 * (100 -
env->resist[
ATNR_FIRE]) / 100;
312 env->stats.hp -= dam;
314 if (
env->stats.hp < 0)
361 LOG(
llevError,
"BUG: hit_map(): hitter (arch %s, name %s) not on a map\n",
op->arch->name,
op->name);
437 else if ((
tmp->material ||
tmp->materialname) &&
op->stats.dam > 0 && !
tmp->move_block) {
501 if (
hitter->current_weapon != NULL) {
502 switch (
hitter->current_weapon->weapontype) {
533 snprintf(buf1,
MAX_BUF,
"hit");
534 snprintf(buf2,
MAX_BUF,
"hits");
564 if (dam == 9998 &&
op->type ==
DOOR) {
565 snprintf(buf1,
MAX_BUF,
"unlock %s",
op->name);
566 snprintf(buf2,
MAX_BUF,
" unlocks");
570 snprintf(buf1,
MAX_BUF,
"hit %s",
op->name);
571 snprintf(buf2,
MAX_BUF,
" hits");
575 snprintf(buf1,
MAX_BUF,
"missed %s",
op->name);
576 snprintf(buf2,
MAX_BUF,
" misses");
580 snprintf(buf1,
MAX_BUF,
"hit");
581 snprintf(buf2,
MAX_BUF,
"hits");
628 snprintf(
buf,
sizeof(
buf),
"%s's %s%s you.", owner->
name,
hitter->name, buf2);
630 snprintf(
buf,
sizeof(
buf),
"%s%s you.",
hitter->name, buf2);
638 snprintf(
buf,
sizeof(
buf),
"You %s.", buf1);
641 }
else if (owner != NULL && owner->
type ==
PLAYER) {
662 }
else if (
rndm(0, 5) != 0)
683 int *simple_attack) {
685 LOG(
llevError,
"BUG: get_attack_mode(): freed object\n");
688 *target =
HEAD(*target);
690 if ((*hitter)->env != NULL || (*target)->env != NULL) {
696 || (*hitter)->map == NULL
698 LOG(
llevError,
"BUG: hitter (arch %s, name %s) with no relation to target\n", (*hitter)->arch->name, (*hitter)->name);
729 return new_mode != simple_attack;
750 int simple_attack, roll, dam;
752 tag_t op_tag, hitter_tag;
753 const char *anim_suffix = NULL;
760 if (
hitter->current_weapon != NULL) {
767 if (
hitter->current_weapon) {
768 anim_suffix =
hitter->current_weapon->anim_suffix;
769 }
else if (
hitter->chosen_skill) {
770 anim_suffix =
hitter->chosen_skill->anim_suffix;
774 anim_suffix =
"attack";
780 hitter_tag =
hitter->count;
786 &&
op->speed_left > -(
FABS(
op->speed))*0.3) {
807 if (roll >= 20 ||
op->stats.ac >= base_wc-roll) {
810 hitter->casting_time = -1;
812 "You attacked and lost your spell!");
814 if (
op->casting_time > -1 && base_dam > 0) {
815 op->casting_time = -1;
818 "You were hit and lost your spell!");
821 "%s was hit by %s and lost a spell.",
826 if (!simple_attack) {
844 "You were hit by a wild attack. You are no longer hidden!");
874 "You are splashed by acid!\n");
897 "The %s arrests you!",
hitter->name);
941 if (
op->weight <= 5000 &&
tmp->stats.hp >= 0) {
962 object *container, *
hitter;
963 int hit_something = 0;
964 tag_t victim_tag, hitter_tag, container_tag;
965 int16_t victim_x, victim_y;
967 const char *old_skill = NULL;
993 container_tag = container->
count;
1000 victim_tag =
victim->count;
1001 hitter_tag =
hitter->count;
1013 if (container != NULL) {
1014 old_skill =
hitter->skill;
1032 if (container != NULL) {
1034 hitter->skill = old_skill;
1040 if (hit_something &&
op->speed <= 10.0) {
1042 if (container == NULL) {
1079 if (hit_something &&
op->speed >= 10.0)
1099 if (!
op->stats.maxhp) {
1104 if (
op->stats.hp < 0) {
1112 assert(
op->stats.maxhp > 0);
1173 int doesnt_slay = 1;
1178 LOG(
llevError,
"hit_with_one_attacktype: Invalid attacknumber passed: %u\n", attacknum);
1183 LOG(
llevError,
"hit_with_one_attacktype called with negative damage: %d\n", dam);
1194 if ((
op->race != NULL && strstr(
op->race,
hitter->slaying))
1215 dam *= (100-
op->resist[attacknum]);
1227 if (
op->resist[attacknum] >= 100
1234 switch (attacknum) {
1308 if (
tmp->magic < -4)
1326 "The %s's acid corrodes your %s!",
1327 name_hitter, name_op);
1357 if (
op->stats.exp <= rate) {
1379 int64_t orig_exp =
op->stats.exp;
1383 if (owner && owner !=
hitter) {
1389 hitter->chosen_skill ?
hitter->chosen_skill->skill : NULL, 0);
1433 LOG(
llevError,
"%s was hit by %s with non-specific chaos.\n", name_op, name_hitter);
1484 if (dam >
op->stats.hp+1)
1485 dam =
op->stats.hp+1;
1486 new_hp =
hitter->stats.hp+dam;
1487 if (new_hp >
hitter->stats.maxhp)
1488 new_hp =
hitter->stats.maxhp;
1489 if (new_hp >
hitter->stats.hp)
1490 hitter->stats.hp = new_hp;
1497 hitter->stats.food += dam;
1509 #ifdef PARTY_KILL_LOG
1510 void party_add_kill(
partylist *party,
const char *
killer,
const char *dead,
long exp);
1546 object *owner = NULL;
1547 const object *skop = NULL;
1549 if (
op->stats.hp >= 0)
1562 maxdam = dam+
op->stats.hp+1;
1570 op->speed_left = -0.05;
1588 "Your pet, the %s, is killed by %s.",
1624 if (
op->type ==
PLAYER && !battleg) {
1625 time_t
t = time(NULL);
1630 tmv = localtime(&
t);
1631 strftime(
buf,
sizeof(
buf),
"%a %b %d %H:%M:%S %Y", tmv);
1641 if (owner->
level <
op->level*2 ||
op->stats.exp > 1000) {
1648 "You killed %s with %s.",
1671 if (pk == 1 && !battleg)
1687 LOG(
llevError,
"kill_object - unable to find skill that killed monster\n");
1692 if ((!skop || skop->
type !=
SKILL) && skill) {
1703 const char *owner_prefix;
1704 const char *op_prefix;
1706 owner_prefix = !battleg && pk && owner->
contr != NULL && !owner->
contr->
peaceful ?
"hostile " :
"";
1707 op_prefix = !battleg && pk &&
op->contr != NULL && !
op->contr->peaceful ?
"hostile " :
"";
1711 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)" :
""));
1713 const char *hitter_prefix;
1714 const char *op_prefix;
1716 hitter_prefix = !battleg && pk &&
hitter->contr != NULL && !
hitter->contr->peaceful ?
"hostile " :
"";
1717 op_prefix = !battleg && pk &&
op->contr != NULL && !
op->contr->peaceful ?
"hostile " :
"";
1719 snprintf(kill_message,
sizeof(kill_message),
"%s%s killed %s%s%s%s.", hitter_prefix,
hitter->name, op_prefix,
op->name,
1721 " in hand to hand combat" :
"", battleg ?
" (duel)" : (pk ?
" (pk)" :
""));
1725 skop =
hitter->chosen_skill;
1727 skill = skop->
skill;
1744 "Your foe has fallen!\nVICTORY!!!");
1767 #ifdef PARTY_KILL_LOG
1823 if (owner != NULL) {
1834 return friendlyfire;
1862 int maxattacktype, attacknum;
1863 int body_attack =
op->head != NULL;
1865 tag_t op_tag, hitter_tag;
1885 hitter_tag =
hitter->count;
1904 if (!simple_attack &&
op->type ==
DOOR) {
1921 LOG(
llevDebug,
"victim (arch %s, name %s) already dead in hit_player()\n",
op->arch->name,
op->name);
1936 dam = (dam > (
rndm(0, 99))) ? 1 : 0;
1956 && !(
op->name && strstr(
hitter->slaying,
op->name))))
1959 && god->race != NULL
1964 maxattacktype =
type;
1965 for (attacknum = 0; attacknum <
NROFATTACKS; attacknum++) {
1968 attacktype = 1<<attacknum;
1982 if (
type&attacktype) {
1987 if (ndam >= maxdam) {
1989 maxattacktype = 1<<attacknum;
1993 if (attacktype ==
AT_DEATH && ndam > 0)
2011 if (friendlyfire && maxdam) {
2022 unsigned int area = 0;
2023 for (at =
op->arch; at != NULL; at = at->
more)
2028 unsigned int remainder = 100*(maxdam%area)/area;
2030 if (
RANDOM()%100 < remainder)
2039 if (owner != NULL) {
2043 if (
op->enemy == NULL ||
rndm(1, 20) == 0)
2057 op->stats.hp -= maxdam;
2060 if (
op->stats.hp >= 0
2062 &&
op->stats.hp < (int16_t)((int32_t)
op->run_away *
op->stats.maxhp / 100)) {
2134 tmp->stats.dam = dam;
2138 if (!skill &&
hitter->chosen_skill)
2139 skill =
hitter->chosen_skill->name;
2141 if (skill && skill !=
tmp->skill) {
2147 tmp->stats.food += dam;
2151 tmp->stats.Con =
MAX(-(dam/4+1), -10);
2152 tmp->stats.Str =
MAX(-(dam/3+2), -10);
2153 tmp->stats.Dex =
MAX(-(dam/6+1), -10);
2154 tmp->stats.Int =
MAX(-dam/7, -10);
2159 "You suddenly feel very ill.");
2173 "Your %s poisons %s.",
2176 tmp->speed_left = 0;
2191 tmp->stats.exp = -speed_penalty;
2196 else if (
tmp->stats.exp > -speed_penalty) {
2197 tmp->stats.exp = -speed_penalty;
2198 tmp->stats.food -= 3;
2205 tmp->speed_left = 0;
2234 speed_penalty = speed_penalty * (100-
op->resist[
ATNR_SLOW]) / 100;
2236 if (speed_penalty < 1)
2238 else if (speed_penalty > 30)
2244 "The world suddenly moves very fast!");
2249 "The world moves even faster!");
2290 if (
tmp->duration > maxduration)
2291 tmp->duration = maxduration;
2295 "You suddenly feel very confused!");
2310 object *
tmp, *owner;
2337 "Your attack blinds %s!",
2340 tmp->stats.food += dam;
2341 if (
tmp->stats.food > 10)
2342 tmp->stats.food = 10;
2362 op->speed_left -=
FABS(
op->speed)*effect;
2374 "You limbs stop moving!");
2405 int atk_lev, def_lev, kill_lev, roll;
2409 || (
op->race && strstr(
op->race,
hitter->slaying))))
2421 def_lev =
op->level;
2423 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);
2439 kill_lev = roll - 48 + atk_lev;
2440 kill_lev = kill_lev * (100 -
op->resist[
ATNR_DEATH]) / 100;
2443 if (kill_lev > def_lev) {
2444 *dam =
op->stats.hp+10;
2449 *dam *= kill_lev/def_lev;
2509 object *attacker =
hitter;
2514 LOG(
llevError,
"BUG: adj_attackroll(): hitter and target not on same map\n");
2521 if (attacker == NULL)
#define object_was_destroyed(op, old_tag)
void commit_crime(object *op, const char *description)
void confuse_living(object *op, object *hitter, int dam)
sstring add_refcount(sstring str)
#define ATNR_CANCELLATION
sstring add_string(const char *str)
void object_remove(object *op)
void remove_friendly_object(object *op)
void object_set_enemy(object *op, object *enemy)
object * object_find_by_type2(const object *who, int type1, int type2)
#define MSG_TYPE_ADMIN_PLAYER
void object_copy_owner(object *op, object *clone)
int monster_stand_in_light(object *op)
void object_update(object *op, int action)
#define QUERY_FLAG(xyz, p)
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
static void attack_message(int dam, int type, object *op, object *hitter)
void make_visible(object *op)
int op_on_battleground(object *op, int *x, int *y, archetype **trophy)
#define MSG_TYPE_ATTACK_DID_HIT
int get_turn_bonus(int stat)
static int adj_attackroll(object *hitter, object *target)
void share_exp(object *op, int64_t exp, const char *skill, int flag)
void spring_trap(object *trap, object *victim)
object * arch_present_in_ob(const archetype *at, const object *op)
static void cancellation(object *op)
#define MSG_TYPE_ATTRIBUTE
#define SET_ANIMATION(ob, newanim)
void play_sound_map(int8_t sound_type, object *emitter, int dir, const char *action)
void shuffle_attack(object *op)
EXTERN materialtype_t * materialt
static int get_attack_mode(object **target, object **hitter, int *simple_attack)
int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
static int did_make_save_item(object *op, int type, object *originator)
static int kill_object(object *op, int dam, object *hitter)
short freearr_x[SIZEOFFREE]
short freearr_y[SIZEOFFREE]
object * find_applied_skill_by_name(const object *op, const char *name)
object * blame(object *op)
method_ret ob_apply(object *op, object *applier, int aflags)
const object * find_god(const char *name)
static void deathstrike_living(object *op, object *hitter, int *dam)
int64_t pk_max_experience
#define MSG_TYPE_ATTACK_DID_KILL
int attack_ob(object *op, object *hitter)
object * object_merge(object *op, object *top)
const EXTERN char * undead_name
struct obj * chosen_skill
void free_string(sstring str)
static event_registration m
materialtype_t * name_to_material(const char *name)
object * hit_with_arrow(object *op, object *victim)
struct obj * current_weapon
#define USING_SKILL(op, skill)
int pk_max_experience_percent
int free_no_drop(object *op)
const char * determine_god(object *op)
#define MSG_TYPE_ATTRIBUTE_BAD_EFFECT_START
#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
void check_physically_infect(object *victim, object *hitter)
int64_t calc_skill_exp(const object *who, const object *op, const object *skill)
int hit_map(object *op, int dir, uint32_t type, int full_hit)
struct _materialtype * next
#define FOR_OB_AND_BELOW_FINISH()
EXTERN Chaos_Attacks ATTACKS[22]
#define MSG_TYPE_ATTACK_PET_DIED
EXTERN attackmess_t attack_mess[NROFATTACKMESS][MAXATTACKMESS]
object * object_present_in_ob(uint8_t type, const object *op)
static void scare_creature(object *target, object *hitter)
void fix_object(object *op)
void counterspell(object *op, int dir)
void fix_stopped_item(object *op, mapstruct *map, object *originator)
void get_attack_message_for_attack_type(int dam, uint8_t atm_type, const char *victim_name, char *buf1, char *buf2)
object * fix_stopped_arrow(object *op)
int rndm(int min, int max)
#define FLAG_UNAGGRESSIVE
#define ATNR_COUNTERSPELL
bool is_criminal(object *op)
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
int slow_living_by(object *op, const int speed_penalty)
#define MSG_TYPE_VICTIM_WAS_HIT
#define FOR_OB_AND_BELOW_PREPARE(op_)
void object_set_owner(object *op, object *owner)
static std::shared_ptr< inja::Environment > env
static void object_get_materialtype(object *op, materialtype_t **mt)
object * create_archetype(const char *name)
int random_roll(int min, int max, const object *op, int goodbad)
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
#define FLAG_KNOWN_MAGICAL
const char *const attacks[NROFATTACKS]
int is_wraith_pl(object *op)
#define OUT_OF_REAL_MAP(M, X, Y)
static void poison_living(object *op, object *hitter, int dam)
static void slow_living(object *op, object *hitter, int dam)
int monster_can_see_enemy(object *op, object *enemy)
static void tear_down_wall(object *op)
#define MSG_TYPE_ATTACK_PET_HIT
void paralyze_living(object *op, int dam)
object * map_find_by_archetype(mapstruct *m, int x, int y, const archetype *at)
#define MSG_TYPE_VICTIM_WAS_PUSHED
void apply_anim_suffix(object *who, const char *suffix)
int friendly_fire(object *op, object *hitter)
void LOG(LogLevel logLevel, const char *format,...)
int did_make_save(const object *op, int level, int bonus)
void monster_npc_call_help(object *op)
int64_t check_exp_loss(const object *op, int64_t exp)
bool object_value_set(const object *op, const char *const key)
archetype * find_archetype(const char *name)
static uint8_t get_attack_message_type(int type, const object *op, const object *hitter)
void esrv_update_item(int flags, object *pl, object *op)
void blind_living(object *op, object *hitter, int dam)
#define MSG_TYPE_ATTACK_FUMBLE
#define CLEAR_FLAG(xyz, p)
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
#define NUM_ANIMATIONS(ob)
static void put_in_icecube(object *op, object *originator)
object * object_insert_in_ob(object *op, object *where)
int player_arrest(object *who)
void update_all_los(const mapstruct *map, int x, int y)
void object_update_speed(object *op)
void object_handle_death_animation(object *op)
object * arch_to_object(archetype *at)
object * ranges[range_size]
void change_object(object *op)
object * object_present_in_ob_by_name(int type, const char *str, const object *op)
void save_throw_object(object *op, uint32_t type, object *originator)
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
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)
void object_free_drop_inventory(object *ob)
static int is_aimed_missile(object *op)
static int abort_attack(object *target, object *hitter, int simple_attack)
void object_replace_insert_in_map(const char *arch_string, object *op)
static int hit_with_one_attacktype(object *op, object *hitter, int dam, uint32_t attacknum)
int player_can_view(object *pl, object *op)
object * object_decrease_nrof(object *op, uint32_t i)
static int attack_ob_simple(object *op, object *hitter, int base_dam, int base_wc)
static void get_attack_message(int dam, int type, const object *op, const object *hitter, char *buf1, char *buf2)
void drain_stat(object *op)
#define FLAG_IS_LIGHTABLE
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
int change_abil(object *op, object *tmp)
#define FLAG_READY_WEAPON
int on_same_map(const object *op1, const object *op2)
#define ATNR_LIFE_STEALING
void kill_player(object *op, const object *killer)
static void thrown_item_effect(object *, object *)
#define FOR_INV_PREPARE(op_, it_)
static const int32_t MAX_FOOD
int process_object(object *op)
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
void events_execute_global_event(int eventcode,...)
void change_luck(object *op, int value)
static int stick_arrow(object *op, object *tmp)
object * object_get_owner(object *op)
#define MSG_TYPE_APPLY_UNAPPLY