mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-28 15:17:46 +00:00
some cleanup, kinda working battle dmg calc
This commit is contained in:
parent
7684687664
commit
f3ba1ce6c0
11 changed files with 178 additions and 17 deletions
|
@ -990,6 +990,18 @@ namespace Sapphire::Common
|
||||||
CircularAoEPlaced = 7
|
CircularAoEPlaced = 7
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class Role : uint8_t
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Tank,
|
||||||
|
Healer,
|
||||||
|
RangedPhysical,
|
||||||
|
RangedMagical,
|
||||||
|
Melee,
|
||||||
|
Crafter,
|
||||||
|
Gatherer
|
||||||
|
};
|
||||||
|
|
||||||
using PlayerStateFlagList = std::vector< PlayerStateFlag >;
|
using PlayerStateFlagList = std::vector< PlayerStateFlag >;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include "ActionLut.h"
|
#include "ActionLut.h"
|
||||||
#include "EffectBuilder.h"
|
#include "EffectBuilder.h"
|
||||||
|
|
||||||
|
#include <Inventory/Item.h>
|
||||||
|
|
||||||
#include <Exd/ExdDataGenerated.h>
|
#include <Exd/ExdDataGenerated.h>
|
||||||
#include <Util/Util.h>
|
#include <Util/Util.h>
|
||||||
#include "Framework.h"
|
#include "Framework.h"
|
||||||
|
@ -357,6 +359,32 @@ void Action::Action::execute()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcDamage( uint32_t potency )
|
||||||
|
{
|
||||||
|
// todo: what do for npcs?
|
||||||
|
auto wepDmg = 1.f;
|
||||||
|
|
||||||
|
if( auto player = m_pSource->getAsPlayer() )
|
||||||
|
{
|
||||||
|
auto item = player->getEquippedWeapon();
|
||||||
|
assert( item );
|
||||||
|
|
||||||
|
auto role = player->getRole();
|
||||||
|
if( role == Common::Role::RangedMagical || role == Common::Role::Healer )
|
||||||
|
{
|
||||||
|
wepDmg = item->getMagicalDmg();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wepDmg = item->getPhysicalDmg();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dmg = Math::CalcStats::calcActionDamage( *m_pSource, potency, wepDmg );
|
||||||
|
|
||||||
|
return std::make_pair( dmg, Common::ActionHitSeverityType::NormalDamage );
|
||||||
|
}
|
||||||
|
|
||||||
void Action::Action::buildEffects()
|
void Action::Action::buildEffects()
|
||||||
{
|
{
|
||||||
snapshotAffectedActors( m_hitActors );
|
snapshotAffectedActors( m_hitActors );
|
||||||
|
@ -390,10 +418,16 @@ void Action::Action::buildEffects()
|
||||||
{
|
{
|
||||||
// todo: this is shit
|
// todo: this is shit
|
||||||
if( lutEntry.curePotency > 0 )
|
if( lutEntry.curePotency > 0 )
|
||||||
|
{
|
||||||
|
|
||||||
m_effectBuilder->healTarget( actor, lutEntry.curePotency );
|
m_effectBuilder->healTarget( actor, lutEntry.curePotency );
|
||||||
|
}
|
||||||
|
|
||||||
else if( lutEntry.potency > 0 )
|
else if( lutEntry.potency > 0 )
|
||||||
m_effectBuilder->damageTarget( actor, lutEntry.potency );
|
{
|
||||||
|
auto dmg = calcDamage( lutEntry.potency );
|
||||||
|
m_effectBuilder->damageTarget( actor, dmg.first, dmg.second );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_effectBuilder->buildAndSendPackets();
|
m_effectBuilder->buildAndSendPackets();
|
||||||
|
|
|
@ -98,6 +98,10 @@ namespace Sapphire::World::Action
|
||||||
*/
|
*/
|
||||||
void addDefaultActorFilters();
|
void addDefaultActorFilters();
|
||||||
|
|
||||||
|
std::pair< uint32_t, Common::ActionHitSeverityType > calcDamage( uint32_t potency );
|
||||||
|
|
||||||
|
std::pair< uint32_t, Common::ActionHitSeverityType > calcHealing( uint32_t potency );
|
||||||
|
|
||||||
|
|
||||||
std::vector< Entity::CharaPtr >& getHitCharas();
|
std::vector< Entity::CharaPtr >& getHitCharas();
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,11 @@ uint32_t EffectResult::getValue() const
|
||||||
return m_value;
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EffectResult::setParam( uint8_t param )
|
||||||
|
{
|
||||||
|
m_param = param;
|
||||||
|
}
|
||||||
|
|
||||||
void EffectResult::damage( uint32_t amount, Common::ActionHitSeverityType severity )
|
void EffectResult::damage( uint32_t amount, Common::ActionHitSeverityType severity )
|
||||||
{
|
{
|
||||||
m_severity = severity;
|
m_severity = severity;
|
||||||
|
@ -49,7 +54,7 @@ Common::EffectEntry EffectResult::buildEffectEntry() const
|
||||||
entry.value = getValue();
|
entry.value = getValue();
|
||||||
entry.hitSeverity = m_severity;
|
entry.hitSeverity = m_severity;
|
||||||
entry.effectType = m_type;
|
entry.effectType = m_type;
|
||||||
|
entry.param = m_param;
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
|
@ -22,6 +22,8 @@ namespace Sapphire::World::Action
|
||||||
|
|
||||||
uint32_t getValue() const;
|
uint32_t getValue() const;
|
||||||
|
|
||||||
|
void setParam( uint8_t param );
|
||||||
|
|
||||||
Common::EffectEntry buildEffectEntry() const;
|
Common::EffectEntry buildEffectEntry() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -33,6 +35,7 @@ namespace Sapphire::World::Action
|
||||||
Common::ActionEffectType m_type;
|
Common::ActionEffectType m_type;
|
||||||
|
|
||||||
uint32_t m_value;
|
uint32_t m_value;
|
||||||
|
uint8_t m_param;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -692,7 +692,7 @@ void Sapphire::Entity::BNpc::autoAttack( CharaPtr pTarget )
|
||||||
srand( static_cast< uint32_t >( tick ) );
|
srand( static_cast< uint32_t >( tick ) );
|
||||||
|
|
||||||
auto pRNGMgr = m_pFw->get< World::Manager::RNGMgr >();
|
auto pRNGMgr = m_pFw->get< World::Manager::RNGMgr >();
|
||||||
auto damage = Math::CalcStats::calculateAutoAttackDamage( *this );
|
auto damage = Math::CalcStats::calcAutoAttackDamage( *this );
|
||||||
|
|
||||||
auto effectPacket = std::make_shared< Server::EffectPacket >( getId(), pTarget->getId(), 7 );
|
auto effectPacket = std::make_shared< Server::EffectPacket >( getId(), pTarget->getId(), 7 );
|
||||||
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
|
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
|
||||||
|
|
|
@ -123,6 +123,67 @@ void Sapphire::Entity::Chara::setClass( Common::ClassJob classJob )
|
||||||
m_class = classJob;
|
m_class = classJob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Sapphire::Common::Role Sapphire::Entity::Chara::getRole() const
|
||||||
|
{
|
||||||
|
switch( getClass() )
|
||||||
|
{
|
||||||
|
case ClassJob::Gladiator:
|
||||||
|
case ClassJob::Marauder:
|
||||||
|
case ClassJob::Paladin:
|
||||||
|
case ClassJob::Warrior:
|
||||||
|
case ClassJob::Darkknight:
|
||||||
|
case ClassJob::Gunbreaker:
|
||||||
|
return Role::Tank;
|
||||||
|
|
||||||
|
case ClassJob::Pugilist:
|
||||||
|
case ClassJob::Lancer:
|
||||||
|
case ClassJob::Monk:
|
||||||
|
case ClassJob::Dragoon:
|
||||||
|
case ClassJob::Rogue:
|
||||||
|
case ClassJob::Ninja:
|
||||||
|
case ClassJob::Samurai:
|
||||||
|
return Role::Melee;
|
||||||
|
|
||||||
|
case ClassJob::Archer:
|
||||||
|
case ClassJob::Bard:
|
||||||
|
case ClassJob::Machinist:
|
||||||
|
case ClassJob::Dancer:
|
||||||
|
return Role::RangedPhysical;
|
||||||
|
|
||||||
|
case ClassJob::Conjurer:
|
||||||
|
case ClassJob::Whitemage:
|
||||||
|
case ClassJob::Scholar:
|
||||||
|
case ClassJob::Astrologian:
|
||||||
|
return Role::Healer;
|
||||||
|
|
||||||
|
case ClassJob::Thaumaturge:
|
||||||
|
case ClassJob::Blackmage:
|
||||||
|
case ClassJob::Arcanist:
|
||||||
|
case ClassJob::Summoner:
|
||||||
|
case ClassJob::Redmage:
|
||||||
|
case ClassJob::Bluemage:
|
||||||
|
return Role::RangedMagical;
|
||||||
|
|
||||||
|
case ClassJob::Carpenter:
|
||||||
|
case ClassJob::Blacksmith:
|
||||||
|
case ClassJob::Armorer:
|
||||||
|
case ClassJob::Goldsmith:
|
||||||
|
case ClassJob::Leatherworker:
|
||||||
|
case ClassJob::Weaver:
|
||||||
|
case ClassJob::Alchemist:
|
||||||
|
case ClassJob::Culinarian:
|
||||||
|
return Role::Crafter;
|
||||||
|
|
||||||
|
case ClassJob::Miner:
|
||||||
|
case ClassJob::Botanist:
|
||||||
|
case ClassJob::Fisher:
|
||||||
|
return Role::Gatherer;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return Role::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*! \param Id of the target to set */
|
/*! \param Id of the target to set */
|
||||||
void Sapphire::Entity::Chara::setTargetId( uint64_t targetId )
|
void Sapphire::Entity::Chara::setTargetId( uint64_t targetId )
|
||||||
{
|
{
|
||||||
|
|
|
@ -209,6 +209,8 @@ namespace Sapphire::Entity
|
||||||
|
|
||||||
void setClass( Common::ClassJob classJob );
|
void setClass( Common::ClassJob classJob );
|
||||||
|
|
||||||
|
Common::Role getRole() const;
|
||||||
|
|
||||||
void setTargetId( uint64_t targetId );
|
void setTargetId( uint64_t targetId );
|
||||||
|
|
||||||
uint64_t getTargetId() const;
|
uint64_t getTargetId() const;
|
||||||
|
|
|
@ -1565,7 +1565,7 @@ void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget )
|
||||||
auto pRNGMgr = m_pFw->get< World::Manager::RNGMgr >();
|
auto pRNGMgr = m_pFw->get< World::Manager::RNGMgr >();
|
||||||
auto variation = static_cast< uint32_t >( pRNGMgr->getRandGenerator< float >( 0, 3 ).next() );
|
auto variation = static_cast< uint32_t >( pRNGMgr->getRandGenerator< float >( 0, 3 ).next() );
|
||||||
|
|
||||||
auto damage = Math::CalcStats::calculateAutoAttackDamage( *this );
|
auto damage = Math::CalcStats::calcAutoAttackDamage( *this );
|
||||||
|
|
||||||
if( getClass() == ClassJob::Machinist || getClass() == ClassJob::Bard || getClass() == ClassJob::Archer )
|
if( getClass() == ClassJob::Machinist || getClass() == ClassJob::Bard || getClass() == ClassJob::Archer )
|
||||||
{
|
{
|
||||||
|
|
|
@ -219,16 +219,9 @@ float CalcStats::autoAttackPotency( const Sapphire::Entity::Chara& chara )
|
||||||
{
|
{
|
||||||
uint32_t aaPotency = AUTO_ATTACK_POTENCY;
|
uint32_t aaPotency = AUTO_ATTACK_POTENCY;
|
||||||
|
|
||||||
// check if ranged class
|
if( chara.getRole() == Common::Role::RangedPhysical )
|
||||||
switch( chara.getClass() )
|
|
||||||
{
|
{
|
||||||
case Common::ClassJob::Machinist:
|
|
||||||
case Common::ClassJob::Bard:
|
|
||||||
case Common::ClassJob::Archer:
|
|
||||||
aaPotency = RANGED_AUTO_ATTACK_POTENCY;
|
aaPotency = RANGED_AUTO_ATTACK_POTENCY;
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float autoAttackDelay = 2.5f;
|
float autoAttackDelay = 2.5f;
|
||||||
|
@ -442,7 +435,7 @@ float CalcStats::healingMagicPotency( const Sapphire::Entity::Chara& chara )
|
||||||
return std::floor( 100.f * ( chara.getStatValue( Common::BaseParam::HealingMagicPotency ) - 292.f ) / 264.f + 100.f ) / 100.f;
|
return std::floor( 100.f * ( chara.getStatValue( Common::BaseParam::HealingMagicPotency ) - 292.f ) / 264.f + 100.f ) / 100.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float CalcStats::calculateAutoAttackDamage( const Sapphire::Entity::Chara& chara )
|
float CalcStats::calcAutoAttackDamage( const Sapphire::Entity::Chara& chara )
|
||||||
{
|
{
|
||||||
// D = ⌊ f(ptc) × f(aa) × f(ap) × f(det) × f(tnc) × traits ⌋ × f(ss) ⌋ ×
|
// D = ⌊ f(ptc) × f(aa) × f(ap) × f(det) × f(tnc) × traits ⌋ × f(ss) ⌋ ×
|
||||||
// f(chr) ⌋ × f(dhr) ⌋ × rand[ 0.95, 1.05 ] ⌋ × buff_1 ⌋ × buff... ⌋
|
// f(chr) ⌋ × f(dhr) ⌋ × rand[ 0.95, 1.05 ] ⌋ × buff_1 ⌋ × buff... ⌋
|
||||||
|
@ -451,12 +444,25 @@ float CalcStats::calculateAutoAttackDamage( const Sapphire::Entity::Chara& chara
|
||||||
auto aa = autoAttack( chara );
|
auto aa = autoAttack( chara );
|
||||||
auto ap = getPrimaryAttackPower( chara );
|
auto ap = getPrimaryAttackPower( chara );
|
||||||
auto det = determination( chara );
|
auto det = determination( chara );
|
||||||
auto ten = tenacity( chara );
|
|
||||||
|
|
||||||
Logger::debug( "auto attack: pot: {} aa: {} ap: {} det: {} ten: {}", pot, aa, ap, det, ten );
|
auto ten = 1.f;
|
||||||
|
if( chara.getRole() == Common::Role::Tank )
|
||||||
|
ten = tenacity( chara );
|
||||||
|
|
||||||
|
// todo: everything after tenacity
|
||||||
auto factor = std::floor( pot * aa * ap * det * ten );
|
auto factor = std::floor( pot * aa * ap * det * ten );
|
||||||
|
|
||||||
|
constexpr auto format = "auto attack: pot: {} aa: {} ap: {} det: {} ten: {} = {}";
|
||||||
|
|
||||||
|
if( auto player = const_cast< Entity::Chara& >( chara ).getAsPlayer() )
|
||||||
|
{
|
||||||
|
player->sendDebug( format, pot, aa, ap, det, ten, factor );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger::debug( format, pot, aa, ap, det, ten, factor );
|
||||||
|
}
|
||||||
|
|
||||||
// todo: traits
|
// todo: traits
|
||||||
|
|
||||||
factor = std::floor( factor * speed( chara ) );
|
factor = std::floor( factor * speed( chara ) );
|
||||||
|
@ -472,6 +478,38 @@ float CalcStats::calculateAutoAttackDamage( const Sapphire::Entity::Chara& chara
|
||||||
return factor;
|
return factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float CalcStats::calcActionDamage( const Sapphire::Entity::Chara& chara, uint32_t ptc, float wepDmg )
|
||||||
|
{
|
||||||
|
// D = ⌊ f(pot) × f(wd) × f(ap) × f(det) × f(tnc) × traits ⌋
|
||||||
|
// × f(chr) ⌋ × f(dhr) ⌋ × rand[ 0.95, 1.05 ] ⌋ buff_1 ⌋ × buff_1 ⌋ × buff... ⌋
|
||||||
|
|
||||||
|
auto pot = potency( ptc );
|
||||||
|
auto wd = weaponDamage( chara, wepDmg );
|
||||||
|
auto ap = getPrimaryAttackPower( chara );
|
||||||
|
auto det = determination( chara );
|
||||||
|
|
||||||
|
auto ten = 1.f;
|
||||||
|
if( chara.getRole() == Common::Role::Tank )
|
||||||
|
ten = tenacity( chara );
|
||||||
|
|
||||||
|
auto factor = std::floor( pot * wd * ap * det * ten );
|
||||||
|
|
||||||
|
constexpr auto format = "dmg: pot: {} wd: {} ap: {} det: {} ten: {} = {}";
|
||||||
|
|
||||||
|
if( auto player = const_cast< Entity::Chara& >( chara ).getAsPlayer() )
|
||||||
|
{
|
||||||
|
player->sendDebug( format, pot, wd, ap, det, ten, factor );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger::debug( format, pot, wd, ap, det, ten, factor );
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: the rest
|
||||||
|
|
||||||
|
return factor;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t CalcStats::primaryStatValue( const Sapphire::Entity::Chara& chara )
|
uint32_t CalcStats::primaryStatValue( const Sapphire::Entity::Chara& chara )
|
||||||
{
|
{
|
||||||
return chara.getStatValue( chara.getPrimaryStat() );
|
return chara.getStatValue( chara.getPrimaryStat() );
|
||||||
|
|
|
@ -128,7 +128,9 @@ namespace Sapphire::Math
|
||||||
|
|
||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
|
|
||||||
static float calculateAutoAttackDamage( const Sapphire::Entity::Chara& chara );
|
static float calcAutoAttackDamage( const Sapphire::Entity::Chara& chara );
|
||||||
|
|
||||||
|
static float calcActionDamage( const Sapphire::Entity::Chara& chara, uint32_t ptc, float wepDmg );
|
||||||
|
|
||||||
static uint32_t primaryStatValue( const Sapphire::Entity::Chara& chara );
|
static uint32_t primaryStatValue( const Sapphire::Entity::Chara& chara );
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Add table
Reference in a new issue