1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-29 07:37:45 +00:00

crit & dh

This commit is contained in:
collett 2020-01-07 19:08:13 +09:00
parent ca06cd4e35
commit ff2ffa379b
8 changed files with 120 additions and 41 deletions

View file

@ -639,9 +639,9 @@ namespace Sapphire::Common
enum class ActionHitSeverityType : uint8_t
{
NormalDamage = 0,
CritHeal = 0,
NormalHeal = 0,
CritDamage = 1,
NormalHeal = 1,
CritHeal = 1,
DirectHitDamage = 2,
CritDirectHitDamage = 3
};
@ -669,7 +669,7 @@ namespace Sapphire::Common
{
Common::ActionEffectType effectType;
Common::ActionHitSeverityType hitSeverity;
uint8_t unk;
Common::ActionHitSeverityType healSeverity;
/*!
* @brief Shows an additional percentage in the battle log
*

View file

@ -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()
@ -486,7 +507,8 @@ void Action::Action::buildEffects()
{
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 )
@ -503,8 +525,8 @@ void Action::Action::buildEffects()
}
else if( m_lutEntry.curePotency > 0 )
{
// todo: calcHealing()
m_effectBuilder->heal( actor, actor, m_lutEntry.curePotency );
auto heal = calcHealing( m_lutEntry.curePotency );
m_effectBuilder->heal( actor, actor, heal.first, heal.second );
if( m_lutEntry.restoreMPPercentage > 0 && shouldRestoreMP )
{

View file

@ -12,7 +12,8 @@ EffectResult::EffectResult( Entity::CharaPtr target, uint64_t runAfter ) :
m_target( std::move( target ) ),
m_delayMs( runAfter ),
m_value( 0 ),
m_severity( Common::ActionHitSeverityType::NormalDamage ),
m_hitSeverity( Common::ActionHitSeverityType::NormalDamage ),
m_healSeverity( Common::ActionHitSeverityType::NormalHeal ),
m_type( Common::ActionEffectType::Nothing ),
m_param( 0 ),
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 )
{
m_severity = severity;
m_hitSeverity = severity;
m_value = amount;
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 )
{
m_severity = severity;
m_healSeverity = severity;
m_value = amount;
m_flag = flag;
@ -89,7 +90,8 @@ Common::EffectEntry EffectResult::buildEffectEntry() const
// todo: that retarded shit so > u16 max numbers work
entry.value = getValue();
entry.hitSeverity = m_severity;
entry.hitSeverity = m_hitSeverity;
entry.healSeverity = m_healSeverity;
entry.effectType = m_type;
entry.param = m_param;
entry.flags = static_cast< uint8_t >( m_flag );

View file

@ -37,7 +37,8 @@ namespace Sapphire::World::Action
Entity::CharaPtr m_target;
Common::ActionHitSeverityType m_severity;
Common::ActionHitSeverityType m_hitSeverity;
Common::ActionHitSeverityType m_healSeverity;
Common::ActionEffectType m_type;
uint32_t m_value;

View file

@ -697,15 +697,15 @@ void Sapphire::Entity::BNpc::autoAttack( CharaPtr pTarget )
auto effectPacket = std::make_shared< Server::EffectPacket >( getId(), pTarget->getId(), 7 );
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
Common::EffectEntry effectEntry{};
effectEntry.value = static_cast< int16_t >( damage );
effectEntry.value = static_cast< int16_t >( damage.first );
effectEntry.effectType = ActionEffectType::Damage;
effectEntry.hitSeverity = ActionHitSeverityType::NormalDamage;
effectEntry.hitSeverity = damage.second;
effectEntry.param = 0x71;
effectPacket->addEffect( effectEntry );
sendToInRangeSet( effectPacket );
pTarget->takeDamage( static_cast< uint16_t >( damage ) );
pTarget->takeDamage( static_cast< uint16_t >( damage.first ) );
}
}

View file

@ -1585,9 +1585,9 @@ void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget )
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
Common::EffectEntry entry{};
entry.value = damage;
entry.value = damage.first;
entry.effectType = Common::ActionEffectType::Damage;
entry.hitSeverity = Common::ActionHitSeverityType::NormalDamage;
entry.hitSeverity = damage.second;
entry.param = 0x72;
effectPacket->addEffect( entry );
@ -1600,9 +1600,9 @@ void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget )
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
Common::EffectEntry entry{};
entry.value = damage;
entry.value = damage.first;
entry.effectType = Common::ActionEffectType::Damage;
entry.hitSeverity = Common::ActionHitSeverityType::NormalDamage;
entry.hitSeverity = damage.second;
entry.param = 0x73;
effectPacket->addEffect( entry );
@ -1611,7 +1611,7 @@ void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget )
}
pTarget->takeDamage( damage );
pTarget->takeDamage( damage.first );
}

View file

@ -104,6 +104,10 @@ const int levelTable[81][6] =
{ 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.
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;
}
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) ⌋ ×
// 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
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: {} = {}";
@ -466,22 +493,10 @@ float CalcStats::calcAutoAttackDamage( const Sapphire::Entity::Chara& chara )
Logger::debug( format, pot, aa, ap, det, ten, factor );
}
// todo: traits
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;
return std::pair( factor, hitType );
}
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 ⌋
// × 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 );
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: {} = {}";
@ -508,9 +542,24 @@ float CalcStats::calcActionDamage( const Sapphire::Entity::Chara& chara, uint32_
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 )

View file

@ -1,6 +1,7 @@
#ifndef _CALCSTATS_H
#define _CALCSTATS_H
#include <random>
#include <Common.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 );
private:
@ -142,7 +145,9 @@ namespace Sapphire::Math
*/
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;
};
}