2017-08-19 00:18:40 +02:00
|
|
|
#include <src/servers/Server_Common/Util/Util.h>
|
2017-08-21 00:02:41 +02:00
|
|
|
#include <src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h>
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-18 17:16:15 +02:00
|
|
|
#include "src/servers/Server_Zone/Actor/Actor.h"
|
2017-08-08 13:53:47 +02:00
|
|
|
#include "StatusEffect.h"
|
|
|
|
#include "StatusEffectContainer.h"
|
2017-08-18 17:16:15 +02:00
|
|
|
#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket142.h"
|
|
|
|
#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket143.h"
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
|
|
|
|
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 )
|
|
|
|
{
|
|
|
|
uint8_t nextSlot = getFreeSlot();
|
|
|
|
// if there is no slot left, do not add the effect
|
|
|
|
if( nextSlot == -1 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
pEffect->applyStatus();
|
|
|
|
m_effectMap[nextSlot] = pEffect;
|
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
GamePacketNew< Server::FFXIVIpcAddStatusEffect, ServerZoneIpcType > statusEffectAdd( m_pOwner->getId() );
|
2017-08-08 13:53:47 +02:00
|
|
|
statusEffectAdd.data().actor_id = m_pOwner->getId();
|
|
|
|
statusEffectAdd.data().actor_id1 = m_pOwner->getId();
|
|
|
|
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;
|
2017-08-10 16:12:54 +02:00
|
|
|
//statusEffectAdd.data().unknown2 = 28;
|
2017-08-12 22:36:52 -03:00
|
|
|
statusEffectAdd.data().param = pEffect->getParam();
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
bool sendToSelf = m_pOwner->isPlayer() ? true : false;
|
|
|
|
m_pOwner->sendToInRangeSet( statusEffectAdd, sendToSelf );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-09-04 01:36:19 -03:00
|
|
|
void Core::StatusEffect::StatusEffectContainer::removeSingleStatusEffectFromId( uint32_t id )
|
|
|
|
{
|
|
|
|
for (auto effectIt : m_effectMap)
|
|
|
|
{
|
|
|
|
if (effectIt.second->getId() == id)
|
|
|
|
{
|
|
|
|
removeStatusEffect( effectIt.first );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-08 13:53:47 +02:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2017-09-06 20:25:58 +02:00
|
|
|
std::map< uint8_t, Core::StatusEffect::StatusEffectPtr > Core::StatusEffect::StatusEffectContainer::getEffectMap() const
|
|
|
|
{
|
|
|
|
return m_effectMap;
|
|
|
|
}
|
|
|
|
|
2017-08-08 13:53:47 +02:00
|
|
|
void Core::StatusEffect::StatusEffectContainer::sendUpdate()
|
|
|
|
{
|
|
|
|
uint64_t currentTimeMs = Util::getTimeMs();
|
|
|
|
|
2017-08-20 22:31:23 +02:00
|
|
|
GamePacketNew< Server::FFXIVIpcStatusEffectList, ServerZoneIpcType > statusEffectList( m_pOwner->getId() );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
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++;
|
|
|
|
}
|
|
|
|
|
2017-08-29 20:28:51 -03:00
|
|
|
bool sendToSelf = m_pOwner->isPlayer();
|
2017-08-08 13:53:47 +02:00
|
|
|
m_pOwner->sendToInRangeSet( statusEffectList, sendToSelf );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Core::StatusEffect::StatusEffectContainer::update()
|
|
|
|
{
|
|
|
|
uint64_t currentTimeMs = Util::getTimeMs();
|
|
|
|
|
2017-08-15 11:51:59 +02:00
|
|
|
uint64_t thisTickDmg = 0;
|
|
|
|
uint64_t thisTickHeal = 0;
|
|
|
|
|
2017-08-08 13:53:47 +02:00
|
|
|
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();
|
2017-08-15 11:51:59 +02:00
|
|
|
|
|
|
|
auto thisEffect = effect->getTickEffect();
|
|
|
|
|
|
|
|
switch( thisEffect.first )
|
|
|
|
{
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
thisTickDmg += thisEffect.second;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
thisTickHeal += thisEffect.second;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2017-08-15 11:51:59 +02:00
|
|
|
|
|
|
|
if( thisTickDmg != 0 )
|
|
|
|
{
|
|
|
|
m_pOwner->takeDamage( thisTickDmg );
|
|
|
|
m_pOwner->sendToInRangeSet( ActorControlPacket142( m_pOwner->getId(), HPFloatingText, 0, 3, thisTickDmg ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( thisTickHeal != 0 )
|
|
|
|
{
|
|
|
|
m_pOwner->heal( thisTickDmg );
|
|
|
|
m_pOwner->sendToInRangeSet( ActorControlPacket142( m_pOwner->getId(), HPFloatingText, 0, 4, thisTickHeal ) );
|
|
|
|
}
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
2017-08-15 15:48:52 +02:00
|
|
|
|
|
|
|
bool Core::StatusEffect::StatusEffectContainer::hasStatusEffect( uint32_t id )
|
|
|
|
{
|
|
|
|
for( auto effectIt : m_effectMap )
|
|
|
|
{
|
|
|
|
if( effectIt.second->getId() == id )
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|