1
Fork 0
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:
NotAdam 2019-07-27 00:37:40 +10:00
parent 7684687664
commit f3ba1ce6c0
11 changed files with 178 additions and 17 deletions

View file

@ -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 >;
} }

View file

@ -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();

View file

@ -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();

View file

@ -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;
} }

View file

@ -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;
}; };
} }

View file

@ -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() ) );

View file

@ -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 )
{ {

View file

@ -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;

View file

@ -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 )
{ {

View file

@ -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: aaPotency = RANGED_AUTO_ATTACK_POTENCY;
case Common::ClassJob::Bard:
case Common::ClassJob::Archer:
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() );

View file

@ -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: