1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-02 16:57:47 +00:00

enum/struct/packet updates, fix dot/hot tick, remove incorrect initial delay for player autoattacks.

This commit is contained in:
collett 2020-01-19 21:20:01 +09:00
parent 3fb6657d7d
commit 60e701dbdd
11 changed files with 73 additions and 74 deletions

View file

@ -412,7 +412,7 @@ namespace Sapphire::Common
struct StatusEffect struct StatusEffect
{ {
uint16_t effect_id; uint16_t effect_id;
uint16_t unknown1; uint16_t param;
float duration; float duration;
uint32_t sourceActorId; uint32_t sourceActorId;
}; };
@ -591,9 +591,10 @@ namespace Sapphire::Common
// DRGGauge3Eyes = 76, // DRGGauge3Eyes = 76,
}; };
enum class ActionType : int8_t enum class AttackType : int8_t
{ {
WeaponOverride = -1, // Needs more investigation (takes the damage type of the equipped weapon)? //WeaponOverride = -1, // Needs more investigation (takes the damage type of the equipped weapon)?
Physical = -1, // seems to be the case
Unknown_0 = 0, Unknown_0 = 0,
Slashing = 1, Slashing = 1,
Piercing = 2, Piercing = 2,
@ -623,6 +624,8 @@ namespace Sapphire::Common
TpGain = 13, TpGain = 13,
GpGain = 14, GpGain = 14,
ApplyStatusEffect = 15, ApplyStatusEffect = 15,
//ApplyStatusEffect2 = 16, // thin air uses this one but works fine with 15 wtf?
StatusNoEffect = 21,
/*! /*!
* @brief Tells the client that it should show combo indicators on actions. * @brief Tells the client that it should show combo indicators on actions.
* *
@ -649,7 +652,9 @@ namespace Sapphire::Common
enum class ActionEffectResultFlag : uint8_t enum class ActionEffectResultFlag : uint8_t
{ {
None = 0, None = 0,
Absorbed = 0x04,
EffectOnSource = 0x80, EffectOnSource = 0x80,
Reflected = 0xA0,
}; };
enum ItemActionType : uint16_t enum ItemActionType : uint16_t

View file

@ -160,7 +160,7 @@ namespace Sapphire::Network::Packets
PlayerStateFlags = 0x02C6, // updated 5.18 PlayerStateFlags = 0x02C6, // updated 5.18
PlayerClassInfo = 0x01B0, // updated 5.18 PlayerClassInfo = 0x01B0, // updated 5.18
ModelEquip = 0x0170, // updated 5.11 ModelEquip = 0x02E6, // updated 5.18
Examine = 0x0366, // updated 5.18 Examine = 0x0366, // updated 5.18
CharaNameReq = 0x0116, // updated 5.18 CharaNameReq = 0x0116, // updated 5.18

View file

@ -422,7 +422,8 @@ namespace Sapphire::Network::Packets::Server
uint16_t current_mp; uint16_t current_mp;
uint16_t max_mp; uint16_t max_mp;
uint16_t currentTp; uint16_t currentTp;
uint16_t unknown1; uint8_t shieldPercentage;
uint8_t unknown1;
Common::StatusEffect effect[30]; Common::StatusEffect effect[30];
uint32_t padding; uint32_t padding;
}; };
@ -439,27 +440,18 @@ namespace Sapphire::Network::Packets::Server
*/ */
struct FFXIVIpcEffectResult : FFXIVIpcBasePacket< EffectResult > struct FFXIVIpcEffectResult : FFXIVIpcBasePacket< EffectResult >
{ {
uint32_t unknown; uint32_t globalSequence;
uint32_t actor_id; uint32_t actor_id;
//uint8_t unknown1;
//uint8_t unknown2;
//uint16_t padding1;
//uint32_t current_hp;
//uint16_t current_mp;
//uint16_t current_tp;
//uint32_t max_hp;
//uint16_t max_mp;
//uint16_t max_something;
uint32_t current_hp; uint32_t current_hp;
uint32_t max_hp; uint32_t max_hp;
uint16_t current_mp; uint16_t current_mp;
uint16_t unknown1; uint16_t current_tp;
uint16_t max_mp; uint16_t max_mp;
uint8_t unknown2; uint8_t unknown1;
uint8_t classId; uint8_t classId;
uint8_t unknown4; uint8_t shieldPercentage;
uint8_t unkFlag; uint8_t entryCount;
uint16_t unknown6; uint16_t unknown2;
struct StatusEntry struct StatusEntry
{ {
@ -467,12 +459,12 @@ namespace Sapphire::Network::Packets::Server
uint8_t unknown3; uint8_t unknown3;
uint16_t id; uint16_t id;
uint16_t param; uint16_t param;
uint16_t unknown5; // Sort this out (old right half of power/param property) uint16_t unknown4; // Sort this out (old right half of power/param property)
float duration; float duration;
uint32_t sourceActorId; uint32_t sourceActorId;
} statusEntries[4]; } statusEntries[4];
uint32_t unknown7; uint32_t unknown5;
}; };
/** /**

View file

@ -565,7 +565,7 @@ bool Action::Action::playerPreCheck( Entity::Player& player )
return false; return false;
// npc actions/non player actions // npc actions/non player actions
if( m_actionData->classJob == -1 ) if( m_actionData->classJob == -1 && !m_actionData->isRoleAction )
return false; return false;
if( player.getLevel() < m_actionData->classJobLevel ) if( player.getLevel() < m_actionData->classJobLevel )
@ -574,7 +574,7 @@ bool Action::Action::playerPreCheck( Entity::Player& player )
auto currentClass = player.getClass(); auto currentClass = player.getClass();
auto actionClass = static_cast< Common::ClassJob >( m_actionData->classJob ); auto actionClass = static_cast< Common::ClassJob >( m_actionData->classJob );
if( actionClass != Common::ClassJob::Adventurer && currentClass != actionClass ) if( actionClass != Common::ClassJob::Adventurer && currentClass != actionClass && !m_actionData->isRoleAction )
{ {
// check if not a base class action // check if not a base class action
auto exdData = m_pFw->get< Data::ExdDataGenerated >(); auto exdData = m_pFw->get< Data::ExdDataGenerated >();

View file

@ -396,6 +396,7 @@ void Sapphire::Entity::BNpc::deaggro( Sapphire::Entity::CharaPtr pChara )
void Sapphire::Entity::BNpc::onTick() void Sapphire::Entity::BNpc::onTick()
{ {
Chara::onTick();
if( m_state == BNpcState::Retreat ) if( m_state == BNpcState::Retreat )
{ {
regainHp(); regainHp();

View file

@ -44,6 +44,7 @@ Sapphire::Entity::Chara::Chara( ObjKind type, FrameworkPtr pFw ) :
m_lastTickTime = 0; m_lastTickTime = 0;
m_lastUpdate = 0; m_lastUpdate = 0;
m_lastAttack = Util::getTimeMs();
m_bonusStats.fill( 0 ); m_bonusStats.fill( 0 );
@ -354,6 +355,8 @@ bool Sapphire::Entity::Chara::checkAction()
void Sapphire::Entity::Chara::update( uint64_t tickCount ) void Sapphire::Entity::Chara::update( uint64_t tickCount )
{ {
updateStatusEffects();
if( std::difftime( static_cast< time_t >( tickCount ), m_lastTickTime ) > 3000 ) if( std::difftime( static_cast< time_t >( tickCount ), m_lastTickTime ) > 3000 )
{ {
onTick(); onTick();
@ -532,16 +535,15 @@ void Sapphire::Entity::Chara::addStatusEffect( StatusEffect::StatusEffectPtr pEf
auto statusEffectAdd = makeZonePacket< FFXIVIpcEffectResult >( getId() ); auto statusEffectAdd = makeZonePacket< FFXIVIpcEffectResult >( getId() );
statusEffectAdd->data().globalSequence = getCurrentTerritory()->getNextEffectSequence();
statusEffectAdd->data().actor_id = pEffect->getTargetActorId(); statusEffectAdd->data().actor_id = pEffect->getTargetActorId();
statusEffectAdd->data().current_hp = getHp(); statusEffectAdd->data().current_hp = getHp();
statusEffectAdd->data().current_mp = static_cast< uint16_t >( getMp() ); statusEffectAdd->data().current_mp = static_cast< uint16_t >( getMp() );
//statusEffectAdd->data().current_tp = getTp(); statusEffectAdd->data().current_tp = getTp();
statusEffectAdd->data().max_hp = getMaxHp(); statusEffectAdd->data().max_hp = getMaxHp();
statusEffectAdd->data().max_mp = static_cast< uint16_t >( getMaxMp() ); statusEffectAdd->data().max_mp = static_cast< uint16_t >( getMaxMp() );
//statusEffectAdd->data().max_something = 1; statusEffectAdd->data().classId = static_cast< uint8_t >( getClass() );
//statusEffectAdd->data().unknown2 = 28; statusEffectAdd->data().entryCount = 1;
statusEffectAdd->data().classId = static_cast< uint8_t >(getClass());
statusEffectAdd->data().unkFlag = 1;
auto& status = statusEffectAdd->data().statusEntries[0]; auto& status = statusEffectAdd->data().statusEntries[0];
@ -681,9 +683,6 @@ void Sapphire::Entity::Chara::updateStatusEffects()
{ {
uint64_t currentTimeMs = Util::getTimeMs(); uint64_t currentTimeMs = Util::getTimeMs();
uint32_t thisTickDmg = 0;
uint32_t thisTickHeal = 0;
for( auto effectIt : m_statusEffectMap ) for( auto effectIt : m_statusEffectMap )
{ {
uint8_t effectIndex = effectIt.first; uint8_t effectIndex = effectIt.first;
@ -694,7 +693,7 @@ void Sapphire::Entity::Chara::updateStatusEffects()
uint32_t duration = effect->getDuration(); uint32_t duration = effect->getDuration();
uint32_t tickRate = effect->getTickRate(); uint32_t tickRate = effect->getTickRate();
if( ( currentTimeMs - startTime ) > duration ) if( duration > 0 && ( currentTimeMs - startTime ) > duration )
{ {
// remove status effect // remove status effect
removeStatusEffect( effectIndex ); removeStatusEffect( effectIndex );
@ -706,41 +705,7 @@ void Sapphire::Entity::Chara::updateStatusEffects()
{ {
effect->setLastTick( currentTimeMs ); effect->setLastTick( currentTimeMs );
effect->onTick(); 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( makeActorControl( getId(), HPFloatingText, 0,
static_cast< uint8_t >( ActionEffectType::Damage ), thisTickDmg ) );
}
if( thisTickHeal != 0 )
{
heal( thisTickDmg );
sendToInRangeSet( makeActorControl( getId(), HPFloatingText, 0,
static_cast< uint8_t >( ActionEffectType::Heal ), thisTickHeal ) );
} }
} }
@ -944,3 +909,42 @@ uint32_t Sapphire::Entity::Chara::getStatValue( Sapphire::Common::BaseParam base
return value + getBonusStat( baseParam ); return value + getBonusStat( baseParam );
} }
void Sapphire::Entity::Chara::onTick()
{
uint32_t thisTickDmg = 0;
uint32_t thisTickHeal = 0;
for( auto effectIt : m_statusEffectMap )
{
auto thisEffect = effectIt.second->getTickEffect();
switch( thisEffect.first )
{
case 1:
{
thisTickDmg += thisEffect.second;
break;
}
case 2:
{
thisTickHeal += thisEffect.second;
break;
}
}
}
if( thisTickDmg != 0 )
{
takeDamage( thisTickDmg );
sendToInRangeSet( makeActorControl( getId(), HPFloatingText, 0,
static_cast< uint8_t >( ActionEffectType::Damage ), thisTickDmg ), true );
}
if( thisTickHeal != 0 )
{
heal( thisTickHeal );
sendToInRangeSet( makeActorControl( getId(), HPFloatingText, 0,
static_cast< uint8_t >( ActionEffectType::Heal ), thisTickHeal ), true );
}
}

View file

@ -251,7 +251,7 @@ namespace Sapphire::Entity
virtual void onActionFriendly( Chara& pSource ) {}; virtual void onActionFriendly( Chara& pSource ) {};
virtual void onTick() {}; virtual void onTick();
virtual void changeTarget( uint64_t targetId ); virtual void changeTarget( uint64_t targetId );

View file

@ -306,7 +306,6 @@ void Sapphire::Entity::Player::calculateStats()
void Sapphire::Entity::Player::setAutoattack( bool mode ) void Sapphire::Entity::Player::setAutoattack( bool mode )
{ {
m_bAutoattack = mode; m_bAutoattack = mode;
m_lastAttack = Util::getTimeMs();
} }
bool Sapphire::Entity::Player::isAutoattackOn() const bool Sapphire::Entity::Player::isAutoattackOn() const
@ -1100,8 +1099,6 @@ void Sapphire::Entity::Player::update( uint64_t tickCount )
if( !isAlive() ) if( !isAlive() )
return; return;
updateStatusEffects();
m_lastUpdate = tickCount; m_lastUpdate = tickCount;
if( !checkAction() ) if( !checkAction() )

View file

@ -370,7 +370,7 @@ void Sapphire::Entity::Player::onDeath()
// TODO: slightly ugly here and way too static. Needs too be done properly // TODO: slightly ugly here and way too static. Needs too be done properly
void Sapphire::Entity::Player::onTick() void Sapphire::Entity::Player::onTick()
{ {
Chara::onTick();
// add 3 seconds to total play time // add 3 seconds to total play time
m_playTime += 3; m_playTime += 3;

View file

@ -96,7 +96,7 @@ namespace Sapphire::Network::Packets::Server
( currentTimeMs - ( currentTimeMs -
effect.second->getStartTimeMs() ) ) / 1000; 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 ].param = effect.second->getParam();
} }
}; };

View file

@ -142,7 +142,7 @@ namespace Sapphire::Network::Packets::Server
( currentTimeMs - ( currentTimeMs -
effect.second->getStartTimeMs() ) ) / 1000; 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 ].param = effect.second->getParam();
} }
}; };