Lua Function Change Existing Monster Name In-Game

Scarlet Ayleid

Well-Known Member
Joined
Jul 7, 2007
Messages
4,057
Best answers
0
Likes
232
#1
Well, my other topic got deleted, dunno why, but whatever

Tested on TFS 0.4 rev 4395, but should also work with pretty much every other server

What it does
This function allows you to rename a single monster in-game so that if you want a single monster with an unique name, you don't have to make a new monster file, simply call this function and the monster's name will be what you wanted

IMPORTANT (Info on how to bypass below)
Tibia Client Limitation:
Tibia client stores in its memories the id of each creature and its name(along with other stuff I believe), so if you for example see a troll in thais, then walk to venore, change the troll name to something else like "FakeTroll" and go back to the Thais troll, you'd still see the name troll because your client had already seen that creature, so it stored its id and name, other players that had never seen that troll before you changed the name will see the new name, but anyone that had already seen it, continues to see the old name, same applies to NPCs and Players.

monster.h
find
Code:
class Monster : public Creature
then add this under public:
Code:
std::string name, nameDescription;
find
Code:
virtual const std::string& getName() const {return mType->name;}
virtual const std::string& getNameDescription() const {return mType->nameDescription;}
virtual std::string getDescription(int32_t) const {return mType->nameDescription + ".";}
replace with
Code:
virtual const std::string& getName() const {return name;}
virtual const std::string& getNameDescription() const {return nameDescription;}
virtual std::string getDescription(int32_t) const {return nameDescription + ".";}
monster.cpp
find
Code:
Monster::Monster(MonsterType* _mType):
then add the following code right above isIdle = true;
Code:
    name = _mType->name;
    nameDescription = _mType->nameDescription;
luascript.h
add near the similar lines
Code:
static int32_t luaSetCreatureName(lua_State* L);
luascript.cpp
add near similar lines
Code:
//setCreatureName(cid, name, description)
lua_register(m_luaState, "setCreatureName", LuaInterface::luaSetCreatureName);
add near similar lines
Code:
int32_t LuaInterface::luaSetCreatureName(lua_State* L)
{
    //setCreatureName(cid, newName, newDescription)
    std::string newDesc = popString(L);
    std::string newName = popString(L);
    ScriptEnviroment* env = getEnv();
    Creature* creature;
    if(creature = env->getCreatureByUID(popNumber(L))){
        Monster* monster = (Monster*)creature;
        monster->name = newName;
        monster->nameDescription = newDesc;
        lua_pushboolean(L, true);
    }
    else{
        errorEx(getError(LUA_ERROR_CREATURE_NOT_FOUND));
        lua_pushboolean(L, false);
    }
    return 1;
}
Done :)


Bypassing Tibia Client Limitation
There is a way to 'fix' the limitation on the sources which involves going thru the spectators list to update the reference to the monster, but I didn't did that because I fixed the problem thru other means, the tibia client only registers the name of the creature if it sees it, so if you create the summon in a distance, change the name and then teleport the monster to where you want it, by doing this the monster will show the expected name and it would be much faster to execute, which would mean less lag because its faster to make a simple teleport then it is to go thru all the spectators list and update the monster.
An example for this would be:

Code:
function createFakeTroll(spawnPos) 
   local farAwayPos = {x = 100, y = 100, z = 7} --Change This!! 
   local monster = doCreateMonster("Troll", farAwayPos) 
   setCreatureName(monster, "FakeTroll", "a fake troll") 
   doTeleportThing(monster, spawnPos) 
end
Rep+ if you like it :p
 
Last edited:

Scarlet Ayleid

Well-Known Member
Joined
Jul 7, 2007
Messages
4,057
Best answers
0
Likes
232
#5
nice work in tfs 8.54 0.3.6 pl1?
don't know for sure, but I believe it should work :)

Nice work!

make Change Player Name In-Game :p
I havent investigated the Player class in the sources, but changing player names in-game might not be very safe because you could generate some problems when saving it to SQL, would it save with the old name or the new name? how would it manage house permissions(since you have to write the player name in the guest/subowner list) and if we could go around those problems, other players would maybe see the new name, but the player itself would always see the old name.(See below why)

Why this happens? Bear with me a little
Tibia client stores in its memories the id of each creature and its name(along with other stuff I believe), so if you for example see a troll in thais, then walk to venore, change the troll name to something else like "FakeTroll" and go back to the Thais troll, you'd still see the name troll because your client had already seen that creature, so it stored its id and name, other players that had never seen that troll before you changed the name will see the new name, but anyone that had already seen it, continues to see the old name, same applies to NPCs and Players,

