mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-29 07:37:45 +00:00
crit & dh
This commit is contained in:
parent
ca06cd4e35
commit
ff2ffa379b
8 changed files with 120 additions and 41 deletions
|
@ -639,9 +639,9 @@ namespace Sapphire::Common
|
||||||
enum class ActionHitSeverityType : uint8_t
|
enum class ActionHitSeverityType : uint8_t
|
||||||
{
|
{
|
||||||
NormalDamage = 0,
|
NormalDamage = 0,
|
||||||
CritHeal = 0,
|
NormalHeal = 0,
|
||||||
CritDamage = 1,
|
CritDamage = 1,
|
||||||
NormalHeal = 1,
|
CritHeal = 1,
|
||||||
DirectHitDamage = 2,
|
DirectHitDamage = 2,
|
||||||
CritDirectHitDamage = 3
|
CritDirectHitDamage = 3
|
||||||
};
|
};
|
||||||
|
@ -669,7 +669,7 @@ namespace Sapphire::Common
|
||||||
{
|
{
|
||||||
Common::ActionEffectType effectType;
|
Common::ActionEffectType effectType;
|
||||||
Common::ActionHitSeverityType hitSeverity;
|
Common::ActionHitSeverityType hitSeverity;
|
||||||
uint8_t unk;
|
Common::ActionHitSeverityType healSeverity;
|
||||||
/*!
|
/*!
|
||||||
* @brief Shows an additional percentage in the battle log
|
* @brief Shows an additional percentage in the battle log
|
||||||
*
|
*
|
||||||
|
|
|
@ -425,9 +425,30 @@ std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcDamage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto dmg = Math::CalcStats::calcActionDamage( *m_pSource, potency, wepDmg );
|
return Math::CalcStats::calcActionDamage( *m_pSource, potency, wepDmg );
|
||||||
|
}
|
||||||
|
|
||||||
return std::make_pair( dmg, Common::ActionHitSeverityType::NormalDamage );
|
std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcHealing( uint32_t potency )
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math::CalcStats::calcActionHealing( *m_pSource, potency, wepDmg );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Action::Action::buildEffects()
|
void Action::Action::buildEffects()
|
||||||
|
@ -486,7 +507,8 @@ void Action::Action::buildEffects()
|
||||||
{
|
{
|
||||||
if( m_lutEntry.curePotency > 0 ) // actions with self heal
|
if( m_lutEntry.curePotency > 0 ) // actions with self heal
|
||||||
{
|
{
|
||||||
m_effectBuilder->heal( actor, m_pSource, m_lutEntry.curePotency, Common::ActionHitSeverityType::NormalHeal, Common::ActionEffectResultFlag::EffectOnSource );
|
auto heal = calcHealing( m_lutEntry.curePotency );
|
||||||
|
m_effectBuilder->heal( actor, m_pSource, heal.first, heal.second, Common::ActionEffectResultFlag::EffectOnSource );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_lutEntry.restoreMPPercentage > 0 && shouldRestoreMP )
|
if( m_lutEntry.restoreMPPercentage > 0 && shouldRestoreMP )
|
||||||
|
@ -503,8 +525,8 @@ void Action::Action::buildEffects()
|
||||||
}
|
}
|
||||||
else if( m_lutEntry.curePotency > 0 )
|
else if( m_lutEntry.curePotency > 0 )
|
||||||
{
|
{
|
||||||
// todo: calcHealing()
|
auto heal = calcHealing( m_lutEntry.curePotency );
|
||||||
m_effectBuilder->heal( actor, actor, m_lutEntry.curePotency );
|
m_effectBuilder->heal( actor, actor, heal.first, heal.second );
|
||||||
|
|
||||||
if( m_lutEntry.restoreMPPercentage > 0 && shouldRestoreMP )
|
if( m_lutEntry.restoreMPPercentage > 0 && shouldRestoreMP )
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,7 +12,8 @@ EffectResult::EffectResult( Entity::CharaPtr target, uint64_t runAfter ) :
|
||||||
m_target( std::move( target ) ),
|
m_target( std::move( target ) ),
|
||||||
m_delayMs( runAfter ),
|
m_delayMs( runAfter ),
|
||||||
m_value( 0 ),
|
m_value( 0 ),
|
||||||
m_severity( Common::ActionHitSeverityType::NormalDamage ),
|
m_hitSeverity( Common::ActionHitSeverityType::NormalDamage ),
|
||||||
|
m_healSeverity( Common::ActionHitSeverityType::NormalHeal ),
|
||||||
m_type( Common::ActionEffectType::Nothing ),
|
m_type( Common::ActionEffectType::Nothing ),
|
||||||
m_param( 0 ),
|
m_param( 0 ),
|
||||||
m_flag( Common::ActionEffectResultFlag::None )
|
m_flag( Common::ActionEffectResultFlag::None )
|
||||||
|
@ -37,7 +38,7 @@ uint64_t EffectResult::getDelay()
|
||||||
|
|
||||||
void EffectResult::damage( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag )
|
void EffectResult::damage( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag )
|
||||||
{
|
{
|
||||||
m_severity = severity;
|
m_hitSeverity = severity;
|
||||||
m_value = amount;
|
m_value = amount;
|
||||||
m_flag = flag;
|
m_flag = flag;
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ void EffectResult::damage( uint32_t amount, Common::ActionHitSeverityType severi
|
||||||
|
|
||||||
void EffectResult::heal( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag )
|
void EffectResult::heal( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag )
|
||||||
{
|
{
|
||||||
m_severity = severity;
|
m_healSeverity = severity;
|
||||||
m_value = amount;
|
m_value = amount;
|
||||||
m_flag = flag;
|
m_flag = flag;
|
||||||
|
|
||||||
|
@ -89,7 +90,8 @@ Common::EffectEntry EffectResult::buildEffectEntry() const
|
||||||
|
|
||||||
// todo: that retarded shit so > u16 max numbers work
|
// todo: that retarded shit so > u16 max numbers work
|
||||||
entry.value = getValue();
|
entry.value = getValue();
|
||||||
entry.hitSeverity = m_severity;
|
entry.hitSeverity = m_hitSeverity;
|
||||||
|
entry.healSeverity = m_healSeverity;
|
||||||
entry.effectType = m_type;
|
entry.effectType = m_type;
|
||||||
entry.param = m_param;
|
entry.param = m_param;
|
||||||
entry.flags = static_cast< uint8_t >( m_flag );
|
entry.flags = static_cast< uint8_t >( m_flag );
|
||||||
|
|
|
@ -37,7 +37,8 @@ namespace Sapphire::World::Action
|
||||||
|
|
||||||
Entity::CharaPtr m_target;
|
Entity::CharaPtr m_target;
|
||||||
|
|
||||||
Common::ActionHitSeverityType m_severity;
|
Common::ActionHitSeverityType m_hitSeverity;
|
||||||
|
Common::ActionHitSeverityType m_healSeverity;
|
||||||
Common::ActionEffectType m_type;
|
Common::ActionEffectType m_type;
|
||||||
|
|
||||||
uint32_t m_value;
|
uint32_t m_value;
|
||||||
|
|
|
@ -697,15 +697,15 @@ void Sapphire::Entity::BNpc::autoAttack( CharaPtr pTarget )
|
||||||
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() ) );
|
||||||
Common::EffectEntry effectEntry{};
|
Common::EffectEntry effectEntry{};
|
||||||
effectEntry.value = static_cast< int16_t >( damage );
|
effectEntry.value = static_cast< int16_t >( damage.first );
|
||||||
effectEntry.effectType = ActionEffectType::Damage;
|
effectEntry.effectType = ActionEffectType::Damage;
|
||||||
effectEntry.hitSeverity = ActionHitSeverityType::NormalDamage;
|
effectEntry.hitSeverity = damage.second;
|
||||||
effectEntry.param = 0x71;
|
effectEntry.param = 0x71;
|
||||||
effectPacket->addEffect( effectEntry );
|
effectPacket->addEffect( effectEntry );
|
||||||
|
|
||||||
sendToInRangeSet( effectPacket );
|
sendToInRangeSet( effectPacket );
|
||||||
|
|
||||||
pTarget->takeDamage( static_cast< uint16_t >( damage ) );
|
pTarget->takeDamage( static_cast< uint16_t >( damage.first ) );
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1585,9 +1585,9 @@ void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget )
|
||||||
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
|
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
|
||||||
|
|
||||||
Common::EffectEntry entry{};
|
Common::EffectEntry entry{};
|
||||||
entry.value = damage;
|
entry.value = damage.first;
|
||||||
entry.effectType = Common::ActionEffectType::Damage;
|
entry.effectType = Common::ActionEffectType::Damage;
|
||||||
entry.hitSeverity = Common::ActionHitSeverityType::NormalDamage;
|
entry.hitSeverity = damage.second;
|
||||||
entry.param = 0x72;
|
entry.param = 0x72;
|
||||||
|
|
||||||
effectPacket->addEffect( entry );
|
effectPacket->addEffect( entry );
|
||||||
|
@ -1600,9 +1600,9 @@ void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget )
|
||||||
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
|
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
|
||||||
|
|
||||||
Common::EffectEntry entry{};
|
Common::EffectEntry entry{};
|
||||||
entry.value = damage;
|
entry.value = damage.first;
|
||||||
entry.effectType = Common::ActionEffectType::Damage;
|
entry.effectType = Common::ActionEffectType::Damage;
|
||||||
entry.hitSeverity = Common::ActionHitSeverityType::NormalDamage;
|
entry.hitSeverity = damage.second;
|
||||||
entry.param = 0x73;
|
entry.param = 0x73;
|
||||||
|
|
||||||
effectPacket->addEffect( entry );
|
effectPacket->addEffect( entry );
|
||||||
|
@ -1611,7 +1611,7 @@ void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pTarget->takeDamage( damage );
|
pTarget->takeDamage( damage.first );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,10 @@ const int levelTable[81][6] =
|
||||||
{ 340, 380, 3300, 3600, 569, 569 },
|
{ 340, 380, 3300, 3600, 569, 569 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::random_device CalcStats::dev;
|
||||||
|
std::mt19937 CalcStats::rng( dev() );
|
||||||
|
std::uniform_int_distribution< std::mt19937::result_type > CalcStats::range100( 0, 99 );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Class used for battle-related formulas and calculations.
|
Class used for battle-related formulas and calculations.
|
||||||
Big thanks to the Theoryjerks group!
|
Big thanks to the Theoryjerks group!
|
||||||
|
@ -438,7 +442,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::calcAutoAttackDamage( const Sapphire::Entity::Chara& chara )
|
std::pair< float, Sapphire::Common::ActionHitSeverityType > 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... ⌋
|
||||||
|
@ -454,6 +458,29 @@ float CalcStats::calcAutoAttackDamage( const Sapphire::Entity::Chara& chara )
|
||||||
|
|
||||||
// todo: everything after tenacity
|
// todo: everything after tenacity
|
||||||
auto factor = std::floor( pot * aa * ap * det * ten );
|
auto factor = std::floor( pot * aa * ap * det * ten );
|
||||||
|
Sapphire::Common::ActionHitSeverityType hitType = Sapphire::Common::ActionHitSeverityType::NormalDamage;
|
||||||
|
|
||||||
|
// todo: traits
|
||||||
|
|
||||||
|
factor = std::floor( factor * speed( chara ) );
|
||||||
|
|
||||||
|
if( criticalHitProbability( chara ) > range100( rng ) )
|
||||||
|
{
|
||||||
|
factor *= criticalHitBonus( chara );
|
||||||
|
hitType = Sapphire::Common::ActionHitSeverityType::CritDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( directHitProbability( chara ) > range100( rng ) )
|
||||||
|
{
|
||||||
|
factor *= 1.25f;
|
||||||
|
hitType = hitType == Sapphire::Common::ActionHitSeverityType::CritDamage ?
|
||||||
|
Sapphire::Common::ActionHitSeverityType::CritDirectHitDamage :
|
||||||
|
Sapphire::Common::ActionHitSeverityType::DirectHitDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
factor *= 1.0f + ( ( range100( rng ) - 50.0f ) / 1000.0f );
|
||||||
|
|
||||||
|
// todo: buffs
|
||||||
|
|
||||||
constexpr auto format = "auto attack: pot: {} aa: {} ap: {} det: {} ten: {} = {}";
|
constexpr auto format = "auto attack: pot: {} aa: {} ap: {} det: {} ten: {} = {}";
|
||||||
|
|
||||||
|
@ -466,22 +493,10 @@ float CalcStats::calcAutoAttackDamage( const Sapphire::Entity::Chara& chara )
|
||||||
Logger::debug( format, pot, aa, ap, det, ten, factor );
|
Logger::debug( format, pot, aa, ap, det, ten, factor );
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: traits
|
return std::pair( factor, hitType );
|
||||||
|
|
||||||
factor = std::floor( factor * speed( chara ) );
|
|
||||||
|
|
||||||
// todo: surely this aint right?
|
|
||||||
//factor = std::floor( factor * criticalHitProbability( chara ) );
|
|
||||||
//factor = std::floor( factor * directHitProbability( chara ) );
|
|
||||||
|
|
||||||
// todo: random 0.95 - 1.05 factor
|
|
||||||
|
|
||||||
// todo: buffs
|
|
||||||
|
|
||||||
return factor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float CalcStats::calcActionDamage( const Sapphire::Entity::Chara& chara, uint32_t ptc, float wepDmg )
|
std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActionDamage( const Sapphire::Entity::Chara& chara, uint32_t ptc, float wepDmg )
|
||||||
{
|
{
|
||||||
// D = ⌊ f(pot) × f(wd) × f(ap) × f(det) × f(tnc) × traits ⌋
|
// 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... ⌋
|
// × f(chr) ⌋ × f(dhr) ⌋ × rand[ 0.95, 1.05 ] ⌋ buff_1 ⌋ × buff_1 ⌋ × buff... ⌋
|
||||||
|
@ -496,6 +511,25 @@ float CalcStats::calcActionDamage( const Sapphire::Entity::Chara& chara, uint32_
|
||||||
ten = tenacity( chara );
|
ten = tenacity( chara );
|
||||||
|
|
||||||
auto factor = std::floor( pot * wd * ap * det * ten );
|
auto factor = std::floor( pot * wd * ap * det * ten );
|
||||||
|
Sapphire::Common::ActionHitSeverityType hitType = Sapphire::Common::ActionHitSeverityType::NormalDamage;
|
||||||
|
|
||||||
|
if( criticalHitProbability( chara ) > range100( rng ) )
|
||||||
|
{
|
||||||
|
factor *= criticalHitBonus( chara );
|
||||||
|
hitType = Sapphire::Common::ActionHitSeverityType::CritDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( directHitProbability( chara ) > range100( rng ) )
|
||||||
|
{
|
||||||
|
factor *= 1.25f;
|
||||||
|
hitType = hitType == Sapphire::Common::ActionHitSeverityType::CritDamage ?
|
||||||
|
Sapphire::Common::ActionHitSeverityType::CritDirectHitDamage :
|
||||||
|
Sapphire::Common::ActionHitSeverityType::DirectHitDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
factor *= 1.0f + ( ( range100( rng ) - 50.0f ) / 1000.0f );
|
||||||
|
|
||||||
|
// todo: buffs
|
||||||
|
|
||||||
constexpr auto format = "dmg: pot: {} ({}) wd: {} ({}) ap: {} det: {} ten: {} = {}";
|
constexpr auto format = "dmg: pot: {} ({}) wd: {} ({}) ap: {} det: {} ten: {} = {}";
|
||||||
|
|
||||||
|
@ -508,9 +542,24 @@ float CalcStats::calcActionDamage( const Sapphire::Entity::Chara& chara, uint32_
|
||||||
Logger::debug( format, pot, ptc, wd, wepDmg, ap, det, ten, factor );
|
Logger::debug( format, pot, ptc, wd, wepDmg, ap, det, ten, factor );
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: the rest
|
return std::pair( factor, hitType );
|
||||||
|
}
|
||||||
|
|
||||||
return factor;
|
std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActionHealing( const Sapphire::Entity::Chara& chara, uint32_t ptc, float wepDmg )
|
||||||
|
{
|
||||||
|
// lol just for testing
|
||||||
|
auto factor = std::floor( ptc * chara.getLevel() / 4.0f );
|
||||||
|
Sapphire::Common::ActionHitSeverityType hitType = Sapphire::Common::ActionHitSeverityType::NormalHeal;
|
||||||
|
|
||||||
|
if( criticalHitProbability( chara ) > range100( rng ) )
|
||||||
|
{
|
||||||
|
factor *= criticalHitBonus( chara );
|
||||||
|
hitType = Sapphire::Common::ActionHitSeverityType::CritHeal;
|
||||||
|
}
|
||||||
|
|
||||||
|
factor *= 1.0f + ( ( range100( rng ) - 50.0f ) / 1000.0f );
|
||||||
|
|
||||||
|
return std::pair( factor, hitType );
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t CalcStats::primaryStatValue( const Sapphire::Entity::Chara& chara )
|
uint32_t CalcStats::primaryStatValue( const Sapphire::Entity::Chara& chara )
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef _CALCSTATS_H
|
#ifndef _CALCSTATS_H
|
||||||
#define _CALCSTATS_H
|
#define _CALCSTATS_H
|
||||||
|
|
||||||
|
#include <random>
|
||||||
#include <Common.h>
|
#include <Common.h>
|
||||||
#include "Forwards.h"
|
#include "Forwards.h"
|
||||||
|
|
||||||
|
@ -128,9 +129,11 @@ namespace Sapphire::Math
|
||||||
|
|
||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
|
|
||||||
static float calcAutoAttackDamage( const Sapphire::Entity::Chara& chara );
|
static std::pair< float, Common::ActionHitSeverityType > calcAutoAttackDamage( const Sapphire::Entity::Chara& chara );
|
||||||
|
|
||||||
static float calcActionDamage( const Sapphire::Entity::Chara& chara, uint32_t ptc, float wepDmg );
|
static std::pair< float, Common::ActionHitSeverityType > calcActionDamage( const Sapphire::Entity::Chara& chara, uint32_t ptc, float wepDmg );
|
||||||
|
|
||||||
|
static std::pair< float, Common::ActionHitSeverityType > calcActionHealing( 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:
|
||||||
|
@ -142,7 +145,9 @@ namespace Sapphire::Math
|
||||||
*/
|
*/
|
||||||
static float calcAttackPower( const Sapphire::Entity::Chara& chara, uint32_t attackPower );
|
static float calcAttackPower( const Sapphire::Entity::Chara& chara, uint32_t attackPower );
|
||||||
|
|
||||||
|
static std::random_device dev;
|
||||||
|
static std::mt19937 rng;
|
||||||
|
static std::uniform_int_distribution< std::mt19937::result_type > range100;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue