diff --git a/CMakeLists.txt b/CMakeLists.txt index acb43b44..1284d86b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,4 @@ +cmake_policy(SET CMP0014 NEW) cmake_minimum_required(VERSION 2.6) project (Sapphire) diff --git a/src/servers/Server_Zone/Script/ScriptManager.cpp b/src/servers/Server_Zone/Script/ScriptManager.cpp new file mode 100644 index 00000000..1779ebef --- /dev/null +++ b/src/servers/Server_Zone/Script/ScriptManager.cpp @@ -0,0 +1,488 @@ +#include +#include +#include + +#include + +#include "src/servers/Server_Zone/Zone/Zone.h" +#include "src/servers/Server_Zone/Actor/Player.h" +#include "src/servers/Server_Zone/Actor/BattleNpc.h" +#include "src/servers/Server_Zone/ServerZone.h" +#include "src/servers/Server_Zone/Event/Event.h" +#include "src/servers/Server_Zone/Event/EventHelper.h" +#include "src/servers/Server_Zone/StatusEffect/StatusEffect.h" +#include "src/servers/Server_Zone/Network/PacketWrappers/ServerNoticePacket.h" +#include "src/servers/Server_Zone/Script/ScriptManager.h" + +#include +#include +#include +#include +#include + +extern Core::Logger g_log; +extern Core::Data::ExdData g_exdData; +extern Core::ServerZone g_serverZone; +extern Core::Scripting::ScriptManager g_scriptManager; + +Core::Scripting::ScriptManager::ScriptManager() +{ + m_pChaiHandler = create_chaiscript(); +} + +Core::Scripting::ScriptManager::~ScriptManager() +{ + +} + +void Core::Scripting::ScriptManager::loadDir( std::string dirname, std::set& chaiFiles ) +{ + + boost::filesystem::path targetDir( dirname ); + + boost::filesystem::recursive_directory_iterator iter( targetDir ), eod; + + BOOST_FOREACH( boost::filesystem::path const& i, make_pair( iter, eod ) ) + { + + if( is_regular_file( i ) && boost::filesystem::extension( i.string() ) == ".chai" || + boost::filesystem::extension( i.string() ) == ".inc" ) + { + chaiFiles.insert( i.string() ); + } + } + +} + +void Core::Scripting::ScriptManager::onPlayerFirstEnterWorld( Core::Entity::PlayerPtr pPlayer ) +{ + try + { + std::string test = m_onFirstEnterWorld( *pPlayer ); + } + catch( const std::exception &e ) + { + std::string what = e.what(); + g_log.Log( LoggingSeverity::error, what ); + } +} + +bool Core::Scripting::ScriptManager::registerBnpcTemplate( std::string templateName, uint32_t bnpcBaseId, uint32_t bnpcNameId, uint32_t modelId, std::string aiName ) +{ + return g_serverZone.registerBnpcTemplate( templateName, bnpcBaseId, bnpcNameId, modelId, aiName ); +} + +void Core::Scripting::ScriptManager::reload() +{ + auto handler = create_chaiscript(); + m_pChaiHandler.swap( handler ); + init(); +} + +const boost::shared_ptr& Core::Scripting::ScriptManager::getHandler() const +{ + return m_pChaiHandler; +} + + +bool Core::Scripting::ScriptManager::onTalk( Core::Entity::PlayerPtr pPlayer, uint64_t actorId, uint32_t eventId ) +{ + std::string eventName = "onTalk"; + std::string objName = Event::getEventName( eventId ); + + pPlayer->sendDebug("Actor: " + + std::to_string( actorId ) + + " \neventId: " + + std::to_string( eventId ) + + " (0x" + boost::str( boost::format( "%|08X|" ) + % static_cast< uint64_t >( eventId & 0xFFFFFFF ) ) + ")" ); + + uint16_t eventType = eventId >> 16; + + try + { + // Get object from engine + auto obj = m_pChaiHandler->eval( objName ); + pPlayer->sendDebug( "Calling: " + objName + "." + eventName ); + + pPlayer->eventStart( actorId, eventId, Event::Event::Talk, 0, 0 ); + + auto fn = m_pChaiHandler->eval< std::function< void( chaiscript::Boxed_Value &, uint32_t, Entity::Player&, uint64_t ) > >( eventName ); + fn( obj, eventId, *pPlayer, actorId ); + + pPlayer->checkEvent( eventId ); + } + catch( std::exception& e ) + { + + if( eventType == Common::EventType::Quest ) + { + auto questInfo = g_exdData.getQuestInfo( eventId ); + if( questInfo ) + { + pPlayer->sendDebug( "Quest not implemented: " + questInfo->name + "\n" + e.what() ); + return false; + } + } + + pPlayer->sendDebug( e.what() ); + return false; + } + return true; +} + +bool Core::Scripting::ScriptManager::onEnterTerritory( Core::Entity::PlayerPtr pPlayer, uint32_t eventId, + uint16_t param1, uint16_t param2 ) +{ + std::string eventName = "onEnterTerritory"; + std::string objName = Event::getEventName( eventId ); + + try + { + // Get object from engine + auto obj = m_pChaiHandler->eval( objName ); + + pPlayer->sendDebug( "Calling: " + objName + "." + eventName ); + + pPlayer->eventStart( pPlayer->getId(), eventId, Event::Event::EnterTerritory, 0, pPlayer->getZoneId() ); + + auto fn = m_pChaiHandler->eval< std::function< void( chaiscript::Boxed_Value &, uint32_t, Entity::Player&, uint16_t, uint16_t ) > >( eventName ); + fn( obj, eventId, *pPlayer, param1, param2 ); + + pPlayer->checkEvent( eventId ); + } + catch( std::exception& e ) + { + pPlayer->sendDebug( e.what() ); + return false; + } + return true; +} + +bool Core::Scripting::ScriptManager::onWithinRange( Entity::PlayerPtr pPlayer, uint32_t eventId, uint32_t param1, float x, float y, float z ) +{ + std::string eventName = "onWithinRange"; + std::string objName = Event::getEventName( eventId ); + + try + { + // Get object from engine + auto obj = m_pChaiHandler->eval( Event::getEventName( eventId ) ); + + pPlayer->sendDebug( "Calling: " + objName + "." + eventName ); + + pPlayer->eventStart( pPlayer->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, *pPlayer, param1, x, y, z ); + + pPlayer->checkEvent( eventId ); + } + catch( std::exception& e ) + { + pPlayer->sendDebug( e.what() ); + return false; + } + return true; +} + +bool Core::Scripting::ScriptManager::onOutsideRange( Entity::PlayerPtr pPlayer, uint32_t eventId, uint32_t param1, float x, float y, float z ) +{ + std::string eventName = "onOutsideRange"; + std::string objName = Event::getEventName( eventId ); + + try + { + // Get object from engine + auto obj = m_pChaiHandler->eval( Event::getEventName( eventId ) ); + + pPlayer->sendDebug( "Calling: " + objName + "." + eventName ); + + pPlayer->eventStart( pPlayer->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, *pPlayer, param1, x, y, z ); + + pPlayer->checkEvent( eventId ); + } + catch( std::exception& e ) + { + pPlayer->sendDebug( e.what() ); + return false; + } + return true; +} + +bool Core::Scripting::ScriptManager::onEmote( Core::Entity::PlayerPtr pPlayer, uint64_t actorId, + uint32_t eventId, uint8_t emoteId ) +{ + std::string eventName = "onEmote"; + std::string objName = Event::getEventName( eventId ); + + try + { + auto obj = m_pChaiHandler->eval( Event::getEventName( eventId ) ); + + pPlayer->sendDebug( "Calling: " + objName + "." + eventName ); + + pPlayer->eventStart( actorId, eventId, Event::Event::Emote, 0, emoteId ); + + auto fn = m_pChaiHandler->eval< std::function< void( chaiscript::Boxed_Value &, uint32_t, Entity::Player&, uint64_t, uint8_t ) > >( eventName ); + fn( obj, eventId, *pPlayer, actorId, emoteId ); + + pPlayer->checkEvent( eventId ); + } + catch( std::exception& e ) + { + uint16_t eventType = eventId >> 16; + + if( eventType == Common::EventType::Quest ) + { + auto questInfo = g_exdData.getQuestInfo( eventId ); + if( questInfo ) + { + pPlayer->sendDebug( "Quest not implemented: " + questInfo->name + "\n" + e.what() ); + return false; + } + } + return false; + } + return true; +} + +bool Core::Scripting::ScriptManager::onEventHandlerReturn( Core::Entity::PlayerPtr pPlayer, uint32_t eventId, uint16_t subEvent, + uint16_t param1, uint16_t param2, uint16_t param3 ) +{ + + pPlayer->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 ) ); + + try + { + auto pEvent = pPlayer->getEvent( eventId ); + 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( *pPlayer, eventId, param1, param2, param3 ); + if( !pEvent->hasPlayedScene() ) + pPlayer->eventFinish( eventId, 1 ); + else + pEvent->setPlayedScene( false ); + } + // else, finish the event. + else + pPlayer->eventFinish( eventId, 1 ); + } + } + catch( std::exception& e ) + { + pPlayer->sendNotice( e.what() ); + return false; + } + + return true; +} + +bool Core::Scripting::ScriptManager::onEventHandlerTradeReturn( Core::Entity::PlayerPtr pPlayer, uint32_t eventId, + 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( *pPlayer, eventId, subEvent, param, catalogId ); + } + catch( ... ) + { + return false; + } + + return true; +} + +bool Core::Scripting::ScriptManager::onEventItem( Entity::PlayerPtr pPlayer, uint32_t eventItemId, + uint32_t eventId, uint32_t castTime, uint64_t targetId ) +{ + std::string eventName = "onEventItem"; + std::string objName = Event::getEventName( eventId ); + + try + { + auto obj = m_pChaiHandler->eval( Event::getEventName( eventId ) ); + + pPlayer->sendDebug( "Calling: " + objName + "." + eventName ); + + pPlayer->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, *pPlayer, eventItemId, castTime, targetId ); + } + catch( std::exception& e ) + { + pPlayer->sendNotice( e.what() ); + return false; + } + + return true; + +} + +bool Core::Scripting::ScriptManager::onMobKill( Entity::PlayerPtr pPlayer, uint16_t nameId ) +{ + std::string eventName = "onBnpcKill_" + std::to_string( nameId ); + + + // loop through all active quests and try to call available onMobKill callbacks + for( size_t i = 0; i < 30; i++ ) + { + auto activeQuests = pPlayer->getQuestActive( i ); + if( !activeQuests ) + continue; + + uint16_t questId = activeQuests->c.questId; + if( questId != 0 ) + { + auto obj = m_pChaiHandler->eval( Event::getEventName( 0x00010000 | questId ) ); + std::string objName = Event::getEventName( 0x00010000 | questId ); + + pPlayer->sendDebug("Calling: " + objName + "." + eventName); + + try + { + auto fn = m_pChaiHandler->eval< std::function< void( chaiscript::Boxed_Value &, Entity::Player& ) > >(eventName); + fn( obj, *pPlayer ); + } + catch( std::exception& e ) + { + g_log.info( e.what() ); + } + + } + } + + return true; +} + +bool Core::Scripting::ScriptManager::onCastFinish( Entity::PlayerPtr pPlayer, Entity::ActorPtr pTarget, uint32_t actionId ) +{ + std::string eventName = "onFinish"; + + try + { + auto obj = m_pChaiHandler->eval( "skillDef_" + std::to_string( actionId ) ); + std::string objName = "skillDef_" + std::to_string( actionId ); + + pPlayer->sendDebug( "Calling: " + objName + "." + eventName ); + auto fn = m_pChaiHandler->eval< std::function< void( chaiscript::Boxed_Value &, Entity::Player&, Entity::Actor& ) > >( eventName ); + fn( obj, *pPlayer, *pTarget ); + } + catch( std::exception& e ) + { + pPlayer->sendUrgent( e.what() ); + } + + return true; +} + +bool Core::Scripting::ScriptManager::onStatusReceive( Entity::ActorPtr pActor, uint32_t effectId ) +{ + std::string eventName = "onReceive"; + + try + { + auto obj = m_pChaiHandler->eval( "statusDef_" + std::to_string( effectId ) ); + std::string objName = "statusDef_" + std::to_string( effectId ); + + if( pActor->isPlayer() ) + pActor->getAsPlayer()->sendDebug( "Calling: " + objName + "." + eventName ); + + auto fn = m_pChaiHandler->eval< std::function< void( chaiscript::Boxed_Value &, Entity::Actor&) > >( eventName ); + fn( obj, *pActor ); + } + catch( std::exception& e ) + { + if( pActor->isPlayer() ) + pActor->getAsPlayer()->sendUrgent( e.what() ); + } + + return true; +} + +bool Core::Scripting::ScriptManager::onStatusTick( Entity::ActorPtr pActor, Core::StatusEffect::StatusEffect& effect ) +{ + std::string eventName = "onTick"; + + try + { + auto obj = m_pChaiHandler->eval( "statusDef_" + std::to_string( effect.getId() ) ); + std::string objName = "statusDef_" + std::to_string( effect.getId() ); + + if( pActor->isPlayer() ) + pActor->getAsPlayer()->sendDebug( "Calling: " + objName + "." + eventName ); + + auto fn = m_pChaiHandler->eval< std::function< void( chaiscript::Boxed_Value &, Entity::Actor&, Core::StatusEffect::StatusEffect& ) > >( eventName ); + fn( obj, *pActor, effect ); + } + catch( std::exception& e ) + { + if( pActor->isPlayer() ) + pActor->getAsPlayer()->sendUrgent( e.what() ); + } + + return true; +} + +bool Core::Scripting::ScriptManager::onStatusTimeOut( Entity::ActorPtr pActor, uint32_t effectId ) +{ + std::string eventName = "onTimeOut"; + + try + { + auto obj = m_pChaiHandler->eval( "statusDef_" + std::to_string( effectId ) ); + std::string objName = "statusDef_" + std::to_string( effectId ); + + if( pActor->isPlayer() ) + pActor->getAsPlayer()->sendDebug( "Calling: " + objName + "." + eventName ); + + auto fn = m_pChaiHandler->eval< std::function< void( chaiscript::Boxed_Value &, Entity::Actor& ) > >( eventName ); + fn( obj, *pActor ); + } + catch( std::exception& e ) + { + if( pActor->isPlayer() ) + pActor->getAsPlayer()->sendUrgent( e.what() ); + } + + return true; +} + +bool Core::Scripting::ScriptManager::onZoneInit( ZonePtr pZone ) +{ + std::string eventName = "onZoneInit_" + pZone->getInternalName(); + + try + { + auto fn = m_pChaiHandler->eval< std::function< void( Zone& ) > >( eventName ); + fn( *pZone ); + } + catch( std::exception& e ) + { + g_log.info( e.what() ); + return false; + } + + return true; + +} + diff --git a/src/servers/Server_Zone/Script/ScriptManager.h b/src/servers/Server_Zone/Script/ScriptManager.h new file mode 100644 index 00000000..bbdd6c27 --- /dev/null +++ b/src/servers/Server_Zone/Script/ScriptManager.h @@ -0,0 +1,71 @@ +#ifndef _SCRIPTMANAGER_H_ +#define _SCRIPTMANAGER_H_ + +#include +#include +#include + +#include +#include "../Forwards.h" + + +namespace chaiscript +{ + class ChaiScript; +} + +namespace Core +{ + namespace Scripting + { + + class ScriptManager + { + private: + + boost::shared_ptr< chaiscript::ChaiScript > m_pChaiHandler; + + std::function< std::string( Entity::Player& ) > m_onFirstEnterWorld; + // auto fn = m_pChaiHandler->eval< std::function >( "onFirstEnterWorld" ); + + public: + ScriptManager(); + ~ScriptManager(); + + int32_t init(); + void reload(); + + const boost::shared_ptr< chaiscript::ChaiScript >& getHandler() const; + + void onPlayerFirstEnterWorld( Entity::PlayerPtr pPlayer ); + + static bool registerBnpcTemplate( std::string templateName, uint32_t bnpcBaseId, uint32_t bnpcNameId, uint32_t modelId, std::string aiName ); + + bool onTalk( Entity::PlayerPtr pPlayer, uint64_t actorId, uint32_t eventId ); + bool onEnterTerritory( Entity::PlayerPtr pPlayer, uint32_t eventId, uint16_t param1, uint16_t param2 ); + bool onWithinRange( Entity::PlayerPtr pPlayer, uint32_t eventId, uint32_t param1, float x, float y, float z ); + bool onOutsideRange( Entity::PlayerPtr pPlayer, uint32_t eventId, uint32_t param1, float x, float y, float z ); + bool onEmote( Entity::PlayerPtr pPlayer, uint64_t actorId, uint32_t eventId, uint8_t emoteId ); + bool onEventItem( Entity::PlayerPtr pPlayer, uint32_t eventItemId, uint32_t eventId, uint32_t castTime, uint64_t targetId ); + + bool onMobKill( Entity::PlayerPtr pPlayer, uint16_t nameId ); + + bool onCastFinish( Entity::PlayerPtr pPlayer, Entity::ActorPtr pTarget, uint32_t actionId ); + + bool onStatusReceive( Entity::ActorPtr pActor, uint32_t effectId ); + bool onStatusTick( Entity::ActorPtr pActor, Core::StatusEffect::StatusEffect& effect ); + bool onStatusTimeOut( Entity::ActorPtr pActor, uint32_t effectId ); + + bool onZoneInit( ZonePtr pZone ); + + bool onEventHandlerReturn( Entity::PlayerPtr pPlayer, uint32_t eventId, uint16_t subEvent, uint16_t param1, uint16_t param2, uint16_t param3 ); + bool onEventHandlerTradeReturn( Entity::PlayerPtr pPlayer, uint32_t eventId, uint16_t subEvent, uint16_t param, uint32_t catalogId ); + + + void loadDir( std::string dirname, std::set& chaiFiles ); + + + }; + } +} +#endif diff --git a/src/servers/Server_Zone/Script/ScriptManagerInit.cpp b/src/servers/Server_Zone/Script/ScriptManagerInit.cpp new file mode 100644 index 00000000..64a80d9d --- /dev/null +++ b/src/servers/Server_Zone/Script/ScriptManagerInit.cpp @@ -0,0 +1,210 @@ +#include +#include + +#include + +#include "src/servers/Server_Zone/Script/ScriptManager.h" + +#include "src/servers/Server_Zone/Zone/Zone.h" +#include "src/servers/Server_Zone/Actor/Player.h" +#include "src/servers/Server_Zone/Actor/BattleNpc.h" +#include "src/servers/Server_Zone/Event/Event.h" +#include "src/servers/Server_Zone/Event/EventHelper.h" + +#include "src/servers/Server_Zone/Network/PacketWrappers/ServerNoticePacket.h" +#include "src/servers/Server_Zone/StatusEffect/StatusEffect.h" + +#include +#include +#include +#include +#include + + +extern Core::Logger g_log; + +int Core::Scripting::ScriptManager::init() +{ + // ACTOR / PLAYER BINDINGS + ///////////////////////////////////////////////////////////////////////////////////////////// + m_pChaiHandler->add( chaiscript::fun( &Entity::Actor::getName ), "getName" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Actor::getId ), "getId" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Actor::getHp ), "getHp" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Actor::getMp ), "getMp" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Actor::getTp ), "getTp" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Actor::getLevel ), "getLevel" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Actor::getTargetId ), "getTargetId" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Actor::addStatusEffect ), "addStatusEffect" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Actor::addStatusEffectById ), "addStatusEffectById" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Actor::addStatusEffectByIdIfNotExist ), "addStatusEffectByIdIfNotExist" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Actor::takeDamage ), "takeDamage" ); + + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::forceZoneing ), "setZone" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getClassAsInt ), "getClass" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getRace ), "getRace" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getGender ), "getGender" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::isFirstLogin ), "isFirstLogin" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setFirstLogin ), "setFirstLogin" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::gainExp ), "gainExp" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::unlock ), "unlock" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::registerAetheryte ), "aetheryteRegister" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::learnAction ), "learnAction" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getHomepoint ), "getHomepoint" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setHomepoint ), "setHomepoint" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::returnToHomepoint ), "returnToHomepoint" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::teleport ), "teleport" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::prepareZoning ), "prepareZoning" ); + + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getCurrency ), "getCurrency" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::addCurrency ), "addCurrency" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::removeCurrency ), "removeCurrency" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getCrystal ), "getCrystals" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::addCrystal ), "addCrystals" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::removeCrystal ), "removeCrystals" ); + + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::updateQuest ), "questUpdate" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::finishQuest ), "questFinish" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::sendQuestMessage ), "questMessage" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestSeq ), "questGetSeq" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::hasQuest ), "hasQuest" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getZoneId ), "getZoneId" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::handleScriptSkill ), "handleScriptSkill" ); + + + m_pChaiHandler->add( chaiscript::fun( &Core::Event::mapEventActorToRealActor ), "mapActor" ); + + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8A ), "getQuestUI8A" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8B ), "getQuestUI8B" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8C ), "getQuestUI8C" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8D ), "getQuestUI8D" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8E ), "getQuestUI8E" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8F ), "getQuestUI8F" ); + + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8AH ), "getQuestUI8AH" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8BH ), "getQuestUI8BH" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8CH ), "getQuestUI8CH" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8DH ), "getQuestUI8DH" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8EH ), "getQuestUI8EH" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8FH ), "getQuestUI8FH" ); + + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8AL ), "getQuestUI8AL" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8BL ), "getQuestUI8BL" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8CL ), "getQuestUI8CL" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8DL ), "getQuestUI8DL" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8EL ), "getQuestUI8EL" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI8FL ), "getQuestUI8FL" ); + + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI16A ), "getQuestUI16A" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI16B ), "getQuestUI16B" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI16C ), "getQuestUI16C" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestUI32A ), "getQuestUI32A" ); + + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestBitFlag8 ), "getQuestBitFlag8" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestBitFlag16 ), "getQuestBitFlag16" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestBitFlag24 ), "getQuestBitFlag24" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestBitFlag32 ), "getQuestBitFlag32" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestBitFlag40 ), "getQuestBitFlag40" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::getQuestBitFlag48 ), "getQuestBitFlag48" ); + + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8A ), "setQuestUI8A" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8B ), "setQuestUI8B" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8C ), "setQuestUI8C" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8D ), "setQuestUI8D" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8E ), "setQuestUI8E" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8F ), "setQuestUI8F" ); + + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8AH ), "setQuestUI8AH" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8BH ), "setQuestUI8BH" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8CH ), "setQuestUI8CH" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8DH ), "setQuestUI8DH" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8EH ), "setQuestUI8EH" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8FH ), "setQuestUI8FH" ); + + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8AL ), "setQuestUI8AL" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8BL ), "setQuestUI8BL" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8CL ), "setQuestUI8CL" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8DL ), "setQuestUI8DL" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8EL ), "setQuestUI8EL" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI8FL ), "setQuestUI8FL" ); + + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI16A ), "setQuestUI16A" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI16B ), "setQuestUI16B" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI16C ), "setQuestUI16C" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestUI32A ), "setQuestUI32A" ); + + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestBitFlag8 ), "setQuestBitFlag8" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestBitFlag16 ), "setQuestBitFlag16" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestBitFlag24 ), "setQuestBitFlag24" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestBitFlag32 ), "setQuestBitFlag32" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestBitFlag40 ), "setQuestBitFlag40" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::setQuestBitFlag48 ), "setQuestBitFlag48" ); + + m_pChaiHandler->add(chaiscript::fun(&Entity::Player::giveQuestRewards), "giveQuestRewards"); + + m_pChaiHandler->add( chaiscript::fun< void, Entity::Player, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t >( &Entity::Player::eventPlay ), "eventPlay" ); + m_pChaiHandler->add( chaiscript::fun< void, Entity::Player, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, EventReturnCallback >( &Entity::Player::eventPlay ), "eventPlay" ); + m_pChaiHandler->add( chaiscript::fun< void, Entity::Player, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, EventReturnCallback >( &Entity::Player::eventPlay ), "eventPlay" ); + m_pChaiHandler->add( chaiscript::fun< void, Entity::Player, uint32_t, uint32_t, uint32_t, EventReturnCallback >( &Entity::Player::eventPlay ), "eventPlay" ); + m_pChaiHandler->add( chaiscript::fun< void, Entity::Player, uint32_t, uint32_t, uint32_t >( &Entity::Player::eventPlay ), "eventPlay" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::eventActionStart ), "eventActionStart" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::eventItemActionStart ), "eventItemActionStart" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::changePosition ), "changePos" ); + + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::tryAddItem ), "tryAddItem" ); + + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::isAetheryteRegistered ), "isAetheryteRegistered" ); + m_pChaiHandler->add( chaiscript::fun( &Entity::Player::isActionLearned ), "isActionLearned" ); + + m_pChaiHandler->add( chaiscript::base_class< Entity::Actor, Entity::Player >() ); + m_pChaiHandler->add( chaiscript::base_class< Entity::Actor, Entity::BattleNpc >() ); + m_pChaiHandler->add( chaiscript::user_type< Entity::Actor >(), "Actor" ); + m_pChaiHandler->add( chaiscript::user_type< Entity::Player >(), "Player" ); + m_pChaiHandler->add( chaiscript::user_type< Entity::BattleNpc >(), "BattleNpc" ); + m_pChaiHandler->add( chaiscript::user_type< StatusEffect::StatusEffect >(), "StatusEffect" ); + + m_pChaiHandler->add( chaiscript::fun( &StatusEffect::StatusEffect::registerTickEffect ), "registerTickEffect" ); + + m_pChaiHandler->add( chaiscript::user_type< Zone >(), "Zone" ); + m_pChaiHandler->add( chaiscript::fun( &Zone::getName ), "getName" ); + + m_pChaiHandler->add( chaiscript::fun( ®isterBnpcTemplate ), "registerBnpcTemplate" ); + + // EVENT BINDINGS + ///////////////////////////////////////////////////////////////////////////////////////////// + + std::set< std::string > chaiFiles; + + g_log.info( "ScriptEngine: Loading Scripts..." ); + loadDir( "scripts/chai", chaiFiles ); + + uint16_t scriptCount = 0; + uint16_t errorCount = 0; + for( auto itr = chaiFiles.begin(); itr != chaiFiles.end(); ++itr ) + { + auto& fileName = *itr; + + try + { + m_pChaiHandler->eval_file( fileName ); + scriptCount++; + } + catch( std::exception& e ) + { + g_log.Log( LoggingSeverity::error, e.what() ); + errorCount++; + } + + } + + g_log.info( "\tloaded " + std::to_string( scriptCount ) + + " scripts, " + std::to_string( errorCount ) + " errors." ); + + std::function f = + m_pChaiHandler->eval< std::function >( "onFirstEnterWorld" ); + + m_onFirstEnterWorld = f; + + + return true; +} +