XP calculations are done in game.cpp and melee.cpp.
There are following formulas:
- 25% chance to get 1 xp/75% chance to get 0 xp for
skill_melee
per successful smash (via void game::smash())
if (u.get_skill_level( skill_melee ) == 0) {
u.practice( skill_melee, rng(0, 1) * rng(0, 1));
}
- Practice melee
skill_melee
, skill_bashing
, skill_cutting
, skill_stabbing
and skill_unarmed
proportional to damage dealt (via static void melee_train( player &p, int lo, int hi, const item &weap ))
static void melee_train( player &p, int lo, int hi, const item &weap ) {
p.practice( skill_melee, ceil( rng( lo, hi ) / 2.0 ), hi );
// allocate XP proportional to damage stats
// Pure unarmed needs a special case because it has 0 weapon damage
int cut = weap.damage_melee( DT_CUT );
int stab = weap.damage_melee( DT_STAB );
int bash = weap.damage_melee( DT_BASH ) + ( weap.is_null() ? 1 : 0 );
float total = std::max( cut + stab + bash, 1 );
p.practice( skill_cutting, ceil( cut / total * rng( lo, hi ) ), hi );
p.practice( skill_stabbing, ceil( stab / total * rng( lo, hi ) ), hi );
// Unarmed skill scaled bashing damage and so scales with bashing damage
p.practice( weap.has_flag( "UNARMED_WEAPON" ) ? skill_unarmed : skill_bashing,
ceil( bash / total * rng( lo, hi ) ), hi );
}
- When CQB bionic is not active train
skill_melee
(via void player::melee_attack(Creature &t, bool allow_special, const matec_id &force_technique, int hit_spread))
When hit_spread
is less than 0:
// Practice melee and relevant weapon skill (if any) except when using CQB bionic
if( !has_active_bionic( bio_cqb ) ) {
melee_train( *this, 2, 5, cur_weapon );
}
When hit_spread
is more than or equal to 0:
// Practice melee and relevant weapon skill (if any) except when using CQB bionic
if( !has_active_bionic( bio_cqb ) ) {
melee_train( *this, 5, 10, cur_weapon );
}
- Gain 0 to 10 xp with equal chance with
skill_unarmed
once per combo (via void player::perform_special_attacks(Creature &t))
if( !practiced ) {
// Practice unarmed, at most once per combo
practiced = true;
practice( skill_unarmed, rng( 0, 10 ) );
}