@ -48,6 +48,8 @@ All rights reserved.
# include "Menu.h"
# include "GameState.h"
# include "MenuComponent.h"
# include <string_view>
INCLUDE_MONSTER_DATA
INCLUDE_MONSTER_LIST
@ -69,9 +71,6 @@ InputGroup Player::KEY_ITEM1;
InputGroup Player : : KEY_ITEM2 ;
InputGroup Player : : KEY_ITEM3 ;
ItemAttributable PlayerStats : : equipStats ;
ItemAttributable PlayerStats : : baseStats ;
std : : set < MenuComponent * > Player : : moneyListeners ;
Player : : Player ( )
@ -87,15 +86,15 @@ Player::Player(Player*player)
void Player : : Initialize ( ) {
Player : : GROUND_SLAM_SPIN_TIME = " Warrior.Ability 2.SpinTime " _F ;
SetBaseStat ( ItemAttribute : : health , hp ) ;
SetBaseStat ( ItemAttribute : : defense , 0 ) ;
SetBaseStat ( ItemAttribute : : attack , " Warrior.BaseAtk " _I ) ;
SetBaseStat ( ItemAttribute : : moveSpdPct , 100 ) ;
SetBaseStat ( ItemAttribute : : cdrPct , 0 ) ;
SetBaseStat ( ItemAttribute : : critPct , 0 ) ;
SetBaseStat ( ItemAttribute : : critDmgPct , 0 ) ;
SetBaseStat ( ItemAttribute : : healthPct , 0 ) ;
SetBaseStat ( ItemAttribute : : healthPctRecoveryPer6sec , 0 ) ;
SetBaseStat ( " Health " , hp ) ;
SetBaseStat ( " Defense " , 0 ) ;
SetBaseStat ( " Attack " , " Warrior.BaseAtk " _I ) ;
SetBaseStat ( " Move Spd % " , 100 ) ;
SetBaseStat ( " CDR " , 0 ) ;
SetBaseStat ( " Crit Rate " , 0 ) ;
SetBaseStat ( " Crit Dmg " , 0 ) ;
SetBaseStat ( " Health % " , 0 ) ;
SetBaseStat ( " HP6 Recovery % " , 0 ) ;
}
bool Player : : SetX ( float x ) {
@ -184,7 +183,7 @@ const int Player::GetHealth()const{
}
const int Player : : GetMaxHealth ( ) const {
return GetStat ( ItemAttribute : : health ) ;
return GetStat ( " Health " ) ;
}
const int Player : : GetMana ( ) const {
@ -196,22 +195,19 @@ const int Player::GetMaxMana()const{
}
const int Player : : GetAttack ( ) {
float mod_atk = float ( GetStat ( ItemAttribute : : attack ) ) ;
for ( Buff & b : GetBuffs ( BuffType : : ATTACK_UP ) ) {
mod_atk + = GetStat ( ItemAttribute : : attack ) * b . intensity ;
}
for ( Buff & b : GetBuffs ( BuffType : : ATTACK_PCT_UP ) ) {
mod_atk + = GetStat ( ItemAttribute : : attack ) * b . intensity ;
}
float mod_atk = float ( GetStat ( " Attack " ) ) ;
mod_atk + = Get ( " Attack " ) ;
mod_atk + = Get ( " Attack % " ) ;
return int ( mod_atk ) ;
}
float Player : : GetMoveSpdMult ( ) {
float mod_moveSpd = GetStat ( ItemAttribute : : moveSpdPct ) / 100.f ;
for ( Buff & b : GetBuffs ( BuffType : : SLOWDOWN ) ) {
float mod_moveSpd = GetStat ( " Move Spd % " ) / 100.f ;
mod_moveSpd + = ItemAttribute : : Get ( " Move Spd % " , this ) ;
for ( const Buff & b : GetBuffs ( BuffType : : SLOWDOWN ) ) {
mod_moveSpd - = mod_moveSpd * b . intensity ;
}
for ( Buff & b : GetBuffs ( BuffType : : BLOCK_SLOWDOWN ) ) {
for ( const Buff & b : GetBuffs ( BuffType : : BLOCK_SLOWDOWN ) ) {
mod_moveSpd - = mod_moveSpd * b . intensity ;
}
return mod_moveSpd ;
@ -606,11 +602,31 @@ bool Player::HasIframes(){
bool Player : : Hurt ( int damage , bool onUpperLevel , float z ) {
if ( hp < = 0 | | HasIframes ( ) | | OnUpperLevel ( ) ! = onUpperLevel | | abs ( GetZ ( ) - z ) > 1 ) return false ;
if ( GetState ( ) = = State : : BLOCK ) damage * = int ( 1 - " Warrior.Right Click Ability.DamageReduction " _F ) ;
float mod_dmg = float ( damage ) ;
lastCombatTime = 0 ;
for ( Buff & b : GetBuffs ( BuffType : : DAMAGE_REDUCTION ) ) {
mod_dmg - = damage * b . intensity ;
if ( GetState ( ) = = State : : BLOCK ) {
mod_dmg = 0 ;
} else {
float otherDmgTaken = 1 - GetDamageReductionFromBuffs ( ) ;
float armorDmgTaken = 1 - GetDamageReductionFromArmor ( ) ;
lastCombatTime = 0 ;
float finalPctDmgTaken = armorDmgTaken * otherDmgTaken ;
if ( finalPctDmgTaken < = 0.06f ) {
std : : cout < < " WARNING! Damage Reduction has somehow ended up below 6%, which is over the cap! " < < std : : endl ;
}
finalPctDmgTaken = std : : max ( 0.0625f , finalPctDmgTaken ) ; //Apply Damage Cap.
float minPctDmgReduction = 0.00 ' 05f * GetStat ( " Defense " ) ;
float finalPctDmgReduction = 1 - finalPctDmgTaken ;
float pctDmgReductionDiff = finalPctDmgReduction - minPctDmgReduction ;
float dmgRoll = minPctDmgReduction + util : : random ( pctDmgReductionDiff ) ;
mod_dmg * = 1 - dmgRoll ;
mod_dmg = std : : ceil ( mod_dmg ) ;
}
hp = std : : max ( 0 , hp - int ( mod_dmg ) ) ;
if ( lastHitTimer > 0 ) {
@ -719,6 +735,12 @@ void Player::UpdateIdleAnimation(Key direction){
void Player : : AddBuff ( BuffType type , float duration , float intensity ) {
buffList . push_back ( Buff { type , duration , intensity } ) ;
}
void Player : : AddBuff ( BuffType type , float duration , float intensity , std : : set < ItemAttribute > attr ) {
buffList . push_back ( Buff { type , duration , intensity , attr } ) ;
}
void Player : : AddBuff ( BuffType type , float duration , float intensity , std : : set < std : : string > attr ) {
buffList . push_back ( Buff { type , duration , intensity , attr } ) ;
}
void Player : : AddBuff ( BuffType type , float duration , float intensity , float timeBetweenTicks , std : : function < void ( Crawler * , int ) > repeatAction ) {
buffList . push_back ( Buff { type , duration , intensity , timeBetweenTicks , repeatAction } ) ;
}
@ -727,9 +749,9 @@ bool Player::OnUpperLevel(){
return upperLevel ;
}
std : : vector < Buff > Player : : GetBuffs ( BuffType buff ) {
const std : : vector < Buff > Player : : GetBuffs ( BuffType buff ) const {
std : : vector < Buff > filteredBuffs ;
std : : copy_if ( buffList . begin ( ) , buffList . end ( ) , std : : back_inserter ( filteredBuffs ) , [ buff ] ( Buff & b ) { return b . type = = buff ; } ) ;
std : : copy_if ( buffList . begin ( ) , buffList . end ( ) , std : : back_inserter ( filteredBuffs ) , [ buff ] ( const Buff b ) { return b . type = = buff ; } ) ;
return filteredBuffs ;
}
@ -809,7 +831,7 @@ void Player::SetIframes(float duration){
}
bool Player : : Heal ( int damage ) {
hp = std : : clamp ( hp + damage , 0 , GetStat ( ItemAttribute : : health ) ) ;
hp = std : : clamp ( hp + damage , 0 , GetStat ( " Health " ) ) ;
if ( damage > 0 ) {
DAMAGENUMBER_LIST . push_back ( std : : make_shared < DamageNumber > ( GetPos ( ) , damage , true , HEALTH_GAIN ) ) ;
}
@ -873,23 +895,31 @@ void Player::SetItem3UseFunc(Ability a){
useItem3 = a ;
} ;
const int Player : : GetStat ( ItemAttribute a ) const {
return PlayerStats : : GetStat ( a ) ;
const int & Player : : GetStat ( std : : string_view a ) const {
return GetStat ( ItemAttribute : : Get ( a ) ) ;
}
const int Player : : GetBase Stat ( ItemAttribute a ) const {
return PlayerStats : : GetBase Stat( a ) ;
const int & Player : : GetStat ( ItemAttribute a ) const {
return stats . Get Stat( a ) ;
}
const int & Player : : GetBaseStat ( std : : string_view a ) const {
return GetBaseStat ( ItemAttribute : : Get ( a ) ) ;
}
const int & Player : : GetBaseStat ( ItemAttribute a ) const {
return stats . GetBaseStat ( a ) ;
}
void PlayerStats : : RecalculateEquipStats ( ) {
void EntityStats : : RecalculateEquipStats ( ) {
baseStats . copyTo ( equipStats ) ;
for ( int i = int ( EquipSlot : : HELMET ) ; i < = int ( EquipSlot : : RING2 ) ; i < < = 1 ) {
EquipSlot slot = EquipSlot ( i ) ;
std : : weak_ptr < Item > equip = Inventory : : GetEquip ( slot ) ;
if ( ISBLANK ( equip ) ) continue ;
for ( ItemAttribute a = ItemAttribute ( int ( ItemAttribute : : ENUM_START ) + 1 ) ; a < ItemAttribute : : ENUM_END ; a = ItemA ttribute( int ( a ) + 1 ) ) {
equipStats . A ( a ) + = equip . lock ( ) - > GetStats ( ) . A_Read ( a ) ;
for ( auto & [ key , size ] : ItemAttribute : : a ttributes ) {
equipStats . A ( key ) + = equip . lock ( ) - > GetStats ( ) . A_Read ( key ) ;
}
}
@ -897,27 +927,36 @@ void PlayerStats::RecalculateEquipStats(){
for ( const auto & [ set , equipCount ] : setCounts ) {
const Stats & setStats = set [ equipCount ] ;
for ( ItemAttribute a = ItemAttribute ( int ( ItemAttribute : : ENUM_START ) + 1 ) ; a < ItemAttribute : : ENUM_END ; a = ItemA ttribute( int ( a ) + 1 ) ) {
equipStats . A ( a ) + = setStats . A_Read ( a ) ;
for ( auto & [ key , size ] : ItemAttribute : : a ttributes ) {
equipStats . A ( key ) + = setStats . A_Read ( key ) ;
}
}
for ( MenuComponent * component : Menu : : equipStatListeners ) {
component - > OnEquipStatsUpdate ( ) ;
}
}
const int PlayerStats : : GetStat ( ItemAttribute stat ) {
return equipStats . A ( stat ) ;
const int & EntityStats : : GetStat ( ItemAttribute stat ) const {
return equipStats . A_Read ( stat ) ;
}
const int & EntityStats : : GetStat ( std : : string_view stat ) const {
return equipStats . A_Read ( stat ) ;
}
const int PlayerStats : : GetBaseStat ( ItemAttribute stat ) {
return baseStats . A ( stat ) ;
const int & EntityStats : : GetBaseStat ( ItemAttribute stat ) const {
return baseStats . A_Read ( stat ) ;
}
const int & EntityStats : : GetBaseStat ( std : : string_view stat ) const {
return baseStats . A_Read ( stat ) ;
}
void PlayerStats : : SetBaseStat ( ItemAttribute stat , int val ) {
void Entity Stats: : SetBaseStat ( ItemAttribute stat , int val ) {
baseStats . A ( stat ) = val ;
RecalculateEquipStats ( ) ;
}
void Player : : SetBaseStat ( std : : string_view a , int val ) {
stats . SetBaseStat ( ItemAttribute : : Get ( a ) , val ) ;
}
void Player : : SetBaseStat ( ItemAttribute a , int val ) {
PlayerStats : : SetBaseStat ( a , val ) ;
stats . SetBaseStat ( a , val ) ;
}
const std : : string & ItemSet : : GetSetName ( ) const {
@ -926,14 +965,52 @@ const std::string&ItemSet::GetSetName()const{
uint32_t Player : : GetMoney ( ) const {
return money ;
} ;
}
void Player : : SetMoney ( uint32_t newMoney ) {
money = newMoney ;
for ( auto & component : moneyListeners ) {
component - > OnPlayerMoneyUpdate ( newMoney ) ;
}
} ;
}
void Player : : AddMoneyListener ( MenuComponent * component ) {
if ( moneyListeners . count ( component ) ) ERR ( " WARNING! Trying to add a second copy of component " < < std : : quoted ( component - > GetName ( ) ) ) ;
moneyListeners . insert ( component ) ;
}
const float Player : : GetDamageReductionFromBuffs ( ) const {
float dmgReduction = 0 ;
for ( const Buff & b : GetBuffs ( BuffType : : DAMAGE_REDUCTION ) ) {
dmgReduction + = b . intensity ;
}
return std : : min ( 0.75f , dmgReduction ) ;
} ;
const float Player : : GetDamageReductionFromArmor ( ) const {
float dmgReduction = 0 ;
dmgReduction + = Stats : : GetDamageReductionPct ( GetStat ( " Defense " ) ) ;
return std : : min ( 0.75f , dmgReduction ) ;
} ;
void Player : : RecalculateEquipStats ( ) {
stats . RecalculateEquipStats ( ) ;
}
const std : : vector < Buff > Player : : GetStatBuffs ( const std : : vector < std : : string > & attr ) const {
std : : vector < Buff > statUpBuffs ;
std : : copy_if ( buffList . begin ( ) , buffList . end ( ) , std : : back_inserter ( statUpBuffs ) , [ & ] ( const Buff b ) {
return b . type = = STAT_UP & & std : : find_if ( attr . begin ( ) , attr . end ( ) , [ & ] ( const std : : string & attr ) { return b . attr . count ( ItemAttribute : : Get ( attr ) ) ; } ) ! = attr . end ( ) ;
} ) ;
return statUpBuffs ;
}
const ItemAttributable & EntityStats : : GetStats ( ) const {
return equipStats ;
}
const ItemAttributable & Player : : GetStats ( ) const {
return stats . GetStats ( ) ;
} ;
ItemAttribute & Player : : Get ( std : : string_view attr ) {
return ItemAttribute : : Get ( attr , this ) ;
}