Even in this version of the code this happens, because to go over that limitation would require some serious source editing, so in order to prevent the above from happening in my scripts, what I do is I made a far away 3x3 square where I first summon the monsters there where no one can see them, change their names and then teleport them to the place I want, that way I'm certain that no one has seen the creature before its name was changed

What is exacly do ?
Basically, this allows you to change the name of a monster in-game
You have a dog, and for some reason, you want that single dog to be named "Woof", instead of making a new monster file with just a different name, just use this function on the dog and change its name while no one is looking(see above for why) and it'll forever be named "Woof" until server restarts or it dies(where in both cases you'd have to use the function again :))
 
Last edited:
Joined
Oct 21, 2009
Messages
1,534
Best answers
9
Likes
126
Location
Poland
#6
So i can create multiple monsters with named ex. Demon and put them strongest attributes than Demon ?
Ex. I create 2 demons -> demon.xml, demon-a.xml, and all its named Demon, but different attributes ?
 

Scarlet Ayleid

Well-Known Member
Joined
Jul 7, 2007
Messages
4,057
Best answers
0
Likes
232
#7
this doesn't change any attribute, it just changes their names
For example, you have 5 demons in your map(demon.xml) and you want to scare one of your players into thinking that one of them is Orshabaal, so you just use the function on one of the demons and name it Orshabaal, now you have the same 5 demons, but 4 of them are named Demon, the other one is named Orshabaal, but every attribute is the same as Demon since he is actually a Demon, just with a different name
 
Last edited:

Scarlet Ayleid

Well-Known Member
Joined
Jul 7, 2007
Messages
4,057
Best answers
0
Likes
232
#11
There was a slight mistype in the first post, those changes are to be made on monster.cpp/h, not monsters.cpp/h

I just checked the source code of 0.3.6, it should be compatible :)
If you get any error, let me know
 
Joined
Aug 22, 2010
Messages
114
Best answers
0
Likes
1
#12
There was a slight mistype in the first post, those changes are to be made on monster.cpp/h, not monsters.cpp/h

I just checked the source code of 0.3.6, it should be compatible :)
If you get any error, let me know
Plz create a new tags to guide all to changes is necessary in the tfs 0.3.6 sources
because the lines that you ask to change is not similar, the sorces of tfs 0.4 and 0.3.6 is a very little diferent and a few lines are not present in tfs 0.3.6
I try apply the changes but is not possible i search for the lines to change and the editor return not exist this line.
If is possible make a new tutorial to tfs 0.3.6

Thks

Sorry for the english is not better but is mine.
 

Scarlet Ayleid

Well-Known Member
Joined
Jul 7, 2007
Messages
4,057
Best answers
0
Likes
232
#13
Just went thru the 0.3.6pl1 sources, there was a small difference, I edited the first post so that the tags can be found easily in both 0.4 and 0.3.6

Any more problems, feel free to ask
 
Joined
Aug 22, 2010
Messages
114
Best answers
0
Likes
1
#14
is right ?
i use this function but i need a log off to the changes
if i online dont change on re-login the names are changed...

Code:
////////////////////////////////////////////////////////////////////////
// OpenTibia - an opensource roleplaying game
////////////////////////////////////////////////////////////////////////
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
////////////////////////////////////////////////////////////////////////

#ifndef __MONSTER__
#define __MONSTER__

#include "monsters.h"
#include "raids.h"
#include "tile.h"

class Creature;
class Game;
class Spawn;

enum TargetSearchType_t
{
	TARGETSEARCH_DEFAULT,
	TARGETSEARCH_RANDOM,
	TARGETSEARCH_ATTACKRANGE,
	TARGETSEARCH_NEAREST
};

typedef std::list<Creature*> CreatureList;
class Monster : public Creature
{
	private:
		Monster(MonsterType* _mType);

[B][COLOR="red"]	public:
        std::string name, nameDescription;[/COLOR][/B]
#ifdef __ENABLE_SERVER_DIAGNOSTIC__
		static uint32_t monsterCount;
#endif
		virtual ~Monster();

		static Monster* createMonster(MonsterType* mType);
		static Monster* createMonster(const std::string& name);

		virtual Monster* getMonster() {return this;}
		virtual const Monster* getMonster() const {return this;}

		virtual uint32_t rangeId() {return 0x40000000;}
		static AutoList<Monster> autoList;

		void addList() {autoList[id] = this;}
		void removeList() {autoList.erase(id);}

		virtual const std::string& getName() const {return name;}
        virtual const std::string& getNameDescription() const {return nameDescription;}
        virtual std::string getDescription(int32_t) const {return nameDescription + ".";}

		virtual RaceType_t getRace() const {return mType->race;}
		virtual int32_t getArmor() const {return mType->armor;}
		virtual int32_t getDefense() const {return mType->defense;}
		virtual MonsterType* getMonsterType() const {return mType;}
		virtual bool isPushable() const {return mType->pushable && (baseSpeed > 0);}
		virtual bool isAttackable() const {return mType->isAttackable;}
		virtual bool isImmune(CombatType_t type) const;

