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

Spawn overworld mobs with accurate MaxHp

This commit is contained in:
Mordred 2021-12-30 13:57:08 +01:00
parent b7aaeb38b1
commit d244ad437b
5 changed files with 68 additions and 10 deletions

View file

@ -95,7 +95,7 @@ Sapphire::Entity::BNpc::BNpc( uint32_t id, std::shared_ptr< Common::BNPCInstance
m_modelChara = bNpcBaseData->data().Model;
m_enemyType = bNpcBaseData->data().Battalion;
m_class = ClassJob::Adventurer;
m_class = ClassJob::Gladiator;
m_pCurrentTerritory = std::move( pZone );
@ -109,6 +109,9 @@ Sapphire::Entity::BNpc::BNpc( uint32_t id, std::shared_ptr< Common::BNPCInstance
m_hp = m_maxHp;
m_mp = 200;
if( m_level <= BnpcBaseHp.size() )
m_maxHp = BnpcBaseHp[ m_level - 1 ];
m_state = BNpcState::Idle;
m_status = ActorStatus::Idle;
@ -153,6 +156,8 @@ Sapphire::Entity::BNpc::BNpc( uint32_t id, std::shared_ptr< Common::BNPCInstance
m_naviTargetReachedDistance = 4.f;
calculateStats();
}
Sapphire::Entity::BNpc::BNpc( uint32_t id, std::shared_ptr< Common::BNPCInstanceObject > pInfo, TerritoryPtr pZone, uint32_t hp, Common::BNpcType type ) :
@ -198,7 +203,7 @@ Sapphire::Entity::BNpc::BNpc( uint32_t id, std::shared_ptr< Common::BNPCInstance
m_modelChara = bNpcBaseData->data().Model;
m_enemyType = bNpcBaseData->data().Battalion;
m_class = ClassJob::Adventurer;
m_class = ClassJob::Gladiator;
m_pCurrentTerritory = std::move( pZone );
@ -962,3 +967,10 @@ uint32_t Sapphire::Entity::BNpc::getLayoutId() const
{
return m_layoutId;
}
void Sapphire::Entity::BNpc::init()
{
m_maxHp = Sapphire::Math::CalcStats::calculateMaxHp( *getAsChara() );
m_hp = m_maxHp;
max_hp = m_maxHp;
}

View file

@ -39,6 +39,19 @@ namespace Sapphire::Entity
Untargetable = 32,
};
const std::array< uint32_t, 50 > BnpcBaseHp =
{ 44,51, 59, 68, 91,
108, 126, 143, 160, 192,
217, 243, 268, 293, 319,
344, 369, 394, 420, 413,
458, 493, 532, 568, 594,
641, 677,714, 750, 780,
887, 965, 1055, 1142, 1220,
1306, 1409, 1515, 1587, 1601,
1703, 1789, 1872, 2008, 2112,
2180, 2314, 2383, 2501, 2589
};
/*!
\class BNpc
\brief Base class for all BNpcs
@ -55,6 +68,8 @@ namespace Sapphire::Entity
virtual ~BNpc() override;
void init();
void spawn( PlayerPtr pTarget ) override;
void despawn( PlayerPtr pTarget ) override;

View file

@ -151,6 +151,36 @@ uint32_t CalcStats::calculateMaxHp( Player& player )
return result;
}
uint32_t CalcStats::calculateMaxHp( Chara& chara )
{
auto& exdData = Common::Service< Data::ExdData >::ref();
// TODO: Replace ApproxBaseHP with something that can get us an accurate BaseHP.
// Is there any way to pull reliable BaseHP without having to manually use a pet for every level, and using the values from a table?
// More info here: https://docs.google.com/spreadsheets/d/1de06KGT0cNRUvyiXNmjNgcNvzBCCQku7jte5QxEQRbs/edit?usp=sharing
auto classInfo = exdData.getRow< Component::Excel::ClassJob >( static_cast< uint8_t >( chara.getClass() ) );
auto paramGrowthInfo = exdData.getRow< Component::Excel::ParamGrow >( chara.getLevel() );
if( !classInfo || !paramGrowthInfo )
return 0;
uint8_t level = chara.getLevel();
auto vitMod = chara.getBonusStat( Common::BaseParam::Vitality );
float baseStat = calculateBaseStat( chara );
uint16_t vitStat = static_cast< uint16_t >( chara.getStatValue( Common::BaseParam::Vitality ) ) + static_cast< uint16_t >( vitMod );
uint16_t hpMod = paramGrowthInfo->data().ParamBase;
uint16_t jobModHp = classInfo->data().Hp;
float approxBaseHp = 0.0f; // Read above
approxBaseHp = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::HP ] );
uint16_t result = static_cast< uint16_t >( floor( jobModHp * ( approxBaseHp / 100.0f ) ) +
floor( hpMod / 100.0f * ( vitStat - baseStat ) ) );
return result;
}
uint32_t CalcStats::calculateMaxMp( Player& player )
{
auto& exdData = Common::Service< Data::ExdData >::ref();
@ -311,7 +341,8 @@ float CalcStats::autoAttackPotency( const Sapphire::Entity::Chara& chara )
}
// factors in f(PTC) in order to not lose precision
return std::floor( aaPotency / 3.f * autoAttackDelay ) / 100.f;
//return std::floor( aaPotency / 3.f * autoAttackDelay ) / 100.f;
return std::floor( aaPotency / 100.f );
}
float CalcStats::weaponDamage( const Sapphire::Entity::Chara& chara, float weaponDamage )
@ -498,7 +529,7 @@ float CalcStats::autoAttack( const Sapphire::Entity::Chara& chara )
auto level = chara.getLevel();
auto mainVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::MAIN ] );
auto innerCalc = std::floor( ( mainVal * primaryStatValue( chara ) / 1000.f ) + weaponDamage );
auto innerCalc = std::floor( ( mainVal * static_cast< float >( primaryStatValue( chara ) ) / 1000.f ) + weaponDamage );
return std::floor( innerCalc * ( autoAttackDelay / 3.f ) );
}
@ -518,12 +549,9 @@ std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcAutoA
auto ap = getPrimaryAttackPower( chara );
auto det = determination( chara );
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 );
Sapphire::Common::ActionHitSeverityType hitType = Sapphire::Common::ActionHitSeverityType::NormalDamage;
// todo: traits
@ -552,14 +580,14 @@ std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcAutoA
if( auto player = const_cast< Entity::Chara& >( chara ).getAsPlayer() )
{
PlayerMgr::sendDebug( *player, format, pot, aa, ap, det, ten, factor );
PlayerMgr::sendDebug( *player, format, pot, aa, ap, det, 1, factor );
}
else
{
// Logger::debug( format, pot, aa, ap, det, ten, factor );
}
return std::pair( factor, hitType );
return std::pair( factor * 3, hitType );
}
std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActionDamage( const Sapphire::Entity::Chara& chara, uint32_t ptc, float wepDmg )

View file

@ -16,6 +16,7 @@ namespace Sapphire::Math
static float calculateBaseStat( const Entity::Chara& chara );
static uint32_t calculateMaxHp( Sapphire::Entity::Player& player );
static uint32_t calculateMaxHp( Sapphire::Entity::Chara& chara );
static uint32_t calculateMaxMp( Sapphire::Entity::Player& player );

View file

@ -41,6 +41,7 @@
#include "Manager/RNGMgr.h"
#include "Manager/NaviMgr.h"
#include "Math/CalcStats.h"
using namespace Sapphire::Common;
using namespace Sapphire::Network::Packets;
@ -833,6 +834,7 @@ void Sapphire::Territory::updateSpawnPoints()
{
auto& server = Common::Service< World::WorldServer >::ref();
auto pBNpc = std::make_shared< Entity::BNpc >( getNextActorId(), spawn.infoPtr, shared_from_this() );
pBNpc->init();
spawn.bnpcPtr = pBNpc;
pushActor( pBNpc );