diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 906e3f6d376..c6389761010 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -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 diff --git a/Source/lua/lua.cpp b/Source/lua/lua.cpp index cca6b2994ff..f07b82898fe 100644 --- a/Source/lua/lua.cpp +++ b/Source/lua/lua.cpp @@ -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" @@ -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)); diff --git a/Source/lua/modules/player.cpp b/Source/lua/modules/player.cpp new file mode 100644 index 00000000000..1629265a514 --- /dev/null +++ b/Source/lua/modules/player.cpp @@ -0,0 +1,22 @@ +#include "lua/modules/player.hpp" + +#include + +#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 diff --git a/Source/lua/modules/player.hpp b/Source/lua/modules/player.hpp new file mode 100644 index 00000000000..69479000638 --- /dev/null +++ b/Source/lua/modules/player.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace devilution { + +sol::table LuaPlayerModule(sol::state_view &lua); + +} // namespace devilution diff --git a/Source/lua/modules/towners.cpp b/Source/lua/modules/towners.cpp new file mode 100644 index 00000000000..48e55ade902 --- /dev/null +++ b/Source/lua/modules/towners.cpp @@ -0,0 +1,55 @@ +#include "lua/modules/towners.hpp" + +#include +#include + +#include + +#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> { + 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 diff --git a/Source/lua/modules/towners.hpp b/Source/lua/modules/towners.hpp new file mode 100644 index 00000000000..9af1f1013d8 --- /dev/null +++ b/Source/lua/modules/towners.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace devilution { + +sol::table LuaTownersModule(sol::state_view &lua); + +} // namespace devilution diff --git a/Source/towners.cpp b/Source/towners.cpp index d07d45cfbdf..b84f5b4d58f 100644 --- a/Source/towners.cpp +++ b/Source/towners.cpp @@ -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; @@ -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 }); } @@ -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 }); } @@ -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) @@ -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 }); } @@ -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 }); } @@ -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 }); } @@ -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 }); } @@ -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 }); } @@ -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 }); } @@ -217,7 +209,6 @@ void InitCows(Towner &towner, const TownerData &townerData) NewTownerAnim(towner, (*CowSprites)[static_cast(townerData.dir)], 12, 3); towner._tAnimFrame = GenerateRnd(11); - towner.name = _("Cow"); const Point position = townerData.position; int16_t cowId = dMonster[position.x][position.y]; @@ -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) @@ -252,7 +242,6 @@ 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) @@ -260,7 +249,6 @@ 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) @@ -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 diff --git a/Source/towners.h b/Source/towners.h index e0ae3f05612..3bf4d9cb67b 100644 --- a/Source/towners.h +++ b/Source/towners.h @@ -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; diff --git a/assets/lua/repl_prelude.lua b/assets/lua/repl_prelude.lua index 6c54e37a49b..b871affbce7 100644 --- a/assets/lua/repl_prelude.lua +++ b/assets/lua/repl_prelude.lua @@ -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')