		bool canPushItems() const {return mType->canPushItems;}
		bool canPushCreatures() const {return mType->canPushCreatures;}
		bool isHostile() const {return mType->isHostile;}
		virtual bool isWalkable() const {return mType->isWalkable;}
		virtual bool canSeeInvisibility() const {return Creature::isImmune(CONDITION_INVISIBLE);}
		uint32_t getManaCost() const {return mType->manaCost;}

		void setSpawn(Spawn* _spawn) {spawn = _spawn;}
		void setRaid(Raid* _raid) {raid = _raid;}

		virtual void onAttackedCreature(Creature* target);
		virtual void onAttackedCreatureDisappear(bool isLogout);
		virtual void onAttackedCreatureDrain(Creature* target, int32_t points);

		virtual void onCreatureAppear(const Creature* creature);
		virtual void onCreatureDisappear(const Creature* creature, bool isLogout);
		virtual void onCreatureMove(const Creature* creature, const Tile* newTile, const Position& newPos,
			const Tile* oldTile, const Position& oldPos, bool teleport);

		virtual void drainHealth(Creature* attacker, CombatType_t combatType, int32_t damage);
		virtual void changeHealth(int32_t healthChange);
		virtual bool getNextStep(Direction& dir, uint32_t& flags);
		virtual void onFollowCreatureComplete(const Creature* creature);

		virtual void onThink(uint32_t interval);

		virtual bool challengeCreature(Creature* creature);
		virtual bool convinceCreature(Creature* creature);

		virtual void setNormalCreatureLight();
		virtual bool getCombatValues(int32_t& min, int32_t& max);

		virtual void doAttacking(uint32_t interval);
		virtual bool hasExtraSwing() {return extraMeleeAttack;}

		bool searchTarget(TargetSearchType_t searchType = TARGETSEARCH_DEFAULT);
		bool selectTarget(Creature* creature);

		const CreatureList& getTargetList() {return targetList;}
		const CreatureList& getFriendList() {return friendList;}

		bool isTarget(Creature* creature);
		bool isFleeing() const {return getHealth() <= mType->runAwayHealth;}

		virtual BlockType_t blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage,
			bool checkDefense = false, bool checkArmor = false);

	private:
		CreatureList targetList;
		CreatureList friendList;

		MonsterType* mType;

		int32_t minCombatValue;
		int32_t maxCombatValue;
		uint32_t attackTicks;
		uint32_t targetTicks;
		uint32_t targetChangeTicks;
		uint32_t defenseTicks;
		uint32_t yellTicks;
		int32_t targetChangeCooldown;
		bool resetTicks;
		bool isIdle;
		bool extraMeleeAttack;

		Spawn* spawn;
		Raid* raid;

		bool isMasterInRange;
		bool teleportToMaster;

		virtual void onCreatureEnter(Creature* creature);
		virtual void onCreatureLeave(Creature* creature);
		void onCreatureFound(Creature* creature, bool pushFront = false);

		bool doTeleportToMaster();
		void updateLookDirection();

		void updateTargetList();
		void clearTargetList();
		void clearFriendList();

		virtual bool onDeath();
		virtual Item* createCorpse(DeathList deathList);
		bool despawn();
		bool inDespawnRange(const Position& pos);

		void setIdle(bool _idle);
		void updateIdleStatus();
		bool getIdleStatus() const {return isIdle;}

		virtual void onAddCondition(ConditionType_t type, bool hadCondition);
		virtual void onEndCondition(ConditionType_t type);
		virtual void onCreatureConvinced(const Creature* convincer, const Creature* creature);

		bool canUseAttack(const Position& pos, const Creature* target) const;
		bool canUseSpell(const Position& pos, const Position& targetPos,
			const spellBlock_t& sb, uint32_t interval, bool& inRange);
		bool getRandomStep(const Position& creaturePos, Direction& dir);
		bool getDanceStep(const Position& creaturePos, Direction& dir,
			bool keepAttack = true, bool keepDistance = true);
		bool isInSpawnRange(const Position& toPos);
		bool canWalkTo(Position pos, Direction dir);

		bool pushItem(Item* item, int32_t radius);
		void pushItems(Tile* tile);
		bool pushCreature(Creature* creature);
		void pushCreatures(Tile* tile);

		void onThinkTarget(uint32_t interval);
		void onThinkYell(uint32_t interval);
		void onThinkDefense(uint32_t interval);

		bool isFriend(const Creature* creature);
		bool isOpponent(const Creature* creature);

		virtual uint64_t getLostExperience() const {return ((skillLoss ? mType->experience : 0));}
		virtual void dropLoot(Container* corpse);
		virtual uint32_t getDamageImmunities() const {return mType->damageImmunities;}
		virtual uint32_t getConditionImmunities() const {return mType->conditionImmunities;}
		virtual uint16_t getLookCorpse() {return mType->lookCorpse;}
		virtual uint16_t getLookCorpse() const {return mType->lookCorpse;}
		virtual void getPathSearchParams(const Creature* creature, FindPathParams& fpp) const;
		virtual bool useCacheMap() const {return true;}
};
#endif
its my changes is right ?
 
