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:
parent
deebcd76c3
commit
5ff8965ed5
16 changed files with 58 additions and 21 deletions
|
@ -28,6 +28,7 @@ public:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
action.disableGenericHandler();
|
action.disableGenericHandler();
|
||||||
|
action.interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,6 +28,7 @@ public:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
action.disableGenericHandler();
|
action.disableGenericHandler();
|
||||||
|
action.interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
|
@ -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 ) )
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -51,7 +51,7 @@ void ItemAction::execute()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemAction::interrupt()
|
void ItemAction::interrupt( Common::ActionInterruptType type )
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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() );
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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() )
|
||||||
|
|
|
@ -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 )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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() );
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
Loading…
Add table
Reference in a new issue