mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-25 02:57:45 +00:00
Merge branch 'master' of https://github.com/SapphireMordred/Sapphire into party_crap
This commit is contained in:
commit
899f0fa272
22 changed files with 424 additions and 395 deletions
|
@ -22,7 +22,7 @@ When making a PR, please make sure that it follows our style guidelines and good
|
||||||
|
|
||||||
### Coding style
|
### Coding style
|
||||||
|
|
||||||
Indentations are Allman-style based, 4-space, no tabs.
|
Indentations are Allman-style based, 3-space, no tabs.
|
||||||
Space between arguments in function calls, as well as for types.
|
Space between arguments in function calls, as well as for types.
|
||||||
|
|
||||||
Example (shortened from ActionHandler.cpp):
|
Example (shortened from ActionHandler.cpp):
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<ListenIp>127.0.0.1</ListenIp>
|
<ListenIp>127.0.0.1</ListenIp>
|
||||||
<!-- Path of FFXIV dat files -->
|
<!-- Path of FFXIV dat files -->
|
||||||
<DataPath>C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack\\ffxiv</DataPath>
|
<DataPath>C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack\\ffxiv</DataPath>
|
||||||
|
<!-- <DataPath>/opt/sapphire_3_15_0/bin/sqpack</DataPath> -->
|
||||||
<!-- IP of the lobby server -->
|
<!-- IP of the lobby server -->
|
||||||
<LobbyHost>127.0.0.1</LobbyHost>
|
<LobbyHost>127.0.0.1</LobbyHost>
|
||||||
<!-- IP of the frontier server -->
|
<!-- IP of the frontier server -->
|
||||||
|
|
|
@ -855,7 +855,7 @@ struct FFXIVIpcPlayerStats : FFXIVIpcBasePacket<PlayerStats>
|
||||||
uint32_t unknown;
|
uint32_t unknown;
|
||||||
uint32_t unknown_1;
|
uint32_t unknown_1;
|
||||||
uint32_t unknown_2;
|
uint32_t unknown_2;
|
||||||
uint32_t parry;
|
uint32_t tenacity;
|
||||||
uint32_t attack;
|
uint32_t attack;
|
||||||
uint32_t defense;
|
uint32_t defense;
|
||||||
uint32_t accuracy;
|
uint32_t accuracy;
|
||||||
|
@ -877,7 +877,11 @@ struct FFXIVIpcPlayerStats : FFXIVIpcBasePacket<PlayerStats>
|
||||||
uint32_t skillSpeed;
|
uint32_t skillSpeed;
|
||||||
uint32_t spellSpeed1;
|
uint32_t spellSpeed1;
|
||||||
uint32_t spellSpeedMod;
|
uint32_t spellSpeedMod;
|
||||||
uint32_t unknown_6[5];
|
uint32_t unknown_6;
|
||||||
|
uint32_t craftsmanship;
|
||||||
|
uint32_t control;
|
||||||
|
uint32_t gathering;
|
||||||
|
uint32_t perception;
|
||||||
uint32_t resistanceSlow;
|
uint32_t resistanceSlow;
|
||||||
uint32_t resistanceSilence;
|
uint32_t resistanceSilence;
|
||||||
uint32_t resistanceBlind;
|
uint32_t resistanceBlind;
|
||||||
|
@ -886,7 +890,7 @@ struct FFXIVIpcPlayerStats : FFXIVIpcBasePacket<PlayerStats>
|
||||||
uint32_t resistanceSleep;
|
uint32_t resistanceSleep;
|
||||||
uint32_t resistanceBind;
|
uint32_t resistanceBind;
|
||||||
uint32_t resistanceHeavy;
|
uint32_t resistanceHeavy;
|
||||||
uint32_t unknown_7[9];
|
uint32_t unknown_7[9]; // possibly level sync stats.
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -921,10 +925,11 @@ struct FFXIVIpcPlayerStateFlags : FFXIVIpcBasePacket<PlayerStateFlags>
|
||||||
struct FFXIVIpcPlayerClassInfo : FFXIVIpcBasePacket<PlayerClassInfo>
|
struct FFXIVIpcPlayerClassInfo : FFXIVIpcBasePacket<PlayerClassInfo>
|
||||||
{
|
{
|
||||||
uint16_t classId;
|
uint16_t classId;
|
||||||
uint16_t unknown;
|
uint8_t unknown;
|
||||||
uint16_t level;
|
uint8_t isSpecialist;
|
||||||
uint16_t level1;
|
uint16_t level; // Locks actions, equipment, prob more
|
||||||
uint8_t unknownFields[48];
|
uint16_t level1; // Locks roles, prob more
|
||||||
|
uint32_t roleActions[10];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -200,7 +200,7 @@ void Core::Network::SapphireAPI::deleteCharacter( std::string name, uint32_t acc
|
||||||
g_charaDb.execute( "DELETE FROM charaitemcrystal WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
|
g_charaDb.execute( "DELETE FROM charaitemcrystal WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
|
||||||
g_charaDb.execute( "DELETE FROM charaiteminventory WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
|
g_charaDb.execute( "DELETE FROM charaiteminventory WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
|
||||||
g_charaDb.execute( "DELETE FROM charaitemgearset WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
|
g_charaDb.execute( "DELETE FROM charaitemgearset WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
|
||||||
g_charaDb.execute( "DELETE FROM charaquest WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
|
g_charaDb.execute( "DELETE FROM charaquestnew WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector< Core::PlayerMinimal > Core::Network::SapphireAPI::getCharList( uint32_t accountId )
|
std::vector< Core::PlayerMinimal > Core::Network::SapphireAPI::getCharList( uint32_t accountId )
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket144.h"
|
#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket144.h"
|
||||||
#include "src/servers/Server_Zone/Network/PacketWrappers/UpdateHpMpTpPacket.h"
|
#include "src/servers/Server_Zone/Network/PacketWrappers/UpdateHpMpTpPacket.h"
|
||||||
|
|
||||||
#include "src/servers/Server_Zone/StatusEffect/StatusEffectContainer.h"
|
|
||||||
#include "src/servers/Server_Zone/StatusEffect/StatusEffect.h"
|
#include "src/servers/Server_Zone/StatusEffect/StatusEffect.h"
|
||||||
#include "src/servers/Server_Zone/Action/ActionCollision.h"
|
#include "src/servers/Server_Zone/Action/ActionCollision.h"
|
||||||
#include "src/servers/Server_Zone/ServerZone.h"
|
#include "src/servers/Server_Zone/ServerZone.h"
|
||||||
|
@ -33,6 +32,11 @@ using namespace Core::Network::Packets::Server;
|
||||||
|
|
||||||
Core::Entity::Actor::Actor()
|
Core::Entity::Actor::Actor()
|
||||||
{
|
{
|
||||||
|
// initialize the free slot queue
|
||||||
|
for( uint8_t i = 0; i < MAX_STATUS_EFFECTS; i++ )
|
||||||
|
{
|
||||||
|
m_statusEffectFreeSlotQueue.push( i );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::Entity::Actor::~Actor()
|
Core::Entity::Actor::~Actor()
|
||||||
|
@ -794,7 +798,30 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint16_t actionId, u
|
||||||
/*! \param StatusEffectPtr to be applied to the actor */
|
/*! \param StatusEffectPtr to be applied to the actor */
|
||||||
void Core::Entity::Actor::addStatusEffect( StatusEffect::StatusEffectPtr pEffect )
|
void Core::Entity::Actor::addStatusEffect( StatusEffect::StatusEffectPtr pEffect )
|
||||||
{
|
{
|
||||||
m_pStatusEffectContainer->addStatusEffect( pEffect );
|
int8_t nextSlot = getStatusEffectFreeSlot();
|
||||||
|
// if there is no slot left, do not add the effect
|
||||||
|
if( nextSlot == -1 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
pEffect->applyStatus();
|
||||||
|
m_statusEffectMap[nextSlot] = pEffect;
|
||||||
|
|
||||||
|
ZoneChannelPacket< Server::FFXIVIpcAddStatusEffect > statusEffectAdd( getId() );
|
||||||
|
statusEffectAdd.data().actor_id = pEffect->getTargetActorId();
|
||||||
|
statusEffectAdd.data().actor_id1 = pEffect->getSrcActorId();
|
||||||
|
statusEffectAdd.data().current_hp = getHp();
|
||||||
|
statusEffectAdd.data().current_mp = getMp();
|
||||||
|
statusEffectAdd.data().current_tp = getTp();
|
||||||
|
statusEffectAdd.data().duration = static_cast< float >( pEffect->getDuration() ) / 1000;
|
||||||
|
statusEffectAdd.data().effect_id = pEffect->getId();
|
||||||
|
statusEffectAdd.data().effect_index = nextSlot;
|
||||||
|
statusEffectAdd.data().max_hp = getMaxHp();
|
||||||
|
statusEffectAdd.data().max_mp = getMaxMp();
|
||||||
|
statusEffectAdd.data().max_something = 1;
|
||||||
|
//statusEffectAdd.data().unknown2 = 28;
|
||||||
|
statusEffectAdd.data().param = pEffect->getParam();
|
||||||
|
|
||||||
|
sendToInRangeSet( statusEffectAdd, isPlayer() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \param StatusEffectPtr to be applied to the actor */
|
/*! \param StatusEffectPtr to be applied to the actor */
|
||||||
|
@ -809,7 +836,7 @@ void Core::Entity::Actor::addStatusEffectById( uint32_t id, int32_t duration, En
|
||||||
/*! \param StatusEffectPtr to be applied to the actor */
|
/*! \param StatusEffectPtr to be applied to the actor */
|
||||||
void Core::Entity::Actor::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Actor& pSource, uint16_t param )
|
void Core::Entity::Actor::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Actor& pSource, uint16_t param )
|
||||||
{
|
{
|
||||||
if( !m_pStatusEffectContainer->hasStatusEffect( id ) )
|
if( !hasStatusEffect( id ) )
|
||||||
{
|
{
|
||||||
StatusEffect::StatusEffectPtr effect( new StatusEffect::StatusEffect( id, pSource.shared_from_this(),
|
StatusEffect::StatusEffectPtr effect( new StatusEffect::StatusEffect( id, pSource.shared_from_this(),
|
||||||
shared_from_this(), duration, 3000 ) );
|
shared_from_this(), duration, 3000 ) );
|
||||||
|
@ -818,17 +845,6 @@ void Core::Entity::Actor::addStatusEffectByIdIfNotExist( uint32_t id, int32_t du
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \param Status that should be removed, based on its ID. */
|
|
||||||
void Core::Entity::Actor::removeSingleStatusEffectFromId( uint32_t id )
|
|
||||||
{
|
|
||||||
m_pStatusEffectContainer->removeSingleStatusEffectFromId( id );
|
|
||||||
}
|
|
||||||
|
|
||||||
Core::StatusEffect::StatusEffectContainerPtr Core::Entity::Actor::getStatusEffectContainer() const
|
|
||||||
{
|
|
||||||
return m_pStatusEffectContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Core::Entity::Actor::getRotation() const
|
float Core::Entity::Actor::getRotation() const
|
||||||
{
|
{
|
||||||
return m_rot;
|
return m_rot;
|
||||||
|
@ -838,3 +854,154 @@ void Core::Entity::Actor::setRotation( float rot )
|
||||||
{
|
{
|
||||||
m_rot = rot;
|
m_rot = rot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8_t Core::Entity::Actor::getStatusEffectFreeSlot()
|
||||||
|
{
|
||||||
|
int8_t freeEffectSlot = -1;
|
||||||
|
|
||||||
|
if( m_statusEffectFreeSlotQueue.empty() )
|
||||||
|
return freeEffectSlot;
|
||||||
|
|
||||||
|
freeEffectSlot = m_statusEffectFreeSlotQueue.front();
|
||||||
|
m_statusEffectFreeSlotQueue.pop();
|
||||||
|
|
||||||
|
return freeEffectSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::Entity::Actor::statusEffectFreeSlot( uint8_t slotId )
|
||||||
|
{
|
||||||
|
m_statusEffectFreeSlotQueue.push( slotId );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::Entity::Actor::removeSingleStatusEffectById( uint32_t id )
|
||||||
|
{
|
||||||
|
for( auto effectIt : m_statusEffectMap )
|
||||||
|
{
|
||||||
|
if( effectIt.second->getId() == id )
|
||||||
|
{
|
||||||
|
removeStatusEffect( effectIt.first );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::Entity::Actor::removeStatusEffect( uint8_t effectSlotId )
|
||||||
|
{
|
||||||
|
auto pEffectIt = m_statusEffectMap.find( effectSlotId );
|
||||||
|
if( pEffectIt == m_statusEffectMap.end() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
statusEffectFreeSlot( effectSlotId );
|
||||||
|
|
||||||
|
auto pEffect = pEffectIt->second;
|
||||||
|
pEffect->removeStatus();
|
||||||
|
|
||||||
|
sendToInRangeSet( ActorControlPacket142( getId(), StatusEffectLose, pEffect->getId() ), isPlayer() );
|
||||||
|
|
||||||
|
m_statusEffectMap.erase( effectSlotId );
|
||||||
|
|
||||||
|
sendStatusEffectUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map< uint8_t, Core::StatusEffect::StatusEffectPtr > Core::Entity::Actor::getStatusEffectMap() const
|
||||||
|
{
|
||||||
|
return m_statusEffectMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::Entity::Actor::sendStatusEffectUpdate()
|
||||||
|
{
|
||||||
|
uint64_t currentTimeMs = Util::getTimeMs();
|
||||||
|
|
||||||
|
ZoneChannelPacket< Server::FFXIVIpcStatusEffectList > statusEffectList( getId() );
|
||||||
|
|
||||||
|
statusEffectList.data().current_hp = getHp();
|
||||||
|
statusEffectList.data().current_mp = getMp();
|
||||||
|
statusEffectList.data().currentTp = getTp();
|
||||||
|
statusEffectList.data().max_hp = getMaxHp();
|
||||||
|
statusEffectList.data().max_mp = getMaxMp();
|
||||||
|
uint8_t slot = 0;
|
||||||
|
for( auto effectIt : m_statusEffectMap )
|
||||||
|
{
|
||||||
|
float timeLeft = static_cast< float >( effectIt.second->getDuration() -
|
||||||
|
( currentTimeMs - effectIt.second->getStartTimeMs() ) ) / 1000;
|
||||||
|
statusEffectList.data().effect[slot].duration = timeLeft;
|
||||||
|
statusEffectList.data().effect[slot].effect_id = effectIt.second->getId();
|
||||||
|
statusEffectList.data().effect[slot].sourceActorId = effectIt.second->getSrcActorId();
|
||||||
|
slot++;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendToInRangeSet( statusEffectList, isPlayer() );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::Entity::Actor::updateStatusEffects()
|
||||||
|
{
|
||||||
|
uint64_t currentTimeMs = Util::getTimeMs();
|
||||||
|
|
||||||
|
uint32_t thisTickDmg = 0;
|
||||||
|
uint32_t thisTickHeal = 0;
|
||||||
|
|
||||||
|
for( auto effectIt : m_statusEffectMap )
|
||||||
|
{
|
||||||
|
uint8_t effectIndex = effectIt.first;
|
||||||
|
auto effect = effectIt.second;
|
||||||
|
|
||||||
|
uint64_t lastTick = effect->getLastTickMs();
|
||||||
|
uint64_t startTime = effect->getStartTimeMs();
|
||||||
|
uint32_t duration = effect->getDuration();
|
||||||
|
uint32_t tickRate = effect->getTickRate();
|
||||||
|
|
||||||
|
if( ( currentTimeMs - startTime ) > duration )
|
||||||
|
{
|
||||||
|
// remove status effect
|
||||||
|
removeStatusEffect( effectIndex );
|
||||||
|
// break because removing invalidates iterators
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( currentTimeMs - lastTick ) > tickRate )
|
||||||
|
{
|
||||||
|
effect->setLastTick( currentTimeMs );
|
||||||
|
effect->onTick();
|
||||||
|
|
||||||
|
auto thisEffect = effect->getTickEffect();
|
||||||
|
|
||||||
|
switch( thisEffect.first )
|
||||||
|
{
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
thisTickDmg += thisEffect.second;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
thisTickHeal += thisEffect.second;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if( thisTickDmg != 0 )
|
||||||
|
{
|
||||||
|
takeDamage( thisTickDmg );
|
||||||
|
sendToInRangeSet( ActorControlPacket142( getId(), HPFloatingText, 0, static_cast< uint8_t >( ActionEffectType::Damage ), thisTickDmg ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( thisTickHeal != 0 )
|
||||||
|
{
|
||||||
|
heal( thisTickDmg );
|
||||||
|
sendToInRangeSet( ActorControlPacket142( getId(), HPFloatingText, 0, static_cast< uint8_t >( ActionEffectType::Heal ), thisTickHeal ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Core::Entity::Actor::hasStatusEffect( uint32_t id )
|
||||||
|
{
|
||||||
|
if( m_statusEffectMap.find( id ) != m_statusEffectMap.end() )
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "src/servers/Server_Zone/Forwards.h"
|
#include "src/servers/Server_Zone/Forwards.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
namespace Entity {
|
namespace Entity {
|
||||||
|
@ -79,7 +80,7 @@ public:
|
||||||
uint32_t mnd = 0;
|
uint32_t mnd = 0;
|
||||||
uint32_t pie = 0;
|
uint32_t pie = 0;
|
||||||
|
|
||||||
uint32_t parry = 0;
|
uint32_t tenacity = 0;
|
||||||
uint32_t attack = 0;
|
uint32_t attack = 0;
|
||||||
uint32_t defense = 0;
|
uint32_t defense = 0;
|
||||||
uint32_t accuracy = 0;
|
uint32_t accuracy = 0;
|
||||||
|
@ -160,11 +161,15 @@ protected:
|
||||||
uint64_t m_targetId;
|
uint64_t m_targetId;
|
||||||
/*! Ptr to a queued action */
|
/*! Ptr to a queued action */
|
||||||
Action::ActionPtr m_pCurrentAction;
|
Action::ActionPtr m_pCurrentAction;
|
||||||
/*! Container for status effects */
|
|
||||||
StatusEffect::StatusEffectContainerPtr m_pStatusEffectContainer;
|
|
||||||
/*! Invincibility type */
|
/*! Invincibility type */
|
||||||
Common::InvincibilityType m_invincibilityType;
|
Common::InvincibilityType m_invincibilityType;
|
||||||
|
|
||||||
|
/*! Status effects */
|
||||||
|
const uint8_t MAX_STATUS_EFFECTS = 30;
|
||||||
|
std::queue< uint8_t > m_statusEffectFreeSlotQueue;
|
||||||
|
std::vector< std::pair< uint8_t, uint32_t> > m_statusEffectList;
|
||||||
|
std::map< uint8_t, StatusEffect::StatusEffectPtr > m_statusEffectMap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Actor();
|
Actor();
|
||||||
|
|
||||||
|
@ -174,6 +179,30 @@ public:
|
||||||
|
|
||||||
uint32_t getId() const;
|
uint32_t getId() const;
|
||||||
|
|
||||||
|
/// Status effect functions
|
||||||
|
void addStatusEffect( StatusEffect::StatusEffectPtr pEffect );
|
||||||
|
void removeStatusEffect( uint8_t effectSlotId );
|
||||||
|
void removeSingleStatusEffectById( uint32_t id );
|
||||||
|
void updateStatusEffects();
|
||||||
|
|
||||||
|
bool hasStatusEffect( uint32_t id );
|
||||||
|
|
||||||
|
int8_t getStatusEffectFreeSlot();
|
||||||
|
void statusEffectFreeSlot( uint8_t slotId );
|
||||||
|
|
||||||
|
std::map< uint8_t, Core::StatusEffect::StatusEffectPtr > getStatusEffectMap() const;
|
||||||
|
|
||||||
|
void sendStatusEffectUpdate();
|
||||||
|
// add a status effect by id
|
||||||
|
void addStatusEffectById( uint32_t id, int32_t duration, Entity::Actor& pSource, uint16_t param = 0 );
|
||||||
|
|
||||||
|
// add a status effect by id if it doesn't exist
|
||||||
|
void addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Actor& pSource, uint16_t param = 0 );
|
||||||
|
|
||||||
|
// remove a status effect by id
|
||||||
|
void removeSingleStatusEffectFromId( uint32_t id );
|
||||||
|
/// End Status Effect Functions
|
||||||
|
|
||||||
void setPosition( const Common::FFXIVARR_POSITION3& pos );
|
void setPosition( const Common::FFXIVARR_POSITION3& pos );
|
||||||
void setPosition( float x, float y, float z );
|
void setPosition( float x, float y, float z );
|
||||||
|
|
||||||
|
@ -303,20 +332,6 @@ public:
|
||||||
// set the current cell
|
// set the current cell
|
||||||
void setCell( Cell* pCell );
|
void setCell( Cell* pCell );
|
||||||
|
|
||||||
// add a status effect
|
|
||||||
void addStatusEffect( StatusEffect::StatusEffectPtr pEffect );
|
|
||||||
|
|
||||||
// add a status effect by id
|
|
||||||
void addStatusEffectById( uint32_t id, int32_t duration, Entity::Actor& pSource, uint16_t param = 0 );
|
|
||||||
|
|
||||||
// add a status effect by id if it doesn't exist
|
|
||||||
void addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Actor& pSource, uint16_t param = 0 );
|
|
||||||
|
|
||||||
// remove a status effect by id
|
|
||||||
void removeSingleStatusEffectFromId( uint32_t id );
|
|
||||||
|
|
||||||
//get the status effect container
|
|
||||||
StatusEffect::StatusEffectContainerPtr getStatusEffectContainer() const;
|
|
||||||
|
|
||||||
// TODO: Why did i even declare them publicly here?!
|
// TODO: Why did i even declare them publicly here?!
|
||||||
std::set< ActorPtr > m_inRangeActors;
|
std::set< ActorPtr > m_inRangeActors;
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include "src/servers/Server_Zone/Network/PacketWrappers/MoveActorPacket.h"
|
#include "src/servers/Server_Zone/Network/PacketWrappers/MoveActorPacket.h"
|
||||||
#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket142.h"
|
#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket142.h"
|
||||||
#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket143.h"
|
#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket143.h"
|
||||||
#include "src/servers/Server_Zone/StatusEffect/StatusEffectContainer.h"
|
|
||||||
|
|
||||||
using namespace Core::Common;
|
using namespace Core::Common;
|
||||||
using namespace Core::Network::Packets;
|
using namespace Core::Network::Packets;
|
||||||
|
@ -40,7 +39,7 @@ Core::Entity::BattleNpc::~BattleNpc()
|
||||||
|
|
||||||
Core::Entity::BattleNpc::BattleNpc( uint16_t modelId, uint16_t nameid, const Common::FFXIVARR_POSITION3& spawnPos,
|
Core::Entity::BattleNpc::BattleNpc( uint16_t modelId, uint16_t nameid, const Common::FFXIVARR_POSITION3& spawnPos,
|
||||||
uint16_t bnpcBaseId, uint32_t type, uint8_t level, uint8_t behaviour,
|
uint16_t bnpcBaseId, uint32_t type, uint8_t level, uint8_t behaviour,
|
||||||
uint32_t mobType )
|
uint32_t mobType ) : Actor()
|
||||||
{
|
{
|
||||||
BattleNpc::m_nextID++;
|
BattleNpc::m_nextID++;
|
||||||
m_id = BattleNpc::m_nextID;
|
m_id = BattleNpc::m_nextID;
|
||||||
|
@ -87,11 +86,6 @@ Core::Entity::BattleNpc::BattleNpc( uint16_t modelId, uint16_t nameid, const Com
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::Entity::BattleNpc::initStatusEffectContainer()
|
|
||||||
{
|
|
||||||
m_pStatusEffectContainer = StatusEffect::StatusEffectContainerPtr( new StatusEffect::StatusEffectContainer( shared_from_this() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// spawn this player for pTarget
|
// spawn this player for pTarget
|
||||||
void Core::Entity::BattleNpc::spawn( Core::Entity::PlayerPtr pTarget )
|
void Core::Entity::BattleNpc::spawn( Core::Entity::PlayerPtr pTarget )
|
||||||
{
|
{
|
||||||
|
@ -487,9 +481,7 @@ void Core::Entity::BattleNpc::update( int64_t currTime )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !m_pStatusEffectContainer )
|
updateStatusEffects();
|
||||||
initStatusEffectContainer();
|
|
||||||
m_pStatusEffectContainer->update();
|
|
||||||
float distance = Math::Util::distance( m_pos.x, m_pos.y, m_pos.z,
|
float distance = Math::Util::distance( m_pos.x, m_pos.y, m_pos.z,
|
||||||
m_posOrigin.x, m_posOrigin.y, m_posOrigin.z );
|
m_posOrigin.x, m_posOrigin.y, m_posOrigin.z );
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,6 @@
|
||||||
|
|
||||||
#include "src/servers/Server_Zone/Script/ScriptManager.h"
|
#include "src/servers/Server_Zone/Script/ScriptManager.h"
|
||||||
|
|
||||||
#include "src/servers/Server_Zone/StatusEffect/StatusEffectContainer.h"
|
|
||||||
|
|
||||||
#include "src/servers/Server_Zone/Inventory/Item.h"
|
#include "src/servers/Server_Zone/Inventory/Item.h"
|
||||||
|
|
||||||
#include "src/servers/Server_Zone/Inventory/Inventory.h"
|
#include "src/servers/Server_Zone/Inventory/Inventory.h"
|
||||||
|
@ -57,6 +55,7 @@ using namespace Core::Network::Packets::Server;
|
||||||
|
|
||||||
// player constructor
|
// player constructor
|
||||||
Core::Entity::Player::Player() :
|
Core::Entity::Player::Player() :
|
||||||
|
Actor(),
|
||||||
m_lastWrite( 0 ),
|
m_lastWrite( 0 ),
|
||||||
m_lastPing( 0 ),
|
m_lastPing( 0 ),
|
||||||
m_bIsLogin( false ),
|
m_bIsLogin( false ),
|
||||||
|
@ -243,6 +242,7 @@ void Core::Entity::Player::calculateStats()
|
||||||
m_baseStats.critHitRate = paramGrowthInfo.base_secondary;
|
m_baseStats.critHitRate = paramGrowthInfo.base_secondary;
|
||||||
m_baseStats.attackPotMagic = paramGrowthInfo.base_secondary;
|
m_baseStats.attackPotMagic = paramGrowthInfo.base_secondary;
|
||||||
m_baseStats.healingPotMagic = paramGrowthInfo.base_secondary;
|
m_baseStats.healingPotMagic = paramGrowthInfo.base_secondary;
|
||||||
|
m_baseStats.tenacity = paramGrowthInfo.base_secondary;
|
||||||
|
|
||||||
m_baseStats.max_mp = Math::CalcStats::calculateMaxMp( getAsPlayer() );
|
m_baseStats.max_mp = Math::CalcStats::calculateMaxMp( getAsPlayer() );
|
||||||
|
|
||||||
|
@ -440,6 +440,9 @@ void Core::Entity::Player::setZone( uint32_t zoneId )
|
||||||
gcAffPacket.data().gcRank[1] = m_gcRank[1];
|
gcAffPacket.data().gcRank[1] = m_gcRank[1];
|
||||||
gcAffPacket.data().gcRank[2] = m_gcRank[2];
|
gcAffPacket.data().gcRank[2] = m_gcRank[2];
|
||||||
queuePacket( gcAffPacket );
|
queuePacket( gcAffPacket );
|
||||||
|
|
||||||
|
m_itemLevel = getInventory()->calculateEquippedGearItemLevel();
|
||||||
|
sendItemLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
ZoneChannelPacket< FFXIVIpcInitZone > initZonePacket( getId() );
|
ZoneChannelPacket< FFXIVIpcInitZone > initZonePacket( getId() );
|
||||||
|
@ -1050,7 +1053,7 @@ void Core::Entity::Player::update( int64_t currTime )
|
||||||
if( !isAlive() )
|
if( !isAlive() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_pStatusEffectContainer->update();
|
updateStatusEffects();
|
||||||
|
|
||||||
m_lastUpdate = currTime;
|
m_lastUpdate = currTime;
|
||||||
|
|
||||||
|
@ -1583,6 +1586,11 @@ void Core::Entity::Player::setOpeningSequence( uint8_t seq )
|
||||||
m_openingSequence = seq;
|
m_openingSequence = seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t Core::Entity::Player::getItemLevel() const
|
||||||
|
{
|
||||||
|
return m_itemLevel;
|
||||||
|
}
|
||||||
|
|
||||||
/// Tells client to offset their eorzean time by given timestamp.
|
/// Tells client to offset their eorzean time by given timestamp.
|
||||||
void Core::Entity::Player::setEorzeaTimeOffset( uint64_t timestamp )
|
void Core::Entity::Player::setEorzeaTimeOffset( uint64_t timestamp )
|
||||||
{
|
{
|
||||||
|
|
|
@ -208,6 +208,10 @@ public:
|
||||||
void unequipItem( Inventory::EquipSlot equipSlotId, ItemPtr pItem );
|
void unequipItem( Inventory::EquipSlot equipSlotId, ItemPtr pItem );
|
||||||
/*! equip a weapon, possibly forcing a job change */
|
/*! equip a weapon, possibly forcing a job change */
|
||||||
void equipWeapon( ItemPtr pItem );
|
void equipWeapon( ItemPtr pItem );
|
||||||
|
/*! get player ilvl */
|
||||||
|
uint16_t getItemLevel() const;
|
||||||
|
/*! send player ilvl */
|
||||||
|
void sendItemLevel();
|
||||||
/*! get a const pointer to the inventory object */
|
/*! get a const pointer to the inventory object */
|
||||||
InventoryPtr getInventory() const;
|
InventoryPtr getInventory() const;
|
||||||
/*! get the current main hand model */
|
/*! get the current main hand model */
|
||||||
|
@ -599,16 +603,20 @@ private:
|
||||||
|
|
||||||
uint8_t m_openingSequence;
|
uint8_t m_openingSequence;
|
||||||
|
|
||||||
|
uint16_t m_itemLevel;
|
||||||
InventoryPtr m_pInventory;
|
InventoryPtr m_pInventory;
|
||||||
|
|
||||||
std::map< uint32_t, Event::EventPtr > m_eventMap;
|
std::map< uint32_t, Event::EventPtr > m_eventMap;
|
||||||
std::map< uint32_t, uint8_t > m_playerIdToSpawnIdMap; // maps player to spawn id
|
std::map< uint32_t, uint8_t > m_playerIdToSpawnIdMap; // maps player to spawn id
|
||||||
std::queue< uint8_t > m_freeSpawnIdQueue; // queue with spawn ids free to be assigned
|
std::queue< uint8_t > m_freeSpawnIdQueue; // queue with spawn ids free to be assigned
|
||||||
std::queue< uint8_t > m_freeHateSlotQueue; // queue with "hate slots" free to be assigned
|
std::queue< uint8_t > m_freeHateSlotQueue; // queue with "hate slots" free to be assigned
|
||||||
std::map< uint32_t, uint8_t > m_actorIdTohateSlotMap;
|
std::map< uint32_t, uint8_t > m_actorIdTohateSlotMap;
|
||||||
|
|
||||||
std::map< uint32_t, uint8_t > m_questIdToQuestIdx; // quest mapping, quest id to quest container index
|
std::map< uint32_t, uint8_t > m_questIdToQuestIdx; // quest mapping, quest id to quest container index
|
||||||
std::map< uint8_t, uint32_t > m_questIdxToQuestId; // quest mapping, quest container index to questId
|
std::map< uint8_t, uint32_t > m_questIdxToQuestId; // quest mapping, quest container index to questId
|
||||||
boost::shared_ptr< Common::QuestActive > m_activeQuests[30];
|
boost::shared_ptr< Common::QuestActive > m_activeQuests[30];
|
||||||
int16_t m_questTracking[5];
|
int16_t m_questTracking[5];
|
||||||
|
|
||||||
uint8_t m_stateFlags[7];
|
uint8_t m_stateFlags[7];
|
||||||
uint8_t m_gmRank;
|
uint8_t m_gmRank;
|
||||||
uint16_t zoneId;
|
uint16_t zoneId;
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
#include <src/servers/Server_Common/Common.h>
|
#include <src/servers/Server_Common/Common.h>
|
||||||
|
#include <src/servers/Server_Common/Exd/ExdData.h>
|
||||||
|
#include <src/servers/Server_Common/Network/GamePacket.h>
|
||||||
|
#include <src/servers/Server_Common/Logging/Logger.h>
|
||||||
|
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
|
|
||||||
#include "src/servers/Server_Zone/Zone/ZoneMgr.h"
|
#include "src/servers/Server_Zone/Zone/ZoneMgr.h"
|
||||||
#include "src/servers/Server_Zone/Zone/Zone.h"
|
#include "src/servers/Server_Zone/Zone/Zone.h"
|
||||||
|
|
||||||
#include <src/servers/Server_Common/Network/GamePacket.h>
|
#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket142.h"
|
||||||
|
|
||||||
#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket143.h"
|
#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket143.h"
|
||||||
|
|
||||||
#include "src/servers/Server_Zone/Inventory/Inventory.h"
|
#include "src/servers/Server_Zone/Inventory/Inventory.h"
|
||||||
#include "src/servers/Server_Zone/Inventory/Item.h"
|
#include "src/servers/Server_Zone/Inventory/Item.h"
|
||||||
|
|
||||||
|
extern Core::Logger g_log;
|
||||||
|
|
||||||
using namespace Core::Common;
|
using namespace Core::Common;
|
||||||
using namespace Core::Network::Packets;
|
using namespace Core::Network::Packets;
|
||||||
using namespace Core::Network::Packets::Server;
|
using namespace Core::Network::Packets::Server;
|
||||||
|
@ -21,6 +25,11 @@ Core::InventoryPtr Core::Entity::Player::getInventory() const
|
||||||
return m_pInventory;
|
return m_pInventory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Core::Entity::Player::sendItemLevel()
|
||||||
|
{
|
||||||
|
queuePacket( ActorControlPacket142( getId(), SetItemLevel, getItemLevel(), 0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: This has to be redone and simplified
|
// TODO: This has to be redone and simplified
|
||||||
void Core::Entity::Player::equipWeapon( Core::ItemPtr pItem )
|
void Core::Entity::Player::equipWeapon( Core::ItemPtr pItem )
|
||||||
{
|
{
|
||||||
|
@ -77,10 +86,10 @@ void Core::Entity::Player::equipWeapon( Core::ItemPtr pItem )
|
||||||
}
|
}
|
||||||
|
|
||||||
// equip an item
|
// equip an item
|
||||||
void Core::Entity::Player::equipItem( Inventory::EquipSlot equipSlotId, Core::ItemPtr pItem, bool sendModel )
|
void Core::Entity::Player::equipItem( Inventory::EquipSlot equipSlotId, Core::ItemPtr pItem, bool sendUpdate )
|
||||||
{
|
{
|
||||||
|
|
||||||
// Console->outDebOnly("Equipping into slot %i", equipSlotID);
|
//g_log.debug( "Equipping into slot " + std::to_string( equipSlotId ) );
|
||||||
|
|
||||||
uint64_t model = pItem->getModelId1();
|
uint64_t model = pItem->getModelId1();
|
||||||
uint64_t model2 = pItem->getModelId2();
|
uint64_t model2 = pItem->getModelId2();
|
||||||
|
@ -109,14 +118,21 @@ void Core::Entity::Player::equipItem( Inventory::EquipSlot equipSlotId, Core::It
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( sendModel )
|
if( sendUpdate )
|
||||||
|
{
|
||||||
this->sendModel();
|
this->sendModel();
|
||||||
|
m_itemLevel = getInventory()->calculateEquippedGearItemLevel();
|
||||||
|
sendItemLevel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::Entity::Player::unequipItem( Inventory::EquipSlot equipSlotId, ItemPtr pItem )
|
void Core::Entity::Player::unequipItem( Inventory::EquipSlot equipSlotId, ItemPtr pItem )
|
||||||
{
|
{
|
||||||
m_modelEquip[static_cast< uint8_t >( equipSlotId )] = 0;
|
m_modelEquip[static_cast< uint8_t >( equipSlotId )] = 0;
|
||||||
sendModel();
|
sendModel();
|
||||||
|
|
||||||
|
m_itemLevel = getInventory()->calculateEquippedGearItemLevel();
|
||||||
|
sendItemLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Core::Entity::Player::getCurrency( uint8_t type ) const
|
uint32_t Core::Entity::Player::getCurrency( uint8_t type ) const
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
|
|
||||||
#include "src/servers/Server_Zone/Network/GameConnection.h"
|
#include "src/servers/Server_Zone/Network/GameConnection.h"
|
||||||
#include "src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h"
|
#include "src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h"
|
||||||
#include "src/servers/Server_Zone/StatusEffect/StatusEffectContainer.h"
|
|
||||||
#include "src/servers/Server_Zone/Inventory/Inventory.h"
|
#include "src/servers/Server_Zone/Inventory/Inventory.h"
|
||||||
|
|
||||||
#include <Server_Common/Database/DatabaseDef.h>
|
#include <Server_Common/Database/DatabaseDef.h>
|
||||||
|
@ -178,7 +177,8 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession )
|
||||||
m_lastTickTime = 0;
|
m_lastTickTime = 0;
|
||||||
|
|
||||||
auto pPlayer = getAsPlayer();
|
auto pPlayer = getAsPlayer();
|
||||||
m_pInventory = InventoryPtr( new Inventory( pPlayer ) );
|
// TODO: remove Inventory and actually inline it in Player class
|
||||||
|
m_pInventory = InventoryPtr( new Inventory( pPlayer.get() ) );
|
||||||
|
|
||||||
pPlayer->calculateStats();
|
pPlayer->calculateStats();
|
||||||
|
|
||||||
|
@ -211,8 +211,6 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession )
|
||||||
|
|
||||||
initSpawnIdQueue();
|
initSpawnIdQueue();
|
||||||
|
|
||||||
m_pStatusEffectContainer = StatusEffect::StatusEffectContainerPtr( new StatusEffect::StatusEffectContainer( shared_from_this() ) );
|
|
||||||
|
|
||||||
if( !m_playerIdToSpawnIdMap.empty() )
|
if( !m_playerIdToSpawnIdMap.empty() )
|
||||||
m_playerIdToSpawnIdMap.clear();
|
m_playerIdToSpawnIdMap.clear();
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "src/servers/Server_Zone/Network/PacketWrappers/ServerNoticePacket.h"
|
#include "src/servers/Server_Zone/Network/PacketWrappers/ServerNoticePacket.h"
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#include <boost/algorithm/clamp.hpp>
|
||||||
|
|
||||||
#include "src/servers/Server_Zone/Forwards.h"
|
#include "src/servers/Server_Zone/Forwards.h"
|
||||||
#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket143.h"
|
#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket143.h"
|
||||||
|
@ -27,7 +28,7 @@ using namespace Core::Network;
|
||||||
using namespace Core::Network::Packets;
|
using namespace Core::Network::Packets;
|
||||||
using namespace Core::Network::Packets::Server;
|
using namespace Core::Network::Packets::Server;
|
||||||
|
|
||||||
Core::Inventory::Inventory( Core::Entity::PlayerPtr pOwner )
|
Core::Inventory::Inventory( Core::Entity::Player* pOwner )
|
||||||
{
|
{
|
||||||
|
|
||||||
m_pOwner = pOwner;
|
m_pOwner = pOwner;
|
||||||
|
@ -438,6 +439,30 @@ bool Core::Inventory::removeCrystal( CrystalType type, uint32_t amount )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Core::Inventory::isOneHandedWeapon( ItemUICategory weaponCategory )
|
||||||
|
{
|
||||||
|
switch ( weaponCategory )
|
||||||
|
{
|
||||||
|
case ItemUICategory::AlchemistsPrimaryTool:
|
||||||
|
case ItemUICategory::ArmorersPrimaryTool:
|
||||||
|
case ItemUICategory::BotanistsPrimaryTool:
|
||||||
|
case ItemUICategory::CulinariansPrimaryTool:
|
||||||
|
case ItemUICategory::OnehandedConjurersArm:
|
||||||
|
case ItemUICategory::CarpentersPrimaryTool:
|
||||||
|
case ItemUICategory::FishersPrimaryTool:
|
||||||
|
case ItemUICategory::GladiatorsArm:
|
||||||
|
case ItemUICategory::GoldsmithsPrimaryTool:
|
||||||
|
case ItemUICategory::LeatherworkersPrimaryTool:
|
||||||
|
case ItemUICategory::MinersPrimaryTool:
|
||||||
|
case ItemUICategory::OnehandedThaumaturgesArm:
|
||||||
|
case ItemUICategory::WeaversPrimaryTool:
|
||||||
|
case ItemUICategory::BlacksmithsPrimaryTool:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Core::Inventory::isObtainable( uint32_t catalogId, uint8_t quantity )
|
bool Core::Inventory::isObtainable( uint32_t catalogId, uint8_t quantity )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -450,7 +475,8 @@ int16_t Core::Inventory::addItem( uint16_t inventoryId, int8_t slotId, uint32_t
|
||||||
|
|
||||||
auto itemInfo = g_exdData.getItemInfo( catalogId );
|
auto itemInfo = g_exdData.getItemInfo( catalogId );
|
||||||
|
|
||||||
if( !itemInfo )
|
// if item data doesn't exist or it's a blank field
|
||||||
|
if( !itemInfo || itemInfo->item_level == 0 )
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -828,6 +854,40 @@ void Core::Inventory::send()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t Core::Inventory::calculateEquippedGearItemLevel()
|
||||||
|
{
|
||||||
|
uint32_t iLvlResult = 0;
|
||||||
|
|
||||||
|
auto gearSetMap = m_inventoryMap[GearSet0]->getItemMap();
|
||||||
|
|
||||||
|
auto it = gearSetMap.begin();
|
||||||
|
|
||||||
|
while ( it != gearSetMap.end() )
|
||||||
|
{
|
||||||
|
auto currItem = it->second;
|
||||||
|
|
||||||
|
if ( currItem )
|
||||||
|
{
|
||||||
|
iLvlResult += currItem->getItemLevel();
|
||||||
|
|
||||||
|
// If item is weapon and isn't one-handed
|
||||||
|
if ( currItem->isWeapon() && !isOneHandedWeapon( currItem->getCategory() ) )
|
||||||
|
{
|
||||||
|
iLvlResult += currItem->getItemLevel();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_log.debug( "Is one handed" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return boost::algorithm::clamp( iLvlResult / 12, 0, 9999 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t Core::Inventory::getFreeSlotsInBags()
|
uint8_t Core::Inventory::getFreeSlotsInBags()
|
||||||
{
|
{
|
||||||
uint8_t slots = 0;
|
uint8_t slots = 0;
|
||||||
|
|
|
@ -13,7 +13,7 @@ using InventoryMap = std::map< uint16_t, ItemContainerPtr >;
|
||||||
class Inventory
|
class Inventory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Inventory( Entity::PlayerPtr pOwner );
|
Inventory( Entity::Player* pOwner );
|
||||||
~Inventory();
|
~Inventory();
|
||||||
|
|
||||||
enum ContainerType : uint16_t
|
enum ContainerType : uint16_t
|
||||||
|
@ -153,6 +153,10 @@ public:
|
||||||
|
|
||||||
bool updateContainer( uint16_t containerId, uint8_t slotId, ItemPtr pItem );
|
bool updateContainer( uint16_t containerId, uint8_t slotId, ItemPtr pItem );
|
||||||
|
|
||||||
|
/*! heck if weapon category qualifies the weapon as onehanded */
|
||||||
|
bool isOneHandedWeapon( Common::ItemUICategory weaponCategory );
|
||||||
|
/*! calculate and return player ilvl based off equipped gear */
|
||||||
|
uint16_t calculateEquippedGearItemLevel();
|
||||||
/*! return the current amount of currency of type */
|
/*! return the current amount of currency of type */
|
||||||
uint32_t getCurrency( CurrencyType type );
|
uint32_t getCurrency( CurrencyType type );
|
||||||
/*! add amount to the current of type */
|
/*! add amount to the current of type */
|
||||||
|
@ -191,7 +195,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Entity::PlayerPtr m_pOwner;
|
Entity::Player* m_pOwner;
|
||||||
InventoryMap m_inventoryMap;
|
InventoryMap m_inventoryMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ Core::Item::Item( uint64_t uId, uint32_t catalogId, uint64_t model1, uint64_t mo
|
||||||
m_magicalDmg = itemInfo->magical_damage;
|
m_magicalDmg = itemInfo->magical_damage;
|
||||||
m_weaponDmg = ( m_physicalDmg != 0 ) ? m_physicalDmg : m_magicalDmg;
|
m_weaponDmg = ( m_physicalDmg != 0 ) ? m_physicalDmg : m_magicalDmg;
|
||||||
m_autoAttackDmg = static_cast< float >( m_weaponDmg * m_delayMs ) / 3000;
|
m_autoAttackDmg = static_cast< float >( m_weaponDmg * m_delayMs ) / 3000;
|
||||||
|
m_itemLevel = itemInfo->item_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::Item::~Item()
|
Core::Item::~Item()
|
||||||
|
@ -57,11 +58,21 @@ uint16_t Core::Item::getMagicalDmg() const
|
||||||
return m_magicalDmg;
|
return m_magicalDmg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t Core::Item::getItemLevel() const
|
||||||
|
{
|
||||||
|
return m_itemLevel;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t Core::Item::getWeaponDmg() const
|
uint16_t Core::Item::getWeaponDmg() const
|
||||||
{
|
{
|
||||||
return m_weaponDmg;
|
return m_weaponDmg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Core::Item::isWeapon() const
|
||||||
|
{
|
||||||
|
return (m_weaponDmg != 0);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t Core::Item::getId() const
|
uint32_t Core::Item::getId() const
|
||||||
{
|
{
|
||||||
return m_id;
|
return m_id;
|
||||||
|
|
|
@ -48,8 +48,12 @@ public:
|
||||||
|
|
||||||
uint16_t getWeaponDmg() const;
|
uint16_t getWeaponDmg() const;
|
||||||
|
|
||||||
|
bool isWeapon() const;
|
||||||
|
|
||||||
float getAutoAttackDmg() const;
|
float getAutoAttackDmg() const;
|
||||||
|
|
||||||
|
uint16_t getItemLevel() const;
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint32_t m_id;
|
uint32_t m_id;
|
||||||
|
@ -71,6 +75,7 @@ protected:
|
||||||
uint16_t m_magicalDmg;
|
uint16_t m_magicalDmg;
|
||||||
uint16_t m_weaponDmg;
|
uint16_t m_weaponDmg;
|
||||||
float m_autoAttackDmg;
|
float m_autoAttackDmg;
|
||||||
|
uint16_t m_itemLevel;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,7 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in
|
||||||
case 0x68: // Remove status (clicking it off)
|
case 0x68: // Remove status (clicking it off)
|
||||||
{
|
{
|
||||||
// todo: check if status can be removed by client from exd
|
// todo: check if status can be removed by client from exd
|
||||||
pPlayer->removeSingleStatusEffectFromId( static_cast< uint32_t >( param1 ) );
|
pPlayer->removeSingleStatusEffectById( static_cast< uint32_t >( param1 ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x69: // Cancel cast
|
case 0x69: // Cancel cast
|
||||||
|
@ -228,10 +228,15 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 0x1B5: // Dye item
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
g_log.debug( "[" + std::to_string( m_pSession->getId() ) + "] Unhandled action: " +
|
g_log.debug( "[" + std::to_string( m_pSession->getId() ) + "] Unhandled action: " +
|
||||||
boost::str( boost::format( "%|04X|" ) % (uint32_t) ( commandId & 0xFFFF ) ) );
|
boost::str( boost::format( "%|04X|" ) % (uint32_t) ( commandId & 0xFFFF ) ) );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include "src/servers/Server_Zone/Forwards.h"
|
#include "src/servers/Server_Zone/Forwards.h"
|
||||||
#include "src/servers/Server_Zone/Inventory/Inventory.h"
|
#include "src/servers/Server_Zone/Inventory/Inventory.h"
|
||||||
#include "src/servers/Server_Zone/Inventory/Item.h"
|
#include "src/servers/Server_Zone/Inventory/Item.h"
|
||||||
#include "src/servers/Server_Zone/StatusEffect/StatusEffectContainer.h"
|
|
||||||
#include "src/servers/Server_Zone/StatusEffect/StatusEffect.h"
|
#include "src/servers/Server_Zone/StatusEffect/StatusEffect.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
@ -122,10 +121,11 @@ namespace Server {
|
||||||
|
|
||||||
uint64_t currentTimeMs = Util::getTimeMs();
|
uint64_t currentTimeMs = Util::getTimeMs();
|
||||||
|
|
||||||
for( auto const& effect : pPlayer->getStatusEffectContainer()->getEffectMap() )
|
for( auto const& effect : pPlayer->getStatusEffectMap() )
|
||||||
{
|
{
|
||||||
m_data.effect[effect.first].effect_id = effect.second->getId();
|
m_data.effect[effect.first].effect_id = effect.second->getId();
|
||||||
m_data.effect[effect.first].duration = static_cast< float >( effect.second->getDuration() - ( currentTimeMs - effect.second->getStartTimeMs() ) ) / 1000;
|
m_data.effect[effect.first].duration = static_cast< float >( effect.second->getDuration() -
|
||||||
|
( currentTimeMs - effect.second->getStartTimeMs() ) ) / 1000;
|
||||||
m_data.effect[effect.first].sourceActorId = effect.second->getSrcActorId();
|
m_data.effect[effect.first].sourceActorId = effect.second->getSrcActorId();
|
||||||
m_data.effect[effect.first].unknown1 = effect.second->getParam();
|
m_data.effect[effect.first].unknown1 = effect.second->getParam();
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ Core::XMLConfigPtr Core::ServerZone::getConfig() const
|
||||||
|
|
||||||
size_t Core::ServerZone::getSessionCount() const
|
size_t Core::ServerZone::getSessionCount() const
|
||||||
{
|
{
|
||||||
return m_sessionMap.size();
|
return m_sessionMapById.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Core::ServerZone::registerBnpcTemplate( std::string templateName, uint32_t bnpcBaseId,
|
bool Core::ServerZone::registerBnpcTemplate( std::string templateName, uint32_t bnpcBaseId,
|
||||||
|
@ -263,7 +263,7 @@ void Core::ServerZone::mainLoop()
|
||||||
auto currTime = static_cast< uint32_t >( time( nullptr ) );
|
auto currTime = static_cast< uint32_t >( time( nullptr ) );
|
||||||
|
|
||||||
lock_guard< std::mutex > lock( this->m_sessionMutex );
|
lock_guard< std::mutex > lock( this->m_sessionMutex );
|
||||||
for( auto sessionIt : this->m_sessionMap )
|
for( auto sessionIt : this->m_sessionMapById )
|
||||||
{
|
{
|
||||||
auto session = sessionIt.second;
|
auto session = sessionIt.second;
|
||||||
if( session && session->getPlayer() )
|
if( session && session->getPlayer() )
|
||||||
|
@ -284,8 +284,8 @@ void Core::ServerZone::mainLoop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto it = this->m_sessionMap.begin();
|
auto it = this->m_sessionMapById.begin();
|
||||||
for( ; it != this->m_sessionMap.end(); )
|
for( ; it != this->m_sessionMapById.end(); )
|
||||||
{
|
{
|
||||||
uint32_t diff = currTime - it->second->getLastDataTime();
|
uint32_t diff = currTime - it->second->getLastDataTime();
|
||||||
|
|
||||||
|
@ -298,7 +298,8 @@ void Core::ServerZone::mainLoop()
|
||||||
// if( it->second.unique() )
|
// if( it->second.unique() )
|
||||||
{
|
{
|
||||||
g_log.info("[" + std::to_string(it->second->getId() ) + "] Session removal" );
|
g_log.info("[" + std::to_string(it->second->getId() ) + "] Session removal" );
|
||||||
it = this->m_sessionMap.erase( it );
|
it = this->m_sessionMapById.erase( it );
|
||||||
|
removeSession( pPlayer->getName() );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -310,7 +311,8 @@ void Core::ServerZone::mainLoop()
|
||||||
it->second->close();
|
it->second->close();
|
||||||
// if( it->second.unique() )
|
// if( it->second.unique() )
|
||||||
{
|
{
|
||||||
it = this->m_sessionMap.erase(it );
|
it = this->m_sessionMapById.erase( it );
|
||||||
|
removeSession( pPlayer->getName() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -329,9 +331,9 @@ bool Core::ServerZone::createSession( uint32_t sessionId )
|
||||||
|
|
||||||
const std::string session_id_str = std::to_string( sessionId );
|
const std::string session_id_str = std::to_string( sessionId );
|
||||||
|
|
||||||
auto it = m_sessionMap.find( sessionId );
|
auto it = m_sessionMapById.find( sessionId );
|
||||||
|
|
||||||
if( it != m_sessionMap.end() )
|
if( it != m_sessionMapById.end() )
|
||||||
{
|
{
|
||||||
g_log.error( "[" + session_id_str + "] Error creating session" );
|
g_log.error( "[" + session_id_str + "] Error creating session" );
|
||||||
return false;
|
return false;
|
||||||
|
@ -340,7 +342,7 @@ bool Core::ServerZone::createSession( uint32_t sessionId )
|
||||||
g_log.info( "[" + session_id_str + "] Creating new session" );
|
g_log.info( "[" + session_id_str + "] Creating new session" );
|
||||||
|
|
||||||
boost::shared_ptr<Session> newSession( new Session( sessionId ) );
|
boost::shared_ptr<Session> newSession( new Session( sessionId ) );
|
||||||
m_sessionMap[sessionId] = newSession;
|
m_sessionMapById[sessionId] = newSession;
|
||||||
|
|
||||||
if( !newSession->loadPlayer() )
|
if( !newSession->loadPlayer() )
|
||||||
{
|
{
|
||||||
|
@ -348,7 +350,7 @@ bool Core::ServerZone::createSession( uint32_t sessionId )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_playerSessionMap[newSession->getPlayer()->getName()] = newSession;
|
m_sessionMapByName[newSession->getPlayer()->getName()] = newSession;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -356,15 +358,15 @@ bool Core::ServerZone::createSession( uint32_t sessionId )
|
||||||
|
|
||||||
void Core::ServerZone::removeSession( uint32_t sessionId )
|
void Core::ServerZone::removeSession( uint32_t sessionId )
|
||||||
{
|
{
|
||||||
m_sessionMap.erase( sessionId );
|
m_sessionMapById.erase( sessionId );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::ServerZone::updateSession( uint32_t id )
|
void Core::ServerZone::updateSession( uint32_t id )
|
||||||
{
|
{
|
||||||
std::lock_guard< std::mutex > lock( m_sessionMutex );
|
std::lock_guard< std::mutex > lock( m_sessionMutex );
|
||||||
auto it = m_sessionMap.find( id );
|
auto it = m_sessionMapById.find( id );
|
||||||
|
|
||||||
if( it != m_sessionMap.end() )
|
if( it != m_sessionMapById.end() )
|
||||||
it->second->loadPlayer();
|
it->second->loadPlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,9 +374,9 @@ Core::SessionPtr Core::ServerZone::getSession( uint32_t id )
|
||||||
{
|
{
|
||||||
//std::lock_guard<std::mutex> lock( m_sessionMutex );
|
//std::lock_guard<std::mutex> lock( m_sessionMutex );
|
||||||
|
|
||||||
auto it = m_sessionMap.find( id );
|
auto it = m_sessionMapById.find( id );
|
||||||
|
|
||||||
if( it != m_sessionMap.end() )
|
if( it != m_sessionMapById.end() )
|
||||||
return ( it->second );
|
return ( it->second );
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -384,9 +386,9 @@ Core::SessionPtr Core::ServerZone::getSession( std::string playerName )
|
||||||
{
|
{
|
||||||
//std::lock_guard<std::mutex> lock( m_sessionMutex );
|
//std::lock_guard<std::mutex> lock( m_sessionMutex );
|
||||||
|
|
||||||
auto it = m_playerSessionMap.find( playerName );
|
auto it = m_sessionMapByName.find( playerName );
|
||||||
|
|
||||||
if (it != m_playerSessionMap.end())
|
if (it != m_sessionMapByName.end())
|
||||||
return (it->second);
|
return (it->second);
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -394,15 +396,15 @@ Core::SessionPtr Core::ServerZone::getSession( std::string playerName )
|
||||||
|
|
||||||
void Core::ServerZone::removeSession( std::string playerName )
|
void Core::ServerZone::removeSession( std::string playerName )
|
||||||
{
|
{
|
||||||
m_playerSessionMap.erase( playerName );
|
m_sessionMapByName.erase( playerName );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::ServerZone::updateSession( std::string playerName )
|
void Core::ServerZone::updateSession( std::string playerName )
|
||||||
{
|
{
|
||||||
std::lock_guard< std::mutex > lock( m_sessionMutex );
|
std::lock_guard< std::mutex > lock( m_sessionMutex );
|
||||||
auto it = m_playerSessionMap.find( playerName );
|
auto it = m_sessionMapByName.find( playerName );
|
||||||
|
|
||||||
if( it != m_playerSessionMap.end() )
|
if( it != m_sessionMapByName.end() )
|
||||||
it->second->loadPlayer();
|
it->second->loadPlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,8 @@ namespace Core {
|
||||||
|
|
||||||
std::mutex m_sessionMutex;
|
std::mutex m_sessionMutex;
|
||||||
|
|
||||||
std::map< uint32_t, SessionPtr > m_sessionMap;
|
std::map< uint32_t, SessionPtr > m_sessionMapById;
|
||||||
std::map< std::string, SessionPtr > m_playerSessionMap;
|
std::map< std::string, SessionPtr > m_sessionMapByName;
|
||||||
|
|
||||||
std::map< uint32_t, uint32_t > m_zones;
|
std::map< uint32_t, uint32_t > m_zones;
|
||||||
|
|
||||||
|
|
|
@ -1,218 +0,0 @@
|
||||||
#include <src/servers/Server_Common/Util/Util.h>
|
|
||||||
#include <src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h>
|
|
||||||
|
|
||||||
#include "src/servers/Server_Zone/Actor/Actor.h"
|
|
||||||
#include "StatusEffect.h"
|
|
||||||
#include "StatusEffectContainer.h"
|
|
||||||
#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket142.h"
|
|
||||||
#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket143.h"
|
|
||||||
|
|
||||||
|
|
||||||
using namespace Core::Common;
|
|
||||||
using namespace Core::Network::Packets;
|
|
||||||
using namespace Core::Network::Packets::Server;
|
|
||||||
|
|
||||||
Core::StatusEffect::StatusEffectContainer::StatusEffectContainer( Entity::ActorPtr pOwner )
|
|
||||||
: m_pOwner( pOwner )
|
|
||||||
{
|
|
||||||
// initialize the free slot queue
|
|
||||||
for( uint8_t i = 0; i < MAX_EFFECTS; i++ )
|
|
||||||
{
|
|
||||||
m_freeEffectSlotQueue.push( i );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int8_t Core::StatusEffect::StatusEffectContainer::getFreeSlot()
|
|
||||||
{
|
|
||||||
int8_t freeEffectSlot = -1;
|
|
||||||
|
|
||||||
if( m_freeEffectSlotQueue.empty() )
|
|
||||||
return freeEffectSlot;
|
|
||||||
|
|
||||||
freeEffectSlot = m_freeEffectSlotQueue.front();
|
|
||||||
m_freeEffectSlotQueue.pop();
|
|
||||||
|
|
||||||
return freeEffectSlot;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::StatusEffect::StatusEffectContainer::freeSlot( uint8_t slotId )
|
|
||||||
{
|
|
||||||
m_freeEffectSlotQueue.push( slotId );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Core::StatusEffect::StatusEffectContainer::~StatusEffectContainer()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Core::StatusEffect::StatusEffectContainer::addStatusEffect( StatusEffectPtr pEffect )
|
|
||||||
{
|
|
||||||
int8_t nextSlot = getFreeSlot();
|
|
||||||
// if there is no slot left, do not add the effect
|
|
||||||
if( nextSlot == -1 )
|
|
||||||
return;
|
|
||||||
|
|
||||||
pEffect->applyStatus();
|
|
||||||
m_effectMap[nextSlot] = pEffect;
|
|
||||||
|
|
||||||
ZoneChannelPacket< Server::FFXIVIpcAddStatusEffect > statusEffectAdd( m_pOwner->getId() );
|
|
||||||
statusEffectAdd.data().actor_id = pEffect->getTargetActorId();
|
|
||||||
statusEffectAdd.data().actor_id1 = pEffect->getSrcActorId();
|
|
||||||
statusEffectAdd.data().current_hp = m_pOwner->getHp();
|
|
||||||
statusEffectAdd.data().current_mp = m_pOwner->getMp();
|
|
||||||
statusEffectAdd.data().current_tp = m_pOwner->getTp();
|
|
||||||
statusEffectAdd.data().duration = static_cast< float >( pEffect->getDuration() ) / 1000;
|
|
||||||
statusEffectAdd.data().effect_id = pEffect->getId();
|
|
||||||
statusEffectAdd.data().effect_index = nextSlot;
|
|
||||||
statusEffectAdd.data().max_hp = m_pOwner->getMaxHp();
|
|
||||||
statusEffectAdd.data().max_mp = m_pOwner->getMaxMp();
|
|
||||||
statusEffectAdd.data().max_something = 1;
|
|
||||||
//statusEffectAdd.data().unknown2 = 28;
|
|
||||||
statusEffectAdd.data().param = pEffect->getParam();
|
|
||||||
|
|
||||||
|
|
||||||
bool sendToSelf = m_pOwner->isPlayer() ? true : false;
|
|
||||||
m_pOwner->sendToInRangeSet( statusEffectAdd, sendToSelf );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::StatusEffect::StatusEffectContainer::removeSingleStatusEffectFromId( uint32_t id )
|
|
||||||
{
|
|
||||||
for (auto effectIt : m_effectMap)
|
|
||||||
{
|
|
||||||
if (effectIt.second->getId() == id)
|
|
||||||
{
|
|
||||||
removeStatusEffect( effectIt.first );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::StatusEffect::StatusEffectContainer::removeStatusEffect( uint8_t effectSlotId )
|
|
||||||
{
|
|
||||||
auto pEffectIt = m_effectMap.find( effectSlotId );
|
|
||||||
if( pEffectIt == m_effectMap.end() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
freeSlot( effectSlotId );
|
|
||||||
|
|
||||||
auto pEffect = pEffectIt->second;
|
|
||||||
pEffect->removeStatus();
|
|
||||||
|
|
||||||
bool sendToSelf = m_pOwner->isPlayer() ? true : false;
|
|
||||||
m_pOwner->sendToInRangeSet( ActorControlPacket142( m_pOwner->getId(), StatusEffectLose, pEffect->getId() ), sendToSelf );
|
|
||||||
|
|
||||||
m_effectMap.erase( effectSlotId );
|
|
||||||
|
|
||||||
sendUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map< uint8_t, Core::StatusEffect::StatusEffectPtr > Core::StatusEffect::StatusEffectContainer::getEffectMap() const
|
|
||||||
{
|
|
||||||
return m_effectMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::StatusEffect::StatusEffectContainer::sendUpdate()
|
|
||||||
{
|
|
||||||
uint64_t currentTimeMs = Util::getTimeMs();
|
|
||||||
|
|
||||||
ZoneChannelPacket< Server::FFXIVIpcStatusEffectList > statusEffectList( m_pOwner->getId() );
|
|
||||||
|
|
||||||
statusEffectList.data().current_hp = m_pOwner->getHp();
|
|
||||||
statusEffectList.data().current_mp = m_pOwner->getMp();
|
|
||||||
statusEffectList.data().currentTp = m_pOwner->getTp();
|
|
||||||
statusEffectList.data().max_hp = m_pOwner->getMaxHp();
|
|
||||||
statusEffectList.data().max_mp = m_pOwner->getMaxMp();
|
|
||||||
uint8_t slot = 0;
|
|
||||||
for( auto effectIt : m_effectMap )
|
|
||||||
{
|
|
||||||
float timeLeft = static_cast< float >( effectIt.second->getDuration() - ( currentTimeMs - effectIt.second->getStartTimeMs() ) ) / 1000;
|
|
||||||
statusEffectList.data().effect[slot].duration = timeLeft;
|
|
||||||
statusEffectList.data().effect[slot].effect_id = effectIt.second->getId();
|
|
||||||
statusEffectList.data().effect[slot].sourceActorId = effectIt.second->getSrcActorId();
|
|
||||||
slot++;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sendToSelf = m_pOwner->isPlayer();
|
|
||||||
m_pOwner->sendToInRangeSet( statusEffectList, sendToSelf );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::StatusEffect::StatusEffectContainer::update()
|
|
||||||
{
|
|
||||||
uint64_t currentTimeMs = Util::getTimeMs();
|
|
||||||
|
|
||||||
uint32_t thisTickDmg = 0;
|
|
||||||
uint32_t thisTickHeal = 0;
|
|
||||||
|
|
||||||
for( auto effectIt : m_effectMap )
|
|
||||||
{
|
|
||||||
uint8_t effectIndex = effectIt.first;
|
|
||||||
auto effect = effectIt.second;
|
|
||||||
|
|
||||||
uint64_t lastTick = effect->getLastTickMs();
|
|
||||||
uint64_t startTime = effect->getStartTimeMs();
|
|
||||||
uint32_t duration = effect->getDuration();
|
|
||||||
uint32_t tickRate = effect->getTickRate();
|
|
||||||
|
|
||||||
if( ( currentTimeMs - startTime ) > duration )
|
|
||||||
{
|
|
||||||
// remove status effect
|
|
||||||
removeStatusEffect( effectIndex );
|
|
||||||
// break because removing invalidates iterators
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ( currentTimeMs - lastTick ) > tickRate )
|
|
||||||
{
|
|
||||||
effect->setLastTick( currentTimeMs );
|
|
||||||
effect->onTick();
|
|
||||||
|
|
||||||
auto thisEffect = effect->getTickEffect();
|
|
||||||
|
|
||||||
switch( thisEffect.first )
|
|
||||||
{
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
thisTickDmg += thisEffect.second;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
thisTickHeal += thisEffect.second;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if( thisTickDmg != 0 )
|
|
||||||
{
|
|
||||||
m_pOwner->takeDamage( thisTickDmg );
|
|
||||||
m_pOwner->sendToInRangeSet( ActorControlPacket142( m_pOwner->getId(), HPFloatingText, 0, static_cast< uint8_t >( ActionEffectType::Damage ), thisTickDmg ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( thisTickHeal != 0 )
|
|
||||||
{
|
|
||||||
m_pOwner->heal( thisTickDmg );
|
|
||||||
m_pOwner->sendToInRangeSet( ActorControlPacket142( m_pOwner->getId(), HPFloatingText, 0, static_cast< uint8_t >( ActionEffectType::Heal ), thisTickHeal ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Core::StatusEffect::StatusEffectContainer::hasStatusEffect( uint32_t id )
|
|
||||||
{
|
|
||||||
for( auto effectIt : m_effectMap )
|
|
||||||
{
|
|
||||||
if( effectIt.second->getId() == id )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
#ifndef _STATUSEFFECTCONTAINER_H_
|
|
||||||
#define _STATUSEFFECTCONTAINER_H_
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "src/servers/Server_Zone/Forwards.h"
|
|
||||||
|
|
||||||
namespace Core
|
|
||||||
{
|
|
||||||
namespace StatusEffect
|
|
||||||
{
|
|
||||||
|
|
||||||
class StatusEffectContainer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
StatusEffectContainer( Entity::ActorPtr pOwner );
|
|
||||||
~StatusEffectContainer();
|
|
||||||
|
|
||||||
void addStatusEffect( StatusEffectPtr pEffect );
|
|
||||||
void removeStatusEffect( uint8_t effectSlotId );
|
|
||||||
void removeSingleStatusEffectFromId( uint32_t id );
|
|
||||||
void update();
|
|
||||||
|
|
||||||
bool hasStatusEffect( uint32_t id );
|
|
||||||
|
|
||||||
int8_t getFreeSlot();
|
|
||||||
void freeSlot( uint8_t slotId );
|
|
||||||
|
|
||||||
std::map< uint8_t, Core::StatusEffect::StatusEffectPtr > getEffectMap() const;
|
|
||||||
|
|
||||||
void sendUpdate();
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
const uint8_t MAX_EFFECTS = 30;
|
|
||||||
|
|
||||||
Entity::ActorPtr m_pOwner;
|
|
||||||
std::queue< uint8_t > m_freeEffectSlotQueue;
|
|
||||||
|
|
||||||
std::vector< std::pair< uint8_t, uint32_t> > m_tickEffectList;
|
|
||||||
std::map< uint8_t, StatusEffectPtr > m_effectMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -47,7 +47,6 @@ namespace Core
|
||||||
{
|
{
|
||||||
|
|
||||||
entry->setCurrentZone( m_pZone );
|
entry->setCurrentZone( m_pZone );
|
||||||
entry->getAsBattleNpc()->initStatusEffectContainer();
|
|
||||||
m_pZone->pushActor( entry );
|
m_pZone->pushActor( entry );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue