• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

TFS 1.X+ Change Existing Monster Name In-Game for TFS 1.3

Dries390

Well-Known Member
Joined
Sep 8, 2007
Messages
91
Solutions
4
Reaction score
70
Hello again everyone. I've been trying to apply the code described by


to Nekiro's downgraded TFS 1.3 8.6. Everything compiles just fine but when trying to actually use the function in a simple script

Lua:
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local name = "Beelzegor, the destroyer"
    local desc = "test"
    local b = doSummonCreature("troll", toPosition)
    setCreatureName(b, name, desc) 
    
end

I simply get a global setCreatureName (nil value) error i.e. I think he cannot find the function defined earlier. Has anybody, hopefully succesfully, applied these changes to TFS 1.3?


Thanks in advance!
 
Hello again everyone! I have seemingly managed to fix the issues with the code above.
monster.h, between l. 42 - l. 44 and l. 71 - l.80
Lua:
class Monster final : public Creature
{
    public:
        std::string name, nameDescription; // Added line

...

        const std::string& getName() const override {
            return name; // Changed line
        }
        const std::string& getNameDescription() const override {
            return nameDescription; // Changed line
        }
        std::string getDescription(int32_t) const override {
            return nameDescription + '.'; // Changed line
        }

luascript.cpp, added behind l. 1044 and behind l. 7095
Lua:
//setCreatureName(cid, name, description)
    lua_register(luaState, "setCreatureName", LuaScriptInterface::luaSetCreatureName);

...

int LuaScriptInterface::luaSetCreatureName(lua_State* L)
{
    //setCreatureName(cid, newName, newDescription)
    Creature* creature = getCreature(L, 1);
    if (creature) {
        Monster* monster = (Monster*)creature;
        std::string newName = getString(L, 2);
        std::string newDesc = getString(L, 3);
        monster->name = newName;
        monster->nameDescription = newDesc;
        pushBoolean(L, false);
    }
    else {
        reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND));
        pushBoolean(L, false);
    }
    return 1;
}

luascript.h, behind l. 784
Lua:
 static int luaSetCreatureName(lua_State* L);

monster.cpp, l. 48 - l.50
Lua:
    name = mType->name;
    nameDescription = mType->nameDescription;

The only problem I've found so far is the description of the killed creature not showing up correctly in the loot log, I will post corrections as soon as I do. If you wish to implement this code, do not forget to read the original thread as there are limitations, i.e. needing to relog to see the correct name, which you might have to work around.
 

Attachments

Hello again everyone! I have seemingly managed to fix the issues with the code above.
monster.h, between l. 42 - l. 44 and l. 71 - l.80
Lua:
class Monster final : public Creature
{
    public:
        std::string name, nameDescription; // Added line

...

        const std::string& getName() const override {
            return name; // Changed line
        }
        const std::string& getNameDescription() const override {
            return nameDescription; // Changed line
        }
        std::string getDescription(int32_t) const override {
            return nameDescription + '.'; // Changed line
        }

luascript.cpp, added behind l. 1044 and behind l. 7095
Lua:
//setCreatureName(cid, name, description)
    lua_register(luaState, "setCreatureName", LuaScriptInterface::luaSetCreatureName);

...

int LuaScriptInterface::luaSetCreatureName(lua_State* L)
{
    //setCreatureName(cid, newName, newDescription)
    Creature* creature = getCreature(L, 1);
    if (creature) {
        Monster* monster = (Monster*)creature;
        std::string newName = getString(L, 2);
        std::string newDesc = getString(L, 3);
        monster->name = newName;
        monster->nameDescription = newDesc;
        pushBoolean(L, false);
    }
    else {
        reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND));
        pushBoolean(L, false);
    }
    return 1;
}

luascript.h, behind l. 784
Lua:
static int luaSetCreatureName(lua_State* L);

monster.cpp, l. 48 - l.50
Lua:
    name = mType->name;
    nameDescription = mType->nameDescription;

The only problem I've found so far is the description of the killed creature not showing up correctly in the loot log, I will post corrections as soon as I do. If you wish to implement this code, do not forget to read the original thread as there are limitations, i.e. needing to relog to see the correct name, which you might have to work around.
The more ideal solution is to spawn the creature in a far off place, then teleport it to the intended destination.
That way you don't have to relog. xD

It's only when the creature get's loaded into your client's memory that it's impossible to change it's name.
 
That's exactly the kind of solution I was looking into, should be easy to write a function that accomplishes this. I'll add it here once I solve the remaining loot issues.
 
I realized trying to push custom names through to the loot log (probably) cannot be done in any simple sort of way so here's the function to spawn named creatures

Lua:
function spawnNamedMonster(name, description, monster, pos)
    local pos = {x = 50, y = 50, z = 7} -- Change this to some far away place on your map
    local m = Game.createMonster(monster, pos) -- Creates monster at far away position
    setCreatureName(m, name, description)  -- Changes monster's name
    m:teleportTo(pos) -- Teleports creature to where it needs to be
end
 
I realized trying to push custom names through to the loot log (probably) cannot be done in any simple sort of way so here's the function to spawn named creatures

Lua:
function spawnNamedMonster(name, description, monster, pos)
    local pos = {x = 50, y = 50, z = 7} -- Change this to some far away place on your map
    local m = Game.createMonster(monster, pos) -- Creates monster at far away position
    setCreatureName(m, name, description)  -- Changes monster's name
    m:teleportTo(pos) -- Teleports creature to where it needs to be
end

It looks like you’re getting there. You shouldn’t overwrite function arguments (pos) inside the function. You should also verify that variable “m” exists / is valid before altering it in any way (changing its name and teleporting it).

Red
 
Everything works on this end so the question can be considered solved. My version of spawnNamedMonster is much more intricate (optional spawning in an area instead of position, optional outfit argument, etc) so I made a couple errors throwing out the code other people don't need. Fixed version for people interested:

Lua:
function spawnNamedMonster(name, description, monster, pos)
    local positionSpawn = {x = 50, y = 50, z = 7} -- Change this to some far away place on your map
    local m = Game.createMonster(monster, positionSpawn) -- Creates monster at far away position
    if m then
        setCreatureName(m, name, description)  -- Changes monster's name
        m:teleportTo(pos) -- Teleports creature to where it needs to be
    end
end
 
Interesting tidbit; leaving

C++:
const std::string& getNameDescription() const override {
            return mType->nameDescription;

in monster.h will leave descriptions on examination intact but also fixes the combat messages you get at the bottom of the client back to the standard creature.xml description.
 
Back
Top