From 03df9ab4d558a3196fc8857d67cf5911dff43958 Mon Sep 17 00:00:00 2001 From: collett Date: Sat, 4 Jan 2020 21:12:54 +0900 Subject: [PATCH] some aoe fixes --- src/world/Action/Action.cpp | 63 +++++++++++++++++++++++---------- src/world/Action/Action.h | 5 +++ src/world/Manager/ActionMgr.cpp | 6 ++-- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index 698cc043..a5e15b88 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -1,5 +1,4 @@ #include "Action.h" -#include "ActionLut.h" #include "EffectBuilder.h" #include @@ -127,6 +126,15 @@ bool Action::Action::init() // todo: add missing rows for secondaryCostType/secondaryCostType and rename the current rows to primaryCostX + if( ActionLut::validEntryExists( static_cast< uint16_t >( getId() ) ) ) + { + m_lutEntry = ActionLut::getEntry( static_cast< uint16_t >( getId() ) ); + } + else + { + std::memset( &m_lutEntry, 0, sizeof( ActionEntry ) ); + } + addDefaultActorFilters(); return true; @@ -235,7 +243,7 @@ bool Action::Action::update() if( !m_pTarget->isAlive() ) { // interrupt the cast if target died - setInterrupted( Common::ActionInterruptType::RegularInterrupt ); + setInterrupted( Common::ActionInterruptType::RegularInterrupt ); interrupt(); return true; } @@ -428,7 +436,7 @@ void Action::Action::buildEffects() snapshotAffectedActors( m_hitActors ); auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >(); - auto hasLutEntry = ActionLut::validEntryExists( static_cast< uint16_t >( getId() ) ); + auto hasLutEntry = hasValidLutEntry(); if( !pScriptMgr->onExecute( *this ) && !hasLutEntry ) { @@ -443,21 +451,19 @@ void Action::Action::buildEffects() if( !hasLutEntry || m_hitActors.empty() ) return; - auto lutEntry = ActionLut::getEntry( static_cast< uint16_t >( getId() ) ); - // no script exists but we have a valid lut entry if( auto player = getSourceChara()->getAsPlayer() ) { player->sendDebug( "Hit target: pot: {} (c: {}, f: {}, r: {}), heal pot: {}, mpp: {}", - lutEntry.potency, lutEntry.comboPotency, lutEntry.flankPotency, lutEntry.rearPotency, - lutEntry.curePotency, lutEntry.restoreMPPercentage ); + m_lutEntry.potency, m_lutEntry.comboPotency, m_lutEntry.flankPotency, m_lutEntry.rearPotency, + m_lutEntry.curePotency, m_lutEntry.restoreMPPercentage ); } for( auto& actor : m_hitActors ) { - if( lutEntry.potency > 0 ) + if( m_lutEntry.potency > 0 ) { - auto dmg = calcDamage( isCorrectCombo() ? lutEntry.comboPotency : lutEntry.potency ); + auto dmg = calcDamage( isCorrectCombo() ? m_lutEntry.comboPotency : m_lutEntry.potency ); m_effectBuilder->damageTarget( actor, dmg.first, dmg.second ); if( dmg.first > 0 ) @@ -470,18 +476,18 @@ void Action::Action::buildEffects() if( !isComboAction() || isCorrectCombo() ) { - if( lutEntry.curePotency > 0 ) // actions with self heal + if( m_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 ); + m_effectBuilder->selfHeal( actor, m_pSource, m_lutEntry.curePotency ); } - if( lutEntry.restoreMPPercentage > 0 ) + if( m_lutEntry.restoreMPPercentage > 0 ) { - m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMp() * lutEntry.restoreMPPercentage / 100 ); + m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMp() * m_lutEntry.restoreMPPercentage / 100 ); } if( !m_actionData->preservesCombo ) // we need something like m_actionData->hasNextComboAction @@ -490,20 +496,20 @@ void Action::Action::buildEffects() } } } - else if( lutEntry.curePotency > 0 ) + else if( m_lutEntry.curePotency > 0 ) { // todo: calcHealing() - m_effectBuilder->healTarget( actor, lutEntry.curePotency ); + m_effectBuilder->healTarget( actor, m_lutEntry.curePotency ); - if( lutEntry.restoreMPPercentage > 0 ) + if( m_lutEntry.restoreMPPercentage > 0 ) { // always restore caster mp I don't think there are any actions that can restore target MP post 5.0 - m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMp() * lutEntry.restoreMPPercentage / 100 ); + m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMp() * m_lutEntry.restoreMPPercentage / 100 ); } } - else if( lutEntry.restoreMPPercentage > 0 ) + else if( m_lutEntry.restoreMPPercentage > 0 ) { - m_effectBuilder->restoreMP( m_pSource, m_pSource, m_pSource->getMp() * lutEntry.restoreMPPercentage / 100 ); + m_effectBuilder->restoreMP( m_pSource, m_pSource, m_pSource->getMp() * m_lutEntry.restoreMPPercentage / 100 ); } } @@ -737,11 +743,24 @@ void Action::Action::addDefaultActorFilters() bool Action::Action::preFilterActor( Sapphire::Entity::Actor& actor ) const { auto kind = actor.getObjKind(); + auto chara = actor.getAsChara(); // todo: are there any server side eobjs that players can hit? if( kind != ObjKind::BattleNpc && kind != ObjKind::Player ) return false; + if( m_lutEntry.potency > 0 && chara == m_pSource ) + { + // damage action shouldn't hit self + return false; + } + + if ( ( m_lutEntry.potency > 0 || m_lutEntry.curePotency > 0 ) && !chara->isAlive() ) + { + // can't deal damage or heal a dead entity + return false; + } + // todo: handle things such based on canTargetX return true; @@ -760,4 +779,10 @@ Sapphire::Entity::CharaPtr Action::Action::getHitChara() } return nullptr; +} + +bool Action::Action::hasValidLutEntry() const +{ + return m_lutEntry.potency != 0 || m_lutEntry.comboPotency != 0 || m_lutEntry.flankPotency != 0 || m_lutEntry.frontPotency != 0 || + m_lutEntry.rearPotency != 0 || m_lutEntry.curePotency != 0 || m_lutEntry.restoreMPPercentage != 0; } \ No newline at end of file diff --git a/src/world/Action/Action.h b/src/world/Action/Action.h index 60c5ffeb..b85f5f03 100644 --- a/src/world/Action/Action.h +++ b/src/world/Action/Action.h @@ -2,6 +2,7 @@ #define _ACTION_H_ #include +#include "ActionLut.h" #include "Util/ActorFilter.h" #include "ForwardsZone.h" @@ -146,6 +147,8 @@ namespace Sapphire::World::Action bool preFilterActor( Entity::Actor& actor ) const; + bool hasValidLutEntry() const; + uint32_t m_id; uint16_t m_sequence; @@ -186,6 +189,8 @@ namespace Sapphire::World::Action std::vector< World::Util::ActorFilterPtr > m_actorFilters; std::vector< Entity::CharaPtr > m_hitActors; + + ActionEntry m_lutEntry; }; } diff --git a/src/world/Manager/ActionMgr.cpp b/src/world/Manager/ActionMgr.cpp index ba2be044..2356d7b3 100644 --- a/src/world/Manager/ActionMgr.cpp +++ b/src/world/Manager/ActionMgr.cpp @@ -27,6 +27,8 @@ void World::Manager::ActionMgr::handlePlacedPlayerAction( Entity::Player& player auto action = Action::make_Action( player.getAsPlayer(), actionId, sequence, actionData, framework() ); + action->setPos( pos ); + if( !action->init() ) return; @@ -37,8 +39,6 @@ void World::Manager::ActionMgr::handlePlacedPlayerAction( Entity::Player& player return; } - action->setPos( pos ); - bootstrapAction( player, action, *actionData ); } @@ -50,6 +50,8 @@ void World::Manager::ActionMgr::handleTargetedPlayerAction( Entity::Player& play action->setTargetId( targetId ); + action->setPos( player.getPos() ); + if( !action->init() ) return;