Skip to content

Commit

Permalink
Fixing monster type name overriding and somes improvements (#389)
Browse files Browse the repository at this point in the history
The real name of the monster was replaced by the name of the look, generating unexpected behavior and in a very specific scenario a crash (when two different monsters had the same "name")
Some improvements related to the creation of monsters and the verification of the monster name in getMonsterType, also preventing any unexpected behavior

New function: Creature::getTypeName(), for get real monster type name
  • Loading branch information
dudantas committed May 27, 2022
1 parent 6b56fbf commit 86e4a90
Show file tree
Hide file tree
Showing 14 changed files with 115 additions and 118 deletions.
2 changes: 2 additions & 0 deletions src/creatures/creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ class Creature : virtual public Thing
}

virtual const std::string& getName() const = 0;
// Real creature name, set on creature creation "createNpcType(typeName) and createMonsterType(typeName)"
virtual const std::string& getTypeName() const = 0;
virtual const std::string& getNameDescription() const = 0;

virtual CreatureType_t getType() const = 0;
Expand Down
4 changes: 4 additions & 0 deletions src/creatures/monsters/monster.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ class Monster final : public Creature
const std::string& getName() const override {
return mType->name;
}
// Real monster name, set on monster creation "createMonsterType(typeName)"
const std::string& getTypeName() const override {
return mType->typeName;
}
const std::string& getNameDescription() const override {
return mType->nameDescription;
}
Expand Down
30 changes: 13 additions & 17 deletions src/creatures/monsters/monsters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -759,13 +759,13 @@ MonsterType* Monsters::loadMonster(const std::string& file, const std::string& m
if (reloading) {
auto it = monsters.find(asLowerCaseString(monsterName));
if (it != monsters.end()) {
mType = &it->second;
mType = it->second;
mType->info = {};
}
}

if (!mType) {
mType = &monsters[asLowerCaseString(monsterName)];
mType = monsters[asLowerCaseString(monsterName)];
}

mType->name = attr.as_string();
Expand Down Expand Up @@ -1452,17 +1452,15 @@ void Monsters::loadLootContainer(const pugi::xml_node& node, LootBlock& lBlock)
MonsterType* Monsters::getMonsterType(const std::string& name)
{
std::string lowerCaseName = asLowerCaseString(name);

auto it = monsters.find(lowerCaseName);
if (it == monsters.end()) {
auto it2 = unloadedMonsters.find(lowerCaseName);
if (it2 == unloadedMonsters.end()) {
return nullptr;
}

return loadMonster(it2->second, name);
}
return &it->second;
if (auto it = monsters.find(lowerCaseName);
it != monsters.end()
// We will only return the MonsterType if it match the exact name of the monster
&& it->first.find(lowerCaseName) != it->first.npos)
{
return it->second;
}
SPDLOG_ERROR("[Monsters::getMonsterType] - Monster with name {} not exist", lowerCaseName);
return nullptr;
}

MonsterType* Monsters::getMonsterTypeByRaceId(uint16_t thisrace) {
Expand All @@ -1477,8 +1475,6 @@ MonsterType* Monsters::getMonsterTypeByRaceId(uint16_t thisrace) {

void Monsters::addMonsterType(const std::string& name, MonsterType* mType)
{
// Suppress [-Werror=unused-but-set-parameter]
// https://stackoverflow.com/questions/1486904/how-do-i-best-silence-a-warning-about-unused-variables
(void) mType;
mType = &monsters[asLowerCaseString(name)];
std::string lowerName = asLowerCaseString(name);
monsters[lowerName] = mType;
}
4 changes: 3 additions & 1 deletion src/creatures/monsters/monsters.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ class MonsterType

public:
MonsterType() = default;
explicit MonsterType(const std::string &initName) : name(initName), typeName(initName), nameDescription(initName) {};

// non-copyable
MonsterType(const MonsterType&) = delete;
Expand All @@ -162,6 +163,7 @@ class MonsterType
bool loadCallback(LuaScriptInterface* scriptInterface);

std::string name;
std::string typeName;
std::string nameDescription;

MonsterInfo info;
Expand Down Expand Up @@ -244,7 +246,7 @@ class Monsters
bool deserializeSpell(MonsterSpell* spell, spellBlock_t& sb, const std::string& description = "");

std::unique_ptr<LuaScriptInterface> scriptInterface;
std::map<std::string, MonsterType> monsters;
std::map<std::string, MonsterType*> monsters;

private:
ConditionDamage* getDamageCondition(ConditionType_t conditionType,
Expand Down
4 changes: 4 additions & 0 deletions src/creatures/npcs/npc.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ class Npc final : public Creature
const std::string& getName() const override {
return npcType->name;
}
// Real npc name, set on npc creation "createNpcType(typeName)"
const std::string& getTypeName() const override {
return npcType->typeName;
}
const std::string& getNameDescription() const override {
return npcType->nameDescription;
}
Expand Down
3 changes: 2 additions & 1 deletion src/creatures/npcs/npcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,14 @@ class NpcType

public:
NpcType() = default;
NpcType(std::string name) : name(name), nameDescription(name) {};
explicit NpcType(const std::string &initName) : name(initName), typeName(initName), nameDescription(initName) {};

// non-copyable
NpcType(const NpcType&) = delete;
NpcType& operator=(const NpcType&) = delete;

std::string name;
std::string typeName;
std::string nameDescription;
NpcInfo info;

Expand Down
3 changes: 3 additions & 0 deletions src/creatures/players/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ class Player final : public Creature, public Cylinder
void setName(std::string newName) {
this->name = std::move(newName);
}
const std::string& getTypeName() const override {
return name;
}
const std::string& getNameDescription() const override {
return name;
}
Expand Down
28 changes: 10 additions & 18 deletions src/lua/functions/core/game/game_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,17 @@
// Game
int GameFunctions::luaGameCreateMonsterType(lua_State* L) {
// Game.createMonsterType(name)
if (getScriptEnv()->getScriptInterface() != &g_scripts().getScriptInterface()) {
reportErrorFunc("MonsterTypes can only be registered in the Scripts interface.");
lua_pushnil(L);
return 1;
}

MonsterType* monsterType = g_monsters().getMonsterType(getString(L, 1));
if (monsterType) {
monsterType->info.lootItems.clear();
monsterType->info.attackSpells.clear();
monsterType->info.defenseSpells.clear();
pushUserdata<MonsterType>(L, monsterType);
setMetatable(L, -1, "MonsterType");
} else if (isString(L, 1)) {
monsterType = new MonsterType();
if (isString(L, 1)) {
std::string name = getString(L, 1);
auto monsterType = new MonsterType(name);
g_monsters().addMonsterType(name, monsterType);
monsterType = g_monsters().getMonsterType(getString(L, 1));
monsterType->name = name;
if (!monsterType) {
reportErrorFunc("MonsterType is nullptr");
pushBoolean(L, false);
delete monsterType;
return 1;
}

monsterType->nameDescription = "a " + name;
pushUserdata<MonsterType>(L, monsterType);
setMetatable(L, -1, "MonsterType");
Expand Down Expand Up @@ -195,7 +187,7 @@ int GameFunctions::luaGameGetMonsterTypes(lua_State* L) {
lua_createtable(L, type.size(), 0);

for (auto& mType : type) {
pushUserdata<MonsterType>(L, &mType.second);
pushUserdata<MonsterType>(L, mType.second);
setMetatable(L, -1, "MonsterType");
lua_setfield(L, -2, mType.first.c_str());
}
Expand Down
13 changes: 12 additions & 1 deletion src/lua/functions/creatures/creature_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ int CreatureFunctions::luaCreatureGetId(lua_State* L) {
}

int CreatureFunctions::luaCreatureGetName(lua_State* L) {
// creature:getName()
// creature:getTypeName()
const Creature* creature = getUserdata<const Creature>(L, 1);
if (creature) {
pushString(L, creature->getName());
Expand All @@ -199,6 +199,17 @@ int CreatureFunctions::luaCreatureGetName(lua_State* L) {
return 1;
}

int CreatureFunctions::luaCreatureGetTypeName(lua_State* L) {
// creature:getName()
const Creature* creature = getUserdata<const Creature>(L, 1);
if (creature) {
pushString(L, creature->getTypeName());
} else {
lua_pushnil(L);
}
return 1;
}

int CreatureFunctions::luaCreatureGetTarget(lua_State* L) {
// creature:getTarget()
Creature* creature = getUserdata<Creature>(L, 1);
Expand Down
2 changes: 2 additions & 0 deletions src/lua/functions/creatures/creature_functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class CreatureFunctions final : LuaScriptInterface {
registerMethod(L, "Creature", "getParent", CreatureFunctions::luaCreatureGetParent);
registerMethod(L, "Creature", "getId", CreatureFunctions::luaCreatureGetId);
registerMethod(L, "Creature", "getName", CreatureFunctions::luaCreatureGetName);
registerMethod(L, "Creature", "getTypeName", CreatureFunctions::luaCreatureGetTypeName);
registerMethod(L, "Creature", "getTarget", CreatureFunctions::luaCreatureGetTarget);
registerMethod(L, "Creature", "setTarget", CreatureFunctions::luaCreatureSetTarget);
registerMethod(L, "Creature", "getFollowCreature", CreatureFunctions::luaCreatureGetFollowCreature);
Expand Down Expand Up @@ -117,6 +118,7 @@ class CreatureFunctions final : LuaScriptInterface {

static int luaCreatureGetId(lua_State* L);
static int luaCreatureGetName(lua_State* L);
static int luaCreatureGetTypeName(lua_State* L);

static int luaCreatureGetTarget(lua_State* L);
static int luaCreatureSetTarget(lua_State* L);
Expand Down
11 changes: 11 additions & 0 deletions src/lua/functions/creatures/monster/monster_type_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,17 @@ int MonsterTypeFunctions::luaMonsterTypeGetDefenseList(lua_State* L) {
return 1;
}

int MonsterTypeFunctions::luaMonsterTypeGetTypeName(lua_State* L) {
// monsterType:getTypeName()
const MonsterType* monsterType = getUserdata<MonsterType>(L, 1);
if (!monsterType) {
return 1;
}

pushString(L, monsterType->typeName);
return 1;
}

int MonsterTypeFunctions::luaMonsterTypeAddDefense(lua_State* L) {
// monsterType:addDefense(monsterspell)
MonsterType* monsterType = getUserdata<MonsterType>(L, 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ class MonsterTypeFunctions final : LuaScriptInterface {
registerMethod(L, "MonsterType", "getDefenseList", MonsterTypeFunctions::luaMonsterTypeGetDefenseList);
registerMethod(L, "MonsterType", "addDefense", MonsterTypeFunctions::luaMonsterTypeAddDefense);

registerMethod(L, "MonsterType", "getTypeName", MonsterTypeFunctions::luaMonsterTypeGetTypeName);

registerMethod(L, "MonsterType", "getElementList", MonsterTypeFunctions::luaMonsterTypeGetElementList);
registerMethod(L, "MonsterType", "addElement", MonsterTypeFunctions::luaMonsterTypeAddElement);

Expand Down Expand Up @@ -201,6 +203,8 @@ class MonsterTypeFunctions final : LuaScriptInterface {
static int luaMonsterTypeGetDefenseList(lua_State* L);
static int luaMonsterTypeAddDefense(lua_State* L);

static int luaMonsterTypeGetTypeName(lua_State* L);

static int luaMonsterTypeGetElementList(lua_State* L);
static int luaMonsterTypeAddElement(lua_State* L);

Expand Down

0 comments on commit 86e4a90

Please sign in to comment.