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
{
action.disableGenericHandler();
action.interrupt();
}
}
};

View file

@ -28,6 +28,7 @@ public:
else
{
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 );
if( effectEntry.second )

View file

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

View file

@ -41,7 +41,6 @@ namespace Sapphire::World::Action
bool isInterrupted() const;
Common::ActionInterruptType getInterruptType() const;
void setInterrupted( Common::ActionInterruptType type );
uint32_t getCastTime() const;
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, ...)
*/
virtual void interrupt();
virtual void interrupt( Common::ActionInterruptType type = Common::ActionInterruptType::RegularInterrupt );
/*!
* @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 )
return;
m_interruptType = type;
try
{

View file

@ -22,7 +22,7 @@ public:
void execute() override;
void interrupt() override;
void interrupt( Common::ActionInterruptType type = Common::ActionInterruptType::None) override;
private:
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 interrupt() override;
void interrupt( Common::ActionInterruptType type = Common::ActionInterruptType::None ) override;
private:
void handleVFXItem();

View file

@ -101,6 +101,14 @@ void World::Manager::ActionMgr::bootstrapAction( Entity::Player& player,
Action::ActionPtr currentAction,
Data::Action& actionData )
{
for( const auto& statusIt : player.getStatusEffectMap() )
{
statusIt.second->onBeforeActionStart( currentAction );
}
if( currentAction->isInterrupted() )
return;
if( !currentAction->preCheck() )
{
player.sendDebug( "preCheck failed" );
@ -109,11 +117,6 @@ void World::Manager::ActionMgr::bootstrapAction( Entity::Player& player,
return;
}
for( const auto& statusIt : player.getStatusEffectMap() )
{
statusIt.second->onBeforeActionStart( currentAction );
}
if( player.getCurrentAction() )
{
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
{
if( player.getCurrentAction() )
player.getCurrentAction()->setInterrupted( Common::ActionInterruptType::RegularInterrupt );
player.getCurrentAction()->interrupt();
break;
}
case ClientTriggerType::Examine:

View file

@ -200,7 +200,7 @@ void Sapphire::Network::GameConnection::updatePositionHandler( FrameworkPtr pFw,
player.setPos( updatePositionPacket.data().position );
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( !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 )
{
}

View file

@ -140,6 +140,8 @@ namespace Sapphire::ScriptAPI
public:
explicit ActionScript( uint32_t actionId );
virtual void onBeforePreCheck( Sapphire::World::Action::Action& action );
virtual void onStart( 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;
}
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 )
{
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 onBeforePreCheck( World::Action::Action& action );
bool onStart( World::Action::Action& action );
bool onInterrupt( World::Action::Action& action );