Skip to content

Commit

Permalink
Lua: Add basic APIs for walking to a towner
Browse files Browse the repository at this point in the history
This may not be how we'll eventually expose towners
but it's good enough for now.
  • Loading branch information
glebm committed Jan 26, 2025
1 parent 5b66f12 commit 32f9cc9
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 13 deletions.
2 changes: 2 additions & 0 deletions Source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,9 @@ set(libdevilutionx_SRCS
lua/modules/dev/towners.cpp
lua/modules/i18n.cpp
lua/modules/log.cpp
lua/modules/player.cpp
lua/modules/render.cpp
lua/modules/towners.cpp
lua/repl.cpp

panels/charpanel.cpp
Expand Down
4 changes: 4 additions & 0 deletions Source/lua/lua.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
#include "lua/modules/audio.hpp"
#include "lua/modules/i18n.hpp"
#include "lua/modules/log.hpp"
#include "lua/modules/player.hpp"
#include "lua/modules/render.hpp"
#include "lua/modules/towners.hpp"
#include "options.h"
#include "plrmsg.h"
#include "utils/console.h"
Expand Down Expand Up @@ -236,7 +238,9 @@ void LuaInitialize()
"devilutionx.i18n", LuaI18nModule(lua),
"devilutionx.log", LuaLogModule(lua),
"devilutionx.audio", LuaAudioModule(lua),
"devilutionx.player", LuaPlayerModule(lua),
"devilutionx.render", LuaRenderModule(lua),
"devilutionx.towners", LuaTownersModule(lua),
"devilutionx.message", [](std::string_view text) { EventPlrMsg(text, UiFlags::ColorRed); },
// This package is loaded without a sandbox:
"inspect", RunScript(/*env=*/std::nullopt, "inspect", /*optional=*/false));
Expand Down
22 changes: 22 additions & 0 deletions Source/lua/modules/player.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "lua/modules/player.hpp"

#include <sol/sol.hpp>

#include "engine/point.hpp"
#include "lua/metadoc.hpp"
#include "player.h"

namespace devilution {

sol::table LuaPlayerModule(sol::state_view &lua)
{
sol::table table = lua.create_table();
SetDocumented(table, "walk_to", "(x: integer, y: integer)",
"Walk to the given coordinates",
[](int x, int y) {
NetSendCmdLoc(MyPlayerId, true, CMD_WALKXY, Point { x, y });
});
return table;
}

} // namespace devilution
9 changes: 9 additions & 0 deletions Source/lua/modules/player.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <sol/sol.hpp>

namespace devilution {

sol::table LuaPlayerModule(sol::state_view &lua);

} // namespace devilution
55 changes: 55 additions & 0 deletions Source/lua/modules/towners.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include "lua/modules/towners.hpp"

#include <optional>
#include <utility>

#include <sol/sol.hpp>

#include "engine/point.hpp"
#include "lua/metadoc.hpp"
#include "player.h"
#include "towners.h"

namespace devilution {
namespace {

const char *const TownerTableNames[NUM_TOWNER_TYPES] {
"griswold",
"pepin",
"deadguy",
"ogden",
"cain",
"farnham",
"adria",
"gillian",
"wirt",
"cow",
"lester",
"celia",
"nut",
};

void PopulateTownerTable(_talker_id townerId, sol::table &out)
{
SetDocumented(out, "position", "()",
"Returns towner coordinates",
[townerId]() -> std::optional<std::pair<int, int>> {
const Towner *towner = GetTowner(townerId);
if (towner == nullptr) return std::nullopt;
return std::make_pair(towner->position.x, towner->position.y);
});
}
} // namespace

sol::table LuaTownersModule(sol::state_view &lua)
{
sol::table table = lua.create_table();
for (uint8_t townerId = TOWN_SMITH; townerId < NUM_TOWNER_TYPES; ++townerId) {
sol::table townerTable = lua.create_table();
PopulateTownerTable(static_cast<_talker_id>(townerId), townerTable);
SetDocumented(table, TownerTableNames[townerId], /*signature=*/"", TownerLongNames[townerId], std::move(townerTable));
}
return table;
}

} // namespace devilution
9 changes: 9 additions & 0 deletions Source/lua/modules/towners.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <sol/sol.hpp>

namespace devilution {

sol::table LuaTownersModule(sol::state_view &lua);

} // namespace devilution
30 changes: 17 additions & 13 deletions Source/towners.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ void InitTownerInfo(int16_t i, const TownerData &townerData)
auto &towner = Towners[i];

