mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-28 07:07:45 +00:00
minor cleanup and move mp cost calc into calcstats
This commit is contained in:
parent
3f44b6c91b
commit
6938e16618
4 changed files with 104 additions and 88 deletions
|
@ -931,6 +931,18 @@ namespace Sapphire::Common
|
||||||
uint16_t cost;
|
uint16_t cost;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum LevelTableEntry : uint8_t
|
||||||
|
{
|
||||||
|
PIE,
|
||||||
|
MP,
|
||||||
|
MAIN,
|
||||||
|
SUB,
|
||||||
|
DIV,
|
||||||
|
HP,
|
||||||
|
ELMT,
|
||||||
|
THREAT
|
||||||
|
};
|
||||||
|
|
||||||
using PlayerStateFlagList = std::vector< PlayerStateFlag >;
|
using PlayerStateFlagList = std::vector< PlayerStateFlag >;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include "Framework.h"
|
#include "Framework.h"
|
||||||
#include "Script/ScriptMgr.h"
|
#include "Script/ScriptMgr.h"
|
||||||
|
|
||||||
|
#include <Math/CalcStats.h>
|
||||||
|
|
||||||
#include "Actor/Player.h"
|
#include "Actor/Player.h"
|
||||||
#include "Actor/BNpc.h"
|
#include "Actor/BNpc.h"
|
||||||
|
|
||||||
|
@ -302,7 +304,8 @@ void Sapphire::Action::Action::calculateActionCost()
|
||||||
}
|
}
|
||||||
case ActionPrimaryCostType::MagicPoints:
|
case ActionPrimaryCostType::MagicPoints:
|
||||||
{
|
{
|
||||||
calculateMPCost( m_primaryCost );
|
// todo: not sure if we should store the final value like this?
|
||||||
|
m_primaryCost = Math::CalcStats::calculateMpCost( *m_pSource, m_primaryCost );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ActionPrimaryCostType::TacticsPoints:
|
case ActionPrimaryCostType::TacticsPoints:
|
||||||
|
@ -325,88 +328,6 @@ void Sapphire::Action::Action::calculateActionCost()
|
||||||
// todo: secondary cost type needs to be handled
|
// todo: secondary cost type needs to be handled
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: this shouldn't be in action and instead be in some general stat calc util
|
|
||||||
void Sapphire::Action::Action::calculateMPCost( uint16_t baseCost )
|
|
||||||
{
|
|
||||||
auto level = m_pSource->getLevel();
|
|
||||||
|
|
||||||
// each level range is 1-10, 11-20, 21-30, ... therefore:
|
|
||||||
// level 50 should be in the 4th group, not the 5th
|
|
||||||
// dividing by 10 on the border will break this unless we subtract 1
|
|
||||||
auto levelGroup = std::max< uint8_t >( level - 1, 1 ) / 10;
|
|
||||||
|
|
||||||
float cost = baseCost;
|
|
||||||
|
|
||||||
// thanks to andrew for helping me figure this shit out, should be pretty accurate
|
|
||||||
switch( levelGroup )
|
|
||||||
{
|
|
||||||
// level 1-10
|
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
// r^2 = 0.9999
|
|
||||||
cost = 0.0952f * level + 0.9467f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// level 11-20
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
// r^2 = 1
|
|
||||||
cost = 0.19f * level;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// level 21-30
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
// r^2 = 1
|
|
||||||
cost = 0.38f * level - 3.8f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// level 31-40
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
// r^2 = 1
|
|
||||||
cost = 0.6652f * level - 12.358f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// level 41-50
|
|
||||||
case 4:
|
|
||||||
{
|
|
||||||
// r^2 = 1
|
|
||||||
cost = 1.2352f * level - 35.159f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// level 51-60
|
|
||||||
case 5:
|
|
||||||
{
|
|
||||||
// r^2 = 1
|
|
||||||
cost = 0.0654f * std::exp( 0.1201f * level );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// level 61-70
|
|
||||||
case 6:
|
|
||||||
{
|
|
||||||
// r^2 = 0.9998
|
|
||||||
cost = 0.2313f * ( level * level ) - 26.98f * level + 875.21f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// m_primaryCost is the base cost, cost is the multiplier for the current player level
|
|
||||||
m_primaryCost = static_cast< uint16_t >( std::round( cost * baseCost ) );
|
|
||||||
|
|
||||||
if( auto player = m_pSource->getAsPlayer() )
|
|
||||||
player->sendDebug( "calculated mp cost: {0}", m_primaryCost );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Sapphire::Action::Action::precheck()
|
bool Sapphire::Action::Action::precheck()
|
||||||
{
|
{
|
||||||
if( auto player = m_pSource->getAsPlayer() )
|
if( auto player = m_pSource->getAsPlayer() )
|
||||||
|
|
|
@ -184,11 +184,91 @@ uint32_t CalcStats::calculateMaxMp( PlayerPtr pPlayer, Sapphire::FrameworkPtr pF
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t CalcStats::calculateMpCost( const Sapphire::Entity::Chara& chara, uint16_t baseCost )
|
||||||
|
{
|
||||||
|
auto level = chara.getLevel();
|
||||||
|
|
||||||
|
// each level range is 1-10, 11-20, 21-30, ... therefore:
|
||||||
|
// level 50 should be in the 4th group, not the 5t
|
||||||
|
// dividing by 10 on the border will break this unless we subtract 1
|
||||||
|
auto levelGroup = std::max< decltype( level ) >( level - 1, 1 ) / 10;
|
||||||
|
|
||||||
|
float cost = baseCost;
|
||||||
|
|
||||||
|
// thanks to andrew for helping me figure this shit out
|
||||||
|
// played with this some more and it seems to be accurate for everything i've tried
|
||||||
|
switch( levelGroup )
|
||||||
|
{
|
||||||
|
// level 1-10
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
// r^2 = 0.9999
|
||||||
|
cost = 0.0952f * level + 0.9467f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// level 11-20
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
// r^2 = 1
|
||||||
|
cost = 0.19f * level;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// level 21-30
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
// r^2 = 1
|
||||||
|
cost = 0.38f * level - 3.8f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// level 31-40
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
// r^2 = 1
|
||||||
|
cost = 0.6652f * level - 12.358f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// level 41-50
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
// r^2 = 1
|
||||||
|
cost = 1.2352f * level - 35.159f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// level 51-60
|
||||||
|
case 5:
|
||||||
|
{
|
||||||
|
// r^2 = 1
|
||||||
|
cost = 0.0654f * std::exp( 0.1201f * level );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// level 61-70
|
||||||
|
case 6:
|
||||||
|
{
|
||||||
|
// r^2 = 0.9998
|
||||||
|
cost = 0.2313f * ( level * level ) - 26.98f * level + 875.21f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast< uint16_t >( std::round( cost * baseCost ) );
|
||||||
|
}
|
||||||
|
|
||||||
float CalcStats::pBlk( const Chara& chara )
|
float CalcStats::pBlk( const Chara& chara )
|
||||||
{
|
{
|
||||||
auto level = chara.getLevel();
|
auto level = chara.getLevel();
|
||||||
float blockRate = static_cast< float >( chara.getBonusStat( Common::BaseParam::BlockRate ) );
|
float blockRate = static_cast< float >( chara.getBonusStat( Common::BaseParam::BlockRate ) );
|
||||||
float levelVal = static_cast< float >( levelTable[ level ][ 4 ] );
|
float levelVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] );
|
||||||
|
|
||||||
return std::floor( ( 30 * blockRate ) / levelVal + 10 );
|
return std::floor( ( 30 * blockRate ) / levelVal + 10 );
|
||||||
}
|
}
|
||||||
|
@ -201,8 +281,8 @@ float CalcStats::pDhr( const Chara& chara )
|
||||||
float dhRate = static_cast< float >( chara.getBonusStat( Common::BaseParam::DirectHitRate ) ) +
|
float dhRate = static_cast< float >( chara.getBonusStat( Common::BaseParam::DirectHitRate ) ) +
|
||||||
baseStats.accuracy;
|
baseStats.accuracy;
|
||||||
|
|
||||||
float divVal = static_cast< float >( levelTable[ level ][ 4 ] );
|
float divVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] );
|
||||||
float subVal = static_cast< float >( levelTable[ level ][ 3 ] );
|
float subVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::SUB ] );
|
||||||
|
|
||||||
return std::floor( 550.f * ( dhRate - subVal ) / divVal ) / 10.f;
|
return std::floor( 550.f * ( dhRate - subVal ) / divVal ) / 10.f;
|
||||||
}
|
}
|
||||||
|
@ -215,8 +295,8 @@ float CalcStats::pChr( const Chara& chara )
|
||||||
float chRate = static_cast< float >( chara.getBonusStat( Common::BaseParam::CriticalHit ) ) +
|
float chRate = static_cast< float >( chara.getBonusStat( Common::BaseParam::CriticalHit ) ) +
|
||||||
baseStats.critHitRate;
|
baseStats.critHitRate;
|
||||||
|
|
||||||
float divVal = static_cast< float >( levelTable[ level ][ 4 ] );
|
float divVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] );
|
||||||
float subVal = static_cast< float >( levelTable[ level ][ 3 ] );
|
float subVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::SUB ] );
|
||||||
|
|
||||||
return std::floor( 200.f * ( chRate - subVal ) / divVal + 50.f ) / 10.f;
|
return std::floor( 200.f * ( chRate - subVal ) / divVal + 50.f ) / 10.f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,12 @@ namespace Sapphire::Math
|
||||||
|
|
||||||
static uint32_t calculateMaxHp( Sapphire::Entity::PlayerPtr pPlayer, FrameworkPtr pFw );
|
static uint32_t calculateMaxHp( Sapphire::Entity::PlayerPtr pPlayer, FrameworkPtr pFw );
|
||||||
|
|
||||||
|
static uint16_t calculateMpCost( const Sapphire::Entity::Chara& chara, uint16_t baseCost );
|
||||||
|
|
||||||
static float pBlk( const Sapphire::Entity::Chara& );
|
static float pBlk( const Sapphire::Entity::Chara& );
|
||||||
static float pDhr( const Sapphire::Entity::Chara& );
|
static float pDhr( const Sapphire::Entity::Chara& );
|
||||||
static float pChr( const Sapphire::Entity::Chara& );
|
static float pChr( const Sapphire::Entity::Chara& );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue