diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index c0c7f8ee..48c49a10 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -419,6 +419,7 @@ void Sapphire::Action::Action::calculateActionCost() } } +// todo: this shouldn't be in action and instead be in some general stat calc util void Sapphire::Action::Action::calculateMPCost( uint8_t costArrayIndex ) { auto level = m_pSource->getLevel(); diff --git a/src/world/Action/EventAction.cpp b/src/world/Action/EventAction.cpp new file mode 100644 index 00000000..84be1368 --- /dev/null +++ b/src/world/Action/EventAction.cpp @@ -0,0 +1,129 @@ +#include +#include +#include +#include + +#include "Network/PacketWrappers/ActorControlPacket142.h" +#include "Network/PacketWrappers/ActorControlPacket143.h" + +#include "Actor/Player.h" + +#include "EventAction.h" +#include "Framework.h" + +using namespace Sapphire::Common; +using namespace Sapphire::Network; +using namespace Sapphire::Network::Packets; +using namespace Sapphire::Network::Packets::Server; +using namespace Sapphire::Network::ActorControl; + +Sapphire::Action::EventAction::EventAction( Entity::CharaPtr pActor, uint32_t eventId, uint16_t action, + ActionCallback finishRef, ActionCallback interruptRef, uint64_t additional, + FrameworkPtr pFw ) +{ + m_additional = additional; + m_eventId = eventId; + m_id = action; + m_pFw = pFw; + auto pExdData = pFw->get< Data::ExdDataGenerated >(); + m_castTime = pExdData->get< Sapphire::Data::EventAction >( action )->castTime * 1000; // TODO: Add security checks. + m_onActionFinishClb = std::move( finishRef ); + m_onActionInterruptClb = std::move( interruptRef ); + m_pSource = std::move( pActor ); + m_interruptType = Common::ActionInterruptType::None; +} + +Sapphire::Action::EventAction::~EventAction() = default; + +void Sapphire::Action::EventAction::castStart() +{ + if( !m_pSource ) + return; + + m_startTime = Util::getTimeMs(); + + auto control = makeActorControl142( m_pSource->getId(), ActorControlType::CastStart, 1, m_id, 0x4000004E ); + + if( m_pSource->isPlayer() ) + { + m_pSource->sendToInRangeSet( control, true ); + if( m_pSource->getAsPlayer()->hasStateFlag( PlayerStateFlag::InNpcEvent ) ) + m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::InNpcEvent ); + } + else + m_pSource->sendToInRangeSet( control ); +} + +void Sapphire::Action::EventAction::castFinish() +{ + if( !m_pSource ) + return; + + try + { + auto pEvent = m_pSource->getAsPlayer()->getEvent( m_eventId ); + + pEvent->setPlayedScene( false ); + + if( m_onActionFinishClb ) + m_onActionFinishClb( *m_pSource->getAsPlayer(), m_eventId, m_additional ); + + auto control = makeActorControl142( m_pSource->getId(), ActorControlType::CastStart, 0, m_id ); + + if( !pEvent->hasPlayedScene() ) + m_pSource->getAsPlayer()->eventFinish( m_eventId, 1 ); + else + pEvent->setPlayedScene( false ); + + if( m_pSource->isPlayer() ) + { + //m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied2 ); + m_pSource->sendToInRangeSet( control, true ); + } + else + m_pSource->sendToInRangeSet( control ); + } + catch( std::exception& e ) + { + Logger::error( e.what() ); + } + +} + +void Sapphire::Action::EventAction::castInterrupt() +{ + if( !m_pSource ) + return; + + try + { + + auto control = makeActorControl142( m_pSource->getId(), ActorControlType::CastInterrupt, 0x219, 0x04, m_id ); + + if( m_pSource->isPlayer() ) + { + auto control1 = makeActorControl143( m_pSource->getId(), ActorControlType::FreeEventPos, m_eventId ); + + //m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::NoCombat ); + //m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 ); + m_pSource->sendToInRangeSet( control ); + m_pSource->sendToInRangeSet( control1 ); + + m_pSource->getAsPlayer()->queuePacket( control1 ); + m_pSource->getAsPlayer()->queuePacket( control ); + m_pSource->getAsPlayer()->eventFinish( m_eventId, 1 ); + + } + else + m_pSource->sendToInRangeSet( control ); + + if( m_onActionInterruptClb ) + m_onActionInterruptClb( *m_pSource->getAsPlayer(), m_eventId, m_additional ); + + } + catch( std::exception& e ) + { + Logger::error( e.what() ); + } + +} diff --git a/src/world/Action/EventAction.h b/src/world/Action/EventAction.h new file mode 100644 index 00000000..2db43c37 --- /dev/null +++ b/src/world/Action/EventAction.h @@ -0,0 +1,38 @@ +#ifndef _EVENTACTION_H_ +#define _EVENTACTION_H_ + +#include + +#include "ForwardsZone.h" +#include "Action.h" + +namespace Sapphire::Action +{ + +class EventAction : public Action +{ + +public: + virtual ~EventAction(); + + EventAction( Entity::CharaPtr pActor, uint32_t eventId, uint16_t action, + ActionCallback finishRef, ActionCallback interruptRef, uint64_t additional, FrameworkPtr pFw ); + + void castStart() override; + + void castFinish() override; + + void castInterrupt() override; + +private: + uint32_t m_eventId; + uint64_t m_additional; + + ActionCallback m_onActionFinishClb; + ActionCallback m_onActionInterruptClb; + +}; + +} + +#endif diff --git a/src/world/Actor/PlayerEvent.cpp b/src/world/Actor/PlayerEvent.cpp index 7876d724..83fb5276 100644 --- a/src/world/Actor/PlayerEvent.cpp +++ b/src/world/Actor/PlayerEvent.cpp @@ -15,6 +15,8 @@ #include "ServerMgr.h" #include "Framework.h" +#include "Action/EventAction.h" + using namespace Sapphire::Common; using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets::Server; @@ -280,27 +282,28 @@ void Sapphire::Entity::Player::eventActionStart( uint32_t eventId, ActionCallback interruptCallback, uint64_t additional ) { -// auto pEventAction = Action::make_EventAction( getAsChara(), eventId, action, -// finishCallback, interruptCallback, additional, m_pFw ); -// -// setCurrentAction( pEventAction ); -// auto pEvent = getEvent( eventId ); -// -// if( !pEvent && getEventCount() ) -// { -// // We're trying to play a nested event, need to start it first. -// eventStart( getId(), eventId, Event::EventHandler::Nest, 0, 0 ); -// pEvent = getEvent( eventId ); -// } -// else if( !pEvent ) -// { -// Logger::error( "Could not find event #{0}, event has not been started!", eventId ); -// return; -// } -// -// if( pEvent ) -// pEvent->setPlayedScene( true ); -// pEventAction->onCastStart(); + auto pEventAction = Action::make_EventAction( getAsChara(), eventId, action, + finishCallback, interruptCallback, additional, m_pFw ); + + auto pEvent = getEvent( eventId ); + + if( !pEvent && getEventCount() ) + { + // We're trying to play a nested event, need to start it first. + eventStart( getId(), eventId, Event::EventHandler::Nest, 0, 0 ); + pEvent = getEvent( eventId ); + } + else if( !pEvent ) + { + Logger::error( "Could not find event #{0}, event has not been started!", eventId ); + return; + } + + if( pEvent ) + pEvent->setPlayedScene( true ); + + setCurrentAction( pEventAction ); + pEventAction->castStart(); } diff --git a/src/world/ForwardsZone.h b/src/world/ForwardsZone.h index f5ea396f..b73f47e8 100644 --- a/src/world/ForwardsZone.h +++ b/src/world/ForwardsZone.h @@ -84,7 +84,7 @@ TYPE_FORWARD( EventHandler ); namespace Action { TYPE_FORWARD( Action ); -TYPE_FORWARD( ActionCast ); +TYPE_FORWARD( EventAction ); } namespace Network