mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-27 14:57:44 +00:00
slight effect rework; support multiple ct/tg per action for both aoe and singletarget; fix several inconsistencies with effect packets;
This commit is contained in:
parent
3b02afe99b
commit
3d5bcc7d67
9 changed files with 140 additions and 103 deletions
|
@ -106,10 +106,11 @@ bool Action::Action::init()
|
||||||
case Common::ClassJob::Bard:
|
case Common::ClassJob::Bard:
|
||||||
case Common::ClassJob::Archer:
|
case Common::ClassJob::Archer:
|
||||||
m_range = 25;
|
m_range = 25;
|
||||||
|
break;
|
||||||
// anything that isnt ranged
|
// anything that isnt ranged
|
||||||
default:
|
default:
|
||||||
m_range = 3;
|
m_range = 3;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,7 +432,7 @@ void Action::Action::execute()
|
||||||
|
|
||||||
// set currently casted action as the combo action if it interrupts a combo
|
// set currently casted action as the combo action if it interrupts a combo
|
||||||
// ignore it otherwise (ogcds, etc.)
|
// ignore it otherwise (ogcds, etc.)
|
||||||
if( !m_actionData->data().ComboContinue )
|
if( m_actionData->data().ComboContinue )
|
||||||
{
|
{
|
||||||
// potential combo starter or correct combo from last action, must hit something to progress combo
|
// potential combo starter or correct combo from last action, must hit something to progress combo
|
||||||
if( !m_hitActors.empty() && ( !isComboAction() || isCorrectCombo() ) )
|
if( !m_hitActors.empty() && ( !isComboAction() || isCorrectCombo() ) )
|
||||||
|
@ -512,7 +513,7 @@ void Action::Action::buildEffects()
|
||||||
if( !hasLutEntry || m_hitActors.empty() )
|
if( !hasLutEntry || m_hitActors.empty() )
|
||||||
{
|
{
|
||||||
// send any effect packet added by script or an empty one just to play animation for other players
|
// send any effect packet added by script or an empty one just to play animation for other players
|
||||||
m_effectBuilder->buildAndSendPackets();
|
m_effectBuilder->buildAndSendPackets( m_hitActors );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,14 +534,14 @@ void Action::Action::buildEffects()
|
||||||
if( m_lutEntry.potency > 0 )
|
if( m_lutEntry.potency > 0 )
|
||||||
{
|
{
|
||||||
auto dmg = calcDamage( isCorrectCombo() ? m_lutEntry.comboPotency : m_lutEntry.potency );
|
auto dmg = calcDamage( isCorrectCombo() ? m_lutEntry.comboPotency : m_lutEntry.potency );
|
||||||
m_effectBuilder->damage( actor, actor, dmg.first, dmg.second );
|
m_effectBuilder->damage( m_pSource, actor, dmg.first, dmg.second );
|
||||||
|
|
||||||
if( dmg.first > 0 )
|
if( dmg.first > 0 )
|
||||||
actor->onActionHostile( m_pSource );
|
actor->onActionHostile( m_pSource );
|
||||||
|
|
||||||
if( isCorrectCombo() && shouldApplyComboSucceedEffect )
|
if( isCorrectCombo() && shouldApplyComboSucceedEffect )
|
||||||
{
|
{
|
||||||
m_effectBuilder->comboSucceed( actor );
|
m_effectBuilder->comboSucceed( m_pSource );
|
||||||
shouldApplyComboSucceedEffect = false;
|
shouldApplyComboSucceedEffect = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,9 +559,10 @@ void Action::Action::buildEffects()
|
||||||
shouldRestoreMP = false;
|
shouldRestoreMP = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !m_actionData->data().ComboContinue ) // we need something like m_actionData->hasNextComboAction
|
if( m_actionData->data().ComboContinue ) // we need something like m_actionData->hasNextComboAction
|
||||||
{
|
{
|
||||||
m_effectBuilder->startCombo( actor, getId() ); // this is on all targets hit
|
m_effectBuilder->startCombo( m_pSource, getId() ); // this is on all targets hit
|
||||||
|
m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -582,7 +584,7 @@ void Action::Action::buildEffects()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_effectBuilder->buildAndSendPackets();
|
m_effectBuilder->buildAndSendPackets( m_hitActors );
|
||||||
|
|
||||||
// TODO: disabled, reset kills our queued actions
|
// TODO: disabled, reset kills our queued actions
|
||||||
// at this point we're done with it and no longer need it
|
// at this point we're done with it and no longer need it
|
||||||
|
|
|
@ -33,159 +33,169 @@ uint64_t EffectBuilder::getResultDelayMs()
|
||||||
return Common::Util::getTimeMs() + 850;
|
return Common::Util::getTimeMs() + 850;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectBuilder::moveToResultList( Entity::CharaPtr& chara, EffectResultPtr result )
|
void EffectBuilder::addResultToActor( Entity::CharaPtr& chara, EffectResultPtr result )
|
||||||
{
|
{
|
||||||
auto it = m_resolvedEffects.find( chara->getId() );
|
auto it = m_actorEffectsMap.find( chara->getId() );
|
||||||
if( it == m_resolvedEffects.end() )
|
if( it == m_actorEffectsMap.end() )
|
||||||
{
|
{
|
||||||
// create a new one
|
// create a new one
|
||||||
auto resultList = std::make_shared< std::vector< EffectResultPtr > >();
|
auto resultList = std::vector< EffectResultPtr >();
|
||||||
|
|
||||||
m_resolvedEffects[ chara->getId() ] = resultList;
|
resultList.push_back( std::move( result ) );
|
||||||
|
|
||||||
resultList->push_back( std::move( result ) );
|
m_actorEffectsMap[ chara->getId() ] = resultList;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
it->second->push_back( std::move( result ) );
|
it->second.push_back( std::move( result ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectBuilder::heal( Entity::CharaPtr& effectTarget, Entity::CharaPtr& healingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag )
|
void EffectBuilder::heal( Entity::CharaPtr& effectTarget, Entity::CharaPtr& healingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag )
|
||||||
{
|
{
|
||||||
EffectResultPtr nextResult = make_EffectResult( healingTarget, getResultDelayMs() );
|
EffectResultPtr nextResult = make_EffectResult( healingTarget, getResultDelayMs() );
|
||||||
nextResult->heal( amount, severity, flag );
|
nextResult->heal( amount, severity, flag );
|
||||||
moveToResultList( effectTarget, nextResult );
|
addResultToActor( effectTarget, nextResult );
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectBuilder::restoreMP( Entity::CharaPtr& target, Entity::CharaPtr& restoringTarget, uint32_t amount, Common::ActionEffectResultFlag flag )
|
void EffectBuilder::restoreMP( Entity::CharaPtr& target, Entity::CharaPtr& restoringTarget, uint32_t amount, Common::ActionEffectResultFlag flag )
|
||||||
{
|
{
|
||||||
EffectResultPtr nextResult = make_EffectResult( restoringTarget, getResultDelayMs() ); // restore mp source actor
|
EffectResultPtr nextResult = make_EffectResult( restoringTarget, getResultDelayMs() ); // restore mp source actor
|
||||||
nextResult->restoreMP( amount, flag );
|
nextResult->restoreMP( amount, flag );
|
||||||
moveToResultList( target, nextResult );
|
addResultToActor( target, nextResult );
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectBuilder::damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag )
|
void EffectBuilder::damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag )
|
||||||
{
|
{
|
||||||
EffectResultPtr nextResult = make_EffectResult( damagingTarget, getResultDelayMs() );
|
EffectResultPtr nextResult = make_EffectResult( damagingTarget, getResultDelayMs() );
|
||||||
nextResult->damage( amount, severity, flag );
|
nextResult->damage( amount, severity, flag );
|
||||||
moveToResultList( effectTarget, nextResult );
|
addResultToActor( damagingTarget, nextResult );
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectBuilder::startCombo( Entity::CharaPtr& target, uint16_t actionId )
|
void EffectBuilder::startCombo( Entity::CharaPtr& target, uint16_t actionId )
|
||||||
{
|
{
|
||||||
EffectResultPtr nextResult = make_EffectResult( target, 0 );
|
EffectResultPtr nextResult = make_EffectResult( target, 0 );
|
||||||
nextResult->startCombo( actionId );
|
nextResult->startCombo( actionId );
|
||||||
moveToResultList( target, nextResult );
|
addResultToActor( target, nextResult );
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectBuilder::comboSucceed( Entity::CharaPtr& target )
|
void EffectBuilder::comboSucceed( Entity::CharaPtr& target )
|
||||||
{
|
{
|
||||||
EffectResultPtr nextResult = make_EffectResult( target, 0 );
|
EffectResultPtr nextResult = make_EffectResult( target, 0 );
|
||||||
nextResult->comboSucceed();
|
nextResult->comboSucceed();
|
||||||
moveToResultList( target, nextResult );
|
addResultToActor( target, nextResult );
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint8_t param )
|
void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, uint16_t statusId, uint8_t param )
|
||||||
{
|
{
|
||||||
EffectResultPtr nextResult = make_EffectResult( target, 0 );
|
EffectResultPtr nextResult = make_EffectResult( target, 0 );
|
||||||
nextResult->applyStatusEffect( statusId, param );
|
nextResult->applyStatusEffect( statusId, param );
|
||||||
moveToResultList( target, nextResult );
|
addResultToActor( target, nextResult );
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectBuilder::mount( Entity::CharaPtr& target, uint16_t mountId )
|
void EffectBuilder::mount( Entity::CharaPtr& target, uint16_t mountId )
|
||||||
{
|
{
|
||||||
EffectResultPtr nextResult = make_EffectResult( target, getResultDelayMs() );
|
EffectResultPtr nextResult = make_EffectResult( target, getResultDelayMs() );
|
||||||
nextResult->mount( mountId );
|
nextResult->mount( mountId );
|
||||||
moveToResultList( target, nextResult );
|
addResultToActor( target, nextResult );
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectBuilder::buildAndSendPackets()
|
void EffectBuilder::buildAndSendPackets( const std::vector< Entity::CharaPtr >& targetList )
|
||||||
{
|
{
|
||||||
auto targetCount = m_resolvedEffects.size();
|
|
||||||
Logger::debug( "EffectBuilder result: " );
|
Logger::debug( "EffectBuilder result: " );
|
||||||
Logger::debug( "Targets afflicted: {}", targetCount );
|
Logger::debug( "Targets afflicted: {}", targetList.size() );
|
||||||
|
|
||||||
auto globalSequence = m_sourceChara->getCurrentTerritory()->getNextEffectSequence();
|
|
||||||
|
|
||||||
do // we want to send at least one packet even nothing is hit so other players can see
|
do // we want to send at least one packet even nothing is hit so other players can see
|
||||||
{
|
{
|
||||||
auto packet = buildNextEffectPacket( globalSequence );
|
auto packet = buildNextEffectPacket( targetList );
|
||||||
m_sourceChara->sendToInRangeSet( packet, true );
|
m_sourceChara->sendToInRangeSet( packet, true );
|
||||||
}
|
}
|
||||||
while( !m_resolvedEffects.empty() );
|
while( !m_actorEffectsMap.empty() );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( uint32_t globalSequence )
|
std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( const std::vector< Entity::CharaPtr >& targetList )
|
||||||
{
|
{
|
||||||
auto remainingTargetCount = m_resolvedEffects.size();
|
auto remainingTargetCount = targetList.size();
|
||||||
|
auto globalSequence = m_sourceChara->getCurrentTerritory()->getNextEffectSequence();
|
||||||
|
|
||||||
if( remainingTargetCount > 1 ) // use AoeEffect packets
|
if( remainingTargetCount > 1 ) // use AoeEffect packets
|
||||||
{
|
{
|
||||||
auto effectResult = makeZonePacket< FFXIVIpcActionResult >( m_sourceChara->getId() );
|
auto effectPacket = std::make_shared< EffectPacket >( m_sourceChara->getId(), m_actionId );
|
||||||
Common::CalcResultParam* pEntry;
|
effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) );
|
||||||
uint64_t* pEffectTargetId;
|
effectPacket->setSequence( globalSequence, m_sequence );
|
||||||
|
effectPacket->setTargetActor( targetList[ 0 ]->getId() );
|
||||||
effectResult->data().ActionKey = m_actionId;
|
|
||||||
effectResult->data().ActionKind = 1;
|
|
||||||
effectResult->data().Action = static_cast< uint16_t >( m_actionId );
|
|
||||||
effectResult->data().MainTarget = m_sourceChara->getId();
|
|
||||||
effectResult->data().DirTarget = Common::Util::floatToUInt16Rot( m_sourceChara->getRot() );
|
|
||||||
effectResult->data().Flag = Common::ActionEffectDisplayType::ShowActionName;
|
|
||||||
effectResult->data().TargetCount = static_cast< uint8_t >( remainingTargetCount );
|
|
||||||
effectResult->data().RequestId = m_sequence;
|
|
||||||
effectResult->data().ResultId = globalSequence;
|
|
||||||
|
|
||||||
uint8_t targetIndex = 0;
|
uint8_t targetIndex = 0;
|
||||||
for( auto it = m_resolvedEffects.begin(); it != m_resolvedEffects.end(); )
|
for( auto it = m_actorEffectsMap.begin(); it != m_actorEffectsMap.end(); )
|
||||||
{
|
{
|
||||||
auto resultList = it->second;
|
// get all effect results for an actor
|
||||||
assert( !resultList->empty() );
|
auto actorResultList = it->second;
|
||||||
auto firstResult = resultList->data()[ 0 ];
|
|
||||||
pEffectTargetId[ targetIndex ] = firstResult->getTarget()->getId();
|
|
||||||
Logger::debug( " - id: {}", pEffectTargetId[ targetIndex ] );
|
|
||||||
|
|
||||||
for( auto i = 0; i < resultList->size(); i++ )
|
for( auto i = 0; i < actorResultList.size(); ++i )
|
||||||
{
|
{
|
||||||
auto result = resultList->data()[ i ];
|
auto result = actorResultList.data()[ i ];
|
||||||
pEntry[ targetIndex * 8 + i ] = result->buildEffectEntry();
|
auto effect = result->buildEffectEntry();
|
||||||
|
|
||||||
|
// if effect result is a source/caster effect
|
||||||
|
if( result->getTarget() == m_sourceChara )
|
||||||
|
{
|
||||||
|
effectPacket->addSourceEffect( effect );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
effectPacket->addTargetEffect( effect, result->getTarget()->getId() );
|
||||||
|
}
|
||||||
|
|
||||||
m_sourceChara->getCurrentTerritory()->addEffectResult( std::move( result ) );
|
m_sourceChara->getCurrentTerritory()->addEffectResult( std::move( result ) );
|
||||||
}
|
}
|
||||||
resultList->clear();
|
|
||||||
|
|
||||||
it = m_resolvedEffects.erase( it );
|
|
||||||
|
|
||||||
|
actorResultList.clear();
|
||||||
|
it = m_actorEffectsMap.erase( it );
|
||||||
targetIndex++;
|
targetIndex++;
|
||||||
|
|
||||||
if( targetIndex == 15 )
|
if( targetIndex == 15 )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return effectResult;
|
return effectPacket;
|
||||||
}
|
}
|
||||||
else if( remainingTargetCount == 1 ) // use Effect for single target
|
else if( remainingTargetCount == 1 ) // use Effect for single target
|
||||||
{
|
{
|
||||||
auto resultList = m_resolvedEffects.begin()->second;
|
Logger::debug( " - id: {}", targetList[0]->getId() );
|
||||||
assert( !resultList->empty() );
|
Logger::debug( "------------------------------------------" );
|
||||||
auto firstResult = resultList->data()[ 0 ];
|
|
||||||
Logger::debug( " - id: {}", firstResult->getTarget()->getId() );
|
|
||||||
|
|
||||||
auto seq = m_sourceChara->getCurrentTerritory()->getNextEffectSequence();
|
auto effectPacket = std::make_shared< EffectPacket1 >( m_sourceChara->getId(), targetList[ 0 ]->getId(), m_actionId );
|
||||||
|
|
||||||
auto effectPacket = std::make_shared< EffectPacket1 >( m_sourceChara->getId(), firstResult->getTarget()->getId(), m_actionId );
|
|
||||||
effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) );
|
effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) );
|
||||||
effectPacket->setSequence( seq, m_sequence );
|
effectPacket->setSequence( globalSequence, m_sequence );
|
||||||
|
|
||||||
for( int i = 0; i < resultList->size(); i++ )
|
for( auto it = m_actorEffectsMap.begin(); it != m_actorEffectsMap.end(); )
|
||||||
{
|
{
|
||||||
auto result = resultList->data()[ i ];
|
// get all effect results for an actor
|
||||||
effectPacket->addTargetEffect( result->buildEffectEntry() );
|
auto actorResultList = it->second;
|
||||||
|
|
||||||
|
for( auto i = 0; i < actorResultList.size(); ++i )
|
||||||
|
{
|
||||||
|
auto result = actorResultList.data()[ i ];
|
||||||
|
auto effect = result->buildEffectEntry();
|
||||||
|
|
||||||
|
// if effect result is a source/caster effect
|
||||||
|
if( result->getTarget() == m_sourceChara )
|
||||||
|
{
|
||||||
|
effectPacket->addSourceEffect( effect );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
effectPacket->addTargetEffect( effect );
|
||||||
|
}
|
||||||
|
|
||||||
m_sourceChara->getCurrentTerritory()->addEffectResult( std::move( result ) );
|
m_sourceChara->getCurrentTerritory()->addEffectResult( std::move( result ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
resultList->clear();
|
actorResultList.clear();
|
||||||
|
it = m_actorEffectsMap.erase( it );
|
||||||
|
}
|
||||||
|
|
||||||
m_resolvedEffects.clear();
|
m_actorEffectsMap.clear();
|
||||||
|
|
||||||
return effectPacket;
|
return effectPacket;
|
||||||
}
|
}
|
||||||
|
@ -202,6 +212,8 @@ std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( uint32_
|
||||||
effectPacket->data().RequestId = m_sequence;
|
effectPacket->data().RequestId = m_sequence;
|
||||||
effectPacket->data().ResultId = globalSequence;
|
effectPacket->data().ResultId = globalSequence;
|
||||||
|
|
||||||
|
m_actorEffectsMap.clear();
|
||||||
|
|
||||||
return effectPacket;
|
return effectPacket;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -29,22 +29,21 @@ namespace Sapphire::World::Action
|
||||||
|
|
||||||
void mount( Entity::CharaPtr& target, uint16_t mountId );
|
void mount( Entity::CharaPtr& target, uint16_t mountId );
|
||||||
|
|
||||||
void buildAndSendPackets();
|
void buildAndSendPackets( const std::vector< Entity::CharaPtr >& targetList );
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void moveToResultList( Entity::CharaPtr& chara, EffectResultPtr result );
|
void addResultToActor( Entity::CharaPtr& chara, EffectResultPtr result );
|
||||||
|
|
||||||
uint64_t getResultDelayMs();
|
uint64_t getResultDelayMs();
|
||||||
|
|
||||||
std::shared_ptr< Sapphire::Network::Packets::FFXIVPacketBase > buildNextEffectPacket( uint32_t globalSequence );
|
std::shared_ptr< Sapphire::Network::Packets::FFXIVPacketBase > buildNextEffectPacket( const std::vector< Entity::CharaPtr >& targetList );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t m_actionId;
|
uint32_t m_actionId;
|
||||||
uint16_t m_sequence;
|
uint16_t m_sequence;
|
||||||
|
|
||||||
Entity::CharaPtr m_sourceChara;
|
Entity::CharaPtr m_sourceChara;
|
||||||
std::unordered_map< uint32_t, std::shared_ptr< std::vector< EffectResultPtr > > > m_resolvedEffects;
|
std::unordered_map< uint32_t, std::vector< EffectResultPtr > > m_actorEffectsMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -65,11 +65,11 @@ void ItemAction::handleVFXItem()
|
||||||
effect.Type = Common::ActionEffectType::CALC_RESULT_TYPE_CHECK_BARRIER;
|
effect.Type = Common::ActionEffectType::CALC_RESULT_TYPE_CHECK_BARRIER;
|
||||||
effect.Value = m_itemAction->data().Calcu0Arg[ 0 ];
|
effect.Value = m_itemAction->data().Calcu0Arg[ 0 ];
|
||||||
|
|
||||||
auto effectPacket = std::make_shared< EffectPacket >( getSourceChara()->getId(), getSourceChara()->getId(), getId() );
|
auto effectPacket = std::make_shared< EffectPacket >( getSourceChara()->getId(), getId() );
|
||||||
effectPacket->setTargetActor( getSourceChara()->getId() );
|
effectPacket->setTargetActor( getSourceChara()->getId() );
|
||||||
effectPacket->setAnimationId( Common::ItemActionType::ItemActionVFX );
|
effectPacket->setAnimationId( Common::ItemActionType::ItemActionVFX );
|
||||||
effectPacket->setDisplayType( Common::ActionEffectDisplayType::ShowItemName );
|
effectPacket->setDisplayType( Common::ActionEffectDisplayType::ShowItemName );
|
||||||
effectPacket->addEffect( effect, static_cast< uint64_t >( getSourceChara()->getId() ) );
|
effectPacket->addTargetEffect( effect, static_cast< uint64_t >( getSourceChara()->getId() ) );
|
||||||
|
|
||||||
m_pSource->sendToInRangeSet( effectPacket, true );
|
m_pSource->sendToInRangeSet( effectPacket, true );
|
||||||
}
|
}
|
|
@ -74,5 +74,5 @@ void MountAction::execute()
|
||||||
|
|
||||||
m_pSource->getAsPlayer()->unsetStateFlag( Common::PlayerStateFlag::Casting );
|
m_pSource->getAsPlayer()->unsetStateFlag( Common::PlayerStateFlag::Casting );
|
||||||
m_effectBuilder->mount( m_pSource, m_mountId );
|
m_effectBuilder->mount( m_pSource, m_mountId );
|
||||||
m_effectBuilder->buildAndSendPackets();
|
m_effectBuilder->buildAndSendPackets( { m_pSource } );
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@
|
||||||
#include "Network/PacketWrappers/ActorControlSelfPacket.h"
|
#include "Network/PacketWrappers/ActorControlSelfPacket.h"
|
||||||
#include "Network/PacketWrappers/ActorControlTargetPacket.h"
|
#include "Network/PacketWrappers/ActorControlTargetPacket.h"
|
||||||
#include "Network/PacketWrappers/UpdateHpMpTpPacket.h"
|
#include "Network/PacketWrappers/UpdateHpMpTpPacket.h"
|
||||||
#include "Network/PacketWrappers/EffectPacket.h"
|
#include "Network/PacketWrappers/EffectPacket1.h"
|
||||||
|
|
||||||
#include "StatusEffect/StatusEffect.h"
|
#include "StatusEffect/StatusEffect.h"
|
||||||
#include "Action/Action.h"
|
#include "Action/Action.h"
|
||||||
|
@ -483,7 +483,6 @@ Will have to be extended for ranged attacks.
|
||||||
*/
|
*/
|
||||||
void Sapphire::Entity::Chara::autoAttack( CharaPtr pTarget )
|
void Sapphire::Entity::Chara::autoAttack( CharaPtr pTarget )
|
||||||
{
|
{
|
||||||
|
|
||||||
uint64_t tick = Util::getTimeMs();
|
uint64_t tick = Util::getTimeMs();
|
||||||
|
|
||||||
// todo: this needs to use the auto attack delay for the equipped weapon
|
// todo: this needs to use the auto attack delay for the equipped weapon
|
||||||
|
@ -495,19 +494,19 @@ void Sapphire::Entity::Chara::autoAttack( CharaPtr pTarget )
|
||||||
|
|
||||||
auto damage = static_cast< uint16_t >( 10 + rand() % 12 );
|
auto damage = static_cast< uint16_t >( 10 + rand() % 12 );
|
||||||
|
|
||||||
auto effectPacket = std::make_shared< EffectPacket >( getId(), pTarget->getId(), 7 );
|
auto effectPacket = std::make_shared< EffectPacket1 >( getId(), pTarget->getId(), 7 );
|
||||||
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
|
effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) );
|
||||||
|
|
||||||
Common::CalcResultParam effectEntry{};
|
Common::CalcResultParam effectEntry{};
|
||||||
effectEntry.Value = static_cast< int16_t >( damage );
|
effectEntry.Value = static_cast< int16_t >( damage );
|
||||||
effectEntry.Type = ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP;
|
effectEntry.Type = ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP;
|
||||||
effectEntry.Arg0 = static_cast< uint8_t >( ActionHitSeverityType::NormalDamage );
|
effectEntry.Arg0 = static_cast< uint8_t >( ActionHitSeverityType::NormalDamage );
|
||||||
effectEntry.Arg2 = 0x71;
|
effectEntry.Arg2 = 0x71;
|
||||||
effectPacket->addEffect( effectEntry, static_cast< uint64_t >( pTarget->getId() ) );
|
effectPacket->addTargetEffect( effectEntry );
|
||||||
|
|
||||||
sendToInRangeSet( effectPacket );
|
sendToInRangeSet( effectPacket );
|
||||||
|
|
||||||
pTarget->takeDamage( damage );
|
pTarget->takeDamage( damage );
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -492,15 +492,16 @@ void Sapphire::World::Manager::DebugCommandMgr::add( char* data, Entity::Player&
|
||||||
uint16_t param1;
|
uint16_t param1;
|
||||||
sscanf( params.c_str(), "%hu", ¶m1 );
|
sscanf( params.c_str(), "%hu", ¶m1 );
|
||||||
|
|
||||||
auto effectPacket = std::make_shared< EffectPacket >( player.getId(), player.getTargetId(), param1 );
|
auto effectPacket = std::make_shared< EffectPacket >( player.getId(), param1 );
|
||||||
effectPacket->setRotation( Common::Util::floatToUInt16Rot( player.getRot() ) );
|
effectPacket->setRotation( Common::Util::floatToUInt16Rot( player.getRot() ) );
|
||||||
|
effectPacket->setTargetActor( player.getTargetId() );
|
||||||
|
|
||||||
Common::CalcResultParam entry{};
|
Common::CalcResultParam entry{};
|
||||||
entry.Value = static_cast< int16_t >( param1 );
|
entry.Value = static_cast< int16_t >( param1 );
|
||||||
entry.Type = Common::ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP;
|
entry.Type = Common::ActionEffectType::CALC_RESULT_TYPE_DAMAGE_HP;
|
||||||
entry.Arg0 = static_cast< uint8_t >( Common::ActionHitSeverityType::NormalDamage );
|
entry.Arg0 = static_cast< uint8_t >( Common::ActionHitSeverityType::NormalDamage );
|
||||||
|
|
||||||
effectPacket->addEffect( entry, static_cast< uint64_t >( player.getId() ) );
|
effectPacket->addTargetEffect( entry, static_cast< uint64_t >( player.getId() ) );
|
||||||
|
|
||||||
auto sequence = player.getCurrentTerritory()->getNextEffectSequence();
|
auto sequence = player.getCurrentTerritory()->getNextEffectSequence();
|
||||||
effectPacket->setSequence( sequence );
|
effectPacket->setSequence( sequence );
|
||||||
|
|
|
@ -14,31 +14,51 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
|
||||||
class EffectPacket : public ZoneChannelPacket< FFXIVIpcActionResult >
|
class EffectPacket : public ZoneChannelPacket< FFXIVIpcActionResult >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EffectPacket( uint64_t sourceId, uint32_t targetId, uint32_t actionId ) :
|
EffectPacket( uint64_t sourceId, uint32_t actionId ) :
|
||||||
ZoneChannelPacket< FFXIVIpcActionResult >( static_cast< uint32_t >( sourceId ), targetId )
|
ZoneChannelPacket< FFXIVIpcActionResult >( static_cast< uint32_t >( sourceId ) )
|
||||||
{
|
{
|
||||||
m_data.Flag = 0;
|
m_data.Flag = 0;
|
||||||
m_data.ActionKey = actionId;
|
m_data.ActionKey = actionId;
|
||||||
m_data.Action = static_cast< uint16_t >( actionId );
|
m_data.Action = static_cast< uint16_t >( actionId );
|
||||||
m_data.ActionKind = 1;
|
m_data.ActionKind = 1;
|
||||||
|
|
||||||
m_data.LockTime = 0.6f;
|
m_data.MainTarget = Common::INVALID_GAME_OBJECT_ID;
|
||||||
m_data.MainTarget = static_cast< uint64_t >( targetId );
|
m_data.BallistaEntityId = Common::INVALID_GAME_OBJECT_ID;
|
||||||
|
|
||||||
m_data.ActionArg = Common::ActionEffectDisplayType::ShowActionName;
|
m_data.LockTime = 0.6f;
|
||||||
|
|
||||||
|
m_data.TargetCount = 0;
|
||||||
|
|
||||||
std::memset( m_data.CalcResult, 0, sizeof( Common::CalcResult ) * 16 );
|
std::memset( m_data.CalcResult, 0, sizeof( Common::CalcResult ) * 16 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void addEffect( const Common::CalcResultParam& effect, uint64_t targetId = Common::INVALID_GAME_OBJECT_ID64 )
|
void addTargetEffect( const Common::CalcResultParam& effect, uint64_t targetId = Common::INVALID_GAME_OBJECT_ID64 )
|
||||||
{
|
{
|
||||||
assert( m_data.TargetCount <= 15 );
|
std::memcpy( &m_data.CalcResult[ m_data.TargetCount ].CalcResultTg[ m_targetEffectCount++ ], &effect, sizeof( Common::CalcResultParam ) );
|
||||||
|
|
||||||
|
// iterate and see if we already have this target added
|
||||||
|
bool targetAlreadyAdded = false;
|
||||||
|
for( int i = 0; i < sizeof( m_data.Target ) / sizeof( uint64_t ); ++i )
|
||||||
|
{
|
||||||
|
if( m_data.Target[ i ] == targetId )
|
||||||
|
{
|
||||||
|
targetAlreadyAdded = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::memcpy( &m_data.CalcResult[ m_data.TargetCount ].CalcResultTg, &effect, sizeof( Common::CalcResultParam ) );
|
|
||||||
m_data.Target[ m_data.TargetCount ] = targetId;
|
m_data.Target[ m_data.TargetCount ] = targetId;
|
||||||
|
|
||||||
|
if( !targetAlreadyAdded )
|
||||||
m_data.TargetCount++;
|
m_data.TargetCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addSourceEffect( const Common::CalcResultParam& effect )
|
||||||
|
{
|
||||||
|
// we associate the source effect with the current target index set
|
||||||
|
std::memcpy( &m_data.CalcResult[ m_data.TargetCount - 1 ].CalcResultCt[ m_sourceEffectCount++ ], &effect, sizeof( Common::CalcResultParam ) );
|
||||||
|
}
|
||||||
|
|
||||||
void setAnimationId( uint16_t animationId )
|
void setAnimationId( uint16_t animationId )
|
||||||
{
|
{
|
||||||
m_data.Action = animationId;
|
m_data.Action = animationId;
|
||||||
|
@ -71,6 +91,9 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
|
||||||
m_data.RequestId = static_cast< uint32_t >( sourceSequence );
|
m_data.RequestId = static_cast< uint32_t >( sourceSequence );
|
||||||
m_data.ResultId = static_cast< uint32_t>( sequence );
|
m_data.ResultId = static_cast< uint32_t>( sequence );
|
||||||
}
|
}
|
||||||
|
private:
|
||||||
|
uint8_t m_targetEffectCount{ 0 };
|
||||||
|
uint8_t m_sourceEffectCount{ 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,6 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
|
||||||
|
|
||||||
class EffectPacket1 : public ZoneChannelPacket< FFXIVIpcActionResult1 >
|
class EffectPacket1 : public ZoneChannelPacket< FFXIVIpcActionResult1 >
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
uint8_t m_targetEffectCount{0};
|
|
||||||
uint8_t m_sourceEffectCount{0};
|
|
||||||
public:
|
public:
|
||||||
EffectPacket1( uint64_t sourceId, uint32_t targetId, uint32_t actionId ) :
|
EffectPacket1( uint64_t sourceId, uint32_t targetId, uint32_t actionId ) :
|
||||||
ZoneChannelPacket< FFXIVIpcActionResult1 >( static_cast< uint32_t >( sourceId ), targetId )
|
ZoneChannelPacket< FFXIVIpcActionResult1 >( static_cast< uint32_t >( sourceId ), targetId )
|
||||||
|
@ -76,6 +73,10 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
|
||||||
m_data.RequestId = static_cast< uint32_t >( sourceSequence );
|
m_data.RequestId = static_cast< uint32_t >( sourceSequence );
|
||||||
m_data.ResultId = static_cast< uint32_t>( sequence );
|
m_data.ResultId = static_cast< uint32_t>( sequence );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t m_targetEffectCount{ 0 };
|
||||||
|
uint8_t m_sourceEffectCount{ 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue