2016-01-28 14:52:40 +01:00
|
|
|
/** @file
|
|
|
|
|
*
|
|
|
|
|
* @par History
|
|
|
|
|
* - 2009/10/22 Turley: added OuchHook
|
|
|
|
|
* - 2009/11/26 Turley: Syshook CanDie(mobile)
|
|
|
|
|
*/
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
|
|
|
#include "syshook.h"
|
|
|
|
|
|
2018-01-29 21:55:48 +01:00
|
|
|
#include <stddef.h>
|
|
|
|
|
#include <string>
|
2018-10-13 00:03:40 +02:00
|
|
|
#include <tuple>
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2018-01-29 21:55:48 +01:00
|
|
|
#include "../bscript/bobject.h"
|
2018-10-13 00:03:40 +02:00
|
|
|
#include "../bscript/executor.h"
|
2016-02-11 22:54:43 +01:00
|
|
|
#include "../clib/cfgelem.h"
|
|
|
|
|
#include "../clib/cfgfile.h"
|
|
|
|
|
#include "../clib/fileutil.h"
|
|
|
|
|
#include "../clib/logfacility.h"
|
2018-10-13 00:03:40 +02:00
|
|
|
#include "../clib/strutil.h"
|
2018-01-29 21:55:48 +01:00
|
|
|
#include "../plib/pkg.h"
|
|
|
|
|
#include "../plib/systemstate.h"
|
2018-10-13 15:15:38 +02:00
|
|
|
#include "accounts/account.h"
|
|
|
|
|
#include "accounts/acscrobj.h"
|
2018-01-29 21:55:48 +01:00
|
|
|
#include "globals/uvars.h"
|
2020-04-17 14:53:39 +02:00
|
|
|
#include "guildscrobj.h"
|
2018-10-13 18:24:24 +02:00
|
|
|
#include "module/guildmod.h"
|
|
|
|
|
#include "module/partymod.h"
|
2020-04-17 14:53:39 +02:00
|
|
|
#include "partyscrobj.h"
|
2018-10-13 00:03:40 +02:00
|
|
|
#include "polclass.h"
|
2018-01-29 21:55:48 +01:00
|
|
|
#include "scrdef.h"
|
|
|
|
|
#include "syshookscript.h"
|
2018-10-13 00:03:40 +02:00
|
|
|
#include "uobject.h"
|
2018-10-13 15:15:38 +02:00
|
|
|
#include "uoscrobj.h"
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
namespace Pol
|
|
|
|
|
{
|
|
|
|
|
namespace Core
|
|
|
|
|
{
|
|
|
|
|
using namespace Bscript;
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
ExportedFunction::ExportedFunction( ExportScript* shs, unsigned in_PC )
|
|
|
|
|
: export_script( shs ), PC( in_PC )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
ExportedFunction::~ExportedFunction()
|
|
|
|
|
{
|
2018-07-31 14:30:29 +02:00
|
|
|
export_script = nullptr;
|
2016-02-19 19:26:35 +01:00
|
|
|
PC = 0;
|
|
|
|
|
}
|
|
|
|
|
const std::string& ExportedFunction::scriptname() const
|
|
|
|
|
{
|
|
|
|
|
return export_script->scriptname();
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
bool ExportedFunction::call( BObjectImp* p0 )
|
|
|
|
|
{
|
|
|
|
|
return export_script->call( PC, p0 );
|
|
|
|
|
}
|
|
|
|
|
bool ExportedFunction::call( BObjectImp* p0, BObjectImp* p1 )
|
|
|
|
|
{
|
|
|
|
|
return export_script->call( PC, p0, p1 );
|
|
|
|
|
}
|
|
|
|
|
bool ExportedFunction::call( BObjectImp* p0, BObjectImp* p1, BObjectImp* p2 )
|
|
|
|
|
{
|
|
|
|
|
return export_script->call( PC, p0, p1, p2 );
|
|
|
|
|
}
|
|
|
|
|
bool ExportedFunction::call( BObjectImp* p0, BObjectImp* p1, BObjectImp* p2, BObjectImp* p3 )
|
|
|
|
|
{
|
|
|
|
|
return export_script->call( PC, p0, p1, p2, p3 );
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
std::string ExportedFunction::call_string( BObjectImp* p0, BObjectImp* p1 )
|
|
|
|
|
{
|
|
|
|
|
return export_script->call_string( PC, p0, p1 );
|
|
|
|
|
}
|
|
|
|
|
std::string ExportedFunction::call_string( BObjectImp* p0, BObjectImp* p1, BObjectImp* p2 )
|
|
|
|
|
{
|
|
|
|
|
return export_script->call_string( PC, p0, p1, p2 );
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
int ExportedFunction::call_long( BObjectImp* p0 )
|
|
|
|
|
{
|
|
|
|
|
return export_script->call_long( PC, p0 );
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
int ExportedFunction::call_long( BObjectImp* p0, BObjectImp* p1 )
|
|
|
|
|
{
|
|
|
|
|
return export_script->call_long( PC, p0, p1 );
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
BObject ExportedFunction::call_object( BObjectImp* p0, BObjectImp* p1 )
|
|
|
|
|
{
|
|
|
|
|
return export_script->call_object( PC, p0, p1 );
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
BObject ExportedFunction::call_object( BObjectImp* p0, BObjectImp* p1, BObjectImp* p2 )
|
|
|
|
|
{
|
|
|
|
|
return export_script->call_object( PC, p0, p1, p2 );
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
SystemHooks::SystemHooks()
|
2018-07-31 14:30:29 +02:00
|
|
|
: check_skill_hook( nullptr ),
|
|
|
|
|
open_spellbook_hook( nullptr ),
|
|
|
|
|
get_book_page_hook( nullptr ),
|
|
|
|
|
combat_advancement_hook( nullptr ),
|
|
|
|
|
parry_advancement_hook( nullptr ),
|
|
|
|
|
attack_hook( nullptr ),
|
|
|
|
|
pushthrough_hook( nullptr ),
|
|
|
|
|
speechmul_hook( nullptr ),
|
|
|
|
|
hitmiss_hook( nullptr ),
|
|
|
|
|
on_cast_hook( nullptr ),
|
|
|
|
|
can_decay( nullptr ),
|
|
|
|
|
ouch_hook( nullptr ),
|
|
|
|
|
can_die( nullptr ),
|
|
|
|
|
un_hide( nullptr ),
|
|
|
|
|
close_customhouse_hook( nullptr ),
|
|
|
|
|
warmode_change( nullptr ),
|
2018-10-06 00:12:51 +08:00
|
|
|
can_trade( nullptr ),
|
2018-10-13 18:24:24 +02:00
|
|
|
consume_ammunition_hook( nullptr ),
|
|
|
|
|
uobject_method_script( nullptr ),
|
|
|
|
|
item_method_script( nullptr ),
|
|
|
|
|
equipment_method_script( nullptr ),
|
|
|
|
|
lockable_method_script( nullptr ),
|
|
|
|
|
map_method_script( nullptr ),
|
|
|
|
|
multi_method_script( nullptr ),
|
|
|
|
|
armor_method_script( nullptr ),
|
|
|
|
|
weapon_method_script( nullptr ),
|
|
|
|
|
door_method_script( nullptr ),
|
|
|
|
|
container_method_script( nullptr ),
|
|
|
|
|
boat_method_script( nullptr ),
|
|
|
|
|
house_method_script( nullptr ),
|
|
|
|
|
spellbook_method_script( nullptr ),
|
|
|
|
|
corpse_method_script( nullptr ),
|
|
|
|
|
npc_method_script( nullptr ),
|
2018-10-14 13:13:16 +02:00
|
|
|
character_method_script( nullptr ),
|
2018-10-13 18:24:24 +02:00
|
|
|
client_method_script( nullptr ),
|
|
|
|
|
account_method_script( nullptr ),
|
|
|
|
|
party_method_script( nullptr ),
|
|
|
|
|
guild_method_script( nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
void hook( ExportScript* shs, const std::string& hookname, const std::string& exfuncname )
|
|
|
|
|
{
|
2018-10-14 13:13:16 +02:00
|
|
|
std::unique_ptr<ExportedFunction>* pphook = nullptr;
|
2016-02-19 19:26:35 +01:00
|
|
|
unsigned nargs;
|
|
|
|
|
if ( hookname == "CheckSkill" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 4;
|
|
|
|
|
pphook = &gamestate.system_hooks.check_skill_hook;
|
|
|
|
|
}
|
|
|
|
|
else if ( hookname == "OpenSpellbook" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 1;
|
|
|
|
|
pphook = &gamestate.system_hooks.open_spellbook_hook;
|
|
|
|
|
}
|
|
|
|
|
else if ( hookname == "GetBookPage" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 2;
|
|
|
|
|
pphook = &gamestate.system_hooks.get_book_page_hook;
|
|
|
|
|
}
|
|
|
|
|
else if ( hookname == "CombatAdvancement" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 3;
|
|
|
|
|
pphook = &gamestate.system_hooks.combat_advancement_hook;
|
|
|
|
|
}
|
|
|
|
|
else if ( hookname == "ParryAdvancement" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 4;
|
|
|
|
|
pphook = &gamestate.system_hooks.parry_advancement_hook;
|
|
|
|
|
}
|
|
|
|
|
else if ( hookname == "Attack" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 2;
|
|
|
|
|
pphook = &gamestate.system_hooks.attack_hook;
|
|
|
|
|
}
|
|
|
|
|
else if ( hookname == "Pushthrough" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 2;
|
|
|
|
|
pphook = &gamestate.system_hooks.pushthrough_hook;
|
|
|
|
|
}
|
|
|
|
|
else if ( hookname == "SpeechMul" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 3;
|
|
|
|
|
pphook = &gamestate.system_hooks.speechmul_hook;
|
|
|
|
|
}
|
|
|
|
|
else if ( hookname == "HitMiss" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 2;
|
|
|
|
|
pphook = &gamestate.system_hooks.hitmiss_hook;
|
|
|
|
|
}
|
|
|
|
|
else if ( hookname == "OnCast" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 2;
|
|
|
|
|
pphook = &gamestate.system_hooks.on_cast_hook;
|
|
|
|
|
}
|
|
|
|
|
else if ( hookname == "CanDecay" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 1;
|
|
|
|
|
pphook = &gamestate.system_hooks.can_decay;
|
|
|
|
|
}
|
|
|
|
|
else if ( hookname == "Ouch" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 4;
|
|
|
|
|
pphook = &gamestate.system_hooks.ouch_hook;
|
|
|
|
|
}
|
|
|
|
|
else if ( hookname == "CanDie" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 1;
|
|
|
|
|
pphook = &gamestate.system_hooks.can_die;
|
|
|
|
|
}
|
|
|
|
|
else if ( hookname == "UnHide" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 1;
|
|
|
|
|
pphook = &gamestate.system_hooks.un_hide;
|
|
|
|
|
}
|
|
|
|
|
else if ( hookname == "CloseCustomHouse" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 2;
|
|
|
|
|
pphook = &gamestate.system_hooks.close_customhouse_hook;
|
|
|
|
|
}
|
|
|
|
|
else if ( hookname == "WarmodeChange" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 2;
|
|
|
|
|
pphook = &gamestate.system_hooks.warmode_change;
|
|
|
|
|
}
|
|
|
|
|
else if ( hookname == "CanTrade" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 3;
|
|
|
|
|
pphook = &gamestate.system_hooks.can_trade;
|
|
|
|
|
}
|
2018-10-06 00:12:51 +08:00
|
|
|
else if ( hookname == "ConsumeAmmunition" )
|
|
|
|
|
{
|
|
|
|
|
nargs = 2;
|
|
|
|
|
pphook = &gamestate.system_hooks.consume_ammunition_hook;
|
|
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
INFO_PRINT << "Unknown SystemHook " << hookname << "\n";
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2018-07-31 14:30:29 +02:00
|
|
|
if ( *pphook != nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
INFO_PRINT << "SystemHook " << hookname << " multiply defined\n"
|
|
|
|
|
<< " Already found in: " << gamestate.system_hooks.check_skill_hook->scriptname()
|
|
|
|
|
<< "\n"
|
|
|
|
|
<< " Also defined in: " << shs->scriptname() << "\n";
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
unsigned PC;
|
|
|
|
|
if ( !shs->FindExportedFunction( exfuncname, nargs, PC ) )
|
|
|
|
|
{
|
|
|
|
|
INFO_PRINT << "Exported Function " << exfuncname << " not found in " << shs->scriptname()
|
|
|
|
|
<< "\n";
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2020-04-17 14:53:39 +02:00
|
|
|
*pphook = std::make_unique<ExportedFunction>( shs, PC );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2018-10-13 00:03:40 +02:00
|
|
|
namespace
|
|
|
|
|
{
|
2018-10-13 18:24:24 +02:00
|
|
|
void setMethod( std::unique_ptr<ExportScript>* script, Plib::Package* pkg,
|
|
|
|
|
const std::string& scriptname )
|
2018-10-13 00:03:40 +02:00
|
|
|
{
|
2020-04-17 14:53:39 +02:00
|
|
|
auto shs = std::make_unique<ExportScript>( pkg, scriptname );
|
2018-10-13 00:03:40 +02:00
|
|
|
if ( shs->Initialize() )
|
|
|
|
|
script->swap( shs );
|
|
|
|
|
}
|
|
|
|
|
} // namespace
|
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
void load_system_hooks()
|
|
|
|
|
{
|
|
|
|
|
for ( Plib::Packages::const_iterator citr = Plib::systemstate.packages.begin();
|
|
|
|
|
citr != Plib::systemstate.packages.end(); ++citr )
|
|
|
|
|
{
|
|
|
|
|
Plib::Package* pkg = ( *citr );
|
|
|
|
|
std::string fname = Plib::GetPackageCfgPath( pkg, "syshook.cfg" );
|
|
|
|
|
if ( Clib::FileExists( fname.c_str() ) )
|
|
|
|
|
{
|
2018-10-13 00:03:40 +02:00
|
|
|
Clib::ConfigFile cf( fname.c_str(), "SystemHookScript SystemMethod" );
|
2016-02-19 19:26:35 +01:00
|
|
|
Clib::ConfigElem elem;
|
|
|
|
|
while ( cf.read( elem ) )
|
|
|
|
|
{
|
2018-10-13 00:03:40 +02:00
|
|
|
if ( !stricmp( elem.type(), "SystemHookScript" ) )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2020-04-17 14:53:39 +02:00
|
|
|
auto shs = std::make_unique<ExportScript>( pkg, elem.rest() );
|
2018-10-13 00:03:40 +02:00
|
|
|
if ( shs->Initialize() )
|
|
|
|
|
{
|
|
|
|
|
std::string hookname, exfuncname;
|
|
|
|
|
while ( elem.remove_first_prop( &hookname, &exfuncname ) )
|
|
|
|
|
{
|
|
|
|
|
if ( exfuncname.empty() )
|
|
|
|
|
exfuncname = hookname;
|
2018-10-14 13:13:16 +02:00
|
|
|
hook( shs.get(), hookname, exfuncname );
|
2018-10-13 00:03:40 +02:00
|
|
|
}
|
2018-10-14 13:13:16 +02:00
|
|
|
gamestate.export_scripts.push_back( std::move( shs ) );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
2018-10-13 00:03:40 +02:00
|
|
|
else // SystemMethod
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2018-10-13 00:03:40 +02:00
|
|
|
std::string hookclass, script;
|
|
|
|
|
|
|
|
|
|
while ( elem.remove_first_prop( &hookclass, &script ) )
|
|
|
|
|
{
|
2019-01-12 11:46:30 +01:00
|
|
|
Clib::mklowerASCII( hookclass );
|
2018-10-13 00:03:40 +02:00
|
|
|
if ( !hookclass.compare( "uobject" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.uobject_method_script, pkg, script );
|
|
|
|
|
else if ( !hookclass.compare( "item" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.item_method_script, pkg, script );
|
|
|
|
|
else if ( !hookclass.compare( "equipment" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.equipment_method_script, pkg, script );
|
|
|
|
|
else if ( !hookclass.compare( "lockable" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.lockable_method_script, pkg, script );
|
|
|
|
|
else if ( !hookclass.compare( "map" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.map_method_script, pkg, script );
|
|
|
|
|
else if ( !hookclass.compare( "multi" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.multi_method_script, pkg, script );
|
|
|
|
|
else if ( !hookclass.compare( "armor" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.armor_method_script, pkg, script );
|
|
|
|
|
else if ( !hookclass.compare( "weapon" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.weapon_method_script, pkg, script );
|
|
|
|
|
else if ( !hookclass.compare( "door" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.door_method_script, pkg, script );
|
|
|
|
|
else if ( !hookclass.compare( "container" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.container_method_script, pkg, script );
|
|
|
|
|
else if ( !hookclass.compare( "boat" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.boat_method_script, pkg, script );
|
|
|
|
|
else if ( !hookclass.compare( "house" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.house_method_script, pkg, script );
|
|
|
|
|
else if ( !hookclass.compare( "spellbook" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.spellbook_method_script, pkg, script );
|
|
|
|
|
else if ( !hookclass.compare( "corpse" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.corpse_method_script, pkg, script );
|
|
|
|
|
else if ( !hookclass.compare( "npc" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.npc_method_script, pkg, script );
|
2018-10-14 13:13:16 +02:00
|
|
|
else if ( !hookclass.compare( "character" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.character_method_script, pkg, script );
|
2018-10-13 15:15:38 +02:00
|
|
|
else if ( !hookclass.compare( "client" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.client_method_script, pkg, script );
|
|
|
|
|
else if ( !hookclass.compare( "account" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.account_method_script, pkg, script );
|
2018-10-13 18:24:24 +02:00
|
|
|
else if ( !hookclass.compare( "party" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.party_method_script, pkg, script );
|
|
|
|
|
else if ( !hookclass.compare( "guild" ) )
|
|
|
|
|
setMethod( &gamestate.system_hooks.guild_method_script, pkg, script );
|
2018-10-13 00:03:40 +02:00
|
|
|
else
|
|
|
|
|
POLLOG_INFO << "Unknown class used for method hook: " << hookclass << "\n";
|
|
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2018-10-13 00:03:40 +02:00
|
|
|
BObjectImp* SystemHooks::call_script_method( const char* methodname, Executor* ex,
|
|
|
|
|
UObject* obj ) const
|
|
|
|
|
{
|
|
|
|
|
ExportScript* hook;
|
|
|
|
|
unsigned PC;
|
|
|
|
|
if ( obj->get_method_hook( methodname, ex, &hook, &PC ) )
|
|
|
|
|
return hook->call( PC, obj->make_ref(), ex->fparams );
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-13 15:15:38 +02:00
|
|
|
Bscript::BObjectImp* SystemHooks::call_script_method( const char* methodname, Bscript::Executor* ex,
|
|
|
|
|
Bscript::BApplicObjBase* obj ) const
|
|
|
|
|
{
|
|
|
|
|
ExportScript* script( nullptr );
|
2018-10-13 18:24:24 +02:00
|
|
|
if ( obj->object_type() == &Accounts::accountobjimp_type )
|
2018-10-13 15:15:38 +02:00
|
|
|
script = account_method_script.get();
|
2018-10-13 18:24:24 +02:00
|
|
|
else if ( obj->object_type() == &Module::eclientrefobjimp_type )
|
|
|
|
|
script = client_method_script.get();
|
|
|
|
|
else if ( obj->object_type() == &Module::party_type )
|
|
|
|
|
script = party_method_script.get();
|
|
|
|
|
else if ( obj->object_type() == &Module::guild_type )
|
|
|
|
|
script = guild_method_script.get();
|
2018-10-13 15:15:38 +02:00
|
|
|
|
|
|
|
|
if ( script != nullptr )
|
|
|
|
|
{
|
|
|
|
|
unsigned PC;
|
|
|
|
|
ExportScript* hook;
|
|
|
|
|
if ( get_method_hook( script, methodname, ex, &hook, &PC ) )
|
|
|
|
|
return hook->call( PC, obj, ex->fparams );
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-13 00:03:40 +02:00
|
|
|
bool SystemHooks::get_method_hook( ExportScript* search_script, const char* methodname,
|
|
|
|
|
Bscript::Executor* ex, ExportScript** hook,
|
|
|
|
|
unsigned int* PC ) const
|
|
|
|
|
{
|
|
|
|
|
if ( search_script && search_script->FindExportedFunction(
|
|
|
|
|
methodname, static_cast<unsigned int>( ex->numParams() + 1 ), *PC ) )
|
|
|
|
|
{
|
|
|
|
|
*hook = search_script;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
void SystemHooks::unload_system_hooks()
|
|
|
|
|
{
|
|
|
|
|
gamestate.export_scripts.clear();
|
2018-10-14 13:13:16 +02:00
|
|
|
attack_hook.reset( nullptr );
|
|
|
|
|
check_skill_hook.reset( nullptr );
|
|
|
|
|
combat_advancement_hook.reset( nullptr );
|
|
|
|
|
get_book_page_hook.reset( nullptr );
|
|
|
|
|
hitmiss_hook.reset( nullptr );
|
|
|
|
|
open_spellbook_hook.reset( nullptr );
|
|
|
|
|
parry_advancement_hook.reset( nullptr );
|
|
|
|
|
pushthrough_hook.reset( nullptr );
|
|
|
|
|
speechmul_hook.reset( nullptr );
|
|
|
|
|
on_cast_hook.reset( nullptr );
|
|
|
|
|
can_decay.reset( nullptr );
|
|
|
|
|
ouch_hook.reset( nullptr );
|
|
|
|
|
can_die.reset( nullptr );
|
|
|
|
|
un_hide.reset( nullptr );
|
|
|
|
|
close_customhouse_hook.reset( nullptr );
|
|
|
|
|
warmode_change.reset( nullptr );
|
|
|
|
|
can_trade.reset( nullptr );
|
|
|
|
|
consume_ammunition_hook.reset( nullptr );
|
2018-10-13 00:03:40 +02:00
|
|
|
|
|
|
|
|
uobject_method_script.reset( nullptr );
|
|
|
|
|
item_method_script.reset( nullptr );
|
|
|
|
|
equipment_method_script.reset( nullptr );
|
|
|
|
|
lockable_method_script.reset( nullptr );
|
|
|
|
|
map_method_script.reset( nullptr );
|
|
|
|
|
multi_method_script.reset( nullptr );
|
|
|
|
|
armor_method_script.reset( nullptr );
|
|
|
|
|
weapon_method_script.reset( nullptr );
|
|
|
|
|
door_method_script.reset( nullptr );
|
|
|
|
|
container_method_script.reset( nullptr );
|
|
|
|
|
boat_method_script.reset( nullptr );
|
|
|
|
|
house_method_script.reset( nullptr );
|
|
|
|
|
spellbook_method_script.reset( nullptr );
|
|
|
|
|
corpse_method_script.reset( nullptr );
|
|
|
|
|
npc_method_script.reset( nullptr );
|
2018-10-14 13:13:16 +02:00
|
|
|
character_method_script.reset( nullptr );
|
2018-10-13 15:15:38 +02:00
|
|
|
client_method_script.reset( nullptr );
|
|
|
|
|
account_method_script.reset( nullptr );
|
2018-10-13 18:24:24 +02:00
|
|
|
party_method_script.reset( nullptr );
|
|
|
|
|
guild_method_script.reset( nullptr );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
ExportScript* FindExportScript( const ScriptDef& sd )
|
|
|
|
|
{
|
2018-10-14 13:13:16 +02:00
|
|
|
for ( const auto& ps : gamestate.export_scripts )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
if ( ps->scriptname() == sd.name() )
|
2018-10-14 13:13:16 +02:00
|
|
|
return ps.get();
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2020-04-17 14:53:39 +02:00
|
|
|
auto ps = std::make_unique<ExportScript>( sd );
|
2016-02-19 19:26:35 +01:00
|
|
|
if ( ps->Initialize() )
|
|
|
|
|
{
|
2018-10-14 13:13:16 +02:00
|
|
|
gamestate.export_scripts.push_back( std::move( ps ) );
|
|
|
|
|
return gamestate.export_scripts.back().get();
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
2018-10-14 13:13:16 +02:00
|
|
|
return nullptr;
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
// descriptor is script:function (or :pkg:script:function, or ::script:function?)
|
|
|
|
|
ExportedFunction* FindExportedFunction( Clib::ConfigElem& elem, const Plib::Package* pkg,
|
|
|
|
|
const std::string& descriptor, unsigned nargs,
|
|
|
|
|
bool complain_if_missing )
|
|
|
|
|
{
|
|
|
|
|
// first, split up script and functionname
|
|
|
|
|
auto colon_pos = descriptor.find_last_of( ':' );
|
|
|
|
|
if ( colon_pos == std::string::npos )
|
|
|
|
|
elem.throw_error( "Expected ':' in exported function descriptor (" + descriptor + ")" );
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
std::string scriptname = descriptor.substr( 0, colon_pos );
|
|
|
|
|
std::string functionname = descriptor.substr( colon_pos + 1, std::string::npos );
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
ScriptDef sd( scriptname, pkg, "" );
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
ExportScript* export_script = FindExportScript( sd );
|
|
|
|
|
if ( !export_script )
|
|
|
|
|
{
|
|
|
|
|
if ( complain_if_missing )
|
|
|
|
|
elem.throw_error( "Export Script " + sd.name() + " not found" );
|
|
|
|
|
else
|
2018-07-31 14:30:29 +02:00
|
|
|
return nullptr;
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
unsigned PC;
|
|
|
|
|
if ( !export_script->FindExportedFunction( functionname, nargs, PC ) )
|
|
|
|
|
{
|
|
|
|
|
if ( complain_if_missing )
|
|
|
|
|
elem.throw_error( "Exported Function " + functionname + " not found in " +
|
|
|
|
|
export_script->scriptname() );
|
|
|
|
|
else
|
2018-07-31 14:30:29 +02:00
|
|
|
return nullptr;
|
2016-02-11 22:54:43 +01:00
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
|
|
|
|
|
return new ExportedFunction( export_script, PC );
|
|
|
|
|
}
|
2018-10-06 00:12:51 +08:00
|
|
|
} // namespace Core
|
|
|
|
|
} // namespace Pol
|