Go to the documentation of this file.
75 if (
op->materialname == NULL) {
78 if (
op->material & (*mt)->material) {
103 int i, roll, saves = 0,
attacks = 0, number;
134 if (
op->resist[number] == 100)
136 else if (roll >= mt->
save[number]-
op->magic-
op->resist[number]/100)
138 else if ((20-mt->
save[number])/3 > originator->
stats.
dam)
165 tmp->move_slow_penalty = 0;
204 object *
env =
op->env;
208 int weight =
op->weight;
218 if (
op->map == NULL) {
219 LOG(
llevError,
"Transport %s not on a map but with an item %s in it?\n",
op->name,
op->inv->name);
226 "You are expelled from the %s during its destruction.",
228 inv->contr->transport = NULL;
243 object *badguy =
blame(originator);
244 if (badguy != NULL) {
261 const char *
arch =
op->other_arch->name;
307 "Despite the flame, you feel nothing.");
309 dam = weight / 1000 * (100 -
env->resist[
ATNR_FIRE]) / 100;
316 env->stats.hp -= dam;
318 if (
env->stats.hp < 0)
365 LOG(
llevError,
"BUG: hit_map(): hitter (arch %s, name %s) not on a map\n",
op->arch->name,
op->name);
441 else if ((
tmp->material ||
tmp->materialname) &&
op->stats.dam > 0 && !
tmp->move_block) {
505 if (
hitter->current_weapon != NULL) {
506 switch (
hitter->current_weapon->weapontype) {
537 snprintf(buf1,
MAX_BUF,
"hit");
538 snprintf(buf2,
MAX_BUF,
"hits");
568 if (dam == 9998 &&
op->type ==
DOOR) {
569 snprintf(buf1,
MAX_BUF,
"unlock %s",
op->name);
570 snprintf(buf2,
MAX_BUF,
" unlocks");
574 snprintf(buf1,
MAX_BUF,
"hit %s",
op->name);
575 snprintf(buf2,
MAX_BUF,
" hits");
579 snprintf(buf1,
MAX_BUF,
"missed %s",
op->name);
580 snprintf(buf2,
MAX_BUF,
" misses");
584 snprintf(buf1,
MAX_BUF,
"hit");
585 snprintf(buf2,
MAX_BUF,
"hits");
632 snprintf(
buf,
sizeof(
buf),
"%s's %s%s you.", owner->
name,
hitter->name, buf2);
634 snprintf(
buf,
sizeof(
buf),
"%s%s you.",
hitter->name, buf2);
642 snprintf(
buf,
sizeof(
buf),
"You %s.", buf1);
645 }
else if (owner != NULL && owner->
type ==
PLAYER) {
666 }
else if (
rndm(0, 5) != 0)
687 int *simple_attack) {
689 LOG(
llevError,
"BUG: get_attack_mode(): freed object\n");
692 *target =
HEAD(*target);
694 if ((*hitter)->env != NULL || (*target)->env != NULL) {
700 || (*hitter)->map == NULL
702 LOG(
llevError,
"BUG: hitter (arch %s, name %s) with no relation to target\n", (*hitter)->arch->name, (*hitter)->name);
733 return new_mode != simple_attack;
754 int simple_attack, roll, dam;
756 tag_t op_tag, hitter_tag;
757 const char *anim_suffix = NULL;
764 if (
hitter->current_weapon != NULL) {
771 if (
hitter->current_weapon) {
772 anim_suffix =
hitter->current_weapon->anim_suffix;
773 }
else if (
hitter->chosen_skill) {
774 anim_suffix =
hitter->chosen_skill->anim_suffix;
778 anim_suffix =
"attack";
784 hitter_tag =
hitter->count;
790 &&
op->speed_left > -(
FABS(
op->speed))*0.3) {
811 if (roll >= 20 ||
op->stats.ac >= base_wc-roll) {
814 hitter->casting_time = -1;
816 "You attacked and lost your spell!");
818 if (
op->casting_time > -1 && base_dam > 0) {
819 op->casting_time = -1;
822 "You were hit and lost your spell!");
825 "%s was hit by %s and lost a spell.",
830 if (!simple_attack) {
848 "You were hit by a wild attack. You are no longer hidden!");
878 "You are splashed by acid!\n");
901 "The %s arrests you!",
hitter->name);
945 if (
op->weight <= 5000 &&
tmp->stats.hp >= 0) {
966 object *container, *
hitter;
967 int hit_something = 0;
968 tag_t victim_tag, hitter_tag, container_tag;
969 int16_t victim_x, victim_y;
971 const char *old_skill = NULL;
997 container_tag = container->
count;
1003 victim_map =
victim->map;
1004 victim_tag =
victim->count;
1005 hitter_tag =
hitter->count;
1017 if (container != NULL) {
1018 old_skill =
hitter->skill;
1036 if (container != NULL) {
1038 hitter->skill = old_skill;
1044 if (hit_something &&
op->speed <= 10.0) {
1046 if (container == NULL) {
1083 if (hit_something &&
op->speed >= 10.0)
1103 if (!
op->stats.maxhp) {
1108 if (
op->stats.hp < 0) {
1116 assert(
op->stats.maxhp > 0);
1177 int doesnt_slay = 1;
1182 LOG(
llevError,
"hit_with_one_attacktype: Invalid attacknumber passed: %u\n", attacknum);
1187 LOG(
llevError,
"hit_with_one_attacktype called with negative damage: %d\n", dam);
1198 if ((
op->race != NULL && strstr(
op->race,
hitter->slaying))
1219 dam *= (100-
op->resist[attacknum]);
1231 if (
op->resist[attacknum] >= 100
1238 switch (attacknum) {
1312 if (
tmp->magic < -4)
1330 "The %s's acid corrodes your %s!",
1331 name_hitter, name_op);
1361 if (
op->stats.exp <= rate) {
1383 int64_t orig_exp =
op->stats.exp;
1387 if (owner && owner !=
hitter) {
1393 hitter->chosen_skill ?
hitter->chosen_skill->skill : NULL, 0);
1437 LOG(
llevError,
"%s was hit by %s with non-specific chaos.\n", name_op, name_hitter);
1488 if (dam >
op->stats.hp+1)
1489 dam =
op->stats.hp+1;
1490 new_hp =
hitter->stats.hp+dam;
1491 if (new_hp >
hitter->stats.maxhp)
1492 new_hp =
hitter->stats.maxhp;
1493 if (new_hp >
hitter->stats.hp)
1494 hitter->stats.hp = new_hp;
1501 hitter->stats.food += dam;
1513 #ifdef PARTY_KILL_LOG
1514 void party_add_kill(
partylist *party,
const char *
killer,
const char *dead,
long exp);
1550 object *owner = NULL;
1551 const object *skop = NULL;
1553 if (
op->stats.hp >= 0)
1566 maxdam = dam+
op->stats.hp+1;
1574 op->speed_left = -0.05;
1592 "Your pet, the %s, is killed by %s.",
1628 if (
op->type ==
PLAYER && !battleg) {
1629 time_t
t = time(NULL);
1634 tmv = localtime(&
t);
1635 strftime(
buf,
sizeof(
buf),
"%a %b %d %H:%M:%S %Y", tmv);
1645 if (owner->
level <
op->level*2 ||
op->stats.exp > 1000) {
1652 "You killed %s with %s.",
1675 if (pk == 1 && !battleg)
1691 LOG(
llevError,
"kill_object - unable to find skill that killed monster\n");
1696 if ((!skop || skop->
type !=
SKILL) && skill) {
1707 const char *owner_prefix;
1708 const char *op_prefix;
1710 owner_prefix = !battleg && pk && owner->
contr != NULL && !owner->
contr->
peaceful ?
"hostile " :
"";
1711 op_prefix = !battleg && pk &&
op->contr != NULL && !
op->contr->peaceful ?
"hostile " :
"";
1715 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)" :
""));
1717 const char *hitter_prefix;
1718 const char *op_prefix;
1720 hitter_prefix = !battleg && pk &&
hitter->contr != NULL && !
hitter->contr->peaceful ?
"hostile " :
"";
1721 op_prefix = !battleg && pk &&
op->contr != NULL && !
op->contr->peaceful ?
"hostile " :
"";
1723 snprintf(kill_message,
sizeof(kill_message),
"%s%s killed %s%s%s%s.", hitter_prefix,
hitter->name, op_prefix,
op->name,
1725 " in hand to hand combat" :
"", battleg ?
" (duel)" : (pk ?
" (pk)" :
""));
1729 skop =
hitter->chosen_skill;
1731 skill = skop->
skill;
1748 "Your foe has fallen!\nVICTORY!!!");
1771 #ifdef PARTY_KILL_LOG
1827 if (owner != NULL) {
1838 return friendlyfire;
1866 int maxattacktype, attacknum;
1867 int body_attack =
op->head != NULL;
1869 tag_t op_tag, hitter_tag;
1889 hitter_tag =
hitter->count;
1908 if (!simple_attack &&
op->type ==
DOOR) {
1925 LOG(
llevDebug,
"victim (arch %s, name %s) already dead in hit_player()\n",
op->arch->name,
op->name);
1940 dam = (dam > (
rndm(0, 99))) ? 1 : 0;
1960 && !(
op->name && strstr(
hitter->slaying,
op->name))))
1963 && god->race != NULL
1968 maxattacktype =
type;
1969 for (attacknum = 0; attacknum <
NROFATTACKS; attacknum++) {
1972 attacktype = 1<<attacknum;
1986 if (
type&attacktype) {
1991 if (ndam >= maxdam) {
1993 maxattacktype = 1<<attacknum;
1997 if (attacktype ==
AT_DEATH && ndam > 0)
2015 if (friendlyfire && maxdam) {
2026 unsigned int area = 0;
2027 for (at =
op->arch; at != NULL; at = at->
more)
2032 unsigned int remainder = 100*(maxdam%area)/area;
2034 if (
RANDOM()%100 < remainder)
2043 if (owner != NULL) {
2047 if (
op->enemy == NULL ||
rndm(1, 20) == 0)
2061 op->stats.hp -= maxdam;
2064 if (
op->stats.hp >= 0
2066 &&
op->stats.hp < (int16_t)((int32_t)
op->run_away *
op->stats.maxhp / 100)) {
2138 tmp->stats.dam = dam;
2142 if (!skill &&
hitter->chosen_skill)
2143 skill =
hitter->chosen_skill->name;
2145 if (skill && skill !=
tmp->skill) {
2151 tmp->stats.food += dam;
2155 tmp->stats.Con =
MAX(-(dam/4+1), -10);
2156 tmp->stats.Str =
MAX(-(dam/3+2), -10);
2157 tmp->stats.Dex =
MAX(-(dam/6+1), -10);
2158 tmp->stats.Int =
MAX(-dam/7, -10);
2163 "You suddenly feel very ill.");
2177 "Your %s poisons %s.",
2180 tmp->speed_left = 0;
2195 tmp->stats.exp = -speed_penalty;
2200 else if (
tmp->stats.exp > -speed_penalty) {
2201 tmp->stats.exp = -speed_penalty;
2202 tmp->stats.food -= 3;
2209 tmp->speed_left = 0;
2238 speed_penalty = speed_penalty * (100-
op->resist[
ATNR_SLOW]) / 100;
2240 if (speed_penalty < 1)
2242 else if (speed_penalty > 30)
2248 "The world suddenly moves very fast!");
2253 "The world moves even faster!");
2294 if (
tmp->duration > maxduration)
2295 tmp->duration = maxduration;
2299 "You suddenly feel very confused!");
2314 object *
tmp, *owner;
2341 "Your attack blinds %s!",
2344 tmp->stats.food += dam;
2345 if (
tmp->stats.food > 10)
2346 tmp->stats.food = 10;
2366 op->speed_left -=
FABS(
op->speed)*effect;
2378 "You limbs stop moving!");
2409 int atk_lev, def_lev, kill_lev, roll;
2413 || (
op->race && strstr(
op->race,
hitter->slaying))))
2425 def_lev =
op->level;
2427 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);
2443 kill_lev = roll - 48 + atk_lev;
2444 kill_lev = kill_lev * (100 -
op->resist[
ATNR_DEATH]) / 100;
2447 if (kill_lev > def_lev) {
2448 *dam =
op->stats.hp+10;
2453 *dam *= kill_lev/def_lev;
2513 object *attacker =
hitter;
2518 LOG(
llevError,
"BUG: adj_attackroll(): hitter and target not on same map\n");
2525 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 int attack_ob_simple(object *op, object *hitter, int base_dam, int base_wc)
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)
#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)
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