mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-28 20:27:46 +00:00
Attempt to fix combo actions.
This commit is contained in:
parent
f6bff46c9a
commit
56296d295a
8 changed files with 132 additions and 36 deletions
|
@ -629,6 +629,7 @@ namespace Sapphire::Common
|
|||
* @param value The actionid that starts/continues the combo. eg, 3617 will start a spinning slash and/or syphon strike combo
|
||||
*/
|
||||
StartActionCombo = 28,
|
||||
ComboVisualEffect = 29,
|
||||
Knockback = 33,
|
||||
Mount = 38,
|
||||
VFX = 59, // links to VFX sheet
|
||||
|
|
|
@ -336,7 +336,7 @@ void Action::Action::execute()
|
|||
}
|
||||
}
|
||||
|
||||
if( isComboAction() )
|
||||
if( isCorrectCombo() )
|
||||
{
|
||||
auto player = m_pSource->getAsPlayer();
|
||||
|
||||
|
@ -354,7 +354,7 @@ void Action::Action::execute()
|
|||
|
||||
// set currently casted action as the combo action if it interrupts a combo
|
||||
// ignore it otherwise (ogcds, etc.)
|
||||
if( !m_actionData->preservesCombo )
|
||||
if( !m_actionData->preservesCombo && ( !isComboAction() || isCorrectCombo() ) )
|
||||
{
|
||||
m_pSource->setLastComboActionId( getId() );
|
||||
}
|
||||
|
@ -418,19 +418,40 @@ void Action::Action::buildEffects()
|
|||
|
||||
for( auto& actor : m_hitActors )
|
||||
{
|
||||
// todo: this is shit
|
||||
if( lutEntry.curePotency > 0 )
|
||||
if( lutEntry.potency > 0 )
|
||||
{
|
||||
|
||||
m_effectBuilder->healTarget( actor, lutEntry.curePotency );
|
||||
}
|
||||
|
||||
else if( lutEntry.potency > 0 )
|
||||
{
|
||||
auto dmg = calcDamage( lutEntry.potency );
|
||||
auto dmg = calcDamage( isCorrectCombo() ? lutEntry.comboPotency : lutEntry.potency );
|
||||
m_effectBuilder->damageTarget( actor, dmg.first, dmg.second );
|
||||
|
||||
if ( dmg.first > 0 )
|
||||
actor->onActionHostile( m_pSource );
|
||||
|
||||
if ( isCorrectCombo() )
|
||||
{
|
||||
m_effectBuilder->comboVisualEffect( actor );
|
||||
}
|
||||
|
||||
if ( !isComboAction() || isCorrectCombo() )
|
||||
{
|
||||
if( lutEntry.curePotency > 0 ) // actions with self heal
|
||||
{
|
||||
/*
|
||||
Calling m_effectBuilder->healTarget( m_pSource, lutEntry.curePotency ) seems to work fine,
|
||||
but it will end up sending two Effect packets to the client. However on retail everything is in one single packet.
|
||||
*/
|
||||
m_effectBuilder->selfHeal( actor, m_pSource, lutEntry.curePotency );
|
||||
}
|
||||
|
||||
if ( !m_actionData->preservesCombo ) // we need something like m_actionData->hasNextComboAction
|
||||
{
|
||||
m_effectBuilder->startCombo( actor, getId() );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( lutEntry.curePotency > 0 )
|
||||
{
|
||||
// todo: calcHealing()
|
||||
m_effectBuilder->healTarget( actor, lutEntry.curePotency );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -513,7 +534,7 @@ void Action::Action::setAdditionalData( uint32_t data )
|
|||
m_additionalData = data;
|
||||
}
|
||||
|
||||
bool Action::Action::isComboAction() const
|
||||
bool Action::Action::isCorrectCombo() const
|
||||
{
|
||||
auto lastActionId = m_pSource->getLastComboActionId();
|
||||
|
||||
|
@ -525,6 +546,11 @@ bool Action::Action::isComboAction() const
|
|||
return m_actionData->actionCombo == lastActionId;
|
||||
}
|
||||
|
||||
bool Action::Action::isComboAction() const
|
||||
{
|
||||
return m_actionData->actionCombo != 0;
|
||||
}
|
||||
|
||||
bool Action::Action::primaryCostCheck( bool subtractCosts )
|
||||
{
|
||||
switch( m_primaryCostType )
|
||||
|
|
|
@ -45,6 +45,8 @@ namespace Sapphire::World::Action
|
|||
uint32_t getAdditionalData() const;
|
||||
void setAdditionalData( uint32_t data );
|
||||
|
||||
bool isCorrectCombo() const;
|
||||
|
||||
bool isComboAction() const;
|
||||
|
||||
/*!
|
||||
|
|
|
@ -31,18 +31,17 @@ uint64_t EffectBuilder::getResultDelayMs()
|
|||
return Common::Util::getTimeMs() + 850;
|
||||
}
|
||||
|
||||
EffectResultPtr EffectBuilder::getResult( Entity::CharaPtr& chara )
|
||||
std::shared_ptr< std::vector< EffectResultPtr > > EffectBuilder::getResultList( Entity::CharaPtr& chara )
|
||||
{
|
||||
auto it = m_resolvedEffects.find( chara->getId() );
|
||||
if( it == m_resolvedEffects.end() )
|
||||
{
|
||||
// create a new one and return it
|
||||
// todo: this feels kinda dirty but makes for easy work
|
||||
auto result = make_EffectResult( chara, getResultDelayMs() );
|
||||
auto resultList = std::make_shared< std::vector< EffectResultPtr > >();
|
||||
|
||||
m_resolvedEffects[ chara->getId() ] = result;
|
||||
m_resolvedEffects[ chara->getId() ] = resultList;
|
||||
|
||||
return result;
|
||||
return resultList;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
|
@ -50,18 +49,52 @@ EffectResultPtr EffectBuilder::getResult( Entity::CharaPtr& chara )
|
|||
|
||||
void EffectBuilder::healTarget( Entity::CharaPtr& target, uint32_t amount, Common::ActionHitSeverityType severity )
|
||||
{
|
||||
auto result = getResult( target );
|
||||
assert( result );
|
||||
auto resultList = getResultList( target );
|
||||
assert( resultList );
|
||||
|
||||
result->heal( amount, severity );
|
||||
EffectResultPtr nextResult = make_EffectResult( target, getResultDelayMs() );
|
||||
nextResult->heal( amount, severity, false );
|
||||
resultList->push_back( std::move( nextResult ) );
|
||||
}
|
||||
|
||||
void EffectBuilder::selfHeal( Entity::CharaPtr& target, Entity::CharaPtr& source, uint32_t amount, Common::ActionHitSeverityType severity )
|
||||
{
|
||||
auto resultList = getResultList( target );
|
||||
assert( resultList );
|
||||
|
||||
EffectResultPtr nextResult = make_EffectResult( source, getResultDelayMs() ); // heal the source actor
|
||||
nextResult->heal( amount, severity, true );
|
||||
resultList->push_back( std::move( nextResult ) );
|
||||
}
|
||||
|
||||
void EffectBuilder::damageTarget( Entity::CharaPtr& target, uint32_t amount, Common::ActionHitSeverityType severity )
|
||||
{
|
||||
auto result = getResult( target );
|
||||
assert( result );
|
||||
auto resultList = getResultList( target );
|
||||
assert( resultList );
|
||||
|
||||
result->damage( amount, severity );
|
||||
EffectResultPtr nextResult = make_EffectResult( target, getResultDelayMs() );
|
||||
nextResult->damage( amount, severity );
|
||||
resultList->push_back( std::move( nextResult ) );
|
||||
}
|
||||
|
||||
void EffectBuilder::startCombo( Entity::CharaPtr& target, uint16_t actionId )
|
||||
{
|
||||
auto resultList = getResultList( target );
|
||||
assert( resultList );
|
||||
|
||||
EffectResultPtr nextResult = make_EffectResult( target, 0 );
|
||||
nextResult->startCombo( actionId );
|
||||
resultList->push_back( std::move( nextResult ) );
|
||||
}
|
||||
|
||||
void EffectBuilder::comboVisualEffect( Entity::CharaPtr& target )
|
||||
{
|
||||
auto resultList = getResultList( target );
|
||||
assert( resultList );
|
||||
|
||||
EffectResultPtr nextResult = make_EffectResult( target, 0 );
|
||||
nextResult->comboVisualEffect();
|
||||
resultList->push_back( std::move( nextResult ) );
|
||||
}
|
||||
|
||||
void EffectBuilder::buildAndSendPackets()
|
||||
|
@ -71,22 +104,29 @@ void EffectBuilder::buildAndSendPackets()
|
|||
|
||||
for( auto it = m_resolvedEffects.begin(); it != m_resolvedEffects.end(); )
|
||||
{
|
||||
auto result = it->second;
|
||||
Logger::debug( " - id: {}", result->getTarget()->getId() );
|
||||
auto resultList = it->second;
|
||||
assert( resultList->size() > 0 );
|
||||
auto firstResult = resultList->data()[ 0 ];
|
||||
Logger::debug( " - id: {}", firstResult->getTarget()->getId() );
|
||||
|
||||
auto seq = m_sourceChara->getCurrentTerritory()->getNextEffectSequence();
|
||||
|
||||
auto effectPacket = std::make_shared< Server::EffectPacket >( m_sourceChara->getId(), result->getTarget()->getId(), m_actionId );
|
||||
auto effectPacket = std::make_shared< Server::EffectPacket >( m_sourceChara->getId(), firstResult->getTarget()->getId(), m_actionId );
|
||||
effectPacket->setRotation( Common::Util::floatToUInt16Rot( m_sourceChara->getRot() ) );
|
||||
effectPacket->setSequence( seq, m_sequence );
|
||||
|
||||
effectPacket->addEffect( result->buildEffectEntry() );
|
||||
for( int i = 0; i < resultList->size(); i++ )
|
||||
{
|
||||
auto result = resultList->data()[ i ];
|
||||
effectPacket->addEffect( result->buildEffectEntry() );
|
||||
// add effect to territory
|
||||
m_sourceChara->getCurrentTerritory()->addEffectResult( std::move( result ) );
|
||||
}
|
||||
|
||||
resultList->clear();
|
||||
|
||||
m_sourceChara->sendToInRangeSet( effectPacket, true );
|
||||
|
||||
// add effect to territory
|
||||
m_sourceChara->getCurrentTerritory()->addEffectResult( std::move( result ) );
|
||||
|
||||
it = m_resolvedEffects.erase( it );
|
||||
}
|
||||
}
|
|
@ -15,14 +15,21 @@ namespace Sapphire::World::Action
|
|||
void healTarget( Entity::CharaPtr& target, uint32_t amount,
|
||||
Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalHeal );
|
||||
|
||||
void selfHeal( Entity::CharaPtr& target, Entity::CharaPtr& source, uint32_t amount,
|
||||
Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalHeal );
|
||||
|
||||
void damageTarget( Entity::CharaPtr& target, uint32_t amount,
|
||||
Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalDamage );
|
||||
|
||||
void startCombo( Entity::CharaPtr& target, uint16_t actionId );
|
||||
|
||||
void comboVisualEffect( Entity::CharaPtr& target );
|
||||
|
||||
void buildAndSendPackets();
|
||||
|
||||
|
||||
private:
|
||||
EffectResultPtr getResult( Entity::CharaPtr& chara );
|
||||
std::shared_ptr< std::vector< EffectResultPtr > > getResultList( Entity::CharaPtr& chara );
|
||||
|
||||
uint64_t getResultDelayMs();
|
||||
|
||||
|
@ -31,7 +38,7 @@ namespace Sapphire::World::Action
|
|||
uint16_t m_sequence;
|
||||
|
||||
Entity::CharaPtr m_sourceChara;
|
||||
std::unordered_map< uint32_t, EffectResultPtr > m_resolvedEffects;
|
||||
std::unordered_map< uint32_t, std::shared_ptr< std::vector< EffectResultPtr > > > m_resolvedEffects;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@ EffectResult::EffectResult( Entity::CharaPtr target, uint64_t runAfter ) :
|
|||
m_value( 0 ),
|
||||
m_severity( Common::ActionHitSeverityType::NormalDamage ),
|
||||
m_type( Common::ActionEffectType::Nothing ),
|
||||
m_param( 0 )
|
||||
m_param( 0 ),
|
||||
m_flag( 0 )
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -47,14 +48,28 @@ void EffectResult::damage( uint32_t amount, Common::ActionHitSeverityType severi
|
|||
m_type = Common::ActionEffectType::Damage;
|
||||
}
|
||||
|
||||
void EffectResult::heal( uint32_t amount, Sapphire::Common::ActionHitSeverityType severity )
|
||||
void EffectResult::heal( uint32_t amount, Sapphire::Common::ActionHitSeverityType severity, bool isSelfHeal )
|
||||
{
|
||||
m_severity = severity;
|
||||
m_value = amount;
|
||||
m_flag = isSelfHeal ? 0x80 : 0; // flag == 0x80 displays healing text at source actor
|
||||
|
||||
m_type = Common::ActionEffectType::Heal;
|
||||
}
|
||||
|
||||
void EffectResult::startCombo( uint16_t actionId )
|
||||
{
|
||||
m_value = actionId;
|
||||
m_flag = 0x80;
|
||||
|
||||
m_type = Common::ActionEffectType::StartActionCombo;
|
||||
}
|
||||
|
||||
void EffectResult::comboVisualEffect()
|
||||
{
|
||||
m_type = Common::ActionEffectType::ComboVisualEffect;
|
||||
}
|
||||
|
||||
Common::EffectEntry EffectResult::buildEffectEntry() const
|
||||
{
|
||||
Common::EffectEntry entry{};
|
||||
|
@ -64,6 +79,7 @@ Common::EffectEntry EffectResult::buildEffectEntry() const
|
|||
entry.hitSeverity = m_severity;
|
||||
entry.effectType = m_type;
|
||||
entry.param = m_param;
|
||||
entry.flags = m_flag;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,9 @@ namespace Sapphire::World::Action
|
|||
explicit EffectResult( Entity::CharaPtr target, uint64_t delayMs );
|
||||
|
||||
void damage( uint32_t amount, Common::ActionHitSeverityType severity );
|
||||
void heal( uint32_t amount, Common::ActionHitSeverityType severity );
|
||||
void heal( uint32_t amount, Common::ActionHitSeverityType severity, bool isSelfHeal );
|
||||
void startCombo( uint16_t actionId );
|
||||
void comboVisualEffect();
|
||||
|
||||
Entity::CharaPtr getTarget() const;
|
||||
|
||||
|
@ -40,6 +42,7 @@ namespace Sapphire::World::Action
|
|||
|
||||
uint32_t m_value;
|
||||
uint8_t m_param;
|
||||
uint8_t m_flag;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -25,13 +25,14 @@ namespace Sapphire::Network::Packets::Server
|
|||
m_data.effectTargetId = targetId;
|
||||
|
||||
m_data.effectDisplayType = Common::ActionEffectDisplayType::ShowActionName;
|
||||
|
||||
std::memset(m_data.effects, 0, sizeof(Common::EffectEntry) * 8);
|
||||
}
|
||||
|
||||
void addEffect( const Common::EffectEntry& effect )
|
||||
{
|
||||
assert( m_data.effectCount <= 8 );
|
||||
|
||||
std::memset( m_data.effects, 0, sizeof( Common::EffectEntry ) * 8 );
|
||||
std::memcpy( &m_data.effects[ m_data.effectCount * 8 ], &effect, sizeof( Common::EffectEntry ) );
|
||||
m_data.effectCount++;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue