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;
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.");
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");
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;
1786 "Your foe has fallen!\nVICTORY!!!");
1809 #ifdef PARTY_KILL_LOG
1865 if (owner != NULL) {
1876 return friendlyfire;
1904 int maxattacktype, attacknum;
1905 int body_attack =
op->head != NULL;
1907 tag_t op_tag, hitter_tag;
1927 hitter_tag =
hitter->count;
1946 if (!simple_attack &&
op->type ==
DOOR) {
1963 LOG(
llevDebug,
"victim (arch %s, name %s) already dead in hit_player()\n",
op->arch->name,
op->name);
1978 dam = (dam > (
rndm(0, 99))) ? 1 : 0;
1998 && !(
op->name && strstr(
hitter->slaying,
op->name))))
2001 && god->race != NULL
2006 maxattacktype =
type;
2007 for (attacknum = 0; attacknum <
NROFATTACKS; attacknum++) {
2010 attacktype = 1<<attacknum;
2024 if (
type&attacktype) {
2029 if (ndam >= maxdam) {
2031 maxattacktype = 1<<attacknum;
2035 if (attacktype ==
AT_DEATH && ndam > 0)
2053 if (friendlyfire && maxdam) {
2064 unsigned int area = 0;
2065 for (at =
op->arch; at != NULL; at = at->
more)
2070 unsigned int remainder = 100*(maxdam%
area)/
area;
2072 if (
RANDOM()%100 < remainder)
2081 if (owner != NULL) {
2085 if (
op->enemy == NULL ||
rndm(1, 20) == 0)
2099 op->stats.hp -= maxdam;
2102 if (
op->stats.hp >= 0
2104 &&
op->stats.hp < (int16_t)((int32_t)
op->run_away *
op->stats.maxhp / 100)) {
2178 tmp->stats.dam = dam;
2191 tmp->stats.food += dam;
2195 tmp->stats.Con =
MAX(-(dam/4+1), -10);
2196 tmp->stats.Str =
MAX(-(dam/3+2), -10);
2197 tmp->stats.Dex =
MAX(-(dam/6+1), -10);
2198 tmp->stats.Int =
MAX(-dam/7, -10);
2203 "You suddenly feel very ill.");
2217 "Your %s poisons %s.",
2220 tmp->speed_left = 0;
2235 tmp->stats.exp = -speed_penalty;
2240 else if (
tmp->stats.exp > -speed_penalty) {
2241 tmp->stats.exp = -speed_penalty;
2242 tmp->stats.food -= 3;
2249 tmp->speed_left = 0;
2278 speed_penalty = speed_penalty * (100-
op->resist[
ATNR_SLOW]) / 100;
2280 if (speed_penalty < 1)
2282 else if (speed_penalty > 30)
2288 "The world suddenly moves very fast!");
2293 "The world moves even faster!");
2334 if (
tmp->duration > maxduration)
2335 tmp->duration = maxduration;
2339 "You suddenly feel very confused!");
2354 object *
tmp, *owner;
2381 "Your attack blinds %s!",
2384 tmp->stats.food += dam;
2385 if (
tmp->stats.food > 10)
2386 tmp->stats.food = 10;
2406 op->speed_left -=
FABS(
op->speed)*effect;
2418 "You limbs stop moving!");
2449 int atk_lev, def_lev, kill_lev, roll;
2453 || (
op->race && strstr(
op->race,
hitter->slaying))))
2465 def_lev =
op->level;
2467 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);
2483 kill_lev = roll - 48 + atk_lev;
2484 kill_lev = kill_lev * (100 -
op->resist[
ATNR_DEATH]) / 100;
2487 if (kill_lev > def_lev) {
2488 *dam =
op->stats.hp+10;
2493 *dam *= kill_lev/def_lev;
2553 object *attacker =
hitter;
2558 LOG(
llevError,
"BUG: adj_attackroll(): hitter and target not on same map\n");
2565 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)
Python Guilds Quick outline Add a guild(mapmakers) this is still a problem *after dropping the token to gain access to the stove area
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)
materialtype_t * name_to_material(const char *name)
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)
non standard information is not specified or uptime this means how long since the executable has been started A particular host may have been running a server for quite a long time
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 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)
std::vector< materialtype_t * > materials
int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
object * object_insert_in_ob(object *op, object *where)
const object * find_god(const char *name)
Plugin animator file specs[Config] name
int attack_ob(object *op, object *hitter)
static int hit_with_one_attacktype(object *op, object *hitter, int dam, uint32_t attacknum)
void blind_living(object *op, object *hitter, int dam)
#define MSG_TYPE_ATTACK_DID_KILL
static event_registration m
uint16_t set_friendly_fire
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)
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)
#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_)
TIPS on SURVIVING Crossfire is populated with a wealth of different monsters These monsters can have varying immunities and attack types In some of them can be quite a bit smarter than others It will be important for new players to learn the abilities of different monsters and learn just how much it will take to kill them This section discusses how monsters can interact with players Most monsters in the game are out to mindlessly kill and destroy the players These monsters will help boost a player s after he kills them When fighting a large amount of monsters in a single attempt to find a narrower hallway so that you are not being attacked from all sides Charging into a room full of Beholders for instance would not be open the door and fight them one at a time For there are several maps designed for them Find these areas and clear them out All throughout these a player can find signs and books which they can read by stepping onto them and hitting A to apply the book sign These messages will help the player to learn the system One more always keep an eye on your food If your food drops to your character will soon so BE CAREFUL ! NPCs Non Player Character are special monsters which have intelligence Players may be able to interact with these monsters to help solve puzzles and find items of interest To speak with a monster you suspect to be a simply move to an adjacent square to them and push the double ie Enter your and press< Return > You can also use say if you feel like typing a little extra Other NPCs may not speak to but display intelligence with their movement Some monsters can be and may attack the nearest of your enemies Others can be in that they follow you around and help you in your quest to kill enemies and find treasure SPECIAL ITEMS There are many special items which can be found in of these the most important may be the signs all a player must do is apply the handle In the case of the player must move items over the button to hold it down Some of the larger buttons may need very large items to be moved onto before they can be activated Gates and locked but be for you could fall down into a pit full of ghosts or dragons and not be able to get back out Break away sometimes it may be worth a player s time to test the walls of a map for secret doors Fire such as missile weapons and spells you will notice them going up in smoke ! So be careful not to destroy valuable items Spellbooks sometimes a player can learn the other times they cannot There are many different types of books and scrolls out there Improve item have lower weight
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)
void set_materialname(object *op)
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)
int random_roll(int min, int max, const object *op, int goodbad)
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)
int pk_max_experience_percent
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)
int rndm(int min, int max)
int64_t pk_max_experience
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