mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-27 22:57: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_modelChara = bNpcBaseData->data().Model;
|
||||||
m_enemyType = bNpcBaseData->data().Battalion;
|
m_enemyType = bNpcBaseData->data().Battalion;
|
||||||
|
|
||||||
m_class = ClassJob::Adventurer;
|
m_class = ClassJob::Gladiator;
|
||||||
|
|
||||||
m_pCurrentTerritory = std::move( pZone );
|
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_hp = m_maxHp;
|
||||||
m_mp = 200;
|
m_mp = 200;
|
||||||
|
|
||||||
|
if( m_level <= BnpcBaseHp.size() )
|
||||||
|
m_maxHp = BnpcBaseHp[ m_level - 1 ];
|
||||||
|
|
||||||
m_state = BNpcState::Idle;
|
m_state = BNpcState::Idle;
|
||||||
m_status = ActorStatus::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;
|
m_naviTargetReachedDistance = 4.f;
|
||||||
|
|
||||||
calculateStats();
|
calculateStats();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Sapphire::Entity::BNpc::BNpc( uint32_t id, std::shared_ptr< Common::BNPCInstanceObject > pInfo, TerritoryPtr pZone, uint32_t hp, Common::BNpcType type ) :
|
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_modelChara = bNpcBaseData->data().Model;
|
||||||
m_enemyType = bNpcBaseData->data().Battalion;
|
m_enemyType = bNpcBaseData->data().Battalion;
|
||||||
|
|
||||||
m_class = ClassJob::Adventurer;
|
m_class = ClassJob::Gladiator;
|
||||||
|
|
||||||
m_pCurrentTerritory = std::move( pZone );
|
m_pCurrentTerritory = std::move( pZone );
|
||||||
|
|
||||||
|
@ -962,3 +967,10 @@ uint32_t Sapphire::Entity::BNpc::getLayoutId() const
|
||||||
{
|
{
|
||||||
return m_layoutId;
|
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,
|
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
|
\class BNpc
|
||||||
\brief Base class for all BNpcs
|
\brief Base class for all BNpcs
|
||||||
|
@ -55,6 +68,8 @@ namespace Sapphire::Entity
|
||||||
|
|
||||||
virtual ~BNpc() override;
|
virtual ~BNpc() override;
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
void spawn( PlayerPtr pTarget ) override;
|
void spawn( PlayerPtr pTarget ) override;
|
||||||
void despawn( PlayerPtr pTarget ) override;
|
void despawn( PlayerPtr pTarget ) override;
|
||||||
|
|
||||||
|
|
|
@ -151,6 +151,36 @@ uint32_t CalcStats::calculateMaxHp( Player& player )
|
||||||
return result;
|
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 )
|
uint32_t CalcStats::calculateMaxMp( Player& player )
|
||||||
{
|
{
|
||||||
auto& exdData = Common::Service< Data::ExdData >::ref();
|
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
|
// 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 )
|
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 level = chara.getLevel();
|
||||||
auto mainVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::MAIN ] );
|
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 ) );
|
return std::floor( innerCalc * ( autoAttackDelay / 3.f ) );
|
||||||
}
|
}
|
||||||
|
@ -518,12 +549,9 @@ std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcAutoA
|
||||||
auto ap = getPrimaryAttackPower( chara );
|
auto ap = getPrimaryAttackPower( chara );
|
||||||
auto det = determination( chara );
|
auto det = determination( chara );
|
||||||
|
|
||||||
auto ten = 1.f;
|
|
||||||
if( chara.getRole() == Common::Role::Tank )
|
|
||||||
ten = tenacity( 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 );
|
||||||
Sapphire::Common::ActionHitSeverityType hitType = Sapphire::Common::ActionHitSeverityType::NormalDamage;
|
Sapphire::Common::ActionHitSeverityType hitType = Sapphire::Common::ActionHitSeverityType::NormalDamage;
|
||||||
|
|
||||||
// todo: traits
|
// todo: traits
|
||||||
|
@ -552,14 +580,14 @@ std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcAutoA
|
||||||
|
|
||||||
if( auto player = const_cast< Entity::Chara& >( chara ).getAsPlayer() )
|
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
|
else
|
||||||
{
|
{
|
||||||
// Logger::debug( format, pot, aa, ap, det, ten, factor );
|
// 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 )
|
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 float calculateBaseStat( const Entity::Chara& chara );
|
||||||
|
|
||||||
static uint32_t calculateMaxHp( Sapphire::Entity::Player& player );
|
static uint32_t calculateMaxHp( Sapphire::Entity::Player& player );
|
||||||
|
static uint32_t calculateMaxHp( Sapphire::Entity::Chara& chara );
|
||||||
|
|
||||||
static uint32_t calculateMaxMp( Sapphire::Entity::Player& player );
|
static uint32_t calculateMaxMp( Sapphire::Entity::Player& player );
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
|
|
||||||
#include "Manager/RNGMgr.h"
|
#include "Manager/RNGMgr.h"
|
||||||
#include "Manager/NaviMgr.h"
|
#include "Manager/NaviMgr.h"
|
||||||
|
#include "Math/CalcStats.h"
|
||||||
|
|
||||||
using namespace Sapphire::Common;
|
using namespace Sapphire::Common;
|
||||||
using namespace Sapphire::Network::Packets;
|
using namespace Sapphire::Network::Packets;
|
||||||
|
@ -833,6 +834,7 @@ void Sapphire::Territory::updateSpawnPoints()
|
||||||
{
|
{
|
||||||
auto& server = Common::Service< World::WorldServer >::ref();
|
auto& server = Common::Service< World::WorldServer >::ref();
|
||||||
auto pBNpc = std::make_shared< Entity::BNpc >( getNextActorId(), spawn.infoPtr, shared_from_this() );
|
auto pBNpc = std::make_shared< Entity::BNpc >( getNextActorId(), spawn.infoPtr, shared_from_this() );
|
||||||
|
pBNpc->init();
|
||||||
spawn.bnpcPtr = pBNpc;
|
spawn.bnpcPtr = pBNpc;
|
||||||
|
|
||||||
pushActor( pBNpc );
|
pushActor( pBNpc );
|
||||||
|
|
Loading…
Add table
Reference in a new issue