Skip to content

Commit

Permalink
Scripting: Bindings for the player
Browse files Browse the repository at this point in the history
Added the built-in class `App.Player`. This allows scripts to access player information such as health, armor, and powerup status.

IssueID #1539
  • Loading branch information
skyjake committed Dec 15, 2019
1 parent 55e4359 commit abe3a57
Show file tree
Hide file tree
Showing 12 changed files with 224 additions and 47 deletions.
15 changes: 12 additions & 3 deletions doomsday/apps/client/src/clientapp.cpp
Expand Up @@ -125,6 +125,11 @@ static void continueInitWithEventLoopRunning()
#endif
}

static Value *Function_App_ConsolePlayer(Context &, const Function::ArgumentValues &)
{
return new RecordValue(DoomsdayApp::players().at(consolePlayer).objectNamespace());
}

static Value *Function_App_GamePlugin(Context &, Function::ArgumentValues const &)
{
if (App_CurrentGame().isNull())
Expand Down Expand Up @@ -547,9 +552,13 @@ ClientApp::ClientApp(int &argc, char **argv)
// We must presently set the current game manually (the collection is global).
setGame(games().nullGame());

d->binder.init(scriptSystem()["App"])
<< DENG2_FUNC_NOARG (App_GamePlugin, "gamePlugin")
<< DENG2_FUNC_NOARG (App_Quit, "quit");
// Script bindings.
{
d->binder.init(scriptSystem()["App"])
<< DENG2_FUNC_NOARG (App_ConsolePlayer, "consolePlayer")
<< DENG2_FUNC_NOARG (App_GamePlugin, "gamePlugin")
<< DENG2_FUNC_NOARG (App_Quit, "quit");
}

#if !defined (DENG_MOBILE)
/// @todo Remove the splash screen when file system indexing can be done as
Expand Down
13 changes: 3 additions & 10 deletions doomsday/apps/client/src/world/base/bindings_world.cpp
Expand Up @@ -32,10 +32,7 @@ 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 &)
{
Expand Down Expand Up @@ -77,14 +74,10 @@ static Value *Function_Thing_Recoil(Context &ctx, const Function::ArgumentValues
return nullptr;
}

//-------------------------------------------------------------------------------------------------

void initBindings(Binder &binder, Record &worldModule)
{
// Global functions.
{
binder.init(worldModule)
<< DENG2_FUNC_NOARG(World_ConsolePlayer, "consolePlayer");
}

// Thing
{
Record &thing = worldModule.addSubrecord("Thing");
Expand Down
9 changes: 8 additions & 1 deletion doomsday/apps/libdoomsday/include/doomsday/player.h
Expand Up @@ -96,6 +96,7 @@ typedef struct ddplayer_s {

#ifdef __cplusplus

#include <de/IObject>
#include <de/Record>

class World;
Expand All @@ -109,7 +110,7 @@ class World;
* public. Some members could be moved into an internal, engine-only private class,
* if necessary. -jk
*/
class LIBDOOMSDAY_PUBLIC Player
class LIBDOOMSDAY_PUBLIC Player : public de::IObject
{
public:
// ID number. Each client has a unique ID number.
Expand All @@ -130,6 +131,8 @@ class LIBDOOMSDAY_PUBLIC Player

virtual ~Player();

void initBindings();

virtual void setWorld(World *world);

ddplayer_t &publicData();
Expand Down Expand Up @@ -164,6 +167,10 @@ class LIBDOOMSDAY_PUBLIC Player

DENG2_CAST_METHODS()

// Implements IObject.
de::Record &objectNamespace();
const de::Record &objectNamespace() const;

private:
DENG2_PRIVATE(d)
};
Expand Down
2 changes: 2 additions & 0 deletions doomsday/apps/libdoomsday/include/doomsday/players.h
Expand Up @@ -72,6 +72,8 @@ class LIBDOOMSDAY_PUBLIC Players
*/
int indexOf(ddplayer_s const *publicData) const;

void initBindings();

private:
DENG2_PRIVATE(d)
};
Expand Down
1 change: 1 addition & 0 deletions doomsday/apps/libdoomsday/src/doomsdayapp.cpp
Expand Up @@ -133,6 +133,7 @@ DENG2_PIMPL(DoomsdayApp)
audienceForGameChange += scriptAudienceForGameChange;

initBindings(binder);
players.initBindings();

gameProfiles.setGames(games);
saveGames .setGames(games);
Expand Down
44 changes: 41 additions & 3 deletions doomsday/apps/libdoomsday/src/doomsdayapp_bindings.cpp
Expand Up @@ -17,7 +17,10 @@
*/

#include "doomsday/DoomsdayApp"
#include "doomsday/world/mobj.h"
#include "doomsday/world/thinkerdata.h"

#include <de/Context>
#include <de/Folder>
#include <de/ScriptSystem>

Expand All @@ -37,6 +40,30 @@ static Value *Function_App_Download(Context &, Function::ArgumentValues const &a
return nullptr;
}

//-------------------------------------------------------------------------------------------------

static int playerIndex(const Context &ctx)
{
return ctx.selfInstance().geti("__id__", 0);
}

static Value *Function_Player_Id(Context &ctx, const Function::ArgumentValues &)
{
return new NumberValue(playerIndex(ctx));
}

static Value *Function_Player_Thing(Context &ctx, const Function::ArgumentValues &)
{
const int plrNum = playerIndex(ctx);
if (const mobj_t *mo = DoomsdayApp::players().at(plrNum).publicData().mo)
{
return new RecordValue(THINKER_DATA(mo->thinker, ThinkerData).objectNamespace());
}
return nullptr;
}

//-------------------------------------------------------------------------------------------------

static Value *Function_FS_RefreshPackageFolders(Context &, const Function::ArgumentValues &)
{
LOG_SCR_MSG("Initializing package folders...");
Expand All @@ -49,9 +76,20 @@ static Value *Function_FS_RefreshPackageFolders(Context &, const Function::Argum

void DoomsdayApp::initBindings(Binder &binder)
{
binder.init(ScriptSystem::get()["App"])
auto &scr = ScriptSystem::get();
auto &appModule = scr["App"];

binder.init(appModule)
<< DENG2_FUNC(App_Download, "download", "packageId");

binder.init(ScriptSystem::get()["FS"])
<< DENG2_FUNC_NOARG(FS_RefreshPackageFolders, "refreshPackageFolders");
// Player
{
Record &player = appModule.addSubrecord("Player");
binder.init(player)
<< DENG2_FUNC_NOARG(Player_Id, "id")
<< DENG2_FUNC_NOARG(Player_Thing, "thing");
}

binder.init(scr["FS"])
<< DENG2_FUNC_NOARG(FS_RefreshPackageFolders, "refreshPackageFolders");
}
17 changes: 17 additions & 0 deletions doomsday/apps/libdoomsday/src/player.cpp
Expand Up @@ -19,6 +19,8 @@
#include "doomsday/player.h"
#include "doomsday/world/world.h"

#include <de/ScriptSystem>

using namespace de;

DENG2_PIMPL_NOREF(Player)
Expand Down Expand Up @@ -55,6 +57,11 @@ Player::Player()
Player::~Player()
{}

void Player::initBindings()
{
objectNamespace().addSuperRecord(ScriptSystem::builtInClass("App", "Player"));
}

void Player::setWorld(World *world)
{
if (world)
Expand Down Expand Up @@ -106,6 +113,16 @@ Pinger const &Player::pinger() const
void Player::tick(timespan_t /*elapsed*/)
{}

Record &Player::objectNamespace()
{
return d->info;
}

const Record &Player::objectNamespace() const
{
return d->info;
}

short P_LookDirToShort(float lookDir)
{
int dir = int( lookDir/110.f * DDMAXSHORT );
Expand Down
8 changes: 8 additions & 0 deletions doomsday/apps/libdoomsday/src/players.cpp
Expand Up @@ -96,3 +96,11 @@ int Players::indexOf(ddplayer_s const *publicData) const
}
return -1;
}

void Players::initBindings()
{
for (auto *plr : d->players)
{
plr->initBindings();
}
}
12 changes: 10 additions & 2 deletions doomsday/apps/libdoomsday/src/world/actions.cpp
Expand Up @@ -38,11 +38,13 @@ static String s_currentAction;
static void C_DECL A_DoomsdayScript(void *actor)
{
struct mobj_s *mobj = reinterpret_cast<struct mobj_s *>(actor);
int plrNum = -1;

auto &plrs = DoomsdayApp::players();

// The actor can also be a player in the case of psprites.
// Look up the corresponding player.
{
auto &plrs = DoomsdayApp::players();
for (int i = 0; i < DDMAXPLAYERS; ++i)
{
// Note: It is assumed that the player data structure begins with a pointer to
Expand All @@ -53,6 +55,7 @@ static void C_DECL A_DoomsdayScript(void *actor)
{
// Refer to the player mobj instead.
mobj = plrs.at(i).publicData().mo;
plrNum = i;
}
}
}
Expand All @@ -62,6 +65,11 @@ static void C_DECL A_DoomsdayScript(void *actor)
{
const ThinkerData &data = THINKER_DATA(mobj->thinker, ThinkerData);
Record ns;
if (plrNum >= 0)
{
ns.add(new Variable(QStringLiteral("player"),
new RecordValue(plrs.at(plrNum).objectNamespace())));
}
ns.add(new Variable(QStringLiteral("self"), new RecordValue(data.objectNamespace())));
Process proc(&ns);
const Script script(s_currentAction);
Expand All @@ -76,7 +84,7 @@ static void C_DECL A_DoomsdayScript(void *actor)

static bool isScriptAction(const String &name)
{
return name.contains('(') && name.contains(")");
return !name.beginsWith("A_");
}

void P_GetGameActions()
Expand Down

0 comments on commit abe3a57

Please sign in to comment.