1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-25 19:17:45 +00:00

allow scripts to interrupt actions and bug fixes

This commit is contained in:
collett 2020-02-04 21:57:16 +09:00
parent deebcd76c3
commit 5ff8965ed5
16 changed files with 58 additions and 21 deletions

View file

@ -28,6 +28,7 @@ public:
else else
{ {
action.disableGenericHandler(); action.disableGenericHandler();
action.interrupt();
} }
} }
}; };

View file

@ -28,6 +28,7 @@ public:
else else
{ {
action.disableGenericHandler(); action.disableGenericHandler();
action.interrupt();
} }
} }
}; };

View file

@ -29,7 +29,7 @@ public:
} }
} }
void onStart( Sapphire::World::Action::Action& action ) override void onBeforePreCheck( Sapphire::World::Action::Action& action ) override
{ {
auto effectEntry = action.getSourceChara()->getStatusEffectById( STATUS_ID_FREECURE ); auto effectEntry = action.getSourceChara()->getStatusEffectById( STATUS_ID_FREECURE );
if( effectEntry.second ) if( effectEntry.second )

View file

@ -200,11 +200,6 @@ Common::ActionInterruptType Action::Action::getInterruptType() const
return m_interruptType; return m_interruptType;
} }
void Action::Action::setInterrupted( Common::ActionInterruptType type )
{
m_interruptType = type;
}
uint32_t Action::Action::getCastTime() const uint32_t Action::Action::getCastTime() const
{ {
return m_castTimeMs; return m_castTimeMs;
@ -268,7 +263,6 @@ bool Action::Action::update()
if( !m_pTarget->isAlive() ) if( !m_pTarget->isAlive() )
{ {
// interrupt the cast if target died // interrupt the cast if target died
setInterrupted( Common::ActionInterruptType::RegularInterrupt );
interrupt(); interrupt();
return true; return true;
} }
@ -319,15 +313,23 @@ void Action::Action::start()
player->queuePacket( actionStartPkt ); player->queuePacket( actionStartPkt );
} }
auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >();
pScriptMgr->onStart( *this );
// instantly finish cast if there's no cast time // instantly finish cast if there's no cast time
if( !hasCastTime() ) if( !hasCastTime() )
execute(); execute();
} }
void Action::Action::interrupt() void Action::Action::interrupt( ActionInterruptType type )
{ {
if( isInterrupted() )
return;
assert( m_pSource ); assert( m_pSource );
m_interruptType = type;
// things that aren't players don't care about cooldowns and state flags // things that aren't players don't care about cooldowns and state flags
if( m_pSource->isPlayer() ) if( m_pSource->isPlayer() )
{ {
@ -437,6 +439,9 @@ void Action::Action::buildEffects()
pScriptMgr->onExecute( *this ); pScriptMgr->onExecute( *this );
if( isInterrupted() )
return;
if( m_disableGenericHandler || !hasValidLutEntry() ) if( m_disableGenericHandler || !hasValidLutEntry() )
{ {
// 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
@ -571,6 +576,12 @@ void Action::Action::buildEffects()
bool Action::Action::preCheck() bool Action::Action::preCheck()
{ {
auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >();
pScriptMgr->onBeforePreCheck( *this );
if( isInterrupted() )
return false;
if( auto player = m_pSource->getAsPlayer() ) if( auto player = m_pSource->getAsPlayer() )
{ {
if( !playerPreCheck( *player ) ) if( !playerPreCheck( *player ) )

View file

@ -41,7 +41,6 @@ namespace Sapphire::World::Action
bool isInterrupted() const; bool isInterrupted() const;
Common::ActionInterruptType getInterruptType() const; Common::ActionInterruptType getInterruptType() const;
void setInterrupted( Common::ActionInterruptType type );
uint32_t getCastTime() const; uint32_t getCastTime() const;
void setCastTime( uint32_t castTime ); void setCastTime( uint32_t castTime );
@ -154,7 +153,7 @@ namespace Sapphire::World::Action
* *
* m_interruptType will have the reason why the action was interrupted (eg. damage, movement, ...) * m_interruptType will have the reason why the action was interrupted (eg. damage, movement, ...)
*/ */
virtual void interrupt(); virtual void interrupt( Common::ActionInterruptType type = Common::ActionInterruptType::RegularInterrupt );
/*! /*!
* @brief Called on each player update tick * @brief Called on each player update tick

View file

@ -92,11 +92,13 @@ void Action::EventAction::execute()
} }
void Action::EventAction::interrupt() void Action::EventAction::interrupt( Common::ActionInterruptType type )
{ {
if( !m_pSource ) if( !m_pSource )
return; return;
m_interruptType = type;
try try
{ {

View file

@ -22,7 +22,7 @@ public:
void execute() override; void execute() override;
void interrupt() override; void interrupt( Common::ActionInterruptType type = Common::ActionInterruptType::None) override;
private: private:
uint32_t m_eventId; uint32_t m_eventId;

View file

@ -51,7 +51,7 @@ void ItemAction::execute()
} }
} }
void ItemAction::interrupt() void ItemAction::interrupt( Common::ActionInterruptType type )
{ {
} }

View file

@ -22,7 +22,7 @@ namespace Sapphire::World::Action
void execute() override; void execute() override;
void interrupt() override; void interrupt( Common::ActionInterruptType type = Common::ActionInterruptType::None ) override;
private: private:
void handleVFXItem(); void handleVFXItem();

View file

@ -101,6 +101,14 @@ void World::Manager::ActionMgr::bootstrapAction( Entity::Player& player,
Action::ActionPtr currentAction, Action::ActionPtr currentAction,
Data::Action& actionData ) Data::Action& actionData )
{ {
for( const auto& statusIt : player.getStatusEffectMap() )
{
statusIt.second->onBeforeActionStart( currentAction );
}
if( currentAction->isInterrupted() )
return;
if( !currentAction->preCheck() ) if( !currentAction->preCheck() )
{ {
player.sendDebug( "preCheck failed" ); player.sendDebug( "preCheck failed" );
@ -109,11 +117,6 @@ void World::Manager::ActionMgr::bootstrapAction( Entity::Player& player,
return; return;
} }
for( const auto& statusIt : player.getStatusEffectMap() )
{
statusIt.second->onBeforeActionStart( currentAction );
}
if( player.getCurrentAction() ) if( player.getCurrentAction() )
{ {
player.sendDebug( "Skill queued: {0}", currentAction->getId() ); player.sendDebug( "Skill queued: {0}", currentAction->getId() );

View file

@ -140,7 +140,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( FrameworkPtr pFw,
case ClientTriggerType::CastCancel: // Cancel cast case ClientTriggerType::CastCancel: // Cancel cast
{ {
if( player.getCurrentAction() ) if( player.getCurrentAction() )
player.getCurrentAction()->setInterrupted( Common::ActionInterruptType::RegularInterrupt ); player.getCurrentAction()->interrupt();
break; break;
} }
case ClientTriggerType::Examine: case ClientTriggerType::Examine:

View file

@ -200,7 +200,7 @@ void Sapphire::Network::GameConnection::updatePositionHandler( FrameworkPtr pFw,
player.setPos( updatePositionPacket.data().position ); player.setPos( updatePositionPacket.data().position );
if( ( player.getCurrentAction() != nullptr ) && bPosChanged ) if( ( player.getCurrentAction() != nullptr ) && bPosChanged )
player.getCurrentAction()->setInterrupted( Common::ActionInterruptType::RegularInterrupt ); player.getCurrentAction()->interrupt();
// if no one is in range, don't bother trying to send a position update // if no one is in range, don't bother trying to send a position update
if( !player.hasInRangeActor() ) if( !player.hasInRangeActor() )

View file

@ -88,6 +88,10 @@ namespace Sapphire::ScriptAPI
{ {
} }
void ActionScript::onBeforePreCheck( Sapphire::World::Action::Action& action )
{
}
void ActionScript::onStart( Sapphire::World::Action::Action& action ) void ActionScript::onStart( Sapphire::World::Action::Action& action )
{ {
} }

View file

@ -140,6 +140,8 @@ namespace Sapphire::ScriptAPI
public: public:
explicit ActionScript( uint32_t actionId ); explicit ActionScript( uint32_t actionId );
virtual void onBeforePreCheck( Sapphire::World::Action::Action& action );
virtual void onStart( Sapphire::World::Action::Action& action ); virtual void onStart( Sapphire::World::Action::Action& action );
virtual void onExecute( Sapphire::World::Action::Action& action ); virtual void onExecute( Sapphire::World::Action::Action& action );

View file

@ -329,6 +329,18 @@ bool Sapphire::Scripting::ScriptMgr::onEObjHit( Sapphire::Entity::Player& player
return didCallScript; return didCallScript;
} }
bool Sapphire::Scripting::ScriptMgr::onBeforePreCheck( World::Action::Action& action )
{
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::ActionScript >( action.getId() );
if( script )
{
script->onBeforePreCheck( action );
return true;
}
return false;
}
bool Sapphire::Scripting::ScriptMgr::onExecute( World::Action::Action& action ) bool Sapphire::Scripting::ScriptMgr::onExecute( World::Action::Action& action )
{ {
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::ActionScript >( action.getId() ); auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::ActionScript >( action.getId() );

View file

@ -72,6 +72,8 @@ namespace Sapphire::Scripting
bool onEObjHit( Entity::Player& player, uint64_t actorId, uint32_t actionId ); bool onEObjHit( Entity::Player& player, uint64_t actorId, uint32_t actionId );
bool onBeforePreCheck( World::Action::Action& action );
bool onStart( World::Action::Action& action ); bool onStart( World::Action::Action& action );
bool onInterrupt( World::Action::Action& action ); bool onInterrupt( World::Action::Action& action );