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:
parent
b7aaeb38b1
commit
d244ad437b
5 changed files with 68 additions and 10 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Add table
Reference in a new issue