mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-01 16:37:45 +00:00
change action cost system to allow for a variable amount of costs
This commit is contained in:
parent
bd7860d896
commit
6a9d3c18ec
3 changed files with 119 additions and 84 deletions
|
@ -538,8 +538,9 @@ namespace Sapphire::Common
|
||||||
Unaspected = 7 // Doesn't imply magical unaspected damage - could be unaspected physical
|
Unaspected = 7 // Doesn't imply magical unaspected damage - could be unaspected physical
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ActionCostType : uint8_t
|
enum class ActionCostType : uint8_t
|
||||||
{
|
{
|
||||||
|
None = 0, // ?
|
||||||
MagicPoints = 3,
|
MagicPoints = 3,
|
||||||
TacticsPoints = 5,
|
TacticsPoints = 5,
|
||||||
ClassGaugeWAR = 22,
|
ClassGaugeWAR = 22,
|
||||||
|
|
|
@ -32,11 +32,14 @@ Sapphire::Action::Action::Action( Entity::CharaPtr caster, uint32_t actionId,
|
||||||
{
|
{
|
||||||
m_castTime = static_cast< uint32_t >( action->cast100ms ) * 100;
|
m_castTime = static_cast< uint32_t >( action->cast100ms ) * 100;
|
||||||
|
|
||||||
m_costType = static_cast< Common::ActionCostType >( action->costType );
|
m_actionCost.fill( { Common::ActionCostType::None, 0 } );
|
||||||
m_cost = action->cost;
|
|
||||||
|
|
||||||
if( caster->isPlayer() && isCastedAction() )
|
m_actionCost[ 0 ] = {
|
||||||
calculateMPCost();
|
static_cast< Common::ActionCostType >( action->costType ),
|
||||||
|
action->cost
|
||||||
|
};
|
||||||
|
|
||||||
|
calculateActionCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Sapphire::Action::Action::getId() const
|
uint32_t Sapphire::Action::Action::getId() const
|
||||||
|
@ -44,84 +47,6 @@ uint32_t Sapphire::Action::Action::getId() const
|
||||||
return m_id;
|
return m_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sapphire::Action::Action::calculateMPCost()
|
|
||||||
{
|
|
||||||
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 = m_cost;
|
|
||||||
|
|
||||||
// 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_cost is the base cost, cost is the multiplier for the current player level
|
|
||||||
m_cost = static_cast< uint16_t >( std::round( cost * m_cost ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sapphire::Action::Action::subtractCostFromCaster()
|
void Sapphire::Action::Action::subtractCostFromCaster()
|
||||||
{
|
{
|
||||||
if( !m_pSource->isPlayer() )
|
if( !m_pSource->isPlayer() )
|
||||||
|
@ -353,3 +278,99 @@ void Sapphire::Action::Action::healTarget( uint32_t amount, Entity::Chara& chara
|
||||||
// todo: make sure that we don't add the same actor more than once
|
// todo: make sure that we don't add the same actor more than once
|
||||||
m_effects[ EffectPacketIdentity::HealingEffect ].m_hitActors.emplace_back( chara.getId() );
|
m_effects[ EffectPacketIdentity::HealingEffect ].m_hitActors.emplace_back( chara.getId() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Sapphire::Action::Action::ActionCostArray& Sapphire::Action::Action::getCostArray() const
|
||||||
|
{
|
||||||
|
return m_actionCost;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sapphire::Action::Action::calculateActionCost()
|
||||||
|
{
|
||||||
|
for( uint8_t i = 0; i < m_actionCost.size(); ++i )
|
||||||
|
{
|
||||||
|
auto& entry = m_actionCost[ i ];
|
||||||
|
|
||||||
|
if( entry.m_costType == ActionCostType::MagicPoints )
|
||||||
|
calculateMPCost( i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sapphire::Action::Action::calculateMPCost( uint8_t costArrayIndex )
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
auto& costEntry = m_actionCost[ costArrayIndex ];
|
||||||
|
|
||||||
|
float cost = costEntry.m_cost;
|
||||||
|
|
||||||
|
// 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_cost is the base cost, cost is the multiplier for the current player level
|
||||||
|
costEntry.m_cost = static_cast< uint16_t >( std::round( cost * costEntry.m_cost ) );
|
||||||
|
}
|
|
@ -18,6 +18,14 @@ namespace Sapphire::Action
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
struct ActionCostEntry
|
||||||
|
{
|
||||||
|
Common::ActionCostType m_costType;
|
||||||
|
uint16_t m_cost;
|
||||||
|
};
|
||||||
|
|
||||||
|
using ActionCostArray = std::array< ActionCostEntry, 2 >;
|
||||||
|
|
||||||
Action();
|
Action();
|
||||||
Action( Entity::CharaPtr caster, uint32_t actionId, Data::ActionPtr action, FrameworkPtr fw );
|
Action( Entity::CharaPtr caster, uint32_t actionId, Data::ActionPtr action, FrameworkPtr fw );
|
||||||
|
|
||||||
|
@ -38,6 +46,8 @@ namespace Sapphire::Action
|
||||||
uint32_t getCastTime() const;
|
uint32_t getCastTime() const;
|
||||||
void setCastTime( uint32_t castTime );
|
void setCastTime( uint32_t castTime );
|
||||||
|
|
||||||
|
const ActionCostArray& getCostArray() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Tests whether the action is instantly usable or has a cast assoc'd with it
|
* @brief Tests whether the action is instantly usable or has a cast assoc'd with it
|
||||||
* @return true if action has a cast time
|
* @return true if action has a cast time
|
||||||
|
@ -74,7 +84,8 @@ namespace Sapphire::Action
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void calculateMPCost();
|
void calculateActionCost();
|
||||||
|
void calculateMPCost( uint8_t costArrayIndex );
|
||||||
void subtractCostFromCaster();
|
void subtractCostFromCaster();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -99,6 +110,8 @@ namespace Sapphire::Action
|
||||||
Common::ActionCostType m_costType;
|
Common::ActionCostType m_costType;
|
||||||
uint16_t m_cost;
|
uint16_t m_cost;
|
||||||
|
|
||||||
|
ActionCostArray m_actionCost;
|
||||||
|
|
||||||
uint64_t m_startTime;
|
uint64_t m_startTime;
|
||||||
uint32_t m_castTime;
|
uint32_t m_castTime;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue