3 * Summary: Player related functions.
4 * Written by: Linley Henzell
36 #include "godconduct.h"
37 #include "godpassive.h"
48 #include "map_knowledge.h"
58 #include "player-stats.h"
67 #include "spl-other.h"
68 #include "spl-selfench.h"
69 #include "spl-transloc.h"
76 #include "tagstring.h"
81 #include "transform.h"
88 static void _moveto_maybe_repel_stairs()
90 const dungeon_feature_type new_grid
= env
.grid(you
.pos());
91 const command_type stair_dir
= feat_stair_direction(new_grid
);
93 if (stair_dir
== CMD_NO_CMD
94 || new_grid
== DNGN_ENTER_SHOP
95 || !you
.duration
[DUR_REPEL_STAIRS_MOVE
])
100 int pct
= you
.duration
[DUR_REPEL_STAIRS_CLIMB
] ? 29 : 50;
102 // When the effect is still strong, the chance to actually catch
103 // a stair is smaller. (Assuming the duration starts out at 1000.)
104 const int dur
= std::max(0, you
.duration
[DUR_REPEL_STAIRS_MOVE
] - 700);
107 if (x_chance_in_y(pct
, 100))
109 if (slide_feature_over(you
.pos(), coord_def(-1, -1), false))
111 std::string stair_str
=
112 feature_description(new_grid
, NUM_TRAPS
, "",
113 DESC_CAP_THE
, false);
114 std::string prep
= feat_preposition(new_grid
, true, &you
);
116 mprf("%s slides away as you move %s it!", stair_str
.c_str(),
119 if (player_in_a_dangerous_place() && one_chance_in(5))
120 xom_is_stimulated(32);
125 static bool _check_moveto_cloud(const coord_def
& p
,
126 const std::string
&move_verb
)
128 const int cloud
= env
.cgrid(p
);
129 if (cloud
!= EMPTY_CLOUD
&& !you
.confused())
131 const cloud_type ctype
= env
.cloud
[ cloud
].type
;
132 // Don't prompt if already in a cloud of the same type.
133 if (is_damaging_cloud(ctype
, true)
134 && (env
.cgrid(you
.pos()) == EMPTY_CLOUD
135 || ctype
!= env
.cloud
[ env
.cgrid(you
.pos()) ].type
))
137 std::string prompt
= make_stringf(
138 "Really %s into that cloud of %s?",
140 cloud_name_at_index(cloud
).c_str());
142 if (!yesno(prompt
.c_str(), false, 'n'))
152 static bool _check_moveto_trap(const coord_def
& p
, const std::string
&move_verb
)
154 // If we're walking along, give a chance to avoid traps.
155 const dungeon_feature_type new_grid
= env
.grid(p
);
156 if (new_grid
== DNGN_UNDISCOVERED_TRAP
)
159 (4 + you
.traps_skill()
160 + player_mutation_level(MUT_ACUTE_VISION
)
161 - 2 * player_mutation_level(MUT_BLURRY_VISION
));
163 if (random2(skill
) > 6)
165 if (trap_def
* ptrap
= find_trap(p
))
171 "Wait a moment, %s! Do you really want to %s there?",
172 you
.your_name
.c_str(),
175 if (!you
.running
.is_any_travel())
178 practise(EX_TRAP_PASSIVE
);
183 else if (new_grid
== DNGN_TRAP_MAGICAL
185 || new_grid
== DNGN_TRAP_MECHANICAL
186 && Options
.trap_prompt
188 || new_grid
== DNGN_TRAP_NATURAL
)
190 const trap_type type
= get_trap_type(p
);
191 if (type
== TRAP_ZOT
)
193 std::string prompt
= make_stringf(
194 "Do you really want to %s into the Zot trap",
197 if (!yes_or_no(prompt
.c_str()))
203 else if (new_grid
!= DNGN_TRAP_MAGICAL
&&
204 (you
.airborne() || you
.can_cling_to(p
)))
206 // No prompt (shaft and mechanical traps
207 // ineffective, if flying)
209 else if (type
== TRAP_TELEPORT
210 && (player_equip(EQ_AMULET
, AMU_STASIS
, true)
211 || scan_artefacts(ARTP_PREVENT_TELEPORTATION
,
214 // No prompt (teleport traps are ineffective if
215 // wearing an amulet of stasis)
219 // Prompt for any trap where you might not have enough hp
220 // as defined in init.txt (see trapwalk.lua)
221 if (type
!= TRAP_SHAFT
// Known shafts aren't traps
222 && type
!= TRAP_GOLUBRIA
// don't need a warning here
223 && (new_grid
!= DNGN_TRAP_MECHANICAL
224 || !clua
.callbooleanfn(false, "ch_cross_trap",
225 "s", trap_name_at(p
)))
226 && !crawl_state
.game_is_zotdef())
229 std::string prompt
= make_stringf(
230 "Really %s %s that %s?",
232 (type
== TRAP_ALARM
|| type
== TRAP_PLATE
) ? "onto" : "into",
233 feature_description(new_grid
, type
,
237 if (!yesno(prompt
.c_str(), true, 'n'))
247 static bool _check_moveto_dangerous(const coord_def
& p
,
248 const std::string move_verb
)
250 if (you
.can_swim() && feat_is_water(env
.grid(p
))
251 || you
.can_cling_to(p
)
252 || !is_feat_dangerous(env
.grid(p
)))
256 else if (you
.species
== SP_MERFOLK
&& feat_is_water(env
.grid(p
)))
257 mpr("You cannot swim in your current form.");
259 canned_msg(MSG_UNTHINKING_ACT
);
263 static bool _check_moveto_terrain(const coord_def
& p
,
264 const std::string
&move_verb
)
266 // Only consider terrain if player is not levitating.
267 if (you
.airborne() || you
.can_cling_to(p
))
270 return (_check_moveto_dangerous(p
, move_verb
));
273 bool check_moveto(const coord_def
& p
, const std::string
&move_verb
)
275 return (_check_moveto_terrain(p
, move_verb
)
276 && _check_moveto_cloud(p
, move_verb
)
277 && _check_moveto_trap(p
, move_verb
));
280 void moveto_location_effects(dungeon_feature_type old_feat
,
281 bool stepped
, bool allow_shift
,
282 const coord_def
& old_pos
)
284 const dungeon_feature_type new_grid
= env
.grid(you
.pos());
287 if (is_feat_dangerous(new_grid
) && !you
.can_cling_to(you
.pos()))
289 // Lava and dangerous deep water (ie not merfolk).
290 const coord_def
& entry
= (stepped
) ? old_pos
: you
.pos();
292 // If true, we were shifted and so we're done.
293 if (fall_into_a_pool(entry
, allow_shift
, new_grid
))
297 if (you
.ground_level())
299 if (you
.species
== SP_MERFOLK
)
301 if (feat_is_water(new_grid
) // We're entering water
302 // We're not transformed, or with a form compatible with tail
303 && (you
.form
== TRAN_NONE
304 || you
.form
== TRAN_BLADE_HANDS
))
306 merfolk_start_swimming(stepped
);
308 else if (!feat_is_water(new_grid
) && !is_feat_dangerous(new_grid
))
309 merfolk_stop_swimming();
312 if (feat_is_water(new_grid
) && !stepped
)
315 noisy(4, you
.pos(), "Floosh!");
316 else if (!beogh_water_walk())
317 noisy(8, you
.pos(), "Splash!");
320 if (feat_is_water(new_grid
) && !you
.can_swim() && !beogh_water_walk())
322 you
.time_taken
*= 13 + random2(8);
323 you
.time_taken
/= 10;
325 if (!feat_is_water(old_feat
))
327 mprf("You %s the %s water.",
328 stepped
? "enter" : "fall into",
329 new_grid
== DNGN_SHALLOW_WATER
? "shallow" : "deep");
332 if (new_grid
== DNGN_DEEP_WATER
&& old_feat
!= DNGN_DEEP_WATER
)
333 mpr("You sink to the bottom.");
335 if (!feat_is_water(old_feat
))
337 mpr("Moving in this stuff is going to be slow.");
339 mpr("...and don't expect to remain undetected.");
344 // Icy shield goes down over lava.
345 if (new_grid
== DNGN_LAVA
)
346 expose_player_to_element(BEAM_LAVA
);
349 if (trap_def
* ptrap
= find_trap(you
.pos()))
350 ptrap
->trigger(you
, !stepped
); // blinking makes it hard to evade
353 _moveto_maybe_repel_stairs();
356 // Use this function whenever the player enters (or lands and thus re-enters)
359 // stepped - normal walking moves
360 // allow_shift - allowed to scramble in any direction out of lava/water
361 void move_player_to_grid(const coord_def
& p
, bool stepped
, bool allow_shift
)
363 ASSERT(!crawl_state
.game_is_arena());
364 ASSERT(in_bounds(p
));
366 // assuming that entering the same square means coming from above (levitate)
367 const coord_def old_pos
= you
.pos();
368 const bool from_above
= (old_pos
== p
);
369 const dungeon_feature_type old_grid
=
370 (from_above
) ? DNGN_FLOOR
: grd(old_pos
);
372 // Really must be clear.
373 ASSERT(you
.can_pass_through_feat(grd(p
)));
375 // Better not be an unsubmerged monster either.
376 ASSERT(!monster_at(p
) || monster_at(p
)->submerged()
377 || fedhas_passthrough(monster_at(p
)));
379 // Move the player to new location.
383 // Checking new squares for interesting features.
385 check_for_interesting_features();
387 you
.check_clinging();
388 moveto_location_effects(old_grid
, stepped
, allow_shift
, old_pos
);
391 bool is_feat_dangerous(dungeon_feature_type grid
, bool permanently
)
393 if (you
.permanent_flight() || you
.permanent_levitation()
394 || you
.airborne() && !permanently
)
398 else if (grid
== DNGN_DEEP_WATER
&& !player_likes_water(permanently
)
399 || grid
== DNGN_LAVA
)
407 bool player_in_mappable_area(void)
409 return (!testbits(env
.level_flags
, LFLAG_NOT_MAPPABLE
)
410 && !testbits(get_branch_flags(), BFLAG_NOT_MAPPABLE
));
413 bool player_in_branch(int branch
)
415 return (you
.level_type
== LEVEL_DUNGEON
&& you
.where_are_you
== branch
);
418 bool player_in_level_area(level_area_type area
)
420 return (you
.level_type
== area
);
423 bool player_in_hell(void)
425 return (you
.level_type
== LEVEL_DUNGEON
426 && is_hell_subbranch(you
.where_are_you
));
429 bool player_likes_water(bool permanently
)
431 return (!permanently
&& beogh_water_walk()
432 || (species_likes_water(you
.species
) || !permanently
)
433 && form_likes_water());
436 bool player_in_bat_form()
438 return (you
.form
== TRAN_BAT
);
441 bool player_can_open_doors()
443 // Bats and pigs can't open/close doors.
444 return (you
.form
!= TRAN_BAT
445 && you
.form
!= TRAN_PIG
);
448 bool player_under_penance(void)
450 if (you
.religion
!= GOD_NO_GOD
)
451 return (you
.penance
[you
.religion
]);
456 // TODO: get rid of this.
457 bool player_genus(genus_type which_genus
, species_type species
)
459 if (species
== SP_UNKNOWN
)
460 species
= you
.species
;
462 return (species_genus(species
) == which_genus
);
465 // If transform is true, compare with current transformation instead
466 // of (or in addition to) underlying species.
467 // (See mon-data.h for species/genus use.)
468 bool is_player_same_species(const int mon
, bool transform
)
476 return (mon
== MONS_MEGABAT
);
478 return (mon
== MONS_ICE_BEAST
);
479 // Compare with monster *species*.
481 return (mons_species(mon
) == MONS_LICH
);
482 // Compare with monster *genus*.
484 return (mons_genus(mon
) == MONS_SPIDER
);
486 return (mons_genus(mon
) == MONS_DRAGON
); // Includes all drakes.
488 return (mons_genus(mon
) == MONS_HOG
);
490 case TRAN_BLADE_HANDS
:
492 break; // Check real (non-transformed) form.
496 // Genus would include necrophage and rotting hulk.
497 if (you
.species
== SP_GHOUL
)
498 return (mons_species(mon
) == MONS_GHOUL
);
500 if (you
.species
== SP_MERFOLK
&& mons_genus(mon
) == MONS_MERMAID
)
503 // Note that these are currently considered to be the same species:
504 // * halflings and humans
505 // * dwarves and deep dwarves
507 return (mons_genus(mon
) == mons_genus(player_mons(false)));
510 void update_player_symbol()
512 you
.symbol
= Options
.show_player_species
? player_mons() : transform_mons();
515 monster_type
player_mons(bool transform
)
521 mons
= transform_mons();
522 if (mons
!= MONS_PLAYER
)
526 mons
= player_species_to_mons_species(you
.species
);
528 if (mons
== MONS_ORC
)
530 if (you
.religion
== GOD_BEOGH
)
531 mons
= (you
.piety
>= piety_breakpoint(4)) ? MONS_ORC_HIGH_PRIEST
534 else if (mons
== MONS_OGRE
)
536 const skill_type sk
= best_skill(SK_FIRST_SKILL
, SK_LAST_SKILL
);
537 if (sk
>= SK_SPELLCASTING
&& sk
< SK_INVOCATIONS
)
538 mons
= MONS_OGRE_MAGE
;
544 void update_vision_range()
546 you
.normal_vision
= LOS_RADIUS
;
547 you
.current_vision
= you
.normal_vision
;
549 // Nightstalker gives -1/-2/-3.
550 if (player_mutation_level(MUT_NIGHTSTALKER
))
551 you
.current_vision
-= player_mutation_level(MUT_NIGHTSTALKER
);
553 // Lantern of shadows.
554 if (you
.attribute
[ATTR_SHADOWS
])
555 you
.current_vision
-= 2;
557 set_los_radius(you
.current_vision
);
560 // Checks whether the player's current species can use
561 // use (usually wear) a given piece of equipment.
562 // Note that EQ_BODY_ARMOUR and EQ_HELMET only check
563 // the ill-fitting variant (i.e., not caps and robes).
564 // If special_armour is set to true, special cases
565 // such as bardings, light armour and caps are
566 // considered. Otherwise, these simply return false.
567 // ---------------------------------------------------
568 bool you_can_wear(int eq
, bool special_armour
)
570 if (you
.species
== SP_CAT
)
571 return (eq
== EQ_LEFT_RING
|| eq
== EQ_RIGHT_RING
|| eq
== EQ_AMULET
);
582 if (you
.species
== SP_TROLL
583 || you
.species
== SP_SPRIGGAN
584 || player_genus(GENPC_OGREISH
)
585 || player_genus(GENPC_DRACONIAN
))
589 if (player_mutation_level(MUT_CLAWS
) >= 3)
595 if (you
.species
== SP_NAGA
|| you
.species
== SP_CENTAUR
)
596 return (special_armour
);
597 if (player_mutation_level(MUT_HOOVES
) >= 3
598 || player_mutation_level(MUT_TALONS
) >= 3)
602 // These species cannot wear boots.
603 if (you
.species
== SP_TROLL
604 || you
.species
== SP_SPRIGGAN
605 || player_genus(GENPC_OGREISH
)
606 || player_genus(GENPC_DRACONIAN
))
614 // Anyone can wear robes or a buckler/shield.
617 if (you
.species
== SP_TROLL
618 || you
.species
== SP_SPRIGGAN
619 || player_genus(GENPC_OGREISH
)
620 || player_genus(GENPC_DRACONIAN
))
627 // Anyone can wear caps.
630 if (player_mutation_level(MUT_HORNS
)
631 || player_mutation_level(MUT_BEAK
)
632 || player_mutation_level(MUT_ANTENNAE
))
636 if (you
.species
== SP_TROLL
637 || you
.species
== SP_SPRIGGAN
638 || player_genus(GENPC_OGREISH
)
639 || player_genus(GENPC_DRACONIAN
))
650 bool player_has_feet()
652 if (you
.species
== SP_NAGA
|| you
.species
== SP_CAT
|| you
.fishtail
)
657 if (player_mutation_level(MUT_HOOVES
) >= 3
658 || player_mutation_level(MUT_TALONS
) >= 3)
666 bool player_wearing_slot(int eq
)
668 ASSERT(you
.equip
[eq
] != -1 || !you
.melded
[eq
]);
669 return (you
.equip
[eq
] != -1 && !you
.melded
[eq
]);
672 bool you_tran_can_wear(const item_def
&item
)
674 switch (item
.base_type
)
677 return you_tran_can_wear(EQ_WEAPON
);
680 return you_tran_can_wear(jewellery_is_amulet(item
) ? EQ_AMULET
683 if (item
.sub_type
== ARM_NAGA_BARDING
)
684 return (you
.species
== SP_NAGA
&& you_tran_can_wear(EQ_BOOTS
));
685 else if (item
.sub_type
== ARM_CENTAUR_BARDING
)
686 return (you
.species
== SP_CENTAUR
&& you_tran_can_wear(EQ_BOOTS
));
688 if (get_armour_slot(item
) == EQ_HELMET
689 && !is_hard_helmet(item
)
690 && (you
.form
== TRAN_SPIDER
691 || you
.form
== TRAN_ICE_BEAST
))
696 if (fit_armour_size(item
, you
.body_size()) != 0)
699 return you_tran_can_wear(get_armour_slot(item
), true);
706 bool you_tran_can_wear(int eq
, bool check_mutation
)
713 else if (eq
>= EQ_RINGS
&& eq
<= EQ_RINGS_PLUS2
)
716 // Everybody can wear at least some type of armour.
717 if (eq
== EQ_ALL_ARMOUR
)
720 // Not a transformation, but also temporary -> check first.
723 if (eq
== EQ_GLOVES
&& you
.has_claws(false) >= 3)
728 || player_mutation_level(MUT_HOOVES
) >= 3
729 || player_mutation_level(MUT_TALONS
) >= 3))
735 // No further restrictions.
736 if (you
.form
== TRAN_NONE
|| you
.form
== TRAN_LICH
)
739 // Bats and pigs cannot wear anything except amulets.
740 if ((you
.form
== TRAN_BAT
|| you
.form
== TRAN_PIG
) && eq
!= EQ_AMULET
)
743 // Everyone else can wear jewellery, at least.
744 if (eq
== EQ_LEFT_RING
|| eq
== EQ_RIGHT_RING
|| eq
== EQ_AMULET
)
747 // These cannot use anything but jewellery.
748 if (you
.form
== TRAN_SPIDER
|| you
.form
== TRAN_DRAGON
)
751 if (you
.form
== TRAN_BLADE_HANDS
)
753 if (eq
== EQ_WEAPON
|| eq
== EQ_GLOVES
|| eq
== EQ_SHIELD
)
758 if (you
.form
== TRAN_ICE_BEAST
)
765 if (you
.form
== TRAN_STATUE
)
767 if (eq
== EQ_WEAPON
|| eq
== EQ_CLOAK
|| eq
== EQ_HELMET
)
775 bool player_weapon_wielded()
777 const int wpn
= you
.equip
[EQ_WEAPON
];
782 if (you
.inv
[wpn
].base_type
!= OBJ_WEAPONS
783 && you
.inv
[wpn
].base_type
!= OBJ_STAVES
)
791 // Returns false if the player is wielding a weapon inappropriate for Berserk.
792 bool berserk_check_wielded_weapon()
797 const item_def weapon
= *you
.weapon();
798 if (weapon
.defined() && weapon
.base_type
!= OBJ_STAVES
799 && (weapon
.base_type
!= OBJ_WEAPONS
|| is_range_weapon(weapon
))
800 || you
.attribute
[ATTR_WEAPON_SWAP_INTERRUPTED
])
802 std::string prompt
= "Do you really want to go berserk while "
803 "wielding " + weapon
.name(DESC_NOCAP_YOUR
)
806 if (!yesno(prompt
.c_str(), true, 'n'))
812 you
.attribute
[ATTR_WEAPON_SWAP_INTERRUPTED
] = 0;
818 // Looks in equipment "slot" to see if there is an equipped "sub_type".
819 // Returns number of matches (in the case of rings, both are checked)
820 int player_equip(equipment_type slot
, int sub_type
, bool calc_unid
)
829 // Hands can have more than just weapons.
831 && you
.weapon()->base_type
== OBJ_WEAPONS
832 && you
.weapon()->sub_type
== sub_type
)
839 // Like above, but must be magical staff.
841 && you
.weapon()->base_type
== OBJ_STAVES
842 && you
.weapon()->sub_type
== sub_type
843 && (calc_unid
|| item_type_known(*you
.weapon())))
850 if ((item
= you
.slot_item(EQ_LEFT_RING
))
851 && item
->sub_type
== sub_type
853 || item_type_known(*item
)))
858 if ((item
= you
.slot_item(EQ_RIGHT_RING
))
859 && item
->sub_type
== sub_type
861 || item_type_known(*item
)))
868 if ((item
= you
.slot_item(EQ_LEFT_RING
))
869 && item
->sub_type
== sub_type
871 || item_type_known(*item
)))
876 if ((item
= you
.slot_item(EQ_RIGHT_RING
))
877 && item
->sub_type
== sub_type
879 || item_type_known(*item
)))
886 if ((item
= you
.slot_item(EQ_LEFT_RING
))
887 && item
->sub_type
== sub_type
889 || item_type_known(*item
)))
894 if ((item
= you
.slot_item(EQ_RIGHT_RING
))
895 && item
->sub_type
== sub_type
897 || item_type_known(*item
)))
904 // Doesn't make much sense here... be specific. -- bwr
905 die("EQ_ALL_ARMOUR is not a proper slot");
909 if (! (slot
> EQ_NONE
&& slot
< NUM_EQUIP
))
911 if ((item
= you
.slot_item(slot
))
912 && item
->sub_type
== sub_type
913 && (calc_unid
|| item_type_known(*item
)))
923 // Looks in equipment "slot" to see if equipped item has "special" ego-type
924 // Returns number of matches (jewellery returns zero -- no ego type).
925 // [ds] There's no equivalent of calc_unid or req_id because as of now, weapons
926 // and armour type-id on wield/wear.
927 int player_equip_ego_type(int slot
, int special
, bool calc_unid
)
930 bool melded
= (special
== SPARM_PONDEROUSNESS
);
936 // Hands can have more than just weapons.
937 if ((item
= you
.slot_item(EQ_WEAPON
))
938 && item
->base_type
== OBJ_WEAPONS
939 && get_weapon_brand(*item
) == special
)
952 // no ego types for these slots
956 // Check all armour slots:
957 for (int i
= EQ_MIN_ARMOUR
; i
<= EQ_MAX_ARMOUR
; i
++)
959 if ((item
= you
.slot_item(static_cast<equipment_type
>(i
), melded
))
960 && get_armour_ego_type(*item
) == special
961 && (calc_unid
|| item_type_known(*item
)))
969 if (slot
< EQ_MIN_ARMOUR
|| slot
> EQ_MAX_ARMOUR
)
970 die("invalid slot: %d", slot
);
971 // Check a specific armour slot for an ego type:
972 if ((item
= you
.slot_item(static_cast<equipment_type
>(slot
), melded
))
973 && get_armour_ego_type(*item
) == special
974 && (calc_unid
|| item_type_known(*item
)))
984 // Return's true if the indicated unrandart is equipped
985 // [ds] There's no equivalent of calc_unid or req_id because as of now, weapons
986 // and armour type-id on wield/wear.
987 bool player_equip_unrand(int unrand_index
)
989 unrandart_entry
* entry
= get_unrand_entry(unrand_index
);
990 equipment_type slot
= get_item_slot(entry
->base_type
,
998 // Hands can have more than just weapons.
999 if ((item
= you
.slot_item(slot
))
1000 && item
->base_type
== OBJ_WEAPONS
1001 && is_unrandom_artefact(*item
)
1002 && item
->special
== unrand_index
)
1009 if ((item
= you
.slot_item(EQ_LEFT_RING
))
1010 && is_unrandom_artefact(*item
)
1011 && item
->special
== unrand_index
)
1016 if ((item
= you
.slot_item(EQ_RIGHT_RING
))
1017 && is_unrandom_artefact(*item
)
1018 && item
->special
== unrand_index
)
1029 case EQ_RINGS_PLUS2
:
1031 // no unrandarts for these slots.
1035 if (slot
<= EQ_NONE
|| slot
>= NUM_EQUIP
)
1036 die("invalid slot: %d", slot
);
1037 // Check a specific slot.
1038 if ((item
= you
.slot_item(slot
))
1039 && is_unrandom_artefact(*item
)
1040 && item
->special
== unrand_index
)
1050 int player_evokable_levitation()
1052 return player_equip(EQ_RINGS
, RING_LEVITATION
)
1053 + player_equip_ego_type(EQ_BOOTS
, SPARM_LEVITATION
)
1054 + scan_artefacts(ARTP_LEVITATE
);
1057 int player_evokable_invis()
1059 return (player_equip(EQ_RINGS
, RING_INVISIBILITY
)
1060 + player_equip_ego_type(EQ_ALL_ARMOUR
, SPARM_DARKNESS
)
1061 + scan_artefacts(ARTP_INVISIBLE
));
1064 // Given an adjacent monster, returns true if the player can hit it (the
1065 // monster should not be submerged, or be submerged in shallow water if
1066 // the player has a polearm).
1067 bool player_can_hit_monster(const monster
* mon
)
1069 if (!mon
->submerged())
1072 if (grd(mon
->pos()) != DNGN_SHALLOW_WATER
)
1075 const item_def
*weapon
= you
.weapon();
1076 return (weapon
&& weapon_skill(*weapon
) == SK_POLEARMS
);
1079 int player_teleport(bool calc_unid
)
1081 ASSERT(!crawl_state
.game_is_arena());
1083 // Don't allow any form of teleportation in Sprint.
1084 if (crawl_state
.game_is_sprint())
1090 tp
+= 8 * player_equip(EQ_RINGS
, RING_TELEPORTATION
, calc_unid
);
1093 tp
+= player_mutation_level(MUT_TELEPORT
) * 3;
1095 // randart weapons only
1097 && you
.weapon()->base_type
== OBJ_WEAPONS
1098 && is_artefact(*you
.weapon()))
1100 tp
+= scan_artefacts(ARTP_CAUSE_TELEPORTATION
, calc_unid
);
1108 int rr
= you
.hp_max
/ 3;
1111 rr
= 20 + ((rr
- 20) / 2);
1114 rr
+= 40 * player_equip(EQ_RINGS
, RING_REGENERATION
);
1117 if (you
.duration
[DUR_REGENERATION
]
1118 && !you
.attribute
[ATTR_DIVINE_REGENERATION
])
1123 // Troll leather (except for trolls).
1124 if (player_equip(EQ_BODY_ARMOUR
, ARM_TROLL_LEATHER_ARMOUR
)
1125 && you
.species
!= SP_TROLL
)
1130 // Fast heal mutation.
1131 rr
+= player_mutation_level(MUT_REGENERATION
) * 20;
1133 // Before applying other effects, make sure that there's something
1135 rr
= std::max(1, rr
);
1137 // Healing depending on satiation.
1138 // The better-fed you are, the faster you heal.
1139 if (you
.species
== SP_VAMPIRE
)
1141 if (you
.hunger_state
== HS_STARVING
)
1142 // No regeneration for starving vampires.
1144 else if (you
.hunger_state
== HS_ENGORGED
)
1145 // More bonus regeneration for engorged vampires.
1147 else if (you
.hunger_state
< HS_SATIATED
)
1148 // Halved regeneration for hungry vampires.
1150 else if (you
.hunger_state
>= HS_FULL
)
1151 // Bonus regeneration for full vampires.
1155 // Powered By Death mutation, boosts regen by 10 per corpse in
1156 // a mutation_level * 3 (3/6/9) radius, to a maximum of 7
1157 // corpses. If and only if the duration of the effect is
1159 if (you
.duration
[DUR_POWERED_BY_DEATH
])
1160 rr
+= handle_pbd_corpses(false) * 100;
1162 // Slow heal mutation. Each level reduces your natural healing by
1164 if (player_mutation_level(MUT_SLOW_HEALING
) > 0)
1166 rr
*= 3 - player_mutation_level(MUT_SLOW_HEALING
);
1170 if (you
.stat_zero
[STAT_STR
])
1173 // Trog's Hand. This circumvents the slow healing effect.
1174 if (you
.attribute
[ATTR_DIVINE_REGENERATION
])
1180 int player_hunger_rate(void)
1184 if (player_in_bat_form())
1187 if (you
.species
== SP_TROLL
)
1188 hunger
+= 3; // in addition to the +3 for fast metabolism
1190 if (you
.duration
[DUR_REGENERATION
] && you
.hp
< you
.hp_max
)
1193 // If Cheibriados has slowed your life processes, you will hunger less.
1194 if (you
.religion
== GOD_CHEIBRIADOS
&& you
.piety
>= piety_breakpoint(0))
1197 // Moved here from main.cc... maintaining the >= 40 behaviour.
1198 if (you
.hunger
>= 40)
1200 if (you
.duration
[DUR_INVIS
])
1203 // Berserk has its own food penalty - excluding berserk haste.
1204 // Doubling the hunger cost for haste so that the per turn hunger
1205 // is consistent now that a hasted turn causes 50% the normal hunger
1207 if (you
.duration
[DUR_HASTE
])
1208 hunger
+= haste_mul(5);
1211 if (you
.species
== SP_VAMPIRE
)
1213 switch (you
.hunger_state
)
1216 case HS_NEAR_STARVING
:
1219 case HS_VERY_HUNGRY
:
1239 hunger
+= player_mutation_level(MUT_FAST_METABOLISM
);
1241 if (player_mutation_level(MUT_SLOW_METABOLISM
) > 2)
1243 else if (player_mutation_level(MUT_SLOW_METABOLISM
) > 0)
1248 if (you
.hp
< you
.hp_max
1249 && player_mutation_level(MUT_SLOW_HEALING
) < 3)
1251 hunger
+= 3 * player_equip(EQ_RINGS
, RING_REGENERATION
);
1254 hunger
+= 4 * player_equip(EQ_RINGS
, RING_HUNGER
);
1255 hunger
-= 2 * player_equip(EQ_RINGS
, RING_SUSTENANCE
);
1257 // troll leather armour
1258 if (you
.species
!= SP_TROLL
&& you
.hp
< you
.hp_max
)
1260 if (player_equip(EQ_BODY_ARMOUR
, ARM_TROLL_LEATHER_ARMOUR
))
1261 hunger
+= coinflip() ? 2 : 1;
1265 hunger
+= scan_artefacts(ARTP_METABOLISM
);
1268 hunger
+= you
.burden_state
;
1276 int player_spell_levels(void)
1278 int sl
= (you
.experience_level
- 1) + (you
.skills
[SK_SPELLCASTING
] * 2);
1280 bool fireball
= false;
1281 bool delayed_fireball
= false;
1286 for (int i
= 0; i
< MAX_KNOWN_SPELLS
; i
++)
1288 if (you
.spells
[i
] == SPELL_FIREBALL
)
1290 else if (you
.spells
[i
] == SPELL_DELAYED_FIREBALL
)
1291 delayed_fireball
= true;
1293 if (you
.spells
[i
] != SPELL_NO_SPELL
)
1294 sl
-= spell_difficulty(you
.spells
[i
]);
1297 // Fireball is free for characters with delayed fireball
1298 if (fireball
&& delayed_fireball
)
1299 sl
+= spell_difficulty(SPELL_FIREBALL
);
1301 // Note: This can happen because of level drain. Maybe we should
1302 // force random spells out when that happens. -- bwr
1309 bool player_likes_chunks(bool permanently
)
1311 return (player_mutation_level(MUT_GOURMAND
) > 0
1312 || player_mutation_level(MUT_CARNIVOROUS
) > 0
1313 || (!permanently
&& wearing_amulet(AMU_THE_GOURMAND
)));
1316 // If temp is set to false, temporary sources or resistance won't be counted.
1317 int player_res_fire(bool calc_unid
, bool temp
, bool items
)
1323 // rings of fire resistance/fire
1324 rf
+= player_equip(EQ_RINGS
, RING_PROTECTION_FROM_FIRE
, calc_unid
);
1325 rf
+= player_equip(EQ_RINGS
, RING_FIRE
, calc_unid
);
1328 rf
-= player_equip(EQ_RINGS
, RING_ICE
, calc_unid
);
1331 rf
+= player_equip(EQ_STAFF
, STAFF_FIRE
, calc_unid
);
1334 rf
+= 2 * player_equip(EQ_BODY_ARMOUR
, ARM_DRAGON_ARMOUR
);
1335 rf
+= player_equip(EQ_BODY_ARMOUR
, ARM_GOLD_DRAGON_ARMOUR
);
1336 rf
-= player_equip(EQ_BODY_ARMOUR
, ARM_ICE_DRAGON_ARMOUR
);
1337 rf
+= 2 * player_equip(EQ_BODY_ARMOUR
, ARM_DRAGON_HIDE
);
1338 rf
+= player_equip(EQ_BODY_ARMOUR
, ARM_GOLD_DRAGON_HIDE
);
1339 rf
-= player_equip(EQ_BODY_ARMOUR
, ARM_ICE_DRAGON_HIDE
);
1342 rf
+= player_equip_ego_type(EQ_ALL_ARMOUR
, SPARM_FIRE_RESISTANCE
);
1343 rf
+= player_equip_ego_type(EQ_ALL_ARMOUR
, SPARM_RESISTANCE
);
1346 rf
+= scan_artefacts(ARTP_FIRE
, calc_unid
);
1349 rf
+= che_boost(CB_RFIRE
);
1353 if (you
.species
== SP_MUMMY
)
1357 rf
+= player_mutation_level(MUT_HEAT_RESISTANCE
);
1358 rf
+= player_mutation_level(MUT_MOLTEN_SCALES
) == 3 ? 1 : 0;
1363 if (you
.duration
[DUR_RESIST_FIRE
] > 0)
1366 if (you
.duration
[DUR_FIRE_SHIELD
])
1372 case TRAN_ICE_BEAST
:
1377 monster_type drag
= dragon_form_dragon_type();
1378 if (drag
== MONS_DRAGON
)
1380 else if (drag
== MONS_ICE_DRAGON
)
1397 int player_res_steam(bool calc_unid
, bool temp
, bool items
)
1401 if (you
.species
== SP_PALE_DRACONIAN
)
1404 if (items
&& player_equip(EQ_BODY_ARMOUR
, ARM_STEAM_DRAGON_ARMOUR
))
1407 if (items
&& player_equip(EQ_BODY_ARMOUR
, ARM_STEAM_DRAGON_HIDE
))
1410 return (res
+ player_res_fire(calc_unid
, temp
, items
) / 2);
1413 int player_res_cold(bool calc_unid
, bool temp
, bool items
)
1420 if (you
.duration
[DUR_RESIST_COLD
] > 0)
1423 if (you
.duration
[DUR_FIRE_SHIELD
])
1429 case TRAN_ICE_BEAST
:
1434 monster_type form
= dragon_form_dragon_type();
1435 if (form
== MONS_DRAGON
)
1437 else if (form
== MONS_ICE_DRAGON
)
1448 if (you
.species
== SP_VAMPIRE
)
1450 if (you
.hunger_state
<= HS_NEAR_STARVING
)
1452 else if (you
.hunger_state
< HS_SATIATED
)
1459 // rings of cold resistance/ice
1460 rc
+= player_equip(EQ_RINGS
, RING_PROTECTION_FROM_COLD
, calc_unid
);
1461 rc
+= player_equip(EQ_RINGS
, RING_ICE
, calc_unid
);
1464 rc
-= player_equip(EQ_RINGS
, RING_FIRE
, calc_unid
);
1467 rc
+= player_equip(EQ_STAFF
, STAFF_COLD
, calc_unid
);
1470 rc
+= 2 * player_equip(EQ_BODY_ARMOUR
, ARM_ICE_DRAGON_ARMOUR
);
1471 rc
+= player_equip(EQ_BODY_ARMOUR
, ARM_GOLD_DRAGON_ARMOUR
);
1472 rc
-= player_equip(EQ_BODY_ARMOUR
, ARM_DRAGON_ARMOUR
);
1473 rc
+= 2 * player_equip(EQ_BODY_ARMOUR
, ARM_ICE_DRAGON_HIDE
);
1474 rc
+= player_equip(EQ_BODY_ARMOUR
, ARM_GOLD_DRAGON_HIDE
);
1475 rc
-= player_equip(EQ_BODY_ARMOUR
, ARM_DRAGON_HIDE
);
1478 rc
+= player_equip_ego_type(EQ_ALL_ARMOUR
, SPARM_COLD_RESISTANCE
);
1479 rc
+= player_equip_ego_type(EQ_ALL_ARMOUR
, SPARM_RESISTANCE
);
1482 rc
+= scan_artefacts(ARTP_COLD
, calc_unid
);
1485 rc
+= che_boost(CB_RCOLD
);
1489 rc
+= player_mutation_level(MUT_COLD_RESISTANCE
);
1490 rc
+= player_mutation_level(MUT_ICY_BLUE_SCALES
) == 3 ? 1 : 0;
1491 rc
+= player_mutation_level(MUT_SHAGGY_FUR
) == 3 ? 1 : 0;
1501 int player_res_corr(bool calc_unid
, bool items
)
1503 if (items
&& wearing_amulet(AMU_RESIST_CORROSION
, calc_unid
))
1509 int player_res_acid(bool calc_unid
, bool items
)
1512 if (!form_changed_physiology()
1513 || you
.form
== TRAN_DRAGON
)
1515 if (you
.species
== SP_YELLOW_DRACONIAN
)
1521 if (wearing_amulet(AMU_RESIST_CORROSION
, calc_unid
, true))
1524 if (player_equip_ego_type(EQ_ALL_ARMOUR
, SPARM_PRESERVATION
))
1529 res
+= std::max(0, player_mutation_level(MUT_YELLOW_SCALES
) - 1);
1537 // Returns a factor X such that post-resistance acid damage can be calculated
1538 // as pre_resist_damage * X / 100.
1539 int player_acid_resist_factor()
1541 int res
= player_res_acid();
1552 while (res
-- > 2 && factor
>= 20)
1553 factor
= factor
* 90 / 100;
1559 int player_res_electricity(bool calc_unid
, bool temp
, bool items
)
1565 if (you
.duration
[DUR_INSULATION
])
1569 if (you
.form
== TRAN_STATUE
)
1572 if (you
.attribute
[ATTR_DIVINE_LIGHTNING_PROTECTION
])
1581 re
+= player_equip(EQ_STAFF
, STAFF_AIR
, calc_unid
);
1584 re
+= player_equip(EQ_BODY_ARMOUR
, ARM_STORM_DRAGON_ARMOUR
);
1585 re
+= player_equip(EQ_BODY_ARMOUR
, ARM_STORM_DRAGON_HIDE
);
1588 re
+= scan_artefacts(ARTP_ELECTRICITY
, calc_unid
);
1592 re
+= player_mutation_level(MUT_THIN_METALLIC_SCALES
) == 3 ? 1 : 0;
1593 re
+= player_mutation_level(MUT_SHOCK_RESISTANCE
);
1598 bool player_control_teleport(bool calc_unid
, bool temp
, bool items
)
1600 return ((temp
&& you
.duration
[DUR_CONTROL_TELEPORT
])
1602 && player_equip(EQ_RINGS
, RING_TELEPORT_CONTROL
, calc_unid
))
1603 || player_mutation_level(MUT_TELEPORT_CONTROL
));
1606 int player_res_torment(bool, bool temp
)
1608 return (player_mutation_level(MUT_TORMENT_RESISTANCE
)
1609 || you
.form
== TRAN_LICH
1610 || you
.species
== SP_VAMPIRE
&& you
.hunger_state
== HS_STARVING
1612 (20 * player_mutation_level(MUT_STOCHASTIC_TORMENT_RESISTANCE
)
1616 // Funny that no races are susceptible to poisons. {dlb}
1617 // If temp is set to false, temporary sources or resistance won't be counted.
1618 int player_res_poison(bool calc_unid
, bool temp
, bool items
)
1624 // rings of poison resistance
1625 rp
+= player_equip(EQ_RINGS
, RING_POISON_RESISTANCE
, calc_unid
);
1628 rp
+= player_equip(EQ_STAFF
, STAFF_POISON
, calc_unid
);
1631 rp
+= player_equip_ego_type(EQ_ALL_ARMOUR
, SPARM_POISON_RESISTANCE
);
1634 rp
+= player_equip(EQ_BODY_ARMOUR
, ARM_GOLD_DRAGON_ARMOUR
);
1635 rp
+= player_equip(EQ_BODY_ARMOUR
, ARM_SWAMP_DRAGON_ARMOUR
);
1636 rp
+= player_equip(EQ_BODY_ARMOUR
, ARM_GOLD_DRAGON_HIDE
);
1637 rp
+= player_equip(EQ_BODY_ARMOUR
, ARM_SWAMP_DRAGON_HIDE
);
1640 rp
+= scan_artefacts(ARTP_POISON
, calc_unid
);
1644 rp
+= player_mutation_level(MUT_POISON_RESISTANCE
);
1645 rp
+= player_mutation_level(MUT_SLIMY_GREEN_SCALES
) == 3 ? 1 : 0;
1647 // Only thirsty vampires are naturally poison resistant.
1648 if (you
.species
== SP_VAMPIRE
&& you
.hunger_state
< HS_SATIATED
)
1654 if (you
.duration
[DUR_RESIST_POISON
] > 0)
1661 case TRAN_ICE_BEAST
:
1677 int player_res_sticky_flame(bool calc_unid
, bool temp
, bool items
)
1681 if (you
.species
== SP_MOTTLED_DRACONIAN
)
1684 if (items
&& player_equip(EQ_BODY_ARMOUR
, ARM_MOTTLED_DRAGON_ARMOUR
))
1686 if (items
&& player_equip(EQ_BODY_ARMOUR
, ARM_MOTTLED_DRAGON_HIDE
))
1695 int player_spec_death()
1700 sd
+= player_equip(EQ_STAFF
, STAFF_DEATH
);
1703 if (you
.species
== SP_MUMMY
)
1705 if (you
.experience_level
>= 13)
1707 if (you
.experience_level
>= 26)
1712 if (you
.form
== TRAN_LICH
)
1718 int player_spec_holy()
1720 //if (you.char_class == JOB_PRIEST || you.char_class == JOB_PALADIN)
1725 int player_spec_fire()
1730 sf
+= player_equip(EQ_STAFF
, STAFF_FIRE
);
1733 sf
+= player_equip(EQ_RINGS
, RING_FIRE
);
1735 if (you
.duration
[DUR_FIRE_SHIELD
])
1738 // if it's raining... {due}
1739 if (in_what_cloud(CLOUD_RAIN
))
1745 int player_spec_cold()
1750 sc
+= player_equip(EQ_STAFF
, STAFF_COLD
);
1753 sc
+= player_equip(EQ_RINGS
, RING_ICE
);
1758 int player_spec_earth()
1763 se
+= player_equip(EQ_STAFF
, STAFF_EARTH
);
1768 int player_spec_air()
1773 sa
+= player_equip(EQ_STAFF
, STAFF_AIR
);
1778 int player_spec_conj()
1783 sc
+= player_equip(EQ_STAFF
, STAFF_CONJURATION
);
1788 int player_spec_ench()
1793 se
+= player_equip(EQ_STAFF
, STAFF_ENCHANTMENT
);
1798 int player_spec_summ()
1803 ss
+= player_equip(EQ_STAFF
, STAFF_SUMMONING
);
1808 int player_spec_poison()
1813 sp
+= player_equip(EQ_STAFF
, STAFF_POISON
);
1815 if (player_equip_unrand(UNRAND_OLGREB
))
1826 pe
+= player_equip(EQ_STAFF
, STAFF_ENERGY
);
1831 // If temp is set to false, temporary sources of resistance won't be
1833 int player_prot_life(bool calc_unid
, bool temp
, bool items
)
1837 // Hunger is temporary, true, but that's something you can control,
1838 // especially as life protection only increases the hungrier you
1840 if (you
.species
== SP_VAMPIRE
)
1842 switch (you
.hunger_state
)
1845 case HS_NEAR_STARVING
:
1848 case HS_VERY_HUNGRY
:
1860 // Same here. Your piety status, and, hence, TSO's protection, is
1861 // something you can more or less control.
1862 if (you
.religion
== GOD_SHINING_ONE
&& you
.piety
> pl
* 50)
1863 pl
= you
.piety
/ 50;
1867 // Now, transformations could stop at any time.
1883 if (wearing_amulet(AMU_WARDING
, calc_unid
))
1887 pl
+= player_equip(EQ_RINGS
, RING_LIFE_PROTECTION
, calc_unid
);
1889 // armour (checks body armour only)
1890 pl
+= player_equip_ego_type(EQ_ALL_ARMOUR
, SPARM_POSITIVE_ENERGY
);
1892 // pearl dragon counts
1893 pl
+= player_equip(EQ_BODY_ARMOUR
, ARM_PEARL_DRAGON_ARMOUR
);
1896 pl
+= scan_artefacts(ARTP_NEGATIVE_ENERGY
, calc_unid
);
1899 pl
+= che_boost(CB_RNEG
);
1902 // undead/demonic power
1903 pl
+= player_mutation_level(MUT_NEGATIVE_ENERGY_RESISTANCE
);
1905 pl
= std::min(3, pl
);
1910 // New player movement speed system... allows for a bit more than
1911 // "player runs fast" and "player walks slow" in that the speed is
1912 // actually calculated (allowing for centaurs to get a bonus from
1913 // swiftness and other such things). Levels of the mutation now
1914 // also have meaning (before they all just meant fast). Most of
1915 // this isn't as fast as it used to be (6 for having anything), but
1916 // even a slight speed advantage is very good... and we certainly don't
1917 // want to go past 6 (see below). -- bwr
1918 int player_movement_speed(bool ignore_burden
)
1923 if (you
.form
== TRAN_SPIDER
)
1925 else if (player_in_bat_form())
1926 mv
= 5; // but allowed minimum is six
1927 else if (you
.form
== TRAN_PIG
)
1929 else if (you
.fishtail
)
1932 // moving on liquefied ground takes longer
1933 if (liquefied(you
.pos()) && you
.ground_level())
1937 if (player_equip_ego_type(EQ_BOOTS
, SPARM_RUNNING
))
1940 // ponderous brand and artefact property
1941 mv
+= 2 * player_ponderousness();
1943 // In the air, can fly fast (should be lightly burdened).
1944 if (!ignore_burden
&& you
.light_flight())
1947 // Swiftness is an Air spell, it doesn't work in water, but
1948 // flying players will move faster.
1949 if (you
.duration
[DUR_SWIFTNESS
] > 0 && !you
.in_water())
1950 mv
-= (you
.flight_mode() == FL_FLY
? 4 : 2);
1952 // Mutations: -2, -3, -4, unless innate and shapechanged.
1953 // Not when swimming, since it is "cover the ground quickly".
1954 if (player_mutation_level(MUT_FAST
) > 0
1955 && (!you
.innate_mutations
[MUT_FAST
] || !player_is_shapechanged())
1958 mv
-= player_mutation_level(MUT_FAST
) + 1;
1961 if (player_mutation_level(MUT_SLOW
) > 0 && !player_is_shapechanged())
1963 mv
*= 10 + player_mutation_level(MUT_SLOW
) * 2;
1970 if (you
.burden_state
== BS_ENCUMBERED
)
1972 else if (you
.burden_state
== BS_OVERLOADED
)
1976 // We'll use the old value of six as a minimum, with haste this could
1977 // end up as a speed of three, which is about as fast as we want
1978 // the player to be able to go (since 3 is 3.33x as fast and 2 is 5x,
1979 // which is a bit of a jump, and a bit too fast) -- bwr
1986 // This function differs from the above in that it's used to set the
1987 // initial time_taken value for the turn. Everything else (movement,
1988 // spellcasting, combat) applies a ratio to this value.
1989 int player_speed(void)
1993 for (int i
= 0; i
< NUM_STATS
; ++i
)
1994 if (you
.stat_zero
[i
] > 0)
1997 if (you
.duration
[DUR_SLOW
])
2000 if (you
.duration
[DUR_BERSERK
] && you
.religion
!= GOD_CHEIBRIADOS
)
2002 else if (you
.duration
[DUR_HASTE
])
2005 if (you
.form
== TRAN_STATUE
)
2014 int player_ponderousness()
2016 return (scan_artefacts(ARTP_PONDEROUS
)
2017 + player_equip_ego_type(EQ_ALL_ARMOUR
, SPARM_PONDEROUSNESS
));
2020 static int _player_armour_racial_bonus(const item_def
& item
)
2022 if (item
.base_type
!= OBJ_ARMOUR
)
2025 int racial_bonus
= 0;
2026 const iflags_t armour_race
= get_equip_race(item
);
2028 // get the armour race value that corresponds to the character's race:
2029 const iflags_t racial_type
2030 = ((player_genus(GENPC_DWARVEN
)) ? ISFLAG_DWARVEN
:
2031 (player_genus(GENPC_ELVEN
)) ? ISFLAG_ELVEN
:
2032 (you
.species
== SP_HILL_ORC
) ? ISFLAG_ORCISH
2035 // Dwarven armour is universally good -- bwr
2036 if (armour_race
== ISFLAG_DWARVEN
)
2039 if (racial_type
&& armour_race
== racial_type
)
2041 // Elven armour is light, but still gives one level to elves.
2042 // Orcish and Dwarven armour are worth +2 to the correct
2043 // species, plus the plus that anyone gets with dwarven armour.
2045 if (racial_type
== ISFLAG_ELVEN
)
2050 // an additional bonus for Beogh worshippers
2051 if (you
.religion
== GOD_BEOGH
&& !player_under_penance())
2053 if (you
.piety
>= 185)
2054 racial_bonus
+= racial_bonus
* 9 / 4;
2055 else if (you
.piety
>= 160)
2056 racial_bonus
+= racial_bonus
* 2;
2057 else if (you
.piety
>= 120)
2058 racial_bonus
+= racial_bonus
* 7 / 4;
2059 else if (you
.piety
>= 80)
2060 racial_bonus
+= racial_bonus
* 5 / 4;
2061 else if (you
.piety
>= 40)
2062 racial_bonus
+= racial_bonus
* 3 / 4;
2064 racial_bonus
+= racial_bonus
/ 4;
2068 return racial_bonus
;
2071 bool is_effectively_light_armour(const item_def
*item
)
2074 || (abs(property(*item
, PARM_EVASION
)) < 2));
2077 bool player_effectively_in_light_armour()
2079 const item_def
*armour
= you
.slot_item(EQ_BODY_ARMOUR
, false);
2080 return is_effectively_light_armour(armour
);
2083 // This function returns true if the player has a radically different
2084 // shape... minor changes like blade hands don't count, also note
2085 // that lich transformation doesn't change the character's shape
2086 // (so we end up with Naga-lichs, Spiggan-lichs, Minotaur-lichs)
2087 // it just makes the character undead (with the benefits that implies). - bwr
2088 bool player_is_shapechanged(void)
2090 if (you
.form
== TRAN_NONE
2091 || you
.form
== TRAN_BLADE_HANDS
2092 || you
.form
== TRAN_LICH
)
2100 // An evasion factor based on the player's body size, smaller == higher
2101 // evasion size factor.
2102 int player_evasion_size_factor()
2104 // XXX: you.body_size() implementations are incomplete, fix.
2105 const size_type size
= you
.body_size(PSIZE_BODY
);
2106 return 2 * (SIZE_MEDIUM
- size
);
2109 // The EV penalty to the player for wearing their current shield.
2110 int player_adjusted_shield_evasion_penalty(int scale
)
2112 const item_def
*shield
= you
.slot_item(EQ_SHIELD
, false);
2116 const int base_shield_penalty
= -property(*shield
, PARM_EVASION
);
2118 (base_shield_penalty
* scale
2119 - you
.skill(SK_SHIELDS
) * scale
2120 / (5 + player_evasion_size_factor())));
2123 int player_raw_body_armour_evasion_penalty()
2125 const item_def
*body_armour
= you
.slot_item(EQ_BODY_ARMOUR
, false);
2129 const int base_ev_penalty
= -property(*body_armour
, PARM_EVASION
);
2130 return base_ev_penalty
;
2133 int player_size_adjusted_body_armour_evasion_penalty(int scale
)
2135 const int base_ev_penalty
= player_raw_body_armour_evasion_penalty();
2136 if (!base_ev_penalty
)
2139 const int size
= you
.body_size(PSIZE_BODY
);
2141 const int size_bonus_factor
= (size
- SIZE_MEDIUM
) * scale
/ 4;
2143 const int size_adjusted_penalty
=
2145 scale
* base_ev_penalty
2146 - size_bonus_factor
* base_ev_penalty
);
2148 return (size_adjusted_penalty
);
2151 // The EV penalty to the player for their worn body armour.
2152 int player_adjusted_body_armour_evasion_penalty(int scale
)
2154 const int base_ev_penalty
= player_raw_body_armour_evasion_penalty();
2155 if (!base_ev_penalty
)
2158 return ((base_ev_penalty
2159 + std::max(0, 3 * base_ev_penalty
- you
.strength()))
2160 * (45 - you
.skill(SK_ARMOUR
))
2165 // The total EV penalty to the player for all their worn armour items
2166 // with a base EV penalty (i.e. EV penalty as a base armour property,
2167 // not as a randart property).
2168 static int _player_adjusted_evasion_penalty(const int scale
)
2170 int piece_armour_evasion_penalty
= 0;
2172 // Some lesser armours have small penalties now (barding).
2173 for (int i
= EQ_MIN_ARMOUR
; i
< EQ_MAX_ARMOUR
; i
++)
2175 if (i
== EQ_SHIELD
|| !player_wearing_slot(i
))
2178 // [ds] Evasion modifiers for armour are negatives, change
2179 // those to positive for penalty calc.
2180 const int penalty
= -property(you
.inv
[you
.equip
[i
]], PARM_EVASION
);
2182 piece_armour_evasion_penalty
+= penalty
;
2185 return (piece_armour_evasion_penalty
* scale
+
2186 player_adjusted_body_armour_evasion_penalty(scale
));
2189 // EV bonuses that work even when helpless.
2190 static int _player_para_evasion_bonuses(ev_ignore_type evit
)
2194 if (you
.duration
[DUR_PHASE_SHIFT
] && !(evit
& EV_IGNORE_PHASESHIFT
))
2197 if (player_mutation_level(MUT_DISTORTION_FIELD
) > 0)
2198 evbonus
+= player_mutation_level(MUT_DISTORTION_FIELD
) + 1;
2203 // Player EV bonuses for various effects and transformations. This
2204 // does not include kenku/merfolk EV bonuses for flight/swimming.
2205 int player_evasion_bonuses(ev_ignore_type evit
)
2207 int evbonus
= _player_para_evasion_bonuses(evit
);
2209 if (you
.duration
[DUR_AGILITY
])
2212 if (you
.duration
[DUR_STONEMAIL
])
2215 evbonus
+= player_equip(EQ_RINGS_PLUS
, RING_EVASION
);
2217 if (player_equip_ego_type(EQ_WEAPON
, SPWPN_EVASION
))
2220 evbonus
+= scan_artefacts(ARTP_EVASION
);
2223 if (player_mutation_level(MUT_ICY_BLUE_SCALES
) > 1)
2225 if (player_mutation_level(MUT_MOLTEN_SCALES
) > 1)
2227 evbonus
-= std::max(0, player_mutation_level(MUT_SLIMY_GREEN_SCALES
) - 1);
2228 evbonus
+= std::max(0, player_mutation_level(MUT_GELATINOUS_BODY
) - 1);
2230 // transformation penalties/bonuses not covered by size alone:
2231 if (you
.form
== TRAN_STATUE
)
2232 evbonus
-= 5; // stiff
2237 // Player EV scaling for being flying kenku or swimming merfolk.
2238 int player_scale_evasion(const int prescaled_ev
, const int scale
)
2240 switch (you
.species
)
2243 // Merfolk get an evasion bonus in water.
2246 const int ev_bonus
=
2250 return (prescaled_ev
+ ev_bonus
);
2255 // Flying Kenku get an evasion bonus.
2256 if (you
.flight_mode() == FL_FLY
)
2258 const int ev_bonus
=
2262 return (prescaled_ev
+ ev_bonus
);
2269 return (prescaled_ev
);
2272 // Total EV for player using the revised 0.6 evasion model.
2273 int player_evasion(ev_ignore_type evit
)
2275 const int size_factor
= player_evasion_size_factor();
2276 // Repulsion fields and size are all that matters when paralysed or
2278 if ((you
.cannot_move() || you
.stat_zero
[STAT_DEX
])
2279 && !(evit
& EV_IGNORE_HELPLESS
))
2281 const int paralysed_base_ev
= 2 + size_factor
/ 2;
2282 const int repulsion_ev
= _player_para_evasion_bonuses(evit
);
2283 return std::max(1, paralysed_base_ev
+ repulsion_ev
);
2286 const int scale
= 100;
2287 const int size_base_ev
= (10 + size_factor
) * scale
;
2289 const int adjusted_evasion_penalty
=
2290 _player_adjusted_evasion_penalty(scale
);
2292 // The last two parameters are not important.
2293 const int ev_dex
= stepdown_value(you
.dex(), 10, 24, 72, 72);
2295 const int dodge_bonus
=
2296 (7 + you
.skill(SK_DODGING
) * ev_dex
) * scale
2297 / (20 - size_factor
);
2299 // [ds] Dodging penalty for being in high EVP armour, almost
2300 // identical to v0.5/4.1 penalty, but with the EVP discount being
2301 // 1 instead of 0.5 so that leather armour is fully discounted.
2302 // The 1 EVP of leather armour may still incur an
2303 // adjusted_evasion_penalty, however.
2304 const int armour_dodge_penalty
=
2306 (30 * player_size_adjusted_body_armour_evasion_penalty(scale
)
2308 / std::max(1, (int) you
.strength()));
2310 // Adjust dodge bonus for the effects of being suited up in armour.
2311 const int armour_adjusted_dodge_bonus
=
2312 std::max(0, dodge_bonus
- armour_dodge_penalty
);
2314 const int adjusted_shield_penalty
=
2315 player_adjusted_shield_evasion_penalty(scale
);
2317 const int prestepdown_evasion
=
2319 + armour_adjusted_dodge_bonus
2320 - adjusted_evasion_penalty
2321 - adjusted_shield_penalty
;
2323 const int poststepdown_evasion
=
2324 stepdown_value(prestepdown_evasion
, 20*scale
, 30*scale
, 60*scale
, -1);
2326 const int evasion_bonuses
= player_evasion_bonuses(evit
) * scale
;
2328 const int prescaled_evasion
=
2329 poststepdown_evasion
+ evasion_bonuses
;
2331 const int final_evasion
=
2332 player_scale_evasion(prescaled_evasion
, scale
);
2334 return (unscale_round_up(final_evasion
, scale
));
2337 int player_body_armour_racial_spellcasting_bonus(const int scale
)
2339 const item_def
*body_armour
= you
.slot_item(EQ_BODY_ARMOUR
, false);
2343 const iflags_t armour_race
= get_equip_race(*body_armour
);
2345 // Get the armour race value that corresponds to the character's
2347 const iflags_t player_race
2348 = ((player_genus(GENPC_DWARVEN
)) ? ISFLAG_DWARVEN
:
2349 (player_genus(GENPC_ELVEN
)) ? ISFLAG_ELVEN
:
2350 (you
.species
== SP_HILL_ORC
) ? ISFLAG_ORCISH
2352 int armour_racial_spellcasting_bonus
= 0;
2353 if (armour_race
& ISFLAG_ELVEN
)
2354 armour_racial_spellcasting_bonus
+= 25;
2356 if (armour_race
& ISFLAG_DWARVEN
)
2357 armour_racial_spellcasting_bonus
-= 15;
2359 if (armour_race
& player_race
)
2360 armour_racial_spellcasting_bonus
+= 15;
2362 return (armour_racial_spellcasting_bonus
* scale
);
2365 // Returns the spellcasting penalty (increase in spell failure) for the
2366 // player's worn body armour and shield.
2367 int player_armour_shield_spell_penalty()
2369 const int scale
= 100;
2371 const int body_armour_penalty
=
2372 std::max(25 * player_adjusted_body_armour_evasion_penalty(scale
)
2373 - player_body_armour_racial_spellcasting_bonus(scale
),
2376 const int total_penalty
= body_armour_penalty
2377 + 25 * player_adjusted_shield_evasion_penalty(scale
)
2380 return (std::max(total_penalty
, 0) / scale
);
2383 int player_magical_power(void)
2387 ret
+= 13 * player_equip(EQ_STAFF
, STAFF_POWER
);
2388 ret
+= 9 * player_equip(EQ_RINGS
, RING_MAGICAL_POWER
);
2389 ret
+= scan_artefacts(ARTP_MAGICAL_POWER
);
2394 int player_mag_abil(bool is_weighted
)
2398 // Brilliance Potion
2399 ma
+= 6 * (you
.duration
[DUR_BRILLIANCE
] ? 1 : 0);
2401 ma
+= 3 * player_equip(EQ_RINGS
, RING_WIZARDRY
);
2404 ma
+= 4 * player_equip(EQ_STAFF
, STAFF_WIZARDRY
);
2406 // armour of the Archmagi (checks body armour only)
2407 ma
+= 2 * player_equip_ego_type(EQ_BODY_ARMOUR
, SPARM_ARCHMAGI
);
2409 return ((is_weighted
) ? ((ma
* you
.intel()) / 10) : ma
);
2412 int player_shield_class(void) //jmf: changes for new spell
2417 if (you
.incapacitated())
2420 if (player_wearing_slot(EQ_SHIELD
))
2422 const item_def
& item
= you
.inv
[you
.equip
[EQ_SHIELD
]];
2423 int base_shield
= property(item
, PARM_AC
);
2425 int racial_bonus
= _player_armour_racial_bonus(item
);
2427 // bonus applied only to base, see above for effect:
2428 shield
+= base_shield
* 100;
2429 shield
+= base_shield
* 5 * you
.skill(SK_SHIELDS
);
2430 shield
+= base_shield
* racial_bonus
* 10 / 3;
2432 shield
+= item
.plus
* 100;
2434 if (item
.sub_type
== ARM_BUCKLER
)
2435 stat
= you
.dex() * 38;
2436 else if (item
.sub_type
== ARM_LARGE_SHIELD
)
2437 stat
= you
.dex() * 12 + you
.strength() * 26;
2439 stat
= you
.dex() * 19 + you
.strength() * 19;
2443 if (you
.duration
[DUR_MAGIC_SHIELD
])
2445 stat
= 600 + you
.skill(SK_EVOCATIONS
) * 50;
2446 shield
+= 300 + you
.skill(SK_EVOCATIONS
) * 25;
2449 if (!you
.duration
[DUR_FIRE_SHIELD
]
2450 && you
.duration
[DUR_CONDENSATION_SHIELD
])
2452 shield
+= 300 + (you
.skill(SK_ICE_MAGIC
) * 25);
2453 stat
= std::max(stat
, you
.intel() * 38);
2457 if (you
.duration
[DUR_DIVINE_SHIELD
])
2459 shield
+= you
.attribute
[ATTR_DIVINE_SHIELD
] * 150;
2460 stat
= std::max(stat
, int(you
.attribute
[ATTR_DIVINE_SHIELD
] * 300));
2463 if (shield
+ stat
> 0)
2464 shield
+= skill_bump(SK_SHIELDS
) * 38;
2467 shield
+= player_mutation_level(MUT_LARGE_BONE_PLATES
) > 0 ? 100 + player_mutation_level(MUT_LARGE_BONE_PLATES
) * 100 : 0; // +2, +3, +4
2469 return (shield
+ stat
+ 50) / 100;
2472 int player_sust_abil(bool calc_unid
)
2476 sa
+= player_equip(EQ_RINGS
, RING_SUSTAIN_ABILITIES
, calc_unid
);
2481 int carrying_capacity(burden_state_type bs
)
2483 // Yuck. We need this for gameplay - it nerfs small forms too much
2484 // otherwise - but there's no good way to rationalize here... --sorear
2485 int used_weight
= std::max(you
.body_weight(), you
.body_weight(true));
2487 int cap
= (2 * used_weight
) + (you
.strength() * 300)
2488 + (you
.airborne() ? 1000 : 0);
2489 // We are nice to the lighter species in that strength adds absolutely
2490 // instead of relatively to body weight. --dpeg
2492 if (you
.stat_zero
[STAT_STR
])
2495 if (bs
== BS_UNENCUMBERED
)
2496 return ((cap
* 5) / 6);
2497 else if (bs
== BS_ENCUMBERED
)
2498 return ((cap
* 11) / 12);
2503 int burden_change(void)
2505 const burden_state_type old_burdenstate
= you
.burden_state
;
2506 const bool was_flying_light
= you
.light_flight();
2510 if (you
.duration
[DUR_STONEMAIL
])
2513 for (int bu
= 0; bu
< ENDOFPACK
; bu
++)
2515 if (you
.inv
[bu
].quantity
< 1)
2518 you
.burden
+= item_mass(you
.inv
[bu
]) * you
.inv
[bu
].quantity
;
2521 you
.burden_state
= BS_UNENCUMBERED
;
2522 set_redraw_status(REDRAW_BURDEN
);
2523 you
.redraw_evasion
= true;
2525 // changed the burdened levels to match the change to max_carried
2526 if (you
.burden
< carrying_capacity(BS_UNENCUMBERED
))
2528 you
.burden_state
= BS_UNENCUMBERED
;
2530 // this message may have to change, just testing {dlb}
2531 if (old_burdenstate
!= you
.burden_state
)
2532 mpr("Your possessions no longer seem quite so burdensome.");
2534 else if (you
.burden
< carrying_capacity(BS_ENCUMBERED
))
2536 you
.burden_state
= BS_ENCUMBERED
;
2538 if (old_burdenstate
!= you
.burden_state
)
2540 mpr("You are being weighed down by all of your possessions.");
2541 learned_something_new(HINT_HEAVY_LOAD
);
2546 you
.burden_state
= BS_OVERLOADED
;
2548 if (old_burdenstate
!= you
.burden_state
)
2550 mpr("You are being crushed by all of your possessions.");
2551 learned_something_new(HINT_HEAVY_LOAD
);
2555 // Stop travel if we get burdened (as from potions of might/levitation
2557 if (you
.burden_state
> old_burdenstate
)
2558 interrupt_activity(AI_BURDEN_CHANGE
);
2560 const bool is_flying_light
= you
.light_flight();
2562 if (is_flying_light
!= was_flying_light
)
2564 mpr(is_flying_light
? "You feel quicker in the air."
2565 : "You feel heavier in the air.");
2568 return (you
.burden
);
2571 // force is true for forget_map command on level map.
2572 void forget_map(int chance_forgotten
, bool force
)
2574 ASSERT(!crawl_state
.game_is_arena());
2576 if (force
&& !yesno("Really forget level map?", true, 'n'))
2579 // The radius is only used in labyrinths.
2580 const bool use_lab_check
= (!force
&& you
.level_type
== LEVEL_LABYRINTH
2581 && chance_forgotten
< 100);
2582 const int radius
= (use_lab_check
&& you
.species
== SP_MINOTAUR
) ? 40*40
2584 for (rectangle_iterator
ri(0); ri
; ++ri
)
2586 if (!you
.see_cell(*ri
)
2587 && (force
|| x_chance_in_y(chance_forgotten
, 100)
2588 || use_lab_check
&& (you
.pos()-*ri
).abs() > radius
))
2590 env
.map_knowledge(*ri
).clear();
2592 tile_forget_map(*ri
);
2597 ash_detect_portals(player_in_mappable_area());
2599 tiles
.update_minimap_bounds();
2603 void gain_exp(unsigned int exp_gained
, unsigned int* actual_gain
,
2604 unsigned int* actual_avail_gain
)
2606 if (crawl_state
.game_is_arena())
2608 if (crawl_state
.game_is_sprint() && you
.level_type
== LEVEL_ABYSS
)
2611 if (you
.religion
== GOD_ASHENZARI
&& you
.piety
> piety_breakpoint(0))
2612 exp_gained
= div_rand_round(exp_gained
* (8 + ash_bondage_level()), 8);
2614 const unsigned int old_exp
= you
.experience
;
2615 const int old_avail
= you
.exp_available
;
2617 dprf("gain_exp: %d", exp_gained
);
2619 if (you
.transfer_skill_points
> 0)
2621 int amount
= exp_gained
* 10
2622 / calc_skill_cost(you
.skill_cost_level
,
2623 you
.skills
[you
.transfer_to_skill
]);
2624 if (amount
>= 20 || one_chance_in(20 - amount
))
2626 amount
= std::max(20, amount
);
2627 transfer_skill_points(you
.transfer_from_skill
,
2628 you
.transfer_to_skill
, amount
, false);
2632 if (you
.experience
+ exp_gained
> (unsigned int)MAX_EXP_TOTAL
)
2633 you
.experience
= MAX_EXP_TOTAL
;
2635 you
.experience
+= exp_gained
;
2637 if (you
.duration
[DUR_SAGE
])
2639 // Bonus skill training from Sage.
2641 (exp_gained
* you
.sage_bonus_degree
) / 100 + exp_gained
/ 2;
2642 practise(EX_SAGE
, you
.sage_bonus_skill
);
2643 you
.exp_available
= old_avail
;
2647 if (crawl_state
.game_is_sprint())
2649 exp_gained
= sprint_modify_exp(exp_gained
);
2652 if (you
.exp_available
+ exp_gained
> (unsigned int)MAX_EXP_POOL
)
2653 you
.exp_available
= MAX_EXP_POOL
;
2655 you
.exp_available
+= exp_gained
;
2659 if (actual_gain
!= NULL
)
2660 *actual_gain
= you
.experience
- old_exp
;
2662 if (actual_avail_gain
!= NULL
)
2663 *actual_avail_gain
= you
.exp_available
- old_avail
;
2666 static void _draconian_scale_colour_message()
2668 switch (you
.species
)
2670 case SP_RED_DRACONIAN
:
2671 mpr("Your scales start taking on a fiery red colour.",
2672 MSGCH_INTRINSIC_GAIN
);
2673 perma_mutate(MUT_HEAT_RESISTANCE
, 1);
2676 case SP_WHITE_DRACONIAN
:
2677 mpr("Your scales start taking on an icy white colour.",
2678 MSGCH_INTRINSIC_GAIN
);
2679 perma_mutate(MUT_COLD_RESISTANCE
, 1);
2682 case SP_GREEN_DRACONIAN
:
2683 mpr("Your scales start taking on a lurid green colour.",
2684 MSGCH_INTRINSIC_GAIN
);
2685 perma_mutate(MUT_POISON_RESISTANCE
, 1);
2688 case SP_YELLOW_DRACONIAN
:
2689 mpr("Your scales start taking on a golden yellow colour.",
2690 MSGCH_INTRINSIC_GAIN
);
2693 case SP_GREY_DRACONIAN
:
2694 mpr("Your scales start taking on a dull grey colour.",
2695 MSGCH_INTRINSIC_GAIN
);
2696 perma_mutate(MUT_UNBREATHING
, 1);
2699 case SP_BLACK_DRACONIAN
:
2700 mpr("Your scales start taking on a glossy black colour.",
2701 MSGCH_INTRINSIC_GAIN
);
2702 perma_mutate(MUT_SHOCK_RESISTANCE
, 1);
2705 case SP_PURPLE_DRACONIAN
:
2706 mpr("Your scales start taking on a rich purple colour.",
2707 MSGCH_INTRINSIC_GAIN
);
2710 case SP_MOTTLED_DRACONIAN
:
2711 mpr("Your scales start taking on a weird mottled pattern.",
2712 MSGCH_INTRINSIC_GAIN
);
2715 case SP_PALE_DRACONIAN
:
2716 mpr("Your scales start fading to a pale grey colour.",
2717 MSGCH_INTRINSIC_GAIN
);
2720 case SP_BASE_DRACONIAN
:
2729 static void _felid_extra_life()
2731 if (you
.lives
+ you
.deaths
< you
.max_level
/3 && you
.lives
< 2)
2734 mpr("Extra life!", MSGCH_INTRINSIC_GAIN
);
2736 // Should play the 1UP sound from SMB...
2739 void level_change(bool skip_attribute_increase
)
2741 const bool wiz_cmd
= crawl_state
.prev_cmd
== CMD_WIZARD
2742 || crawl_state
.repeat_cmd
== CMD_WIZARD
;
2744 // necessary for the time being, as level_change() is called
2745 // directly sometimes {dlb}
2746 you
.redraw_experience
= true;
2748 while (you
.experience_level
< 27
2749 && you
.experience
> exp_needed(you
.experience_level
+ 2))
2751 if (!skip_attribute_increase
&& !wiz_cmd
)
2753 crawl_state
.cancel_cmd_all();
2755 if (is_processing_macro())
2756 flush_input_buffer(FLUSH_ABORT_MACRO
);
2759 const int old_hp
= you
.hp
;
2760 const int old_maxhp
= you
.hp_max
;
2765 // [ds] Make sure we increment you.experience_level and apply
2766 // any stat/hp increases only after we've cleared all prompts
2767 // for this experience level. If we do part of the work before
2768 // the prompt, and a player on telnet gets disconnected, the
2769 // SIGHUP will save Crawl in the in-between state and rob the
2770 // player of their level-up perks.
2772 const int new_exp
= you
.experience_level
+ 1;
2774 if (new_exp
<= you
.max_level
)
2776 mprf(MSGCH_INTRINSIC_GAIN
,
2777 "Welcome back to level %d!", new_exp
);
2779 // No more prompts for this XL past this point.
2781 you
.experience_level
= new_exp
;
2782 // Gain back the hp and mp we lose in lose_level(). -- bwr
2786 else // Character has gained a new level
2790 mprf(MSGCH_INTRINSIC_GAIN
,
2791 "You have reached level 27, the final one!");
2795 mprf(MSGCH_INTRINSIC_GAIN
, "You have reached level %d!",
2799 if (!(new_exp
% 3) && !skip_attribute_increase
)
2800 attribute_increase();
2805 brek
= 2 + new_exp
% 2;
2806 else if (new_exp
> 12)
2807 brek
= 4; // up from 2 + rand(3) -- bwr
2809 brek
= 5 + new_exp
% 2; // up from 3 + rand(4) -- bwr
2811 you
.experience_level
= new_exp
;
2815 switch (you
.species
)
2818 if (!(you
.experience_level
% 5))
2819 modify_stat(STAT_RANDOM
, 1, false, "level gain");
2823 if (you
.experience_level
% 3)
2826 if (!(you
.experience_level
% 2))
2829 if (!(you
.experience_level
% 3))
2831 modify_stat((coinflip() ? STAT_INT
2832 : STAT_DEX
), 1, false,
2838 if (you
.experience_level
< 17)
2841 if (!(you
.experience_level
% 3))
2846 if (!(you
.experience_level
% 4))
2847 modify_stat(STAT_INT
, 1, false, "level gain");
2851 if (you
.experience_level
% 3)
2856 if (!(you
.experience_level
% 4))
2858 modify_stat((coinflip() ? STAT_INT
2859 : STAT_DEX
), 1, false,
2864 case SP_MOUNTAIN_DWARF
:
2865 if (!(you
.experience_level
% 2))
2868 if (!(you
.experience_level
% 3))
2871 if (!(you
.experience_level
% 4))
2872 modify_stat(STAT_STR
, 1, false, "level gain");
2878 if (you
.experience_level
== 14)
2880 mpr("You feel somewhat more resistant.",
2881 MSGCH_INTRINSIC_GAIN
);
2882 perma_mutate(MUT_NEGATIVE_ENERGY_RESISTANCE
, 1);
2885 if ((you
.experience_level
== 9)
2886 || (you
.experience_level
== 18))
2888 perma_mutate(MUT_PASSIVE_MAPPING
, 1);
2891 if (!(you
.experience_level
% 4))
2893 modify_stat(coinflip() ? STAT_STR
2894 : STAT_INT
, 1, false,
2900 if (!(you
.experience_level
% 5))
2901 modify_stat(STAT_DEX
, 1, false, "level gain");
2903 if (you
.experience_level
% 3)
2909 if (!(you
.experience_level
% 5))
2911 modify_stat((coinflip() ? STAT_STR
2912 : STAT_DEX
), 1, false,
2916 if (you
.experience_level
< 17)
2919 if (!(you
.experience_level
% 2))
2924 // lower because of HD raise -- bwr
2925 // if (you.experience_level < 17)
2928 if (!(you
.experience_level
% 2))
2931 if (!(you
.experience_level
% 3))
2934 if (!(you
.experience_level
% 5))
2935 modify_stat(STAT_STR
, 1, false, "level gain");
2939 if (you
.experience_level
== 13 || you
.experience_level
== 26)
2941 mpr("You feel more in touch with the powers of death.",
2942 MSGCH_INTRINSIC_GAIN
);
2945 if (you
.experience_level
== 13) // level 13 for now -- bwr
2947 mpr("You can now infuse your body with magic to restore "
2948 "decomposition.", MSGCH_INTRINSIC_GAIN
);
2953 if (you
.experience_level
== 3)
2955 if (you
.hunger_state
> HS_SATIATED
)
2957 mpr("If you weren't so full you could now transform "
2958 "into a vampire bat.", MSGCH_INTRINSIC_GAIN
);
2962 mpr("You can now transform into a vampire bat.",
2963 MSGCH_INTRINSIC_GAIN
);
2966 else if (you
.experience_level
== 6)
2968 mpr("You can now bottle potions of blood from corpses.",
2969 MSGCH_INTRINSIC_GAIN
);
2976 if (!(you
.experience_level
% 4))
2977 modify_stat(STAT_RANDOM
, 1, false, "level gain");
2979 if (!(you
.experience_level
% 3))
2981 mpr("Your skin feels tougher.", MSGCH_INTRINSIC_GAIN
);
2982 you
.redraw_armour_class
= true;
2989 if (!(you
.experience_level
% 2))
2992 if (you
.experience_level
% 3)
2995 if (!(you
.experience_level
% 3))
2996 modify_stat(STAT_STR
, 1, false, "level gain");
3002 if (!(you
.experience_level
% 3))
3003 modify_stat(STAT_STR
, 1, false, "level gain");
3006 case SP_BASE_DRACONIAN
:
3007 if (you
.experience_level
>= 7)
3009 you
.species
= random_draconian_player_species();
3010 update_player_symbol();
3015 _draconian_scale_colour_message();
3017 // We check if any skill has changed level because of
3019 for (int i
= SK_FIRST_SKILL
; i
< NUM_SKILLS
; ++i
)
3020 check_skill_level_change(static_cast<skill_type
>(i
));
3022 case SP_RED_DRACONIAN
:
3023 case SP_WHITE_DRACONIAN
:
3024 case SP_GREEN_DRACONIAN
:
3025 case SP_YELLOW_DRACONIAN
:
3026 case SP_GREY_DRACONIAN
:
3027 case SP_BLACK_DRACONIAN
:
3028 case SP_PURPLE_DRACONIAN
:
3029 case SP_MOTTLED_DRACONIAN
:
3030 case SP_PALE_DRACONIAN
:
3031 if (!(you
.experience_level
% 3))
3034 if (!(you
.experience_level
% 3))
3036 mpr("Your scales feel tougher.", MSGCH_INTRINSIC_GAIN
);
3037 you
.redraw_armour_class
= true;
3040 if (!(you
.experience_level
% 4) && you
.experience_level
> 7)
3042 modify_stat(STAT_RANDOM
, 1, false, "level gain");
3045 if (you
.experience_level
== 14)
3047 switch (you
.species
)
3049 case SP_GREEN_DRACONIAN
:
3050 perma_mutate(MUT_STINGER
, 1);
3052 case SP_YELLOW_DRACONIAN
:
3053 perma_mutate(MUT_ACIDIC_BITE
, 1);
3055 case SP_BLACK_DRACONIAN
:
3056 perma_mutate(MUT_BIG_WINGS
, 1);
3065 if (!(you
.experience_level
% 4))
3067 modify_stat((coinflip() ? STAT_STR
3068 : STAT_DEX
), 1, false,
3072 // lowered because of HD raise -- bwr
3073 // if (you.experience_level < 17)
3076 if (!(you
.experience_level
% 2))
3079 if (!(you
.experience_level
% 3))
3084 if (!(you
.experience_level
% 2))
3085 modify_stat(STAT_RANDOM
, 1, false, "level gain");
3087 // lowered because of HD raise -- bwr
3088 // if (you.experience_level < 17)
3091 if (!(you
.experience_level
% 2))
3094 if (you
.experience_level
% 3)
3099 if (you
.experience_level
< 17)
3102 if (you
.experience_level
% 3)
3107 if (!(you
.experience_level
% 5))
3109 modify_stat((coinflip() ? STAT_INT
3110 : STAT_DEX
), 1, false,
3116 // lowered because of HD raise -- bwr
3117 // if (you.experience_level < 17)
3120 if (!(you
.experience_level
% 2))
3123 if (!(you
.experience_level
% 2))
3126 if (!(you
.experience_level
% 4))
3128 modify_stat((coinflip() ? STAT_STR
3129 : STAT_DEX
), 1, false,
3136 bool gave_message
= false;
3138 mutation_type first_body_facet
= NUM_MUTATIONS
;
3140 for (unsigned i
= 0; i
< you
.demonic_traits
.size(); ++i
)
3142 if (is_body_facet(you
.demonic_traits
[i
].mutation
))
3144 if (first_body_facet
< NUM_MUTATIONS
3145 && you
.demonic_traits
[i
].mutation
3146 != first_body_facet
)
3148 if (you
.experience_level
== level
)
3150 mpr("You feel monstrous as your "
3151 "demonic heritage exerts itself.",
3154 mark_milestone("monstrous", "is a "
3155 "monstrous demonspawn!");
3158 i
= you
.demonic_traits
.size();
3162 if (first_body_facet
== NUM_MUTATIONS
)
3164 first_body_facet
= you
.demonic_traits
[i
].mutation
;
3165 level
= you
.demonic_traits
[i
].level_gained
;
3170 for (unsigned i
= 0; i
< you
.demonic_traits
.size(); ++i
)
3172 if (you
.demonic_traits
[i
].level_gained
3173 == you
.experience_level
)
3177 mpr("Your demonic ancestry asserts itself...",
3178 MSGCH_INTRINSIC_GAIN
);
3180 gave_message
= true;
3182 perma_mutate(you
.demonic_traits
[i
].mutation
, 1);
3186 if (!(you
.experience_level
% 4))
3187 modify_stat(STAT_RANDOM
, 1, false, "level gain");
3192 // lowered because of HD raise -- bwr
3193 // if (you.experience_level < 17)
3196 if (!(you
.experience_level
% 2))
3199 if (!(you
.experience_level
% 3))
3202 if (!(you
.experience_level
% 5))
3203 modify_stat(STAT_STR
, 1, false, "level gain");
3207 if (you
.experience_level
< 17)
3210 if (!(you
.experience_level
% 3))
3213 if (!(you
.experience_level
% 4))
3214 modify_stat(STAT_RANDOM
, 1, false, "level gain");
3216 if (you
.experience_level
== 5)
3218 mpr("You have gained the ability to fly.",
3219 MSGCH_INTRINSIC_GAIN
);
3221 else if (you
.experience_level
== 15)
3222 mpr("You can now fly continuously.", MSGCH_INTRINSIC_GAIN
);
3226 if (!(you
.experience_level
% 5))
3227 modify_stat(STAT_RANDOM
, 1, false, "level gain");
3234 if (you
.experience_level
% 2)
3237 if (!(you
.experience_level
% 5))
3239 modify_stat((coinflip() ? STAT_INT
3240 : STAT_DEX
), 1, false,
3244 if (you
.experience_level
== 6 || you
.experience_level
== 12)
3245 perma_mutate(MUT_SHAGGY_FUR
, 1);
3247 _felid_extra_life();
3256 // // zot defence abilities; must also be updated in abil-show.cc when these levels are changed
3257 if (crawl_state
.game_is_zotdef())
3259 if (you
.experience_level
== 1)
3260 mpr("Your Zot abilities now extend through the making of dart traps.", MSGCH_INTRINSIC_GAIN
);
3261 if (you
.experience_level
== 2)
3262 mpr("Your Zot abilities now extend through the making of oklob saplings.", MSGCH_INTRINSIC_GAIN
);
3263 if (you
.experience_level
== 3)
3264 mpr("Your Zot abilities now extend through the making of arrow traps.", MSGCH_INTRINSIC_GAIN
);
3265 if (you
.experience_level
== 4)
3266 mpr("Your Zot abilities now extend through the making of plants.", MSGCH_INTRINSIC_GAIN
);
3267 if (you
.experience_level
== 4)
3268 mpr("Your Zot abilities now extend through removing curses.", MSGCH_INTRINSIC_GAIN
);
3269 if (you
.experience_level
== 5)
3270 mpr("Your Zot abilities now extend through the making of burning bushes.", MSGCH_INTRINSIC_GAIN
);
3271 if (you
.experience_level
== 6)
3272 mpr("Your Zot abilities now extend through the making of altars and grenades.", MSGCH_INTRINSIC_GAIN
);
3273 if (you
.experience_level
== 7)
3274 mpr("Your Zot abilities now extend through the making of oklob plants.", MSGCH_INTRINSIC_GAIN
);
3275 if (you
.experience_level
== 8)
3276 mpr("Your Zot abilities now extend through the making of net traps.", MSGCH_INTRINSIC_GAIN
);
3277 if (you
.experience_level
== 9)
3278 mpr("Your Zot abilities now extend through the making of ice statues.", MSGCH_INTRINSIC_GAIN
);
3279 if (you
.experience_level
== 10)
3280 mpr("Your Zot abilities now extend through the making of spear traps.", MSGCH_INTRINSIC_GAIN
);
3281 if (you
.experience_level
== 11)
3282 mpr("Your Zot abilities now extend through the making of alarm traps.", MSGCH_INTRINSIC_GAIN
);
3283 if (you
.experience_level
== 12)
3284 mpr("Your Zot abilities now extend through the making of mushroom circles.", MSGCH_INTRINSIC_GAIN
);
3285 if (you
.experience_level
== 13)
3286 mpr("Your Zot abilities now extend through the making of bolt traps.", MSGCH_INTRINSIC_GAIN
);
3287 if (you
.experience_level
== 14)
3288 mpr("Your Zot abilities now extend through the making of orange crystal statues.", MSGCH_INTRINSIC_GAIN
);
3289 if (you
.experience_level
== 15)
3290 mpr("Your Zot abilities now extend through the making of needle traps.", MSGCH_INTRINSIC_GAIN
);
3291 if (you
.experience_level
== 16)
3292 mpr("Your Zot abilities now extend through self-teleportation.", MSGCH_INTRINSIC_GAIN
);
3293 if (you
.experience_level
== 17)
3294 mpr("Your Zot abilities now extend through making water.", MSGCH_INTRINSIC_GAIN
);
3295 if (you
.experience_level
== 18)
3296 mpr("Your Zot abilities now extend through the making of axe traps.", MSGCH_INTRINSIC_GAIN
);
3297 if (you
.experience_level
== 19)
3298 mpr("Your Zot abilities now extend through the making of electric eels.", MSGCH_INTRINSIC_GAIN
);
3299 if (you
.experience_level
== 20)
3300 mpr("Your Zot abilities now extend through the making of silver statues.", MSGCH_INTRINSIC_GAIN
);
3301 // gold and bazaars gained together
3302 if (you
.experience_level
== 21)
3303 mpr("Your Zot abilities now extend through the making of bazaars.", MSGCH_INTRINSIC_GAIN
);
3304 if (you
.experience_level
== 21)
3305 mpr("Your Zot abilities now extend through acquiring gold.", MSGCH_INTRINSIC_GAIN
);
3306 if (you
.experience_level
== 22)
3307 mpr("Your Zot abilities now extend through the making of oklob circles.", MSGCH_INTRINSIC_GAIN
);
3308 if (you
.experience_level
== 23)
3309 mpr("Your Zot abilities now extend through invoking Sage effects.", MSGCH_INTRINSIC_GAIN
);
3310 if (you
.experience_level
== 24)
3311 mpr("Your Zot abilities now extend through acquirement.", MSGCH_INTRINSIC_GAIN
);
3312 if (you
.experience_level
== 25)
3313 mpr("Your Zot abilities now extend through the making of blade traps.", MSGCH_INTRINSIC_GAIN
);
3314 if (you
.experience_level
== 26)
3315 mpr("Your Zot abilities now extend through the making of curse skulls.", MSGCH_INTRINSIC_GAIN
);
3316 if (you
.experience_level
== 27)
3317 mpr("Your Zot abilities now extend through the making of teleport traps.", MSGCH_INTRINSIC_GAIN
);
3320 #if TAG_MAJOR_VERSION == 32
3323 // add hp and mp adjustments - GDL
3324 inc_max_hp(hp_adjust
);
3325 inc_max_mp(mp_adjust
);
3327 deflate_hp(you
.hp_max
, false);
3329 you
.hp
= old_hp
* you
.hp_max
/ old_maxhp
;
3330 you
.magic_points
= std::max(0, you
.magic_points
);
3332 // Get "real" values for note-taking, i.e. ignore Berserk,
3333 // transformations or equipped items.
3334 const int note_maxhp
= get_real_hp(false, false);
3335 const int note_maxmp
= get_real_mp(false);
3338 sprintf(buf
, "HP: %d/%d MP: %d/%d",
3339 std::min(you
.hp
, note_maxhp
), note_maxhp
,
3340 std::min(you
.magic_points
, note_maxmp
), note_maxmp
);
3341 take_note(Note(NOTE_XP_LEVEL_CHANGE
, you
.experience_level
, 0, buf
));
3343 // recalculate for game
3347 if (you
.experience_level
> you
.max_level
)
3348 you
.max_level
= you
.experience_level
;
3350 xom_is_stimulated(16);
3352 learned_something_new(HINT_NEW_LEVEL
);
3355 while (you
.experience
> exp_needed(you
.max_level
+ 2))
3357 ASSERT(you
.experience_level
== 27);
3358 ASSERT(you
.max_level
< 127);
3360 if (you
.species
== SP_CAT
)
3361 _felid_extra_life();
3364 redraw_skill(you
.your_name
, player_title());
3366 // Hints mode arbitrarily ends at xp 7.
3367 if (crawl_state
.game_is_hints() && you
.experience_level
>= 7)
3371 // Here's a question for you: does the ordering of mods make a difference?
3372 // (yes) -- are these things in the right order of application to stealth?
3373 // - 12mar2000 {dlb}
3374 int check_stealth(void)
3376 ASSERT(!crawl_state
.game_is_arena());
3378 // Extreme stealthiness can be enforced by wizmode stealth setting.
3379 if (you
.skills
[SK_STEALTH
] > 27)
3383 if (you
.attribute
[ATTR_SHADOWS
] || you
.berserk() || you
.stat_zero
[STAT_DEX
])
3386 int stealth
= you
.dex() * 3;
3389 if (player_genus(GENPC_DRACONIAN
) && you
.species
!= SP_GREY_DRACONIAN
)
3393 switch (you
.species
) // why not use body_size here?
3404 // Thirsty/bat-form vampires are (much) more stealthy
3405 if (you
.hunger_state
== HS_STARVING
)
3407 else if (player_in_bat_form()
3408 || you
.hunger_state
<= HS_NEAR_STARVING
)
3412 else if (you
.hunger_state
< HS_SATIATED
)
3420 case SP_GREY_DRACONIAN
:
3421 case SP_NAGA
: // not small but very good at stealth
3436 case TRAN_ICE_BEAST
:
3440 race_mod
-= 3; // depends on the base race
3446 race_mod
= 9; // trotters, oinking...
3449 if (you
.species
!= SP_VAMPIRE
)
3452 case TRAN_BLADE_HANDS
:
3453 if (you
.species
== SP_CAT
&& !you
.airborne())
3454 stealth
-= 50; // a constant penalty
3457 race_mod
++; // intentionally tiny, lich form is already overpowered
3463 stealth
+= you
.skill(SK_STEALTH
) * race_mod
;
3465 if (you
.burden_state
> BS_UNENCUMBERED
)
3466 stealth
/= you
.burden_state
;
3471 const item_def
*arm
= you
.slot_item(EQ_BODY_ARMOUR
, false);
3472 const item_def
*cloak
= you
.slot_item(EQ_CLOAK
, false);
3473 const item_def
*boots
= you
.slot_item(EQ_BOOTS
, false);
3477 // [ds] New stealth penalty formula from rob: SP = 6 * (EP^2)
3478 const int ep
= -property(*arm
, PARM_EVASION
);
3479 const int penalty
= 6 * ep
* ep
;
3481 dprf("Stealth penalty for armour (ep: %d): %d", ep
, penalty
);
3486 if (cloak
&& get_equip_race(*cloak
) == ISFLAG_ELVEN
)
3491 if (get_armour_ego_type(*boots
) == SPARM_STEALTH
)
3494 if (get_equip_race(*boots
) == ISFLAG_ELVEN
)
3498 if (you
.duration
[DUR_STEALTH
])
3501 if (you
.duration
[DUR_AGILITY
])
3504 stealth
+= scan_artefacts(ARTP_STEALTH
);
3508 else if (you
.in_water())
3510 // Merfolk can sneak up on monsters underwater -- bwr
3513 else if (!you
.can_swim() && !you
.extra_balanced())
3514 stealth
/= 2; // splashy-splashy
3516 else if (you
.species
== SP_CAT
&& !you
.form
)
3517 stealth
+= 20; // paws
3519 // Radiating silence is the negative complement of shouting all the
3520 // time... a sudden change from background noise to no noise is going
3521 // to clue anything in to the fact that something is very wrong...
3522 // a personal silence spell would naturally be different, but this
3523 // silence radiates for a distance and prevents monster spellcasting,
3524 // which pretty much gives away the stealth game.
3525 // this penalty is dependent on the actual amount of ambient noise
3526 // in the level -doy
3527 if (you
.duration
[DUR_SILENCE
])
3528 stealth
-= 50 + current_level_ambient_noise();
3531 stealth
+= 25 * player_mutation_level(MUT_THIN_SKELETAL_STRUCTURE
);
3532 stealth
+= 40 * player_mutation_level(MUT_NIGHTSTALKER
);
3533 if (player_mutation_level(MUT_TRANSLUCENT_SKIN
) > 1)
3534 stealth
+= 20 * (player_mutation_level(MUT_TRANSLUCENT_SKIN
) - 1);
3536 // it's easier to be stealthy when there's a lot of background noise
3537 stealth
+= 2 * current_level_ambient_noise();
3539 stealth
= std::max(0, stealth
);
3544 // Returns the medium duration value which is usually announced by a special
3545 // message ("XY is about to time out") or a change of colour in the
3547 // Note that these values cannot be relied on when playing since there are
3548 // random decrements precisely to avoid this.
3549 int get_expiration_threshold(duration_type dur
)
3553 case DUR_QUAD_DAMAGE
:
3554 return (3 * BASELINE_DELAY
); // per client.qc
3556 case DUR_FIRE_SHIELD
:
3557 case DUR_SILENCE
: // no message
3558 return (5 * BASELINE_DELAY
);
3560 case DUR_DEFLECT_MISSILES
:
3561 case DUR_REPEL_MISSILES
:
3562 case DUR_REGENERATION
:
3563 case DUR_INSULATION
:
3564 case DUR_RESIST_POISON
:
3565 case DUR_RESIST_FIRE
:
3566 case DUR_RESIST_COLD
:
3572 case DUR_ICY_ARMOUR
:
3573 case DUR_PHASE_SHIFT
:
3574 case DUR_CONTROL_TELEPORT
:
3575 case DUR_DEATH_CHANNEL
:
3576 case DUR_SEE_INVISIBLE
:
3577 return (6 * BASELINE_DELAY
);
3579 case DUR_LEVITATION
:
3580 case DUR_TRANSFORMATION
: // not on status
3581 case DUR_DEATHS_DOOR
: // not on status
3583 return (10 * BASELINE_DELAY
);
3585 // These get no messages when they "flicker".
3588 return (15 * BASELINE_DELAY
);
3590 case DUR_CONFUSING_TOUCH
:
3591 return (20 * BASELINE_DELAY
);
3598 // Is a given duration about to expire?
3599 bool dur_expiring(duration_type dur
)
3601 const int value
= you
.duration
[dur
];
3605 return (value
<= get_expiration_threshold(dur
));
3608 static void _output_expiring_message(duration_type dur
, const char* msg
)
3610 if (you
.duration
[dur
])
3612 const bool expires
= dur_expiring(dur
);
3613 mprf("%s%s", expires
? "Expiring: " : "", msg
);
3617 static void _display_vampire_status()
3619 std::string msg
= "At your current hunger state you ";
3620 std::vector
<std::string
> attrib
;
3622 switch (you
.hunger_state
)
3625 attrib
.push_back("resist poison");
3626 attrib
.push_back("significantly resist cold");
3627 attrib
.push_back("strongly resist negative energy");
3628 attrib
.push_back("resist torment");
3629 attrib
.push_back("do not heal.");
3631 case HS_NEAR_STARVING
:
3632 attrib
.push_back("resist poison");
3633 attrib
.push_back("significantly resist cold");
3634 attrib
.push_back("strongly resist negative energy");
3635 attrib
.push_back("have an extremely slow metabolism");
3636 attrib
.push_back("heal slowly.");
3639 case HS_VERY_HUNGRY
:
3640 attrib
.push_back("resist poison");
3641 attrib
.push_back("resist cold");
3642 attrib
.push_back("significantly resist negative energy");
3643 if (you
.hunger_state
== HS_HUNGRY
)
3644 attrib
.push_back("have a slow metabolism");
3646 attrib
.push_back("have a very slow metabolism");
3647 attrib
.push_back("heal slowly.");
3650 attrib
.push_back("resist negative energy.");
3653 attrib
.push_back("have a fast metabolism");
3654 attrib
.push_back("heal quickly.");
3657 attrib
.push_back("have a very fast metabolism");
3658 attrib
.push_back("heal quickly.");
3661 attrib
.push_back("have an extremely fast metabolism");
3662 attrib
.push_back("heal extremely quickly.");
3666 if (!attrib
.empty())
3668 msg
+= comma_separated_line(attrib
.begin(), attrib
.end());
3673 static void _display_movement_speed()
3675 const int move_cost
= (player_speed() * player_movement_speed()) / 10;
3677 const bool water
= you
.in_water();
3678 const bool swim
= you
.swimming();
3680 const bool lev
= you
.airborne();
3681 const bool fly
= (you
.flight_mode() == FL_FLY
);
3682 const bool swift
= (you
.duration
[DUR_SWIFTNESS
] > 0);
3684 mprf("Your %s speed is %s%s%s.",
3685 // order is important for these:
3686 (swim
) ? "swimming" :
3687 (water
) ? "wading" :
3689 (lev
) ? "levitating"
3692 (water
&& !swim
) ? "uncertain and " :
3693 (!water
&& swift
) ? "aided by the wind" : "",
3695 (!water
&& swift
) ? ((move_cost
>= 10) ? ", but still "
3699 (move_cost
< 8) ? "very quick" :
3700 (move_cost
< 10) ? "quick" :
3701 (move_cost
== 10) ? "average" :
3702 (move_cost
< 13) ? "slow"
3706 static void _display_tohit()
3708 const int to_hit
= calc_your_to_hit(false) * 2;
3709 dprf("To-hit: %d", to_hit
);
3711 // Messages based largely on percentage chance of missing the
3712 // average EV 10 humanoid, and very agile EV 30 (pretty much
3713 // max EV for monsters currently).
3715 // "awkward" - need lucky hit (less than EV)
3716 // "difficult" - worse than 2 in 3
3717 // "hard" - worse than fair chance
3718 mprf("%s given your current equipment.",
3719 (to_hit < 1) ? "You are completely incapable of fighting" :
3720 (to_hit < 5) ? "Hitting even clumsy monsters is extremely awkward" :
3721 (to_hit < 10) ? "Hitting average monsters is awkward" :
3722 (to_hit < 15) ? "Hitting average monsters is difficult" :
3723 (to_hit < 20) ? "Hitting average monsters is hard" :
3724 (to_hit < 30) ? "Very agile monsters are a bit awkward to hit" :
3725 (to_hit < 45) ? "Very agile monsters are a bit difficult to hit" :
3726 (to_hit < 60) ? "Very agile monsters are a bit hard to hit" :
3727 (to_hit < 100) ? "You feel comfortable with your ability to fight"
3728 : "You feel confident with your ability to fight");
3732 static std::string
_attack_delay_desc(int attack_delay
)
3734 return ((attack_delay
>= 200) ? "extremely slow" :
3735 (attack_delay
>= 155) ? "very slow" :
3736 (attack_delay
>= 125) ? "quite slow" :
3737 (attack_delay
>= 105) ? "below average" :
3738 (attack_delay
>= 95) ? "average" :
3739 (attack_delay
>= 75) ? "above average" :
3740 (attack_delay
>= 55) ? "quite fast" :
3741 (attack_delay
>= 45) ? "very fast" :
3742 (attack_delay
>= 35) ? "extremely fast" :
3746 static void _display_attack_delay()
3748 const random_var delay
= calc_your_attack_delay();
3750 // Scale to fit the displayed weapon base delay, i.e.,
3751 // normal speed is 100 (as in 100%).
3752 // We could also compute the variance if desired.
3753 int avg
= static_cast<int>(round(10 * delay
.expected()));
3755 // Haste wasn't counted here, but let's show finesse.
3756 // Can't be done in the above function because of interactions with
3758 if (you
.duration
[DUR_FINESSE
])
3759 avg
= std::max(20, avg
/ 2);
3761 std::string msg
= "Your attack speed is " + _attack_delay_desc(avg
) + ".";
3763 #ifdef DEBUG_DIAGNOSTICS
3766 const int max
= 10 * delay
.max();
3768 msg
+= colour_string(make_stringf(" %d%% (max %d%%)", avg
, max
),
3769 channel_to_colour(MSGCH_DIAGNOSTICS
));
3776 void display_char_status()
3778 if (you
.is_undead
== US_SEMI_UNDEAD
&& you
.hunger_state
== HS_ENGORGED
)
3779 mpr("You feel almost alive.");
3780 else if (you
.is_undead
)
3781 mpr("You are undead.");
3782 else if (you
.duration
[DUR_DEATHS_DOOR
])
3784 _output_expiring_message(DUR_DEATHS_DOOR
,
3785 "You are standing in death's doorway.");
3788 mpr("You are alive.");
3790 const int halo_size
= you
.halo_radius2();
3794 mpr("You are illuminated by a large divine halo.");
3795 else if (halo_size
> 10)
3796 mpr("You are illuminated by a divine halo.");
3798 mpr("You are illuminated by a small divine halo.");
3800 else if (you
.haloed())
3801 mpr("An external divine halo illuminates you.");
3803 if (you
.species
== SP_VAMPIRE
)
3804 _display_vampire_status();
3806 static int statuses
[] = {
3807 STATUS_STR_ZERO
, STATUS_INT_ZERO
, STATUS_DEX_ZERO
,
3808 DUR_TRANSFORMATION
, STATUS_BURDEN
, DUR_SAGE
, DUR_BARGAIN
,
3809 DUR_BREATH_WEAPON
, DUR_LIQUID_FLAMES
, DUR_FIRE_SHIELD
, DUR_ICY_ARMOUR
,
3810 DUR_REPEL_MISSILES
, DUR_DEFLECT_MISSILES
, DUR_JELLY_PRAYER
,
3811 STATUS_REGENERATION
, DUR_SWIFTNESS
, DUR_RESIST_POISON
,
3812 DUR_RESIST_COLD
, DUR_RESIST_FIRE
, DUR_INSULATION
, DUR_STONEMAIL
,
3813 DUR_TELEPORT
, DUR_CONTROL_TELEPORT
,
3814 DUR_DEATH_CHANNEL
, DUR_PHASE_SHIFT
, DUR_SILENCE
, DUR_STONESKIN
,
3815 DUR_SEE_INVISIBLE
, DUR_INVIS
, DUR_CONF
, STATUS_BEHELD
,
3816 DUR_PARALYSIS
, DUR_PETRIFIED
, DUR_SLEEP
, DUR_EXHAUSTED
,
3817 STATUS_SPEED
, DUR_MIGHT
, DUR_BRILLIANCE
, DUR_AGILITY
,
3818 DUR_DIVINE_VIGOUR
, DUR_DIVINE_STAMINA
, DUR_BERSERK
,
3819 STATUS_AIRBORNE
, STATUS_NET
, DUR_POISONING
, STATUS_SICK
,
3820 STATUS_ROT
, STATUS_GLOW
, DUR_CONFUSING_TOUCH
, DUR_SURE_BLADE
,
3821 DUR_AFRAID
, DUR_MIRROR_DAMAGE
, DUR_SCRYING
, STATUS_CLINGING
,
3825 for (unsigned i
= 0; i
< ARRAYSZ(statuses
); ++i
)
3827 fill_status_info(statuses
[i
], &inf
);
3828 if (!inf
.long_text
.empty())
3832 _display_movement_speed();
3834 _display_attack_delay();
3837 mprf("You are %s resistant to hostile enchantments.",
3838 magic_res_adjective(player_res_magic(false)).c_str());
3840 // character evaluates their ability to sneak around:
3841 mprf("You feel %s.", stealth_desc(check_stealth()).c_str());
3842 dprf("stealth: %d", check_stealth());
3845 bool player_item_conserve(bool calc_unid
)
3847 return (player_equip(EQ_AMULET
, AMU_CONSERVATION
, calc_unid
)
3848 || player_equip_ego_type(EQ_ALL_ARMOUR
, SPARM_PRESERVATION
));
3851 int player_mental_clarity(bool calc_unid
, bool items
)
3853 int ret
= 3 * player_equip(EQ_AMULET
, AMU_CLARITY
, calc_unid
) * items
3854 + player_mutation_level(MUT_CLARITY
);
3856 if (you
.religion
== GOD_ASHENZARI
&& you
.piety
>= piety_breakpoint(2)
3857 && !player_under_penance())
3862 return ((ret
> 3) ? 3 : ret
);
3865 int player_spirit_shield(bool calc_unid
)
3867 return player_equip(EQ_AMULET
, AMU_GUARDIAN_SPIRIT
, calc_unid
)
3868 + player_equip_ego_type(EQ_ALL_ARMOUR
, SPARM_SPIRIT_SHIELD
);
3871 // Returns whether the player has the effect of the amulet from a
3872 // non-amulet source.
3873 bool extrinsic_amulet_effect(jewellery_type amulet
)
3877 case AMU_CONTROLLED_FLIGHT
:
3878 return (you
.duration
[DUR_CONTROLLED_FLIGHT
]
3879 || player_genus(GENPC_DRACONIAN
)
3880 || (you
.species
== SP_KENKU
&& you
.experience_level
>= 5)
3881 || you
.form
== TRAN_DRAGON
3882 || you
.form
== TRAN_BAT
);
3884 return player_mental_clarity(true, false);
3885 case AMU_RESIST_CORROSION
:
3886 if (you
.religion
== GOD_JIYVA
&& you
.piety
>= piety_breakpoint(2))
3888 // else fall-through
3889 case AMU_CONSERVATION
:
3890 return (player_equip_ego_type(EQ_ALL_ARMOUR
, SPARM_PRESERVATION
));
3891 case AMU_THE_GOURMAND
:
3892 return (player_mutation_level(MUT_GOURMAND
) > 0);
3898 bool wearing_amulet(jewellery_type amulet
, bool calc_unid
, bool ignore_extrinsic
)
3900 if (!ignore_extrinsic
&& extrinsic_amulet_effect(amulet
))
3903 if (!player_wearing_slot(EQ_AMULET
))
3906 const item_def
& amu(you
.inv
[you
.equip
[EQ_AMULET
]]);
3907 return (amu
.sub_type
== amulet
&& (calc_unid
|| item_type_known(amu
)));
3910 static int _species_exp_mod(species_type species
)
3912 if (player_genus(GENPC_DRACONIAN
, species
))
3914 else if (player_genus(GENPC_DWARVEN
, species
))
3951 unsigned int exp_needed(int lev
)
3955 unsigned int level
= 0;
3958 // Section 1: levels 1- 5, second derivative goes 10-10-20-30.
3959 // Section 2: levels 6-13, second derivative is exponential/doubling.
3960 // Section 3: levels 14-27, second derivative is constant at 6000.
3962 // Section three is constant so we end up with high levels at about
3963 // their old values (level 27 at 850k), without delta2 ever decreasing.
3964 // The values that are considerably different (ie level 13 is now 29000,
3965 // down from 41040 are because the second derivative goes from 9040 to
3966 // 1430 at that point in the original, and then slowly builds back
3967 // up again). This function smoothes out the old level 10-15 area
3972 // level xp delta delta2
3973 // ===== ======= ===== ======
3984 // 11 7760 3850 1920
3985 // 12 15450 7690 3840
3986 // 13 29000 13550 5860
3987 // 14 48500 19500 5950
3988 // 15 74000 25500 6000
3989 // 16 105500 31500 6000
3990 // 17 143000 37500 6000
3991 // 18 186500 43500 6000
3992 // 19 236000 49500 6000
3993 // 20 291500 55500 6000
3994 // 21 353000 61500 6000
3995 // 22 420500 67500 6000
3996 // 23 494000 73500 6000
3997 // 24 573500 79500 6000
3998 // 25 659000 85500 6000
3999 // 26 750500 91500 6000
4000 // 27 848000 97500 6000
4022 level
= 10 + 10 * lev
+ (60 << lev
);
4027 level
= 15500 + 10500 * lev
+ 3000 * lev
* lev
;
4032 return ((level
- 1) * _species_exp_mod(you
.species
) / 10);
4035 // returns bonuses from rings of slaying, etc.
4036 int slaying_bonus(weapon_property_type which_affected
, bool ranged
)
4040 if (which_affected
== PWPN_HIT
)
4042 ret
+= player_equip(EQ_RINGS_PLUS
, RING_SLAYING
);
4043 ret
+= scan_artefacts(ARTP_ACCURACY
);
4044 if (player_equip_ego_type(EQ_GLOVES
, SPARM_ARCHERY
))
4045 ret
+= ranged
? 5 : -1;
4047 else if (which_affected
== PWPN_DAMAGE
)
4049 ret
+= player_equip(EQ_RINGS_PLUS2
, RING_SLAYING
);
4050 ret
+= scan_artefacts(ARTP_DAMAGE
);
4051 if (player_equip_ego_type(EQ_GLOVES
, SPARM_ARCHERY
))
4052 ret
+= ranged
? 3 : -1;
4055 ret
+= std::min(you
.duration
[DUR_SLAYING
] / (13 * BASELINE_DELAY
), 6);
4060 // Checks each equip slot for an evokable item (jewellery or randart).
4061 // Returns true if any of these has the same ability as the one handed in.
4062 bool items_give_ability(const int slot
, artefact_prop_type abil
)
4064 for (int i
= EQ_WEAPON
; i
< NUM_EQUIP
; i
++)
4066 if (!player_wearing_slot(i
))
4069 const int eq
= you
.equip
[i
];
4071 // skip item to compare with
4075 // only weapons give their effects when in our hands
4076 if (i
== EQ_WEAPON
&& you
.inv
[ eq
].base_type
!= OBJ_WEAPONS
)
4079 if (eq
== EQ_LEFT_RING
|| eq
== EQ_RIGHT_RING
)
4081 if (abil
== ARTP_LEVITATE
&& you
.inv
[eq
].sub_type
== RING_LEVITATION
)
4083 if (abil
== ARTP_INVISIBLE
&& you
.inv
[eq
].sub_type
== RING_INVISIBILITY
)
4086 else if (eq
== EQ_AMULET
)
4088 if (abil
== ARTP_BERSERK
&& you
.inv
[eq
].sub_type
== AMU_RAGE
)
4092 // other items are not evokable
4093 if (!is_artefact(you
.inv
[ eq
]))
4096 if (artefact_wpn_property(you
.inv
[ eq
], abil
))
4100 // none of the equipped items possesses this ability
4104 // Checks each equip slot for a randart, and adds up all of those with
4105 // a given property. Slow if any randarts are worn, so avoid where
4107 int scan_artefacts(artefact_prop_type which_property
, bool calc_unid
)
4111 for (int i
= EQ_WEAPON
; i
< NUM_EQUIP
; ++i
)
4113 if (you
.melded
[i
] && which_property
!= ARTP_PONDEROUS
4114 || you
.equip
[i
] == -1)
4119 const int eq
= you
.equip
[i
];
4121 // Only weapons give their effects when in our hands.
4122 if (i
== EQ_WEAPON
&& you
.inv
[ eq
].base_type
!= OBJ_WEAPONS
)
4125 if (!is_artefact(you
.inv
[ eq
]))
4128 // Ignore unidentified items [TileCrawl dump enhancements].
4129 if (!item_ident(you
.inv
[ eq
], ISFLAG_KNOW_PROPERTIES
)
4135 retval
+= artefact_wpn_property(you
.inv
[ eq
], which_property
);
4141 void dec_hp(int hp_loss
, bool fatal
, const char *aux
)
4143 ASSERT(!crawl_state
.game_is_arena());
4145 if (!fatal
&& you
.hp
< 1)
4148 if (!fatal
&& hp_loss
>= you
.hp
)
4149 hp_loss
= you
.hp
- 1;
4154 // If it's not fatal, use ouch() so that notes can be taken. If it IS
4155 // fatal, somebody else is doing the bookkeeping, and we don't want to mess
4158 ouch(hp_loss
, NON_MONSTER
, KILLED_BY_SOMETHING
, aux
);
4162 you
.redraw_hit_points
= true;
4165 void dec_mp(int mp_loss
)
4167 ASSERT(!crawl_state
.game_is_arena());
4172 you
.magic_points
-= mp_loss
;
4174 you
.magic_points
= std::max(0, you
.magic_points
);
4176 if (Options
.magic_point_warning
4177 && you
.magic_points
< (you
.max_magic_points
4178 * Options
.magic_point_warning
) / 100)
4180 mpr("* * * LOW MAGIC WARNING * * *", MSGCH_DANGER
);
4183 take_note(Note(NOTE_MP_CHANGE
, you
.magic_points
, you
.max_magic_points
));
4184 you
.redraw_magic_points
= true;
4187 bool enough_hp(int minimum
, bool suppress_msg
)
4189 ASSERT(!crawl_state
.game_is_arena());
4191 // We want to at least keep 1 HP. -- bwr
4192 if (you
.hp
< minimum
+ 1)
4195 mpr("You haven't enough vitality at the moment.");
4197 crawl_state
.cancel_cmd_again();
4198 crawl_state
.cancel_cmd_repeat();
4205 bool enough_mp(int minimum
, bool suppress_msg
, bool include_items
)
4207 ASSERT(!crawl_state
.game_is_arena());
4211 if (get_real_mp(include_items
) < minimum
)
4214 mpr("You haven't enough magic capacity.");
4216 else if (you
.magic_points
< minimum
)
4219 mpr("You haven't enough magic at the moment.");
4226 crawl_state
.cancel_cmd_again();
4227 crawl_state
.cancel_cmd_repeat();
4233 bool enough_xp(int minimum
, bool suppress_msg
)
4235 ASSERT(!crawl_state
.game_is_arena());
4237 if (you
.exp_available
< minimum
)
4240 mpr("You haven't enough experience in your experience pool.");
4242 crawl_state
.cancel_cmd_again();
4243 crawl_state
.cancel_cmd_repeat();
4249 // Note that "max_too" refers to the base potential, the actual
4250 // resulting max value is subject to penalties, bonuses, and scalings.
4251 void inc_mp(int mp_gain
, bool max_too
)
4253 ASSERT(!crawl_state
.game_is_arena());
4258 bool wasnt_max
= (you
.magic_points
< you
.max_magic_points
);
4260 you
.magic_points
+= mp_gain
;
4263 inc_max_mp(mp_gain
);
4265 if (you
.magic_points
> you
.max_magic_points
)
4266 you
.magic_points
= you
.max_magic_points
;
4268 if (wasnt_max
&& you
.magic_points
== you
.max_magic_points
)
4269 interrupt_activity(AI_FULL_MP
);
4271 take_note(Note(NOTE_MP_CHANGE
, you
.magic_points
, you
.max_magic_points
));
4272 you
.redraw_magic_points
= true;
4275 // Note that "max_too" refers to the base potential, the actual
4276 // resulting max value is subject to penalties, bonuses, and scalings.
4277 // To avoid message spam, don't take notes when HP increases.
4278 void inc_hp(int hp_gain
, bool max_too
)
4280 ASSERT(!crawl_state
.game_is_arena());
4285 bool wasnt_max
= (you
.hp
< you
.hp_max
);
4290 inc_max_hp(hp_gain
);
4292 if (you
.hp
> you
.hp_max
)
4293 you
.hp
= you
.hp_max
;
4295 if (wasnt_max
&& you
.hp
== you
.hp_max
)
4296 interrupt_activity(AI_FULL_HP
);
4298 you
.redraw_hit_points
= true;
4301 void rot_hp(int hp_loss
)
4303 you
.base_hp
-= hp_loss
;
4306 if (you
.species
!= SP_GHOUL
)
4307 xom_is_stimulated(hp_loss
* 32);
4309 you
.redraw_hit_points
= true;
4312 void unrot_hp(int hp_recovered
)
4314 if (hp_recovered
>= 5000 - you
.base_hp
)
4317 you
.base_hp
+= hp_recovered
;
4321 you
.redraw_hit_points
= true;
4326 return (5000 - you
.base_hp
);
4329 void rot_mp(int mp_loss
)
4331 you
.base_magic_points
-= mp_loss
;
4334 you
.redraw_magic_points
= true;
4337 void inc_max_hp(int hp_gain
)
4339 you
.base_hp2
+= hp_gain
;
4342 take_note(Note(NOTE_MAXHP_CHANGE
, you
.hp_max
));
4343 you
.redraw_hit_points
= true;
4346 void dec_max_hp(int hp_loss
)
4348 you
.base_hp2
-= hp_loss
;
4351 take_note(Note(NOTE_MAXHP_CHANGE
, you
.hp_max
));
4352 you
.redraw_hit_points
= true;
4355 void inc_max_mp(int mp_gain
)
4357 you
.base_magic_points2
+= mp_gain
;
4360 take_note(Note(NOTE_MAXMP_CHANGE
, you
.max_magic_points
));
4361 you
.redraw_magic_points
= true;
4364 void dec_max_mp(int mp_loss
)
4366 you
.base_magic_points2
-= mp_loss
;
4369 take_note(Note(NOTE_MAXMP_CHANGE
, you
.max_magic_points
));
4370 you
.redraw_magic_points
= true;
4373 // Use of floor: false = hp max, true = hp min. {dlb}
4374 void deflate_hp(int new_level
, bool floor
)
4376 ASSERT(!crawl_state
.game_is_arena());
4378 if (floor
&& you
.hp
< new_level
)
4380 else if (!floor
&& you
.hp
> new_level
)
4383 // Must remain outside conditional, given code usage. {dlb}
4384 you
.redraw_hit_points
= true;
4387 // Note that "max_too" refers to the base potential, the actual
4388 // resulting max value is subject to penalties, bonuses, and scalings.
4389 void set_hp(int new_amount
, bool max_too
)
4391 ASSERT(!crawl_state
.game_is_arena());
4393 you
.hp
= new_amount
;
4395 if (max_too
&& you
.hp_max
!= new_amount
)
4397 you
.base_hp2
= 5000 + new_amount
;
4401 if (you
.hp
> you
.hp_max
)
4402 you
.hp
= you
.hp_max
;
4405 take_note(Note(NOTE_MAXHP_CHANGE
, you
.hp_max
));
4407 // Must remain outside conditional, given code usage. {dlb}
4408 you
.redraw_hit_points
= true;
4411 // Note that "max_too" refers to the base potential, the actual
4412 // resulting max value is subject to penalties, bonuses, and scalings.
4413 void set_mp(int new_amount
, bool max_too
)
4415 ASSERT(!crawl_state
.game_is_arena());
4417 you
.magic_points
= new_amount
;
4419 if (max_too
&& you
.max_magic_points
!= new_amount
)
4421 // Note that this gets scaled down for values > 18.
4422 you
.base_magic_points2
= 5000 + new_amount
;
4426 if (you
.magic_points
> you
.max_magic_points
)
4427 you
.magic_points
= you
.max_magic_points
;
4429 take_note(Note(NOTE_MP_CHANGE
, you
.magic_points
, you
.max_magic_points
));
4431 take_note(Note(NOTE_MAXMP_CHANGE
, you
.max_magic_points
));
4433 // Must remain outside conditional, given code usage. {dlb}
4434 you
.redraw_magic_points
= true;
4437 // If trans is true, being berserk and/or transformed is taken into account
4438 // here. Else, the base hp is calculated. If rotted is true, calculate the
4439 // real max hp you'd have if the rotting was cured.
4440 int get_real_hp(bool trans
, bool rotted
)
4444 hitp
= (you
.base_hp
- 5000) + (you
.base_hp2
- 5000);
4445 // Important: we shouldn't add Heroism boosts here.
4446 hitp
+= (you
.experience_level
* you
.skills
[SK_FIGHTING
]) /
4447 (you
.species
== SP_CAT
? 7 : 5);
4449 // Being berserk makes you resistant to damage. I don't know why.
4450 if (trans
&& you
.berserk())
4451 hitp
= hitp
* 3 / 2;
4455 // Some transformations give you extra hp.
4462 case TRAN_ICE_BEAST
:
4476 hitp
+= player_rotted();
4478 // Frail and robust mutations, divine vigour, and rugged scale mut.
4479 hitp
*= 100 + (player_mutation_level(MUT_ROBUST
) * 10)
4480 + (you
.attribute
[ATTR_DIVINE_VIGOUR
] * 5)
4481 + (player_mutation_level(MUT_RUGGED_BROWN_SCALES
) ? player_mutation_level(MUT_RUGGED_BROWN_SCALES
) * 2 + 1 : 0)
4482 - (player_mutation_level(MUT_FRAIL
) * 10);
4488 int get_real_mp(bool include_items
)
4490 // base_magic_points2 accounts for species
4491 int enp
= (you
.base_magic_points2
- 5000);
4493 int spell_extra
= (you
.experience_level
* you
.skills
[SK_SPELLCASTING
]) / 4;
4494 int invoc_extra
= (you
.experience_level
* you
.skills
[SK_INVOCATIONS
]) / 6;
4496 enp
+= std::max(spell_extra
, invoc_extra
);
4497 enp
= stepdown_value(enp
, 9, 18, 45, 100);
4499 // This is our "rotted" base (applied after scaling):
4500 enp
+= (you
.base_magic_points
- 5000);
4502 // Yes, we really do want this duplication... this is so the stepdown
4503 // doesn't truncate before we apply the rotted base. We're doing this
4504 // the nice way. -- bwr
4505 enp
= std::min(enp
, 50);
4507 // Now applied after scaling so that power items are more useful -- bwr
4509 enp
+= player_magical_power();
4511 // Analogous to ROBUST/FRAIL
4512 enp
*= 100 + (player_mutation_level(MUT_HIGH_MAGIC
) * 10)
4513 + (you
.attribute
[ATTR_DIVINE_VIGOUR
] * 5)
4514 - (player_mutation_level(MUT_LOW_MAGIC
) * 10);
4518 enp
= 50 + ((enp
- 50) / 2);
4520 if (include_items
&& player_equip_ego_type(EQ_WEAPON
, SPWPN_ANTIMAGIC
))
4523 enp
= std::max(enp
, 0);
4528 int get_contamination_level()
4530 const int glow
= you
.magic_contamination
;
4533 return (glow
/ 20 + 3);
4548 std::string
describe_contamination(int cont
)
4551 return ("You are engulfed in a nimbus of crackling magics!");
4553 return ("Your entire body has taken on an eerie glow!");
4556 return (make_stringf("You are %s with residual magics%s",
4557 (cont
== 4) ? "practically glowing" :
4558 (cont
== 3) ? "heavily infused" :
4559 (cont
== 2) ? "contaminated"
4560 : "lightly contaminated",
4561 (cont
== 4) ? "!" : "."));
4564 return ("You are very lightly contaminated with residual magic.");
4569 // controlled is true if the player actively did something to cause
4570 // contamination (such as drink a known potion of resistance),
4571 // status_only is true only for the status output
4572 void contaminate_player(int change
, bool controlled
, bool msg
)
4574 ASSERT(!crawl_state
.game_is_arena());
4576 int old_amount
= you
.magic_contamination
;
4577 int old_level
= get_contamination_level();
4580 you
.magic_contamination
=
4581 std::max(0, std::min(250, you
.magic_contamination
+ change
));
4583 new_level
= get_contamination_level();
4585 if (you
.magic_contamination
!= old_amount
)
4586 dprf("change: %d radiation: %d", change
, you
.magic_contamination
);
4588 if (msg
&& new_level
>= 1 && old_level
<= 1 && new_level
!= old_level
)
4589 mpr(describe_contamination(new_level
));
4590 else if (msg
&& new_level
!= old_level
)
4592 if (old_level
== 1 && new_level
== 0)
4593 mpr("Your magical contamination has completely faded away.");
4596 mprf((change
> 0) ? MSGCH_WARN
: MSGCH_RECOVERY
,
4597 "You feel %s contaminated with magical energies.",
4598 (change
> 0) ? "more" : "less");
4602 xom_is_stimulated(new_level
* 32);
4604 if (old_level
> 1 && new_level
<= 1
4605 && you
.duration
[DUR_INVIS
] && !you
.backlit())
4607 mpr("You fade completely from view now that you are no longer "
4608 "glowing from magical contamination.");
4612 if (you
.magic_contamination
> 0)
4613 learned_something_new(HINT_GLOWING
);
4615 // Zin doesn't like mutations or mutagenic radiation.
4616 if (you
.religion
== GOD_ZIN
)
4618 // Whenever the glow status is first reached, give a warning message.
4619 if (old_level
< 2 && new_level
>= 2)
4620 did_god_conduct(DID_CAUSE_GLOWING
, 0, false);
4621 // If the player actively did something to increase glowing,
4622 // Zin is displeased.
4623 else if (controlled
&& change
> 0 && old_level
> 1)
4624 did_god_conduct(DID_CAUSE_GLOWING
, 1 + new_level
, true);
4628 bool confuse_player(int amount
, bool resistable
)
4630 ASSERT(!crawl_state
.game_is_arena());
4635 if (resistable
&& player_mental_clarity())
4637 mpr("You feel momentarily confused.");
4638 // Identify the amulet if necessary.
4639 if (player_equip(EQ_AMULET
, AMU_CLARITY
, true))
4641 item_def
* const amu
= you
.slot_item(EQ_AMULET
, false);
4642 if (!item_ident(*amu
, ISFLAG_KNOW_TYPE
))
4644 set_ident_type(amu
->base_type
, amu
->sub_type
, ID_KNOWN_TYPE
);
4645 set_ident_flags(*amu
, ISFLAG_KNOW_TYPE
);
4646 mprf("You are wearing: %s",
4647 amu
->name(DESC_INVENTORY_EQUIP
).c_str());
4653 const int old_value
= you
.duration
[DUR_CONF
];
4654 you
.increase_duration(DUR_CONF
, amount
, 40);
4656 if (you
.duration
[DUR_CONF
] > old_value
)
4658 you
.check_awaken(500);
4660 mprf(MSGCH_WARN
, "You are %sconfused.",
4661 old_value
> 0 ? "more " : "");
4663 learned_something_new(HINT_YOU_ENCHANTED
);
4665 xom_is_stimulated((you
.duration
[DUR_CONF
] - old_value
)
4672 bool curare_hits_player(int death_source
, int amount
, const bolt
&beam
)
4674 ASSERT(!crawl_state
.game_is_arena());
4676 if (player_res_poison() > 0)
4679 poison_player(amount
, beam
.get_source_name(), beam
.name
);
4683 if (you
.res_asphyx() <= 0)
4685 hurted
= roll_dice(2, 6);
4689 mpr("You have difficulty breathing.");
4690 ouch(hurted
, death_source
, KILLED_BY_CURARE
,
4691 "curare-induced apnoea");
4695 potion_effect(POT_SLOWING
, 2 + random2(4 + amount
));
4697 return (hurted
> 0);
4700 bool poison_player(int amount
, std::string source
, std::string source_aux
,
4703 ASSERT(!crawl_state
.game_is_arena());
4705 if (!force
&& player_res_poison() > 0 || amount
<= 0)
4708 const int old_value
= you
.duration
[DUR_POISONING
];
4709 you
.duration
[DUR_POISONING
] += amount
;
4711 if (you
.duration
[DUR_POISONING
] > 40)
4712 you
.duration
[DUR_POISONING
] = 40;
4714 if (you
.duration
[DUR_POISONING
] > old_value
)
4716 mprf(MSGCH_WARN
, "You are %spoisoned.",
4717 old_value
> 0 ? "more " : "");
4719 learned_something_new(HINT_YOU_POISON
);
4722 you
.props
["poisoner"] = source
;
4723 you
.props
["poison_aux"] = source_aux
;
4728 void dec_poison_player()
4730 // If Cheibriados has slowed your life processes, there's a
4731 // chance that your poison level is simply unaffected and
4732 // you aren't hurt by poison.
4733 if (GOD_CHEIBRIADOS
== you
.religion
4734 && you
.piety
>= piety_breakpoint(0)
4738 if (you
.duration
[DUR_POISONING
] > 0)
4740 if (x_chance_in_y(you
.duration
[DUR_POISONING
], 5))
4743 msg_channel_type channel
= MSGCH_PLAIN
;
4744 const char *adj
= "";
4746 if (you
.duration
[DUR_POISONING
] > 10
4747 && random2(you
.duration
[DUR_POISONING
]) >= 8)
4749 hurted
= random2(10) + 5;
4750 channel
= MSGCH_DANGER
;
4753 else if (you
.duration
[DUR_POISONING
] > 5 && coinflip())
4755 hurted
= coinflip() ? 3 : 2;
4756 channel
= MSGCH_WARN
;
4761 ouch(hurted
, NON_MONSTER
, KILLED_BY_POISON
);
4763 mprf(channel
, "You feel %ssick.", adj
);
4765 if ((you
.hp
== 1 && one_chance_in(3)) || one_chance_in(8))
4766 reduce_poison_player(1);
4771 void reduce_poison_player(int amount
)
4776 const int old_value
= you
.duration
[DUR_POISONING
];
4777 you
.duration
[DUR_POISONING
] -= amount
;
4779 if (you
.duration
[DUR_POISONING
] <= 0)
4781 you
.duration
[DUR_POISONING
] = 0;
4782 you
.props
.erase("poisoner");
4783 you
.props
.erase("poison_aux");
4786 if (you
.duration
[DUR_POISONING
] < old_value
)
4788 mprf(MSGCH_RECOVERY
, "You feel %sbetter.",
4789 you
.duration
[DUR_POISONING
] > 0 ? "a little " : "");
4793 bool miasma_player(std::string source
, std::string source_aux
)
4795 ASSERT(!crawl_state
.game_is_arena());
4797 if (you
.res_rotting())
4800 // Zin's protection.
4801 if (you
.religion
== GOD_ZIN
&& x_chance_in_y(you
.piety
, MAX_PIETY
))
4803 simple_god_message(" protects your body from miasma!");
4807 bool success
= poison_player(1, source
, source_aux
);
4809 if (you
.hp_max
> 4 && coinflip())
4815 if (one_chance_in(3))
4817 potion_effect(POT_SLOWING
, 5);
4824 bool napalm_player(int amount
)
4826 ASSERT(!crawl_state
.game_is_arena());
4828 if (player_res_sticky_flame() || amount
<= 0)
4831 const int old_value
= you
.duration
[DUR_LIQUID_FLAMES
];
4832 you
.increase_duration(DUR_LIQUID_FLAMES
, amount
, 100);
4834 if (you
.duration
[DUR_LIQUID_FLAMES
] > old_value
)
4835 mpr("You are covered in liquid flames!", MSGCH_WARN
);
4840 void dec_napalm_player(int delay
)
4842 if (you
.duration
[DUR_LIQUID_FLAMES
] > BASELINE_DELAY
)
4844 if (feat_is_watery(grd(you
.pos())))
4846 mpr("The flames go out!", MSGCH_WARN
);
4847 you
.duration
[DUR_LIQUID_FLAMES
] = 0;
4851 mpr("You are covered in liquid flames!", MSGCH_WARN
);
4853 expose_player_to_element(BEAM_NAPALM
, 12);
4855 const int res_fire
= player_res_fire();
4859 ouch((((random2avg(9, 2) + 1) * delay
) /
4860 (1 + (res_fire
* res_fire
))) / BASELINE_DELAY
, NON_MONSTER
,
4866 ouch(((random2avg(9, 2) + 1) * delay
) / BASELINE_DELAY
,
4867 NON_MONSTER
, KILLED_BY_BURNING
);
4871 ouch(((random2avg(9, 2) + 1) * delay
)
4872 / BASELINE_DELAY
, NON_MONSTER
, KILLED_BY_BURNING
);
4876 if (you
.duration
[DUR_CONDENSATION_SHIELD
] > 0)
4877 remove_condensation_shield();
4878 if (you
.duration
[DUR_ICY_ARMOUR
] > 0)
4879 remove_ice_armour();
4882 you
.duration
[DUR_LIQUID_FLAMES
] -= delay
;
4883 if (you
.duration
[DUR_LIQUID_FLAMES
] < 0)
4884 you
.duration
[DUR_LIQUID_FLAMES
] = 0;
4887 bool slow_player(int turns
)
4889 ASSERT(!crawl_state
.game_is_arena());
4894 if (stasis_blocks_effect(true, true, "%s rumbles.", 20, "%s rumbles."))
4897 // Doubling these values because moving while slowed takes twice the
4899 turns
= haste_mul(turns
);
4900 int threshold
= haste_mul(100);
4902 if (you
.duration
[DUR_SLOW
] >= threshold
* BASELINE_DELAY
)
4903 mpr("You already are as slow as you could be.");
4906 if (you
.duration
[DUR_SLOW
] == 0)
4907 mpr("You feel yourself slow down.");
4909 mpr("You feel as though you will be slow longer.");
4911 you
.increase_duration(DUR_SLOW
, turns
, threshold
);
4912 learned_something_new(HINT_YOU_ENCHANTED
);
4918 void dec_slow_player(int delay
)
4920 if (!you
.duration
[DUR_SLOW
])
4923 if (you
.duration
[DUR_SLOW
] > BASELINE_DELAY
)
4925 // Make slowing and hasting effects last as long.
4926 you
.duration
[DUR_SLOW
] -= you
.duration
[DUR_HASTE
]
4927 ? haste_mul(delay
) : delay
;
4929 if (you
.duration
[DUR_SLOW
] <= BASELINE_DELAY
)
4931 mpr("You feel yourself speed up.", MSGCH_DURATION
);
4932 you
.duration
[DUR_SLOW
] = 0;
4936 // Exhaustion should last as long as slowing.
4937 void dec_exhaust_player(int delay
)
4939 if (!you
.duration
[DUR_EXHAUSTED
])
4942 if (you
.duration
[DUR_EXHAUSTED
] > BASELINE_DELAY
)
4944 you
.duration
[DUR_EXHAUSTED
] -= you
.duration
[DUR_HASTE
]
4945 ? haste_mul(delay
) : delay
;
4947 if (you
.duration
[DUR_EXHAUSTED
] <= BASELINE_DELAY
)
4949 mpr("You feel less exhausted.", MSGCH_DURATION
);
4950 you
.duration
[DUR_EXHAUSTED
] = 0;
4954 bool haste_player(int turns
, bool rageext
)
4956 ASSERT(!crawl_state
.game_is_arena());
4961 if (stasis_blocks_effect(true, true, "%s emits a piercing whistle.", 20,
4962 "%s makes your neck tingle."))
4967 // Cutting the nominal turns in half since hasted actions take half the
4969 turns
= haste_div(turns
);
4970 const int threshold
= 40;
4972 if (!you
.duration
[DUR_HASTE
])
4973 mpr("You feel yourself speed up.");
4974 else if (you
.duration
[DUR_HASTE
] > threshold
* BASELINE_DELAY
)
4975 mpr("You already have as much speed as you can handle.");
4978 mpr("You feel as though your hastened speed will last longer.");
4979 contaminate_player(1, true); // always deliberate
4982 you
.increase_duration(DUR_HASTE
, turns
, threshold
);
4983 did_god_conduct(DID_STIMULANTS
, 4 + random2(4));
4988 void dec_haste_player(int delay
)
4990 if (!you
.duration
[DUR_HASTE
])
4993 if (you
.duration
[DUR_HASTE
] > BASELINE_DELAY
)
4995 int old_dur
= you
.duration
[DUR_HASTE
];
4997 you
.duration
[DUR_HASTE
] -= delay
;
4999 int threshold
= 6 * BASELINE_DELAY
;
5000 // message if we cross the threshold
5001 if (old_dur
> threshold
&& you
.duration
[DUR_HASTE
] <= threshold
)
5003 mpr("Your extra speed is starting to run out.", MSGCH_DURATION
);
5005 you
.duration
[DUR_HASTE
] -= BASELINE_DELAY
;
5008 else if (you
.duration
[DUR_HASTE
] <= BASELINE_DELAY
)
5010 if (!you
.duration
[DUR_BERSERK
])
5011 mpr("You feel yourself slow down.", MSGCH_DURATION
);
5012 you
.duration
[DUR_HASTE
] = 0;
5016 void dec_disease_player(int delay
)
5018 if (you
.disease
> 0)
5020 // If Cheibriados has slowed your life processes, there's a
5021 // chance that your disease level is unaffected.
5022 if (GOD_CHEIBRIADOS
== you
.religion
5023 && you
.piety
>= piety_breakpoint(0)
5029 you
.disease
-= delay
;
5030 if (you
.disease
< 0)
5033 // kobolds and regenerators recuperate quickly
5034 if (you
.disease
> 5 * BASELINE_DELAY
5035 && (you
.species
== SP_KOBOLD
5036 || you
.duration
[DUR_REGENERATION
]
5037 || player_mutation_level(MUT_REGENERATION
) == 3))
5039 you
.disease
-= 2 * BASELINE_DELAY
;
5042 if (you
.disease
== 0)
5043 mpr("You feel your health improve.", MSGCH_RECOVERY
);
5047 void float_player(bool fly
)
5051 mprf("Your tail turns into legs as you %s out of the water.",
5052 fly
? "fly" : "levitate");
5053 merfolk_stop_swimming();
5055 else if (you
.light_flight())
5056 mpr("You swoop lightly up into the air.");
5058 mpr("You fly up into the air.");
5060 mpr("You gently float upwards from the floor.");
5062 // Amulet of Controlled Flight can auto-ID.
5063 if (wearing_amulet(AMU_CONTROLLED_FLIGHT
)
5064 && !extrinsic_amulet_effect(AMU_CONTROLLED_FLIGHT
))
5066 // it's important to do this only if the amulet is not identified yet,
5067 // or you'd get spammed
5068 item_def
& amu(you
.inv
[you
.equip
[EQ_AMULET
]]);
5069 if (!is_artefact(amu
) && !item_type_known(amu
))
5071 set_ident_type(amu
.base_type
, amu
.sub_type
, ID_KNOWN_TYPE
);
5072 set_ident_flags(amu
, ISFLAG_KNOW_PROPERTIES
);
5073 mprf("You are wearing: %s",
5074 amu
.name(DESC_INVENTORY_EQUIP
).c_str());
5081 void levitate_player(int pow
)
5083 bool standing
= !you
.airborne();
5084 mprf(MSGCH_DURATION
,
5085 "You feel %s buoyant.", standing
? "very" : "more");
5087 you
.increase_duration(DUR_LEVITATION
, 25 + random2(pow
), 100);
5090 float_player(false);
5095 // there was another source keeping you aloft
5099 mpr("You float gracefully downwards.");
5101 // Landing kills controlled flight.
5102 you
.duration
[DUR_CONTROLLED_FLIGHT
] = 0;
5103 you
.attribute
[ATTR_LEV_UNCANCELLABLE
] = 0;
5104 // Re-enter the terrain.
5105 move_player_to_grid(you
.pos(), false, true);
5109 int count_worn_ego(int which_ego
)
5112 for (int slot
= EQ_MIN_ARMOUR
; slot
<= EQ_MAX_ARMOUR
; ++slot
)
5114 if (you
.equip
[slot
] != -1 && !you
.melded
[slot
]
5115 && get_armour_ego_type(you
.inv
[you
.equip
[slot
]]) == which_ego
)
5125 : kills(0), m_quiver(0)
5130 player::player(const player
&other
)
5131 : kills(0), m_quiver(0)
5135 // why doesn't this do a copy_from?
5136 player_quiver
* saved_quiver
= m_quiver
;
5139 m_quiver
= saved_quiver
;
5141 kills
= new KillMaster(*(other
.kills
));
5142 *m_quiver
= *(other
.m_quiver
);
5145 // why is this not called "operator="?
5146 void player::copy_from(const player
&other
)
5151 KillMaster
*saved_kills
= kills
;
5152 player_quiver
* saved_quiver
= m_quiver
;
5156 kills
= saved_kills
;
5157 *kills
= *(other
.kills
);
5158 m_quiver
= saved_quiver
;
5159 *m_quiver
= *(other
.m_quiver
);
5163 // player struct initialization
5168 species
= SP_UNKNOWN
;
5169 char_class
= JOB_UNKNOWN
;
5176 wizard
= (Options
.wiz_mode
== WIZ_YES
) ? true : false;
5180 birth_time
= time(0);
5191 max_magic_points
= 0;
5192 base_magic_points
= 5000;
5193 base_magic_points2
= 5000;
5198 stat_zero_cause
.init("");
5199 last_chosen
= STAT_RANDOM
;
5202 hunger_state
= HS_SATIATED
;
5205 hit_points_regeneration
= 0;
5206 magic_points_regeneration
= 0;
5208 experience_level
= 1;
5215 symbol
= MONS_PLAYER
;
5218 for (int i
= 0; i
< ENDOFPACK
; i
++)
5222 burden_state
= BS_UNENCUMBERED
;
5223 spells
.init(SPELL_NO_SPELL
);
5225 char_direction
= GDT_DESCENDING
;
5227 royal_jelly_dead
= false;
5228 transform_uncancellable
= false;
5231 pet_target
= MHITNOT
;
5237 berserk_penalty
= 0;
5240 quiver
.init(ENDOFPACK
);
5241 sacrifice_value
.init(0);
5243 is_undead
= US_ALIVE
;
5245 friendly_pickup
= 0;
5246 #if defined(WIZARD) || defined(DEBUG)
5252 xray_vision
= false;
5255 // In Zot def we turn off all skills with non-zero skill level later
5256 practise_skill
.init(true);
5257 skill_points
.init(0);
5258 ct_skill_points
.init(0);
5259 skill_order
.init(MAX_SKILL_ORDER
);
5261 transfer_from_skill
= SK_NONE
;
5262 transfer_to_skill
= SK_NONE
;
5263 transfer_skill_points
= 0;
5264 transfer_total_skill_points
= 0;
5266 sage_bonus_skill
= NUM_SKILLS
;
5267 sage_bonus_degree
= 0;
5269 skill_cost_level
= 1;
5270 total_skill_points
= 0;
5271 exp_available
= 0; // new games get 25 or 80 later
5273 item_description
.init(255);
5274 unique_items
.init(UNIQ_NOT_EXISTS
);
5275 unique_creatures
.init(false);
5279 kills
= new KillMaster();
5281 level_type
= LEVEL_DUNGEON
;
5282 level_type_name
.clear();
5283 level_type_ext
.clear();
5284 level_type_name_abbrev
.clear();
5285 level_type_origin
.clear();
5286 level_type_tag
.clear();
5288 where_are_you
= BRANCH_MAIN_DUNGEON
;
5290 branch_stairs
.init(0);
5292 religion
= GOD_NO_GOD
;
5293 jiyva_second_name
.clear();
5295 piety_hysteresis
= 0;
5299 num_current_gifts
.init(0);
5300 num_total_gifts
.init(0);
5303 innate_mutations
.init(0);
5304 demonic_traits
.clear();
5306 earth_attunement
= 0;
5307 magic_contamination
= 0;
5309 had_book
.init(false);
5310 seen_spell
.init(false);
5311 seen_weapon
.init(0);
5312 seen_armour
.init(0);
5314 normal_vision
= LOS_RADIUS
;
5315 current_vision
= LOS_RADIUS
;
5317 hell_branch
= NUM_BRANCHES
;
5324 last_view_update
= 0;
5326 spell_letter_table
.init(-1);
5327 ability_letter_table
.init(ABIL_NON_ABILITY
);
5329 uniq_map_tags
.clear();
5330 uniq_map_names
.clear();
5332 global_info
= PlaceInfo();
5333 global_info
.make_global();
5334 global_info
.assert_validity();
5338 m_quiver
= new player_quiver
;
5343 fearmongers
.clear();
5347 zotdef_wave_name
.clear();
5349 last_cast_spell
= SPELL_NO_SPELL
;
5352 // Non-saved UI state:
5353 prev_targ
= MHITNOT
;
5354 prev_grd_targ
.reset();
5359 travel_z
= level_id();
5362 received_weapon_warning
= false;
5365 delay_queue
.clear();
5367 last_keypress_time
= time(0);
5369 #if TAG_MAJOR_VERSION == 32
5370 for (unsigned int i
= 0; i
< ARRAYSZ(montiers
); i
++)
5375 // Volatile (same-turn) state:
5376 turn_is_over
= false;
5378 banished_by
.clear();
5380 wield_change
= false;
5381 redraw_quiver
= false;
5382 redraw_status_flags
= 0;
5383 redraw_hit_points
= false;
5384 redraw_magic_points
= false;
5385 redraw_stats
.init(false);
5386 redraw_experience
= false;
5387 redraw_armour_class
= false;
5388 redraw_evasion
= false;
5390 flash_colour
= BLACK
;
5395 entry_cause
= EC_SELF_EXPLICIT
;
5396 entry_cause_god
= GOD_NO_GOD
;
5398 old_hunger
= hunger
;
5399 transit_stair
= DNGN_UNSEEN
;
5400 entering_level
= false;
5402 reset_escaped_death();
5403 on_current_level
= true;
5410 // Protected fields:
5411 for (int i
= 0; i
< NUM_BRANCHES
; i
++)
5413 branch_info
[i
].level_type
= LEVEL_DUNGEON
;
5414 branch_info
[i
].branch
= i
;
5415 branch_info
[i
].assert_validity();
5418 for (int i
= 0; i
< (NUM_LEVEL_AREA_TYPES
- 1); i
++)
5420 non_branch_info
[i
].level_type
= i
+ 1;
5421 non_branch_info
[i
].branch
= -1;
5422 non_branch_info
[i
].assert_validity();
5426 player_save_info
player_save_info::operator=(const player
& rhs
)
5428 name
= rhs
.your_name
;
5429 experience
= rhs
.experience
;
5430 experience_level
= rhs
.experience_level
;
5431 wizard
= rhs
.wizard
;
5432 species
= rhs
.species
;
5433 class_name
= rhs
.class_name
;
5434 religion
= rhs
.religion
;
5435 jiyva_second_name
= rhs
.jiyva_second_name
;
5437 // [ds] Perhaps we should move game type to player?
5438 saved_game_type
= crawl_state
.type
;
5441 held_in_net
= false;
5447 bool player_save_info::operator<(const player_save_info
& rhs
) const
5449 return experience
< rhs
.experience
5450 || (experience
== rhs
.experience
&& name
< rhs
.name
);
5453 std::string
player_save_info::short_desc() const
5455 std::ostringstream desc
;
5457 const std::string qualifier
=
5458 game_state::game_type_name_for(saved_game_type
);
5459 if (!qualifier
.empty())
5460 desc
<< "[" << qualifier
<< "] ";
5462 desc
<< name
<< ", a level " << experience_level
<< ' '
5463 << species_name(species
) << ' ' << class_name
;
5465 if (religion
== GOD_JIYVA
)
5466 desc
<< " of " << god_name_jiyva(true);
5467 else if (religion
!= GOD_NO_GOD
)
5468 desc
<< " of " << god_name(religion
);
5482 if (CrawlIsCrashing
&& save
)
5488 ASSERT(!save
); // the save file should be closed or deleted
5491 bool player::is_levitating() const
5493 return duration
[DUR_LEVITATION
] || you
.attribute
[ATTR_PERM_LEVITATION
];
5496 void player::clear_clinging()
5498 you
.clinging
= false;
5499 you
.cling_to
.clear();
5502 bool player::in_water() const
5504 return (ground_level() && !beogh_water_walk()
5505 && feat_is_water(grd(pos())));
5508 bool player::can_swim(bool permanently
) const
5510 // Transforming could be fatal if it would cause unequipment of
5511 // stat-boosting boots or heavy armour.
5512 return (species
== SP_MERFOLK
5513 || body_size(PSIZE_BODY
) >= SIZE_GIANT
5518 int player::visible_igrd(const coord_def
&where
) const
5520 if (grd(where
) == DNGN_LAVA
5521 || (grd(where
) == DNGN_DEEP_WATER
5522 && species
!= SP_MERFOLK
&& species
!= SP_GREY_DRACONIAN
))
5527 return (igrd(where
));
5530 bool player::has_spell(spell_type spell
) const
5532 for (int i
= 0; i
< MAX_KNOWN_SPELLS
; i
++)
5534 if (spells
[i
] == spell
)
5541 bool player::cannot_speak() const
5543 if (silenced(pos()))
5546 if (cannot_move()) // we allow talking during sleep ;)
5549 // No transform that prevents the player from speaking yet.
5553 std::string
player::shout_verb() const
5566 if (you
.species
== SP_CAT
)
5567 return coinflip() ? "meow" : "yowl";
5568 // depends on SCREAM mutation
5569 int level
= player_mutation_level(MUT_SCREAM
);
5572 else if (level
== 2)
5579 void player::god_conduct(conduct_type thing_done
, int level
)
5581 ::did_god_conduct(thing_done
, level
);
5584 void player::banish(const std::string
&who
)
5586 ASSERT(!crawl_state
.game_is_arena());
5592 // For semi-undead species (Vampire!) reduce food cost for spells and abilities
5593 // to 50% (hungry, very hungry) or zero (near starving, starving).
5594 int calc_hunger(int food_cost
)
5596 if (you
.is_undead
== US_SEMI_UNDEAD
&& you
.hunger_state
< HS_SATIATED
)
5598 if (you
.hunger_state
<= HS_NEAR_STARVING
)
5601 return (food_cost
/2);
5606 int player::warding() const
5608 if (wearing_amulet(AMU_WARDING
))
5614 bool player::paralysed() const
5616 return (duration
[DUR_PARALYSIS
]);
5619 bool player::cannot_move() const
5621 return (paralysed() || petrified());
5624 bool player::confused() const
5626 return (duration
[DUR_CONF
]);
5629 bool player::caught() const
5631 return (attribute
[ATTR_HELD
]);
5634 bool player::petrified() const
5636 return (duration
[DUR_PETRIFIED
]);
5639 int player::shield_block_penalty() const
5641 return (5 * shield_blocks
* shield_blocks
);
5644 int player::shield_bonus() const
5646 const int shield_class
= player_shield_class();
5647 if (shield_class
<= 0)
5650 return random2avg(shield_class
* 2, 2) / 3 - 1;
5653 int player::shield_bypass_ability(int tohit
) const
5655 return (15 + tohit
/ 2);
5658 void player::shield_block_succeeded(actor
*foe
)
5660 actor::shield_block_succeeded(foe
);
5663 practise(EX_SHIELD_BLOCK
);
5666 int player::skill(skill_type sk
) const
5668 if (you
.duration
[DUR_HEROISM
] && sk
<= SK_LAST_MUNDANE
)
5669 return std::min(skills
[sk
] + 5, 27);
5674 // only for purposes of detection, not disarming
5675 int player::traps_skill() const
5677 int val
= skill(SK_TRAPS_DOORS
);
5679 if (you
.religion
== GOD_ASHENZARI
&& !player_under_penance())
5680 val
+= you
.piety
/ 15;
5685 int player_icemail_armour_class()
5687 if (!you
.mutation
[MUT_ICEMAIL
])
5691 - (you
.duration
[DUR_ICEMAIL_DEPLETED
]
5692 * ICEMAIL_MAX
/ ICEMAIL_TIME
));
5695 int player::armour_class() const
5699 for (int eq
= EQ_MIN_ARMOUR
; eq
<= EQ_MAX_ARMOUR
; ++eq
)
5701 if (eq
== EQ_SHIELD
)
5704 if (!player_wearing_slot(eq
))
5707 const item_def
& item
= inv
[equip
[eq
]];
5708 const int ac_value
= property(item
, PARM_AC
) * 100;
5709 const int racial_bonus
= _player_armour_racial_bonus(item
);
5711 // [ds] effectively: ac_value * (22 + Arm) / 22, where Arm =
5712 // Armour Skill + racial_skill_bonus / 2.
5713 AC
+= ac_value
* (44 + 2 * skill(SK_ARMOUR
) + racial_bonus
) / 44;
5714 AC
+= item
.plus
* 100;
5716 // The deformed don't fit into body armour very well.
5717 // (This includes nagas and centaurs.)
5718 if (eq
== EQ_BODY_ARMOUR
&& (player_mutation_level(MUT_DEFORMED
)
5719 || player_mutation_level(MUT_PSEUDOPODS
)))
5723 AC
+= player_equip(EQ_RINGS_PLUS
, RING_PROTECTION
) * 100;
5725 if (player_equip_ego_type(EQ_WEAPON
, SPWPN_PROTECTION
))
5728 if (player_equip_ego_type(EQ_SHIELD
, SPARM_PROTECTION
))
5731 AC
+= scan_artefacts(ARTP_AC
) * 100;
5733 if (duration
[DUR_ICY_ARMOUR
])
5734 AC
+= 400 + 100 * skills
[SK_ICE_MAGIC
] / 3; // max 13
5736 if (duration
[DUR_STONEMAIL
])
5737 AC
+= 500 + 100 * skills
[SK_EARTH_MAGIC
] / 2; // max 18
5739 if (duration
[DUR_STONESKIN
])
5740 AC
+= 200 + 100 * skills
[SK_EARTH_MAGIC
] / 5; // max 7
5742 if (mutation
[MUT_ICEMAIL
])
5743 AC
+= 100 * player_icemail_armour_class();
5745 if (form
== TRAN_NONE
5746 || form
== TRAN_LICH
5747 || form
== TRAN_BLADE_HANDS
5748 || (form
== TRAN_DRAGON
5749 && player_genus(GENPC_DRACONIAN
)))
5751 // Being a lich doesn't preclude the benefits of hide/scales -- bwr
5753 // Note: Even though necromutation is a high level spell, it does
5754 // allow the character full armour (so the bonus is low). -- bwr
5755 if (form
== TRAN_LICH
)
5756 AC
+= (300 + 100 * skills
[SK_NECROMANCY
] / 6); // max 7
5759 if (player_genus(GENPC_DRACONIAN
))
5761 AC
+= 300 + 100 * (you
.experience_level
/ 3); // max 12
5763 if (form
== TRAN_DRAGON
)
5771 AC
+= 100 * experience_level
/ 3; // max 9
5785 case TRAN_BLADE_HANDS
:
5786 case TRAN_LICH
: // can wear normal body armour (small bonus)
5789 case TRAN_SPIDER
: // low level (small bonus), also gets EV
5790 AC
+= (200 + 100 * skills
[SK_POISON_MAGIC
] / 6); // max 6
5793 case TRAN_ICE_BEAST
:
5794 AC
+= (500 + 100 * (skills
[SK_ICE_MAGIC
] + 1) / 4); // max 12
5796 if (duration
[DUR_ICY_ARMOUR
])
5797 AC
+= (100 + 100 * skills
[SK_ICE_MAGIC
] / 4); // max +7
5800 case TRAN_DRAGON
: // Draconians handled above
5801 AC
+= (700 + 100 * skills
[SK_FIRE_MAGIC
] / 3); // max 16
5804 case TRAN_STATUE
: // main ability is armour (high bonus)
5805 AC
+= (1700 + 100 * skills
[SK_EARTH_MAGIC
] / 2); // max 30
5807 if (duration
[DUR_STONESKIN
] || duration
[DUR_STONEMAIL
])
5808 AC
+= (100 + 100 * skills
[SK_EARTH_MAGIC
] / 4); // max +7
5816 // Scale mutations, etc.
5817 AC
+= player_mutation_level(MUT_TOUGH_SKIN
) ? player_mutation_level(MUT_TOUGH_SKIN
) * 100 : 0; // +1, +2, +3
5818 AC
+= player_mutation_level(MUT_SHAGGY_FUR
) ? player_mutation_level(MUT_SHAGGY_FUR
) * 100 : 0; // +1, +2, +3
5819 AC
+= player_mutation_level(MUT_IRIDESCENT_SCALES
) ? 200 + player_mutation_level(MUT_IRIDESCENT_SCALES
) * 200 : 0; // +4, +6, +8
5820 AC
+= player_mutation_level(MUT_LARGE_BONE_PLATES
) ? 100 + player_mutation_level(MUT_LARGE_BONE_PLATES
) * 100 : 0; // +2, +3, +4
5821 AC
+= player_mutation_level(MUT_ROUGH_BLACK_SCALES
) ? 100 + player_mutation_level(MUT_ROUGH_BLACK_SCALES
) * 300 : 0; // +4, +7, +10
5822 AC
+= player_mutation_level(MUT_RUGGED_BROWN_SCALES
) ? 200 : 0; // +2, +2, +2
5823 AC
+= player_mutation_level(MUT_ICY_BLUE_SCALES
) ? player_mutation_level(MUT_ICY_BLUE_SCALES
) * 100 : 0; // +1, +2, +3
5824 AC
+= player_mutation_level(MUT_MOLTEN_SCALES
) ? player_mutation_level(MUT_MOLTEN_SCALES
) * 100 : 0; // +1, +2, +3
5825 AC
+= player_mutation_level(MUT_SLIMY_GREEN_SCALES
) ? player_mutation_level(MUT_SLIMY_GREEN_SCALES
) * 100 : 0; // +1, +2, +3
5826 AC
+= player_mutation_level(MUT_THIN_METALLIC_SCALES
) ? player_mutation_level(MUT_THIN_METALLIC_SCALES
) * 100 : 0; // +1, +2, +3
5827 AC
+= player_mutation_level(MUT_YELLOW_SCALES
) ? player_mutation_level(MUT_YELLOW_SCALES
) * 100 : 0; // +1, +2, +3
5828 AC
+= player_mutation_level(MUT_GELATINOUS_BODY
) ? (player_mutation_level(MUT_GELATINOUS_BODY
) == 3 ? 200 : 100) : 0; // +1, +1, +2
5832 * Guaranteed damage reduction.
5834 * The percentage of the damage received that is guaranteed to be reduced
5835 * by the armour. As the AC roll is done before GDR is applied, GDR is only
5836 * useful when the AC roll is inferior to it. Therefore a higher GDR means
5837 * more damage reduced, but also more often.
5839 * \f[ GDR = 14 \times (base\_AC - 2)^\frac{1}{2} \f]
5841 * \return GDR as a percentage.
5843 int player::gdr_perc() const
5845 const item_def
*body_armour
= slot_item(EQ_BODY_ARMOUR
, false);
5850 const int body_base_AC
= property(*body_armour
, PARM_AC
);
5851 return (14 * pow(std::max(body_base_AC
- 2, 0), 0.5));
5854 int player::melee_evasion(const actor
*act
, ev_ignore_type evit
) const
5856 return (player_evasion(evit
)
5857 - ((!act
|| act
->visible_to(this)
5858 || (evit
& EV_IGNORE_HELPLESS
)) ? 0 : 10)
5859 - (you_are_delayed()
5860 && !(evit
& EV_IGNORE_HELPLESS
)
5861 && !delay_is_run(current_delay_action())? 5 : 0));
5864 bool player::heal(int amount
, bool max_too
)
5866 ::inc_hp(amount
, max_too
);
5867 return true; /* TODO Check whether the player was healed. */
5870 mon_holy_type
player::holiness() const
5875 if (species
== SP_DEMONSPAWN
)
5876 return (MH_DEMONIC
);
5878 return (MH_NATURAL
);
5881 bool player::undead_or_demonic() const
5883 const mon_holy_type holi
= holiness();
5885 return (holi
== MH_UNDEAD
|| holi
== MH_DEMONIC
);
5888 bool player::is_holy() const
5890 if (is_good_god(religion
))
5896 bool player::is_unholy() const
5898 return (holiness() == MH_DEMONIC
);
5901 bool player::is_evil() const
5903 if (holiness() == MH_UNDEAD
)
5906 if (is_evil_god(religion
))
5912 // This is a stub. Check is used only for silver damage. Worship of chaotic
5913 // gods should probably be checked in the non-existing player::is_unclean,
5914 // which could be used for something Zin-related (such as a priestly monster).
5915 bool player::is_chaotic() const
5920 bool player::is_artificial() const
5925 bool player::is_unbreathing() const
5936 return (player_mutation_level(MUT_UNBREATHING
));
5939 // This is a stub. Makes checking for silver damage a little cleaner.
5940 bool player::is_insubstantial() const
5945 // Output active level of player mutation.
5946 // Might be lower than real mutation for non-"Alive" Vampires.
5947 int player_mutation_level(mutation_type mut
)
5949 const int mlevel
= you
.mutation
[mut
];
5951 if (mutation_is_fully_active(mut
))
5954 // For now, dynamic mutations only apply to semi-undead.
5955 ASSERT(you
.is_undead
== US_SEMI_UNDEAD
);
5957 // Assumption: stat mutations are physical, and thus always fully active.
5958 switch (you
.hunger_state
)
5964 return (std::min(mlevel
, 2));
5966 return (std::min(mlevel
, 1));
5972 int player::res_acid() const
5974 return (player_res_acid());
5977 int player::res_fire() const
5979 return (player_res_fire());
5982 int player::res_steam() const
5984 return (player_res_steam());
5987 int player::res_cold() const
5989 return (player_res_cold());
5992 int player::res_elec() const
5994 return (player_res_electricity() * 2);
5997 int player::res_water_drowning() const
5999 return (is_unbreathing()
6000 || (you
.species
== SP_MERFOLK
&& !form_changed_physiology()));
6003 int player::res_asphyx() const
6005 // The unbreathing are immune to asphyxiation.
6006 if (is_unbreathing())
6012 int player::res_poison(bool temp
) const
6014 return (player_res_poison(true, temp
));
6017 int player::res_rotting(bool temp
) const
6025 case US_HUNGRY_DEAD
:
6026 return 1; // rottable by Zin, not by necromancy
6028 case US_SEMI_UNDEAD
:
6029 return temp
? 1 : 0;
6032 if (!temp
&& you
.form
== TRAN_LICH
)
6034 return 3; // full immunity
6038 int player::res_sticky_flame() const
6040 return (player_res_sticky_flame());
6043 int player::res_holy_energy(const actor
*attacker
) const
6045 if (undead_or_demonic())
6057 int player::res_negative_energy() const
6059 return (player_prot_life());
6062 int player::res_torment() const
6064 return (player_res_torment());
6067 int player::res_wind() const
6069 // Full control of the winds around you can negate a hostile tornado.
6070 return you
.duration
[DUR_TORNADO
] ? 1 : 0;
6073 int player::res_magic() const
6075 return player_res_magic();
6078 int player_res_magic(bool calc_unid
, bool temp
)
6082 switch (you
.species
)
6085 rm
= you
.experience_level
* 3;
6090 case SP_MOUNTAIN_DWARF
:
6094 rm
= you
.experience_level
* 4;
6097 rm
= you
.experience_level
* 5;
6099 case SP_PURPLE_DRACONIAN
:
6102 rm
= you
.experience_level
* 6;
6105 rm
= you
.experience_level
* 7;
6110 rm
+= scan_artefacts(ARTP_MAGIC
, calc_unid
);
6113 rm
+= 30 * player_equip_ego_type(EQ_ALL_ARMOUR
, SPARM_MAGIC_RESISTANCE
,
6116 // rings of magic resistance
6117 rm
+= 40 * player_equip(EQ_RINGS
, RING_PROTECTION_FROM_MAGIC
, calc_unid
);
6119 // Enchantment skill through staff of enchantment (up to 90).
6120 if (player_equip(EQ_STAFF
, STAFF_ENCHANTMENT
, calc_unid
))
6121 rm
+= 3 * (3 + std::max(you
.skill(SK_CHARMS
), you
.skill(SK_HEXES
)));
6124 rm
+= 30 * player_mutation_level(MUT_MAGIC_RESISTANCE
);
6127 if (you
.form
== TRAN_LICH
&& temp
)
6131 if (you
.attribute
[ATTR_DIVINE_REGENERATION
] && temp
)
6134 // Enchantment effect
6135 if (you
.duration
[DUR_LOWERED_MR
] && temp
)
6141 bool player::confusable() const
6143 return (player_mental_clarity() == 0);
6146 bool player::slowable() const
6151 flight_type
player::flight_mode() const
6153 if (form
== TRAN_DRAGON
6154 || form
== TRAN_BAT
)
6158 else if (is_levitating())
6160 return (duration
[DUR_CONTROLLED_FLIGHT
]
6161 || wearing_amulet(AMU_CONTROLLED_FLIGHT
) ? FL_FLY
6168 bool player::permanent_levitation() const
6170 return you
.attribute
[ATTR_PERM_LEVITATION
]
6171 && player_equip_ego_type(EQ_BOOTS
, SPARM_LEVITATION
);
6174 bool player::permanent_flight() const
6176 return you
.attribute
[ATTR_PERM_LEVITATION
]
6177 && species
== SP_KENKU
&& experience_level
>= 15;
6180 bool player::light_flight() const
6182 // Only Kenku get perks for flying light.
6183 return (species
== SP_KENKU
6184 && flight_mode() == FL_FLY
&& travelling_light());
6187 bool player::travelling_light() const
6189 return (burden
< carrying_capacity(BS_UNENCUMBERED
) * 70 / 100);
6192 int player::mons_species() const
6194 if (player_genus(GENPC_DRACONIAN
))
6195 return (MONS_DRACONIAN
);
6201 case SP_HIGH_ELF
: case SP_DEEP_ELF
: case SP_SLUDGE_ELF
:
6205 return (MONS_HUMAN
);
6209 void player::poison(actor
*agent
, int amount
, bool force
)
6211 ::poison_player(amount
, agent
? agent
->name(DESC_NOCAP_A
, true) : "");
6214 void player::expose_to_element(beam_type element
, int st
)
6216 ::expose_player_to_element(element
, st
);
6219 void player::blink(bool allow_partial_control
)
6221 random_blink(allow_partial_control
);
6224 void player::teleport(bool now
, bool abyss_shift
, bool wizard_tele
)
6226 ASSERT(!crawl_state
.game_is_arena());
6229 you_teleport_now(true, abyss_shift
, wizard_tele
);
6234 int player::hurt(const actor
*agent
, int amount
, beam_type flavour
,
6237 // We ignore cleanup_dead here.
6238 if (agent
->atype() == ACT_MONSTER
)
6240 const monster
* mon
= agent
->as_monster();
6241 ouch(amount
, mon
->mindex(),
6242 KILLED_BY_MONSTER
, "", mon
->visible_to(&you
));
6246 // Should never happen!
6247 die("player::hurt() called for self-damage");
6250 if ((flavour
== BEAM_NUKE
|| flavour
== BEAM_DISINTEGRATION
) && can_bleed())
6251 blood_spray(pos(), type
, amount
/ 5);
6256 void player::drain_stat(stat_type s
, int amount
, actor
*attacker
)
6258 if (attacker
== NULL
)
6259 lose_stat(s
, amount
, false, "");
6260 else if (attacker
->atype() == ACT_MONSTER
)
6261 lose_stat(s
, amount
, attacker
->as_monster(), false);
6262 else if (attacker
->atype() == ACT_PLAYER
)
6263 lose_stat(s
, amount
, false, "suicide");
6265 lose_stat(s
, amount
, false, "");
6268 bool player::rot(actor
*who
, int amount
, int immediate
, bool quiet
)
6270 ASSERT(!crawl_state
.game_is_arena());
6272 if (amount
<= 0 && immediate
<= 0)
6277 mpr("You feel terrible.");
6281 // Zin's protection.
6282 if (religion
== GOD_ZIN
&& x_chance_in_y(piety
, MAX_PIETY
))
6284 simple_god_message(" protects your body from decay!");
6293 // Either this, or the actual rotting message should probably
6294 // be changed so that they're easier to tell apart. -- bwr
6295 mprf(MSGCH_WARN
, "You feel your flesh %s away!",
6296 rotting
> 0 ? "rotting" : "start to rot");
6300 learned_something_new(HINT_YOU_ROTTING
);
6303 if (one_chance_in(4))
6304 sicken(50 + random2(100));
6309 bool player::drain_exp(actor
*who
, bool quiet
, int pow
)
6311 return (::drain_exp());
6314 void player::confuse(actor
*who
, int str
)
6316 confuse_player(str
);
6319 void player::paralyse(actor
*who
, int str
)
6321 ASSERT(!crawl_state
.game_is_arena());
6323 // The shock is too mild to do damage.
6324 if (stasis_blocks_effect(true, true, "%s gives you a mild electric shock."))
6327 if (!(who
&& who
->as_monster() && who
->as_monster()->type
== MONS_RED_WASP
)
6328 && (duration
[DUR_PARALYSIS
] || duration
[DUR_PARALYSIS_IMMUNITY
]))
6330 canned_msg(MSG_YOU_RESIST
);
6334 int ¶lysis(duration
[DUR_PARALYSIS
]);
6336 mprf("You %s the ability to move!",
6337 paralysis
? "still haven't" : "suddenly lose");
6339 str
*= BASELINE_DELAY
;
6340 if (str
> paralysis
&& (paralysis
< 3 || one_chance_in(paralysis
)))
6343 if (paralysis
> 13 * BASELINE_DELAY
)
6344 paralysis
= 13 * BASELINE_DELAY
;
6347 void player::petrify(actor
*who
, int str
)
6349 ASSERT(!crawl_state
.game_is_arena());
6351 if (stasis_blocks_effect(true, true, "%s gives you a mild electric shock."))
6354 str
*= BASELINE_DELAY
;
6355 int &petrif(duration
[DUR_PETRIFIED
]);
6357 mprf("You %s the ability to move!",
6358 petrif
? "still haven't" : "suddenly lose");
6360 if (str
> petrif
&& (petrif
< 3 || one_chance_in(petrif
)))
6363 petrif
= std::min(13 * BASELINE_DELAY
, petrif
);
6366 void player::slow_down(actor
*foe
, int str
)
6371 int player::has_claws(bool allow_tran
) const
6375 // these transformations bring claws with them
6376 if (form
== TRAN_DRAGON
)
6379 // transformations other than these will override claws
6380 if (form
!= TRAN_NONE
6381 && form
!= TRAN_STATUE
6382 && form
!= TRAN_LICH
)
6388 if (const int c
= species_has_claws(you
.species
))
6391 return (player_mutation_level(MUT_CLAWS
));
6394 bool player::has_usable_claws(bool allow_tran
) const
6396 return (!player_wearing_slot(EQ_GLOVES
) && has_claws(allow_tran
));
6399 int player::has_talons(bool allow_tran
) const
6403 // transformations other than these will override talons
6404 if (form
!= TRAN_NONE
6405 && form
!= TRAN_BLADE_HANDS
6406 && form
!= TRAN_STATUE
6407 && form
!= TRAN_LICH
)
6413 // XXX: Do merfolk in water belong under allow_tran?
6417 return (player_mutation_level(MUT_TALONS
));
6420 bool player::has_usable_talons(bool allow_tran
) const
6422 return (!player_wearing_slot(EQ_BOOTS
) && has_talons(allow_tran
));
6425 int player::has_fangs(bool allow_tran
) const
6429 // these transformations bring fangs with them
6430 if (form
== TRAN_DRAGON
)
6433 // transformations other than these will override fangs
6434 if (form
!= TRAN_NONE
6435 && form
!= TRAN_BLADE_HANDS
6436 && form
!= TRAN_STATUE
6437 && form
!= TRAN_LICH
)
6443 return (player_mutation_level(MUT_FANGS
));
6446 int player::has_usable_fangs(bool allow_tran
) const
6448 const item_def
* helmet
= you
.slot_item(EQ_HELMET
);
6449 if (helmet
&& get_helmet_desc(*helmet
) == THELM_DESC_VISORED
)
6452 return (has_fangs(allow_tran
));
6455 int player::has_tail(bool allow_tran
) const
6459 // these transformations bring a tail with them
6460 if (form
== TRAN_DRAGON
)
6463 // transformations other than these will override a tail
6464 if (form
!= TRAN_NONE
6465 && form
!= TRAN_BLADE_HANDS
6466 && form
!= TRAN_STATUE
6467 && form
!= TRAN_LICH
)
6473 // XXX: Do merfolk in water belong under allow_tran?
6474 if (player_genus(GENPC_DRACONIAN
)
6476 || player_mutation_level(MUT_STINGER
))
6484 int player::has_usable_tail(bool allow_tran
) const
6486 // TSO worshippers don't use their stinger in order
6487 // to avoid poisoning.
6488 if (you
.religion
== GOD_SHINING_ONE
6489 && player_mutation_level(MUT_STINGER
) > 0)
6494 return (has_tail(allow_tran
));
6497 // Whether the player has a usable offhand for the
6498 // purpose of punching.
6499 // XXX: The weapon check should probably involve HANDS_DOUBLE
6501 bool player::has_usable_offhand() const
6503 if (player_wearing_slot(EQ_SHIELD
))
6506 const item_def
* wp
= slot_item(EQ_WEAPON
);
6508 || hands_reqd(*wp
, body_size()) != HANDS_TWO
6509 || wp
->base_type
== OBJ_STAVES
6510 || weapon_skill(*wp
) == SK_STAVES
);
6513 int player::has_pseudopods(bool allow_tran
) const
6517 // transformations other than these will override pseudopods
6518 if (form
!= TRAN_NONE
6519 && form
!= TRAN_BLADE_HANDS
6520 && form
!= TRAN_STATUE
6521 && form
!= TRAN_LICH
)
6527 return (player_mutation_level(MUT_PSEUDOPODS
));
6530 int player::has_usable_pseudopods(bool allow_tran
) const
6532 return (has_pseudopods(allow_tran
));
6535 bool player::sicken(int amount
)
6537 ASSERT(!crawl_state
.game_is_arena());
6539 if (res_rotting() || amount
<= 0)
6542 // Zin's protection.
6543 if (religion
== GOD_ZIN
&& x_chance_in_y(piety
, MAX_PIETY
))
6545 simple_god_message(" protects your body from disease!");
6549 mpr("You feel ill.");
6551 disease
+= amount
* BASELINE_DELAY
;
6552 if (disease
> 210 * BASELINE_DELAY
)
6553 disease
= 210 * BASELINE_DELAY
;
6555 learned_something_new(HINT_YOU_SICK
);
6559 bool player::can_see_invisible(bool calc_unid
, bool transient
) const
6561 if (crawl_state
.game_is_arena())
6566 si
+= player_equip(EQ_RINGS
, RING_SEE_INVISIBLE
, calc_unid
);
6568 // armour: (checks head armour only)
6569 si
+= player_equip_ego_type(EQ_HELMET
, SPARM_SEE_INVISIBLE
);
6571 if (player_mutation_level(MUT_ACUTE_VISION
) > 0)
6572 si
+= player_mutation_level(MUT_ACUTE_VISION
);
6574 // antennae give sInvis at 3
6575 if (player_mutation_level(MUT_ANTENNAE
) == 3)
6578 if (player_mutation_level(MUT_EYEBALLS
) == 3)
6581 //jmf: added see_invisible spell
6582 if (transient
&& duration
[DUR_SEE_INVISIBLE
] > 0)
6586 int artefacts
= scan_artefacts(ARTP_EYESIGHT
, calc_unid
);
6591 if (you
.religion
== GOD_ASHENZARI
&& you
.piety
>= piety_breakpoint(2)
6592 && !player_under_penance())
6603 bool player::can_see_invisible() const
6605 return (can_see_invisible(true));
6608 bool player::invisible() const
6610 return (duration
[DUR_INVIS
] && !backlit());
6613 bool player::misled() const
6615 return (duration
[DUR_MISLED
]);
6618 bool player::visible_to(const actor
*looker
) const
6620 if (crawl_state
.game_is_arena())
6624 return (can_see_invisible() || !invisible());
6626 const monster
* mon
= looker
->as_monster();
6627 return (!mon
->has_ench(ENCH_BLIND
)
6630 || mon
->can_see_invisible()
6631 || mons_sense_invis(mon
)
6632 && circle_def(pos(), 4, C_ROUND
).contains(mon
->pos()));
6635 bool player::backlit(bool check_haloed
, bool self_halo
) const
6637 if (get_contamination_level() > 1 || duration
[DUR_CORONA
]
6638 || duration
[DUR_LIQUID_FLAMES
] || duration
[DUR_QUAD_DAMAGE
])
6643 return (haloed() && (self_halo
|| halo_radius2() == -1));
6647 bool player::glows_naturally() const
6652 // This is the imperative version.
6653 void player::backlight()
6655 if (!duration
[DUR_INVIS
])
6657 if (duration
[DUR_CORONA
] || you
.glows_naturally())
6658 mpr("You glow brighter.");
6660 mpr("You are outlined in light.");
6662 you
.increase_duration(DUR_CORONA
, random_range(15, 35), 250);
6666 mpr("You feel strangely conspicuous.");
6668 you
.increase_duration(DUR_CORONA
, random_range(3, 5), 250);
6672 bool player::has_lifeforce() const
6674 const mon_holy_type holi
= holiness();
6676 return (holi
== MH_NATURAL
|| holi
== MH_PLANT
);
6679 bool player::can_mutate() const
6684 bool player::can_safely_mutate() const
6690 || is_undead
== US_SEMI_UNDEAD
6691 && hunger_state
== HS_ENGORGED
);
6694 bool player::can_bleed() const
6696 if (is_undead
&& (species
!= SP_VAMPIRE
6697 || hunger_state
<= HS_SATIATED
))
6702 // The corresponding monsters don't bleed either.
6703 if (you
.form
== TRAN_STATUE
|| you
.form
== TRAN_ICE_BEAST
6704 || you
.form
== TRAN_LICH
|| you
.form
== TRAN_SPIDER
)
6711 bool player::mutate()
6713 ASSERT(!crawl_state
.game_is_arena());
6718 if (one_chance_in(5))
6720 if (::mutate(RANDOM_MUTATION
))
6722 learned_something_new(HINT_YOU_MUTATED
);
6727 return (give_bad_mutation());
6730 bool player::is_icy() const
6732 return (form
== TRAN_ICE_BEAST
);
6735 bool player::is_fiery() const
6740 bool player::is_skeletal() const
6745 void player::shiftto(const coord_def
&c
)
6747 crawl_view
.shift_player_to(c
);
6751 void player::reset_prev_move()
6756 bool player::asleep() const
6758 return (duration
[DUR_SLEEP
]);
6761 bool player::cannot_act() const
6763 return (asleep() || cannot_move());
6766 bool player::can_throw_large_rocks() const
6768 return (player_genus(GENPC_OGREISH
) || species
== SP_TROLL
);
6771 bool player::can_smell() const
6773 return (species
!= SP_MUMMY
);
6776 void player::hibernate(int)
6778 ASSERT(!crawl_state
.game_is_arena());
6780 if (!can_hibernate())
6782 canned_msg(MSG_YOU_UNAFFECTED
);
6786 mpr("You fall asleep.");
6789 flash_view(DARKGREY
);
6791 // Do this *after* redrawing the view, or viewwindow() will no-op.
6792 set_duration(DUR_SLEEP
, 3 + random2avg(5, 2));
6795 void player::put_to_sleep(actor
*, int power
)
6797 ASSERT(!crawl_state
.game_is_arena());
6801 canned_msg(MSG_YOU_UNAFFECTED
);
6805 mpr("You fall asleep.");
6808 flash_view(DARKGREY
);
6810 // As above, do this after redraw.
6811 set_duration(DUR_SLEEP
, 5 + random2avg(power
/10, 5));
6814 void player::awake()
6816 ASSERT(!crawl_state
.game_is_arena());
6818 duration
[DUR_SLEEP
] = 0;
6819 mpr("You wake up.");
6823 void player::check_awaken(int disturbance
)
6825 if (asleep() && x_chance_in_y(disturbance
+ 1, 50))
6829 int player::beam_resists(bolt
&beam
, int hurted
, bool doEffects
,
6832 return check_your_resists(hurted
, beam
.flavour
, source
, &beam
, doEffects
);
6835 void player::set_place_info(PlaceInfo place_info
)
6837 place_info
.assert_validity();
6839 if (place_info
.is_global())
6840 global_info
= place_info
;
6841 else if (place_info
.level_type
== LEVEL_DUNGEON
)
6842 branch_info
[place_info
.branch
] = place_info
;
6844 non_branch_info
[place_info
.level_type
- 1] = place_info
;
6847 std::vector
<PlaceInfo
> player::get_all_place_info(bool visited_only
,
6848 bool dungeon_only
) const
6850 std::vector
<PlaceInfo
> list
;
6852 for (int i
= 0; i
< NUM_BRANCHES
; i
++)
6854 if (visited_only
&& branch_info
[i
].num_visits
== 0
6855 || dungeon_only
&& branch_info
[i
].level_type
!= LEVEL_DUNGEON
)
6859 list
.push_back(branch_info
[i
]);
6862 for (int i
= 0; i
< (NUM_LEVEL_AREA_TYPES
- 1); i
++)
6864 if (visited_only
&& non_branch_info
[i
].num_visits
== 0
6865 || dungeon_only
&& non_branch_info
[i
].level_type
!= LEVEL_DUNGEON
)
6869 list
.push_back(non_branch_info
[i
]);
6875 bool player::do_shaft()
6877 dungeon_feature_type force_stair
= DNGN_UNSEEN
;
6879 if (!is_valid_shaft_level())
6882 // Handle instances of do_shaft() being invoked magically when
6883 // the player isn't standing over a shaft.
6884 if (get_trap_type(pos()) != TRAP_SHAFT
)
6889 case DNGN_OPEN_DOOR
:
6890 case DNGN_TRAP_MECHANICAL
:
6891 case DNGN_TRAP_MAGICAL
:
6892 case DNGN_TRAP_NATURAL
:
6893 case DNGN_UNDISCOVERED_TRAP
:
6894 case DNGN_ENTER_SHOP
:
6901 handle_items_on_shaft(pos(), false);
6903 if (!ground_level() || total_weight() == 0)
6906 force_stair
= DNGN_TRAP_NATURAL
;
6909 down_stairs(force_stair
);
6914 bool player::did_escape_death() const
6916 return (escaped_death_cause
!= NUM_KILLBY
);
6919 void player::reset_escaped_death()
6921 escaped_death_cause
= NUM_KILLBY
;
6922 escaped_death_aux
= "";
6925 void player::add_gold(int delta
)
6927 set_gold(gold
+ delta
);
6930 void player::del_gold(int delta
)
6932 set_gold(gold
- delta
);
6935 void player::set_gold(int amount
)
6937 ASSERT(amount
>= 0);
6941 const int old_gold
= gold
;
6943 shopping_list
.gold_changed(old_gold
, gold
);
6947 void player::increase_duration(duration_type dur
, int turns
, int cap
,
6952 cap
*= BASELINE_DELAY
;
6954 you
.duration
[dur
] += turns
* BASELINE_DELAY
;
6955 if (cap
&& you
.duration
[dur
] > cap
)
6956 you
.duration
[dur
] = cap
;
6959 void player::set_duration(duration_type dur
, int turns
,
6960 int cap
, const char * msg
)
6962 you
.duration
[dur
] = 0;
6963 increase_duration(dur
, turns
, cap
, msg
);
6966 void player::goto_place(const level_id
&lid
)
6968 level_type
= lid
.level_type
;
6969 if (level_type
== LEVEL_DUNGEON
)
6971 where_are_you
= static_cast<branch_type
>(lid
.branch
);
6972 absdepth0
= absdungeon_depth(lid
.branch
, lid
.depth
);