towner._ttype = townerData.type;
towner.name = _(TownerLongNames[townerData.type]);
towner.position = townerData.position;
towner.talk = townerData.talk;

Expand Down Expand Up @@ -81,7 +82,6 @@ void InitSmith(Towner &towner, const TownerData &townerData)
};
towner.animOrder = { AnimOrder };
LoadTownerAnimations(towner, "towners\\smith\\smithn", 16, 3);
towner.name = _("Griswold the Blacksmith");
towner.gossip = PickRandomlyAmong({ TEXT_GRISWOLD2, TEXT_GRISWOLD3, TEXT_GRISWOLD4, TEXT_GRISWOLD5, TEXT_GRISWOLD6, TEXT_GRISWOLD7, TEXT_GRISWOLD8, TEXT_GRISWOLD9, TEXT_GRISWOLD10, TEXT_GRISWOLD12, TEXT_GRISWOLD13 });
}

Expand All @@ -103,7 +103,6 @@ void InitBarOwner(Towner &towner, const TownerData &townerData)
};
towner.animOrder = { AnimOrder };
LoadTownerAnimations(towner, "towners\\twnf\\twnfn", 16, 3);
towner.name = _("Ogden the Tavern owner");
towner.gossip = PickRandomlyAmong({ TEXT_OGDEN2, TEXT_OGDEN3, TEXT_OGDEN4, TEXT_OGDEN5, TEXT_OGDEN6, TEXT_OGDEN8, TEXT_OGDEN9, TEXT_OGDEN10 });
}

Expand All @@ -112,7 +111,6 @@ void InitTownDead(Towner &towner, const TownerData &townerData)
towner._tAnimWidth = 96;
towner.animOrder = {};
LoadTownerAnimations(towner, "towners\\butch\\deadguy", 8, 6);
towner.name = _("Wounded Townsman");
}

void InitWitch(Towner &towner, const TownerData &townerData)
Expand All @@ -133,7 +131,6 @@ void InitWitch(Towner &towner, const TownerData &townerData)
};
towner.animOrder = { AnimOrder };
LoadTownerAnimations(towner, "towners\\townwmn1\\witch", 19, 6);
towner.name = _("Adria the Witch");
towner.gossip = PickRandomlyAmong({ TEXT_ADRIA2, TEXT_ADRIA3, TEXT_ADRIA4, TEXT_ADRIA5, TEXT_ADRIA6, TEXT_ADRIA7, TEXT_ADRIA8, TEXT_ADRIA9, TEXT_ADRIA10, TEXT_ADRIA12, TEXT_ADRIA13 });
}

Expand All @@ -142,7 +139,6 @@ void InitBarmaid(Towner &towner, const TownerData &townerData)
towner._tAnimWidth = 96;
towner.animOrder = {};
LoadTownerAnimations(towner, "towners\\townwmn1\\wmnn", 18, 6);
towner.name = _("Gillian the Barmaid");
towner.gossip = PickRandomlyAmong({ TEXT_GILLIAN2, TEXT_GILLIAN3, TEXT_GILLIAN4, TEXT_GILLIAN5, TEXT_GILLIAN6, TEXT_GILLIAN7, TEXT_GILLIAN9, TEXT_GILLIAN10 });
}

Expand All @@ -151,7 +147,6 @@ void InitBoy(Towner &towner, const TownerData &townerData)
towner._tAnimWidth = 96;
towner.animOrder = {};
LoadTownerAnimations(towner, "towners\\townboy\\pegkid1", 20, 6);
towner.name = _("Wirt the Peg-legged boy");
towner.gossip = PickRandomlyAmong({ TEXT_WIRT2, TEXT_WIRT3, TEXT_WIRT4, TEXT_WIRT5, TEXT_WIRT6, TEXT_WIRT7, TEXT_WIRT8, TEXT_WIRT9, TEXT_WIRT11, TEXT_WIRT12 });
}

Expand All @@ -173,7 +168,6 @@ void InitHealer(Towner &towner, const TownerData &townerData)
};
towner.animOrder = { AnimOrder };
LoadTownerAnimations(towner, "towners\\healer\\healer", 20, 6);
towner.name = _("Pepin the Healer");
towner.gossip = PickRandomlyAmong({ TEXT_PEPIN2, TEXT_PEPIN3, TEXT_PEPIN4, TEXT_PEPIN5, TEXT_PEPIN6, TEXT_PEPIN7, TEXT_PEPIN9, TEXT_PEPIN10, TEXT_PEPIN11 });
}

