Since I am unfamiliar with how the lua is retrieved in the sources, I used my own means of getting data from a lua file, with that said with this code you can call up npc scripts that are lua defined.
So let's get to it. Open up npc.cpp and find this
and replace it with this
Next find this
and replace it with this
Next find this
and place this above
Now look for this again
and replace all that code in that method with this
So let's get to it. Open up npc.cpp and find this
C++:
extern LuaEnvironment g_luaEnvironment;
Code:
extern LuaEnvironment g_luaEnvironment, g_lua;
Next find this
C++:
Npc::Npc(const std::string& name) :
Creature(),
filename("data/npc/" + name + ".xml"),
npcEventHandler(nullptr),
masterRadius(-1),
loaded(false)
{
reset();
}
C++:
Npc::Npc(const std::string& name) :
Creature(),
filename("data/npc/"+name+".lua"),
npcEventHandler(nullptr),
masterRadius(-1),
loaded(false)
{
reset();
}
Next find this
C++:
bool Npc::loadFromXml()
and place this above
C++:
static struct N {
const char* name;
int type;
}npclua[] = {
{ "name", LUA_TSTRING },
{ "script", LUA_TSTRING },
{ "skull", LUA_TSTRING },
{ "attackable", LUA_TNUMBER },
{ "floorchange", LUA_TNUMBER },
{ "speed", LUA_TNUMBER },
{ "currency", LUA_TNUMBER },
{ "walkinterval", LUA_TNUMBER },
{ "walkradius", LUA_TNUMBER },
{ "ignoreheight", LUA_TNUMBER },
{ "speechbubble", LUA_TNUMBER },
{ "health", LUA_TTABLE },
{ "look", LUA_TTABLE },
{ "parameters", LUA_TTABLE },
{ NULL, 0 }
}, npchealth[] = {
{ "now", LUA_TNUMBER },
{ "max", LUA_TNUMBER },
{ NULL, 0 }
}, npclook[] = {
{ "type", LUA_TNUMBER },
{ "body", LUA_TNUMBER },
{ "legs", LUA_TNUMBER },
{ "head", LUA_TNUMBER },
{ "feet", LUA_TNUMBER },
{ "addons", LUA_TNUMBER },
{ "typeex", LUA_TNUMBER },
{ "mount", LUA_TNUMBER },
{ NULL, 0 }
}, npcparameters[] = {
{ "key", LUA_TNUMBER },
{ "value", LUA_TNUMBER },
{ NULL, 0 }
};
Now look for this again
C++:
bool Npc::loadFromXml()
C++:
bool Npc::loadFromXml()
{
lua_State *L = luaL_newstate();
std::string str;
if (!L) {
throw std::runtime_error("Failed to allocate memory for npc");
}
luaL_openlibs(L);
if (luaL_dofile(L, filename.c_str())) {
std::cout << "[Error - NPC] " << lua_tostring(L, -1) << std::endl;
lua_close(L);
return false;
}
lua_getglobal(L, "npc");
for (int i = 1; ; i++) {
lua_rawgeti(L, -1, 1);
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
break;
}
luaL_checktype(L, -1, LUA_TTABLE);
for (int npcIndex = 0; npclua[npcIndex].name != NULL; npcIndex++) {
lua_getfield(L, -1, npclua[npcIndex].name);
luaL_checktype(L, -1, npclua[npcIndex].type);
str = npclua[npcIndex].name;
switch (lua_type(L, -1)) {
case LUA_TSTRING:
if (str == "name") {
name = g_lua.getString(L, -1);
}
else if (str == "script"){
std::string sc = lua_tostring(L, -1);
npcEventHandler = new NpcEventsHandler(sc, this);
if (!npcEventHandler->isLoaded()) {
delete npcEventHandler;
npcEventHandler = nullptr;
return false;
}
}
else if (str == "skull") {
setSkull(getSkullType(lua_tostring(L, -1) ));
}
break;
case LUA_TNUMBER:
if (str == "attackable") {
attackable = (lua_tonumber(L, -1) != 0);
}
else if (str == "floorchange") {
floorChange = (lua_tonumber(L, -1) != 0);
}
else if (str == "speed") {
baseSpeed = g_lua.getNumber<uint32_t>(L, -1);
}
else if (str == "walkinterval") {
walkTicks = g_lua.getNumber<uint32_t>(L, -1);
}
else if (str == "walkradius") {
masterRadius = g_lua.getNumber<int32_t>(L, -1);
}
else if (str == "ignoreheight") {
ignoreHeight = (lua_tonumber(L, -1) != 0);
}
else if (str == "speechbubble") {
uint32_t speech = g_lua.getNumber<uint32_t>(L, -1);
if(speech != 0){
speechBubble = speech;
}
}
break;
case LUA_TTABLE:
if (str == "health") {
for (int h = 0; npchealth[h].name != NULL; h++) {
lua_getfield(L, -1, npchealth[h].name);
str = npchealth[h].name;
if (str == "now") {
health = g_lua.getNumber<int32_t>(L, -1);
if(!health || health < 0){
health = 100;
}
}
else if (str == "max") {
healthMax = g_lua.getNumber<int32_t>(L, -1);
if(!healthMax || healthMax < 0){
healthMax = 100;
}
}
lua_pop(L, 1);
}
}
else if (str == "look") {
for (int l = 0; npclook[l].name != NULL; l++) {
lua_getfield(L, -1, npclook[l].name);
str = npclook[l].name;
if (str == "type") {
uint16_t lt = g_lua.getNumber<uint16_t>(L, -1);
if(lt != 0){
defaultOutfit.lookType = lt;
}
}
else if (str == "head") {
uint16_t hd = g_lua.getNumber<uint16_t>(L, -1);
if(hd != 0){
defaultOutfit.lookHead = hd;
}
}
else if (str == "body") {
defaultOutfit.lookBody = g_lua.getNumber<uint16_t>(L, -1);
}
else if (str == "legs") {
defaultOutfit.lookLegs = g_lua.getNumber<uint16_t>(L, -1);
}
else if (str == "feet") {
defaultOutfit.lookFeet = g_lua.getNumber<uint16_t>(L, -1);
}
else if (str == "addons") {
defaultOutfit.lookAddons = g_lua.getNumber<uint16_t>(L, -1);
}
else if (str == "typeex") {
uint16_t tx = g_lua.getNumber<uint16_t>(L, -1);
if(tx != 0){
defaultOutfit.lookTypeEx = tx;
}
}
else if (str == "mount") {
defaultOutfit.lookMount = g_lua.getNumber<uint16_t>(L, -1);
}
lua_pop(L, 1);
}
currentOutfit = defaultOutfit;
}
else if (str == "parameters") {
if (lua_objlen(L, -1) > 0) {
std::string key, value;
for (int i = 1; ; i++) {
lua_rawgeti(L, -1, i);
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
break;
}
for (int p = 0; npcparameters[p].name != NULL; p++) {
lua_getfield(L, -1, npcparameters[p].name);
str = npcparameters[p].name;
if (str == "key") {
key = g_lua.getString(L, -1);
}
else if (str == "value") {
parameters[key] = g_lua.getString(L, -1);
}
lua_pop(L, 1);
}
lua_pop(L, 1);
}
}
}
break;
}
lua_pop(L, 1);
}
}
lua_close(L);
return true;
}