From 9870aa3a486720bb8aa01a2714490faaa2a3ebf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Kera=CC=88nen?= Date: Sat, 16 Nov 2019 21:21:27 +0200 Subject: [PATCH] Scripting: Added more World and Game bindings The following functions were added: - World.consolePlayer() - World.Thing.id() - Game.setMessage() - Game.setYellowMessage() (for Hexen only) --- .../client/src/world/base/bindings_world.cpp | 18 ++++++ doomsday/apps/plugins/common/src/common.cpp | 59 ++++++++++++++++++- 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/doomsday/apps/client/src/world/base/bindings_world.cpp b/doomsday/apps/client/src/world/base/bindings_world.cpp index 1dd0a2e327..eee34afb51 100644 --- a/doomsday/apps/client/src/world/base/bindings_world.cpp +++ b/doomsday/apps/client/src/world/base/bindings_world.cpp @@ -20,6 +20,7 @@ #include "world/clientserverworld.h" #include "world/map.h" #include "world/thinkers.h" +#include "world/p_players.h" #include "audio/audiosystem.h" #include "dd_main.h" @@ -31,6 +32,16 @@ using namespace de; namespace world { +static Value *Function_World_ConsolePlayer(Context &, const Function::ArgumentValues &) +{ + return new NumberValue(consolePlayer); +} + +static Value *Function_Thing_Id(Context &ctx, const Function::ArgumentValues &) +{ + return new NumberValue(ClientServerWorld::contextMobj(ctx).thinker.id); +} + static Value *Function_Thing_Health(Context &ctx, const Function::ArgumentValues &) { return new NumberValue(ClientServerWorld::contextMobj(ctx).health); @@ -54,6 +65,12 @@ static Value *Function_Thing_StartSound(Context &ctx, const Function::ArgumentVa void initBindings(Binder &binder, Record &worldModule) { + // Global functions. + { + binder.init(worldModule) + << DENG2_FUNC_NOARG(World_ConsolePlayer, "consolePlayer"); + } + // Thing { Record &thing = worldModule.addSubrecord("Thing"); @@ -62,6 +79,7 @@ void initBindings(Binder &binder, Record &worldModule) startSoundArgs["volume"] = new NumberValue(1.0); binder.init(thing) + << DENG2_FUNC_NOARG(Thing_Id, "id") << DENG2_FUNC_NOARG(Thing_Health, "health") << DENG2_FUNC_DEFS (Thing_StartSound, "startSound", "id" << "volume", startSoundArgs); diff --git a/doomsday/apps/plugins/common/src/common.cpp b/doomsday/apps/plugins/common/src/common.cpp index 017cf4443d..1cb8526feb 100644 --- a/doomsday/apps/plugins/common/src/common.cpp +++ b/doomsday/apps/plugins/common/src/common.cpp @@ -30,7 +30,9 @@ #include #include #include +#include #include +#include #include int Common_GetInteger(int id) @@ -129,6 +131,7 @@ void Common_Register() //------------------------------------------------------------------------------------------------- static de::Binder *gameBindings; +static de::Record *gameModule; static mobj_t &instanceMobj(const de::Context &ctx) { @@ -198,10 +201,42 @@ static de::Value *Function_Thing_Attack(de::Context &ctx, const de::Function::Ar } #endif +static int playerNumberArgument(const de::Value &arg) +{ + if (de::is(arg)) + { + return CONSOLEPLAYER; + } + const int plrNum = arg.asInt(); + if (plrNum < 0 || plrNum >= MAXPLAYERS) + { + throw de::Error("playerNumberArgument", "Player index out of bounds"); + } + return plrNum; +} + +static de::Value *Function_SetMessage(de::Context &, const de::Function::ArgumentValues &args) +{ + const int plrNum = playerNumberArgument(*args.at(1)); + P_SetMessage(&players[plrNum], args.at(0)->asText().toLatin1()); + return nullptr; +} + +#if defined (__JHEXEN__) +static de::Value *Function_SetYellowMessage(de::Context &, const de::Function::ArgumentValues &args) +{ + const int plrNum = playerNumberArgument(*args.at(1)); + P_SetYellowMessage(&players[plrNum], args.at(0)->asText().toLatin1()); + return nullptr; +} +#endif + void Common_Load() { using namespace de; + gameModule = new Record; + Function::Defaults spawnMissileArgs; spawnMissileArgs["angle"] = new NoneValue; spawnMissileArgs["momz"] = new NumberValue(0.0); @@ -210,18 +245,38 @@ void Common_Load() attackArgs["damage"] = new NumberValue(0.0); attackArgs["missile"] = new NoneValue; + Function::Defaults setMessageArgs; + setMessageArgs["player"] = new NoneValue; + DENG2_ASSERT(gameBindings == nullptr); gameBindings = new Binder(nullptr, Binder::FunctionsOwned); // must delete when plugin unloaded gameBindings->init(ScriptSystem::get().builtInClass("World", "Thing")) #if defined(__JHERETIC__) - << DENG2_FUNC_DEFS(Thing_Attack, "attack", "damage" << "missile", attackArgs) + << DENG2_FUNC_DEFS(Thing_Attack, "attack", "damage" << "missile", attackArgs) #endif - << DENG2_FUNC_DEFS(Thing_SpawnMissile, "spawnMissile", "id" << "angle" << "momz", spawnMissileArgs); + << DENG2_FUNC_DEFS(Thing_SpawnMissile, "spawnMissile", "id" << "angle" << "momz", spawnMissileArgs); + + gameBindings->init(*gameModule) + << DENG2_FUNC_DEFS(SetMessage, "setMessage", "message" << "player", setMessageArgs); + + #if defined(__JHEXEN__) + { + Function::Defaults setYellowMessageArgs; + setYellowMessageArgs["player"] = new NoneValue; + *gameBindings + << DENG2_FUNC_DEFS(SetYellowMessage, "setYellowMessage", "message" << "player", setYellowMessageArgs); + } + #endif + + ScriptSystem::get().addNativeModule("Game", *gameModule); } void Common_Unload() { DENG2_ASSERT(gameBindings != nullptr); + de::ScriptSystem::get().removeNativeModule("Game"); delete gameBindings; gameBindings = nullptr; + delete gameModule; + gameModule = nullptr; }