Expand All @@ -190,7 +184,6 @@ void InitTeller(Towner &towner, const TownerData &townerData)
};
towner.animOrder = { AnimOrder };
LoadTownerAnimations(towner, "towners\\strytell\\strytell", 25, 3);
towner.name = _("Cain the Elder");
towner.gossip = PickRandomlyAmong({ TEXT_STORY2, TEXT_STORY3, TEXT_STORY4, TEXT_STORY5, TEXT_STORY6, TEXT_STORY7, TEXT_STORY9, TEXT_STORY10, TEXT_STORY11 });
}

Expand All @@ -206,7 +199,6 @@ void InitDrunk(Towner &towner, const TownerData &townerData)
};
towner.animOrder = { AnimOrder };
LoadTownerAnimations(towner, "towners\\drunk\\twndrunk", 18, 3);
towner.name = _("Farnham the Drunk");
towner.gossip = PickRandomlyAmong({ TEXT_FARNHAM2, TEXT_FARNHAM3, TEXT_FARNHAM4, TEXT_FARNHAM5, TEXT_FARNHAM6, TEXT_FARNHAM8, TEXT_FARNHAM9, TEXT_FARNHAM10, TEXT_FARNHAM11, TEXT_FARNHAM12, TEXT_FARNHAM13 });
}

Expand All @@ -217,7 +209,6 @@ void InitCows(Towner &towner, const TownerData &townerData)

NewTownerAnim(towner, (*CowSprites)[static_cast<size_t>(townerData.dir)], 12, 3);
towner._tAnimFrame = GenerateRnd(11);
towner.name = _("Cow");

const Point position = townerData.position;
int16_t cowId = dMonster[position.x][position.y];
Expand All @@ -240,7 +231,6 @@ void InitFarmer(Towner &towner, const TownerData &townerData)
towner._tAnimWidth = 96;
towner.animOrder = {};
LoadTownerAnimations(towner, "towners\\farmer\\farmrn2", 15, 3);
towner.name = _("Lester the farmer");
}

void InitCowFarmer(Towner &towner, const TownerData &townerData)
Expand All @@ -252,15 +242,13 @@ void InitCowFarmer(Towner &towner, const TownerData &townerData)
towner._tAnimWidth = 96;
towner.animOrder = {};
LoadTownerAnimations(towner, celPath, 15, 3);
towner.name = _("Complete Nut");
}

void InitGirl(Towner &towner, const TownerData &townerData)
{
towner._tAnimWidth = 96;
towner.animOrder = {};
LoadTownerAnimations(towner, "towners\\girl\\girlw1", 20, 6);
towner.name = _("Celia");
}

void TownDead(Towner &towner)
Expand Down Expand Up @@ -780,6 +768,22 @@ const TownerData TownersData[] = {

Towner Towners[NUM_TOWNERS];

const char *const TownerLongNames[NUM_TOWNER_TYPES] {
N_("Griswold the Blacksmith"),
N_("Pepin the Healer"),
N_("Wounded Townsman"),
N_("Ogden the Tavern owner"),
N_("Cain the Elder"),
N_("Farnham the Drunk"),
N_("Adria the Witch"),
N_("Gillian the Barmaid"),
N_("Wirt the Peg-legged boy"),
N_("Cow"),
N_("Lester the farmer"),
N_("Celia"),
N_("Complete Nut")
};

/** Contains the data related to quest gossip for each towner ID. */
_speech_id QuestDialogTable[NUM_TOWNER_TYPES][MAXQUESTS] = {
// clang-format off
Expand Down
2 changes: 2 additions & 0 deletions Source/towners.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ enum _talker_id : uint8_t {
NUM_TOWNER_TYPES,
};

extern const char *const TownerLongNames[NUM_TOWNER_TYPES];

struct Towner {
OptionalOwnedClxSpriteList ownedAnim;
OptionalClxSpriteList anim;
Expand Down
2 changes: 2 additions & 0 deletions assets/lua/repl_prelude.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ events = require('devilutionx.events')
i18n = require('devilutionx.i18n')
log = require('devilutionx.log')
audio = require('devilutionx.audio')
player = require('devilutionx.player')
render = require('devilutionx.render')
towners = require('devilutionx.towners')
message = require('devilutionx.message')
if _DEBUG then dev = require('devilutionx.dev') end
inspect = require('inspect')

0 comments on commit 32f9cc9

Please sign in to comment.