Browse Source

Lua: Add basic APIs for walking to a towner

This may not be how we'll eventually expose towners
but it's good enough for now.
pull/7679/head
Gleb Mazovetskiy 1 year ago
parent
commit
32f9cc9ad9
  1. 2
      Source/CMakeLists.txt
  2. 4
      Source/lua/lua.cpp
  3. 22
      Source/lua/modules/player.cpp
  4. 9
      Source/lua/modules/player.hpp
  5. 55
      Source/lua/modules/towners.cpp
  6. 9
      Source/lua/modules/towners.hpp
  7. 30
      Source/towners.cpp
  8. 2
      Source/towners.h
  9. 2
      assets/lua/repl_prelude.lua

2
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

4
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));

22
Source/lua/modules/player.cpp

@ -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
Source/lua/modules/player.hpp

@ -0,0 +1,9 @@
#pragma once
#include <sol/sol.hpp>
namespace devilution {
sol::table LuaPlayerModule(sol::state_view &lua);
} // namespace devilution

55
Source/lua/modules/towners.cpp

@ -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
Source/lua/modules/towners.hpp

@ -0,0 +1,9 @@
#pragma once
#include <sol/sol.hpp>
namespace devilution {
sol::table LuaTownersModule(sol::state_view &lua);
} // namespace devilution

30
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<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];
@ -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

2
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;

2
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')

Loading…
Cancel
Save