1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-26 06:27:45 +00:00
sapphire/src/servers/Server_Zone/Script/ScriptManager.cpp

438 lines
13 KiB
C++
Raw Normal View History

#include <Server_Common/Logging/Logger.h>
#include <Server_Common/Exd/ExdData.h>
2017-08-18 17:29:36 +02:00
#include <chaiscript/chaiscript.hpp>
#include "NativeScript.h"
2017-08-18 17:29:36 +02:00
#include "Zone/Zone.h"
#include "Actor/Player.h"
#include "Actor/BattleNpc.h"
#include "ServerZone.h"
#include "Event/Event.h"
#include "Event/EventHelper.h"
#include "StatusEffect/StatusEffect.h"
#include "Network/PacketWrappers/ServerNoticePacket.h"
#include "Script/ScriptManager.h"
2017-08-18 17:29:36 +02:00
#include <boost/lexical_cast.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
extern Core::Logger g_log;
extern Core::Data::ExdData g_exdData;
extern Core::ServerZone g_serverZone;
Core::Scripting::ScriptManager::ScriptManager()
{
m_nativeScriptHandler = create_script_engine();
2017-08-18 17:29:36 +02:00
}
Core::Scripting::ScriptManager::~ScriptManager()
{
}
void Core::Scripting::ScriptManager::loadDir( std::string dirname, std::set<std::string>& chaiFiles )
{
2017-11-26 00:38:33 +11:00
g_log.info( "ScriptEngine: loading scripts from " + dirname );
2017-08-18 17:29:36 +02:00
boost::filesystem::path targetDir( dirname );
boost::filesystem::recursive_directory_iterator iter( targetDir ), eod;
BOOST_FOREACH( boost::filesystem::path const& i, make_pair( iter, eod ) )
{
2017-08-18 17:29:36 +02:00
if( is_regular_file( i ) && boost::filesystem::extension( i.string() ) == ".chai" ||
boost::filesystem::extension( i.string() ) == ".inc" )
{
chaiFiles.insert( i.string() );
}
}
2017-08-18 17:29:36 +02:00
}
void Core::Scripting::ScriptManager::onPlayerFirstEnterWorld( Entity::Player& player )
2017-08-18 17:29:36 +02:00
{
// try
// {
// std::string test = m_onFirstEnterWorld( player );
// }
// catch( const std::exception &e )
// {
// std::string what = e.what();
// g_log.Log( LoggingSeverity::error, what );
// }
2017-08-18 17:29:36 +02:00
}
bool Core::Scripting::ScriptManager::registerBnpcTemplate( std::string templateName, uint32_t bnpcBaseId,
uint32_t bnpcNameId, uint32_t modelId, std::string aiName )
2017-08-18 17:29:36 +02:00
{
return g_serverZone.registerBnpcTemplate( templateName, bnpcBaseId, bnpcNameId, modelId, aiName );
}
void Core::Scripting::ScriptManager::reload()
{
// auto handler = create_chaiscript();
// m_pChaiHandler.swap( handler );
// init();
2017-08-18 17:29:36 +02:00
}
bool Core::Scripting::ScriptManager::onTalk( Entity::Player& player, uint64_t actorId, uint32_t eventId )
2017-08-18 17:29:36 +02:00
{
std::string eventName = "onTalk";
std::string objName = Event::getEventName( eventId );
player.sendDebug( "Actor: " +
std::to_string( actorId ) + " -> " +
std::to_string( Event::mapEventActorToRealActor( static_cast< uint32_t >( actorId ) ) ) +
" \neventId: " +
std::to_string( eventId ) +
" (0x" + boost::str( boost::format( "%|08X|" )
% static_cast< uint64_t >( eventId & 0xFFFFFFF ) ) + ")" );
2017-08-18 17:29:36 +02:00
uint16_t eventType = eventId >> 16;
auto script = m_nativeScriptHandler->getQuestScript( eventId );
if( script )
2017-08-18 17:29:36 +02:00
{
player.sendDebug( "Calling: " + objName + "." + eventName );
2017-08-18 17:29:36 +02:00
player.eventStart( actorId, eventId, Event::Event::Talk, 0, 0 );
2017-08-18 17:29:36 +02:00
script->onTalk( eventId, player, actorId );
2017-08-18 17:29:36 +02:00
player.checkEvent( eventId );
2017-08-18 17:29:36 +02:00
}
else
2017-08-18 17:29:36 +02:00
{
if ( eventType == Common::EventType::Quest )
2017-08-18 17:29:36 +02:00
{
auto questInfo = g_exdData.getQuestInfo( eventId );
if ( questInfo )
2017-08-18 17:29:36 +02:00
{
player.sendUrgent( "Quest not implemented: " + questInfo->name );
2017-08-18 17:29:36 +02:00
return false;
}
}
}
2017-08-18 17:29:36 +02:00
return true;
}
bool Core::Scripting::ScriptManager::onEnterTerritory( Entity::Player& player, uint32_t eventId,
2017-08-18 17:29:36 +02:00
uint16_t param1, uint16_t param2 )
{
std::string eventName = "onEnterTerritory";
std::string objName = Event::getEventName( eventId );
auto script = m_nativeScriptHandler->getZoneScript( player.getZoneId() );
if( script )
2017-08-18 17:29:36 +02:00
{
player.sendDebug( "Calling: " + objName + "." + eventName );
2017-08-18 17:29:36 +02:00
player.eventStart( player.getId(), eventId, Event::Event::EnterTerritory, 0, player.getZoneId() );
2017-08-18 17:29:36 +02:00
script->onEnterZone( player, eventId, param1, param2 );
2017-08-18 17:29:36 +02:00
player.checkEvent( eventId );
return true;
2017-08-18 17:29:36 +02:00
}
return false;
2017-08-18 17:29:36 +02:00
}
bool Core::Scripting::ScriptManager::onWithinRange( Entity::Player& player, uint32_t eventId, uint32_t param1,
float x, float y, float z )
2017-08-18 17:29:36 +02:00
{
// std::string eventName = "onWithinRange";
// std::string objName = Event::getEventName( eventId );
//
// try
// {
// // Get object from engine
// auto obj = m_pChaiHandler->eval( Event::getEventName( eventId ) );
//
// player.sendDebug( "Calling: " + objName + "." + eventName );
//
// player.eventStart( player.getId(), eventId, Event::Event::WithinRange, 1, param1 );
//
// auto fn = m_pChaiHandler->eval< std::function< void( chaiscript::Boxed_Value &, uint32_t, Entity::Player&, uint32_t,
// float, float, float ) > >( eventName );
// fn( obj, eventId, player, param1, x, y, z );
//
// player.checkEvent( eventId );
// }
// catch( std::exception& e )
// {
// player.sendDebug( e.what() );
// return false;
// }
// return true;
return false;
2017-08-18 17:29:36 +02:00
}
bool Core::Scripting::ScriptManager::onOutsideRange( Entity::Player& player, uint32_t eventId, uint32_t param1,
float x, float y, float z )
2017-08-18 17:29:36 +02:00
{
// std::string eventName = "onOutsideRange";
// std::string objName = Event::getEventName( eventId );
//
// try
// {
// // Get object from engine
// auto obj = m_pChaiHandler->eval( Event::getEventName( eventId ) );
//
// player.sendDebug( "Calling: " + objName + "." + eventName );
//
// player.eventStart( player.getId(), eventId, Event::Event::OutsideRange, 1, param1 );
//
// auto fn = m_pChaiHandler->eval< std::function< void( chaiscript::Boxed_Value &, uint32_t, Entity::Player&, uint32_t,
// float, float, float ) > >( eventName );
// fn( obj, eventId, player, param1, x, y, z );
//
// player.checkEvent( eventId );
// }
// catch( std::exception& e )
// {
// player.sendDebug( e.what() );
// return false;
// }
// return true;
return false;
2017-08-18 17:29:36 +02:00
}
bool Core::Scripting::ScriptManager::onEmote( Entity::Player& player, uint64_t actorId,
2017-08-18 17:29:36 +02:00
uint32_t eventId, uint8_t emoteId )
{
std::string eventName = "onEmote";
std::string objName = Event::getEventName( eventId );
auto script = m_nativeScriptHandler->getQuestScript( eventId );
if( script )
2017-08-18 17:29:36 +02:00
{
player.sendDebug( "Calling: " + objName + "." + eventName );
2017-08-18 17:29:36 +02:00
player.eventStart( actorId, eventId, Event::Event::Emote, 0, emoteId );
2017-08-18 17:29:36 +02:00
script->onEmote( actorId, eventId, emoteId, player );
2017-08-18 17:29:36 +02:00
player.checkEvent( eventId );
2017-08-18 17:29:36 +02:00
}
else
2017-08-18 17:29:36 +02:00
{
uint16_t eventType = eventId >> 16;
if( eventType == Common::EventType::Quest )
{
auto questInfo = g_exdData.getQuestInfo( eventId );
if( questInfo )
{
player.sendUrgent( "Quest not implemented: " + questInfo->name );
2017-08-18 17:29:36 +02:00
return false;
}
}
return false;
}
2017-08-18 17:29:36 +02:00
return true;
}
bool Core::Scripting::ScriptManager::onEventHandlerReturn( Entity::Player& player, uint32_t eventId,
uint16_t subEvent, uint16_t param1, uint16_t param2,
uint16_t param3 )
2017-08-18 17:29:36 +02:00
{
player.sendDebug( "eventId: " +
std::to_string( eventId ) +
" ( 0x" + boost::str( boost::format( "%|08X|" ) % ( uint64_t ) ( eventId & 0xFFFFFFF ) ) + " ) " +
" scene: " + std::to_string( subEvent ) +
" p1: " + std::to_string( param1 ) +
" p2: " + std::to_string( param2 ) +
" p3: " + std::to_string( param3 ) );
2017-08-18 17:29:36 +02:00
try
{
auto pEvent = player.getEvent( eventId );
2017-08-18 17:29:36 +02:00
if( pEvent )
{
pEvent->setPlayedScene( false );
// try to retrieve a stored callback
auto eventCallback = pEvent->getEventReturnCallback();
// if there is one, proceed to call it
if( eventCallback )
{
eventCallback( player, eventId, param1, param2, param3 );
2017-08-18 17:29:36 +02:00
if( !pEvent->hasPlayedScene() )
player.eventFinish( eventId, 1 );
2017-08-18 17:29:36 +02:00
else
pEvent->setPlayedScene( false );
}
// else, finish the event.
2017-08-18 17:29:36 +02:00
else
player.eventFinish( eventId, 1 );
2017-08-18 17:29:36 +02:00
}
}
catch( std::exception& e )
{
player.sendNotice( e.what() );
2017-08-18 17:29:36 +02:00
return false;
}
return true;
}
bool Core::Scripting::ScriptManager::onEventHandlerTradeReturn( Entity::Player& player, uint32_t eventId,
2017-08-18 17:29:36 +02:00
uint16_t subEvent, uint16_t param, uint32_t catalogId )
{
// std::string eventName = Event::getEventName( eventId ) + "_TRADE";
//
// try
// {
// auto fn = m_pChaiHandler->eval< std::function< void( Entity::Player&, uint32_t,
// uint16_t, uint16_t, uint32_t ) > >( eventName );
// fn( player, eventId, subEvent, param, catalogId );
// }
// catch( ... )
// {
// return false;
// }
//
// return true;
return false;
2017-08-18 17:29:36 +02:00
}
bool Core::Scripting::ScriptManager::onEventItem( Entity::Player& player, uint32_t eventItemId,
uint32_t eventId, uint32_t castTime, uint64_t targetId )
2017-08-18 17:29:36 +02:00
{
// std::string eventName = "onEventItem";
// std::string objName = Event::getEventName( eventId );
//
// try
// {
// auto obj = m_pChaiHandler->eval( Event::getEventName( eventId ) );
//
// player.sendDebug( "Calling: " + objName + "." + eventName );
//
// player.eventStart( targetId, eventId, Event::Event::Item, 0, 0 );
//
// auto fn = m_pChaiHandler->eval< std::function< void( chaiscript::Boxed_Value &, uint32_t, Entity::Player&,
// uint32_t, uint32_t, uint64_t ) > >( eventName );
// fn( obj, eventId, player, eventItemId, castTime, targetId );
// }
// catch( std::exception& e )
// {
// player.sendNotice( e.what() );
// return false;
// }
//
// return true;
return false;
2017-08-18 17:29:36 +02:00
}
bool Core::Scripting::ScriptManager::onMobKill( Entity::Player& player, uint16_t nameId )
2017-08-18 17:29:36 +02:00
{
std::string eventName = "onBnpcKill_" + std::to_string( nameId );
2017-08-18 17:29:36 +02:00
// loop through all active quests and try to call available onMobKill callbacks
for( size_t i = 0; i < 30; i++ )
{
auto activeQuests = player.getQuestActive( static_cast< uint16_t >( i ) );
2017-08-18 17:29:36 +02:00
if( !activeQuests )
continue;
uint16_t questId = activeQuests->c.questId;
auto script = m_nativeScriptHandler->getQuestScript( questId );
if( script )
2017-08-18 17:29:36 +02:00
{
std::string objName = Event::getEventName( 0x00010000 | questId );
player.sendDebug("Calling: " + objName + "." + eventName);
2017-08-18 17:29:36 +02:00
script->onNpcKill( nameId, player );
2017-08-18 17:29:36 +02:00
}
}
return true;
}
bool Core::Scripting::ScriptManager::onCastFinish( Entity::Player& player, Entity::ActorPtr pTarget, uint32_t actionId )
2017-08-18 17:29:36 +02:00
{
auto script = m_nativeScriptHandler->getAbilityScript( actionId );
if( script )
script->onCastFinish( player, pTarget );
return true;
2017-08-18 17:29:36 +02:00
}
bool Core::Scripting::ScriptManager::onStatusReceive( Entity::ActorPtr pActor, uint32_t effectId )
{
auto script = m_nativeScriptHandler->getStatusEffectScript( effectId );
if( script )
2017-08-18 17:29:36 +02:00
{
if( pActor->isPlayer() )
pActor->getAsPlayer()->sendDebug( "Calling status recieve for statusid: " + effectId );
2017-08-18 17:29:36 +02:00
script->onApply( pActor );
return true;
2017-08-18 17:29:36 +02:00
}
return false;
2017-08-18 17:29:36 +02:00
}
bool Core::Scripting::ScriptManager::onStatusTick( Entity::ActorPtr pActor, Core::StatusEffect::StatusEffect& effect )
{
auto script = m_nativeScriptHandler->getStatusEffectScript( effect.getId() );
if( script )
2017-08-18 17:29:36 +02:00
{
if( pActor->isPlayer() )
pActor->getAsPlayer()->sendDebug( "Calling status tick for statusid: " + effect.getId() );
2017-08-18 17:29:36 +02:00
script->onTick( pActor );
return true;
2017-08-18 17:29:36 +02:00
}
return false;
2017-08-18 17:29:36 +02:00
}
bool Core::Scripting::ScriptManager::onStatusTimeOut( Entity::ActorPtr pActor, uint32_t effectId )
{
auto script = m_nativeScriptHandler->getStatusEffectScript( effectId );
if( script )
2017-08-18 17:29:36 +02:00
{
if( pActor->isPlayer() )
pActor->getAsPlayer()->sendDebug( "Calling status tick for statusid: " + effectId );
2017-08-18 17:29:36 +02:00
script->onExpire( pActor );
return true;
2017-08-18 17:29:36 +02:00
}
return false;
2017-08-18 17:29:36 +02:00
}
bool Core::Scripting::ScriptManager::onZoneInit( ZonePtr pZone )
{
auto script = m_nativeScriptHandler->getZoneScript( pZone->getId() );
if( script )
2017-08-18 17:29:36 +02:00
{
script->onZoneInit();
2017-08-18 17:29:36 +02:00
return true;
}
2017-08-18 17:29:36 +02:00
return false;
2017-08-18 17:29:36 +02:00
}