Last edited:

Scarlet Ayleid

Well-Known Member
Joined
Jul 7, 2007
Messages
4,057
Best answers
0
Likes
232
#15
check the first post, its a client limitation that I can't fix unless I do some serious source editing like changing spectators list and such, which I dont need since I use something like the code below
Tibia Client Limitation:
Tibia client stores in its memories the id of each creature and its name(along with other stuff I believe), so if you for example see a troll in thais, then walk to venore, change the troll name to something else like "FakeTroll" and go back to the Thais troll, you'd still see the name troll because your client had already seen that creature, so it stored its id and name, other players that had never seen that troll before you changed the name will see the new name, but anyone that had already seen it, continues to see the old name, same applies to NPCs and Players
You can easily bypass that if you summon the monster in a far away place, change the name, and then teleport him to you, something like:
Code:
function onUse(...)
     local farawayplace = {x = 100, y = 100, z = 7}
     local mob = doSummonCreature("Dragon",farawayplace)
     setCreatureName(mob, "Fake Dragon", "a fake dragon")
     doTeleportThing(mob, getCreaturePosition(cid))
     return 1
end

EDIT:
Yes, your sources are ok
 
Joined
Aug 22, 2010
Messages
114
Best answers
0
Likes
1
#16
its a good script only for this problem...
sorry i dont read english very well and google tradutor is suck...
but thks for help...
xD
 
Joined
Oct 17, 2010
Messages
78
Best answers
0
Likes
10
#17
hello Scarlet Ayleid there is something wrong in the script that I did? the error

[06/23/2011 21:41:25] [Error - GlobalEvent Interface]
[06/23/2011 21:41:25] data / globalevents / scripts / peoples.lua: onThink
[06/23/2011 21:41:25] Description:
[06/23/2011 21:41:25] (luaSetCreatureName) Creature not found

sorry for bad english I'm using google translator

my script:
function onThink(interval, lastExecution)
local nomes = {"fuinha", "victor", "dodo", "eskilo"}
local s = 35469
local spaws = {
[1] = {x= 95, y= 124,z= 7},
[2] = {x= 96,y= 125,z= 7},
}
if getGlobalStorageValue(35469) < 100 then
setCreatureName(doSummonMonster("Orc", spaws[math.random(1, #spaws)]), nomes[math.random(1, #nomes)], "a fake")
setGlobalStorageValue(35469, 1)
return TRUE
end
end
 

Scarlet Ayleid

Well-Known Member
Joined
Jul 7, 2007
Messages
4,057
Best answers
0
Likes
232
#18
you're using the wrong function to create a monster, you should be using "doCreateMonster(cid, pos)"

the one you're using seems to be to create a monster to act as a summon to something "doSummonMonster(cid, name)"

btw, if your BR, you can message me or add me to MSN(check my profile) and I'll answer in portuguese :)
 
Last edited:
Joined
Aug 22, 2010
Messages
114
Best answers
0
Likes
1
#19
English: Vyctor i explain to you, try this.
Protuguese: Vyctor vo te explica uma coisa faz assim ó.

PHP:
function onThink(interval, lastExecution)
local nomes = {"fuinha", "victor", "dodo", "eskilo"}
local s = 35469
local spaws = {
[1] = {x= 95, y= 124,z= 7},
[2] = {x= 96,y= 125,z= 7},
}
local create_monster = doCreateMonster("Orc", spaws[math.random(1,2)])
if getGlobalStorageValue(35469) < 100 then
setCreatureName(create_monster, nomes[math.random(1, table.maxn(nomes)], "a fake")
setGlobalStorageValue(35469, 1)
return TRUE
end
end
English: Its right bro.
Portuguese: pronto irmão tah feito.
 
Last edited:

Scarlet Ayleid

Well-Known Member
Joined
Jul 7, 2007
Messages
4,057
Best answers
0
Likes
232
#20
English:
yeah, just like perdigs did :)

Portuguese:
sim, exactamente como o perdigs fez :)

@Perdigs
Try not to write in portuguese out of the Portuguese Board, at least not without a proper english translation
Tenta não escrever em portugues fora do forum Portugues, pelo menos sem também escrever o texto em inglês
 
Top