• 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!

Solved Question: Ghost command for TFS 1.2 - admins invisible to staff

Jose Rondón

UTibia
Joined
Oct 11, 2015
Messages
63
Reaction score
25
Location
Venezuela
Hi everyone, i got a question regarding ghost command on TFS 1.2.

I have set my own groups in order to create more ranks avaiable besides tutor, gamemaster and god, i also used flag generator by @HalfWay and in this sense everything seems to be working fine.

However when i try /ghost command in a high ranked staff (such as god or admin), tutors and gamemasters can see me.​

This is my groups.xml (if any use)

<?xml version="1.0" encoding="UTF-8"?>
<groups>
<group id="1" name="player" flags="0" access="0" maxdepotitems="0" maxvipentries="0" />
<group id="2" name="tutor" flags="137455730688" access="1" maxdepotitems="0" maxvipentries="200" />
<group id="3" name="gamemaster" flags="9005456797519" access="1" maxdepotitems="0" maxvipentries="0" />
<group id="4" name="community manager" flags="266273144682" access="1" maxdepotitems="0" maxvipentries="200" />
<group id="5" name="god" flags="272721878906" access="1" maxdepotitems="0" maxvipentries="200" />
<group id="6" name="admin" flags="272730398714" access="1" maxdepotitems="0" maxvipentries="200" />
</groups>

and here my ghost.lua
function onSay(player, words, param)
if not player:getGroup():getAccess() then
return true
end

if player:getAccountType() < ACCOUNT_TYPE_SENIORTUTOR then
return false
end

local position = player:getPosition()
local isGhost = not player:isInGhostMode()

player:setGhostMode(isGhost)
if isGhost then
player:sendTextMessage(MESSAGE_INFO_DESCR, "You are now invisible.")
position:sendMagicEffect(CONST_ME_YALAHARIGHOST)
else
player:sendTextMessage(MESSAGE_INFO_DESCR, "You are visible again.")
position.x = position.x + 1
position:sendMagicEffect(CONST_ME_SMOKE)
end
return false
end

I know, why the hell are you using SENIORTUTOR to limitate your ghost.lua?
It's because i've set gamemasters as SENIORTUTOR in matters of Account Type.
 
group and account type are different things as far as I know
do something like

Code:
print(player:getAccountType())
print(player:getGroup())
 
group and account type are different things as far as I know
do something like

Code:
print(player:getAccountType())
print(player:getGroup())

This is how i am defining ranks.

Admin = AccType 5 - GroupId 6
God = Acctype 4 - GroupId 5
CM = Acctype 3 - GroupId 4
GM = Acctype 3 - GroupId 3
Tutor = AccType 2 - GroupId 2

The original ghost.lua has the same issue. Any thoughs?
 
Did you calculate the flags properly? Try using different flag generators? :)

I used HalfWay's and Comedinha flag generators, same values.

TFS 1.X series differs from 0.X series in the ghost mode feature. In TFS 1.x anyone with access="1" can see players in Ghostmode:
https://github.com/otland/forgotten...959d548702721cd69e3799966/src/player.cpp#L805

You can edit that line to determine who can see who by group id instead of access.

Thank you, also @Zothion and @MatheusMkalo.
Testing now.

jqmL9SO.png



PHP:
1>------ Build started: Project: theforgottenserver, Configuration: Release Win32 ------
1>  player.cpp
1>..\src\player.cpp(812): error C2146: syntax error: missing ')' before identifier 'player'
1>..\src\player.cpp(812): error C2065: 'player': undeclared identifier
1>..\src\player.cpp(812): error C2059: syntax error: ')'
1>..\src\player.cpp(813): error C2065: 'player': undeclared identifier
1>..\src\player.cpp(813): error C2227: left of '->getGroup' must point to class/struct/union/generic type
1>  ..\src\player.cpp(813): note: type is 'unknown-type'
1>..\src\player.cpp(813): error C2227: left of '->id' must point to class/struct/union/generic type
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
 
Last edited by a moderator:
PHP:
1>------ Build started: Project: theforgottenserver, Configuration: Release Win32 ------
1>  player.cpp
1>..\src\player.cpp(813): error C2039: 'getGroup': is not a member of 'Creature'
1>  c:\users\NAME\desktop\engine\tfs custom modifications v2\src\monster.h(26): note: see declaration of 'Creature'
1>..\src\player.cpp(813): error C2227: left of '->id' must point to class/struct/union/generic type
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Failed again :/
 
creature->getPlayer()->getGroup()->id;
maybe

Code:
1>------ Build started: Project: theforgottenserver, Configuration: Release Win32 ------
1>  player.cpp
1>..\src\player.cpp(813): warning C4800: 'uint16_t': forcing value to bool 'true' or 'false' (performance warning)
1>  Generating code
1>  Finished generating code
1>  theforgottenserver.vcxproj -> C:\Users\Holiash\Desktop\Prismatic Engine\Tfs Custom Modifications V2\vc14\Release\theforgottenserver.exe
1>  theforgottenserver.vcxproj -> C:\Users\Holiash\Desktop\Prismatic Engine\Tfs Custom Modifications V2\vc14\Release\theforgottenserver.pdb (Full PDB)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Why is this?
Code:
1>..\src\player.cpp(813): warning C4800: 'uint16_t': forcing value to bool 'true' or 'false' (performance warning)
 
if(creature->getPlayer()) {
probably returns some type of object/userdata and not true or false
creature->isPlayer() might works instead
 
if(creature->getPlayer()) {
probably returns some type of object/userdata and not true or false
creature->isPlayer() might works instead

Im receiving the same warning im afraid.

Code:
1>------ Build started: Project: theforgottenserver, Configuration: Debug Win32 ------
1>  player.cpp
1>..\src\player.cpp(813): warning C4800: 'uint16_t': forcing value to bool 'true' or 'false' (performance warning)
1>  theforgottenserver.vcxproj -> C:\Users\Holiash\Desktop\Prismatic Engine\Tfs Custom Modifications V2\vc14\Debug\theforgottenserver.exe
1>  theforgottenserver.vcxproj -> C:\Users\Holiash\Desktop\Prismatic Engine\Tfs Custom Modifications V2\vc14\Debug\theforgottenserver.pdb (Full PDB)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Update: Compiled but did not have any effect, admins can still be seen by any lower ranked staff.
 
Last edited:
Change:
Code:
if (creature->isInGhostMode() && !group->access) {
    return false;
}

To:
Code:
if (creature->isInGhostMode() && (creature->getPlayer()->group->id > group->id)) {
    return false;
}
 
Code:
1>------ Build started: Project: theforgottenserver, Configuration: Release Win32 ------
1>  player.cpp
1>  Generating code
1>  Finished generating code
1>  theforgottenserver.vcxproj -> C:\Users\Holiash\Desktop\Prismatic Engine\Tfs Custom Modifications V2\vc14\Release\theforgottenserver.exe
1>  theforgottenserver.vcxproj -> C:\Users\Holiash\Desktop\Prismatic Engine\Tfs Custom Modifications V2\vc14\Release\theforgottenserver.pdb (Full PDB)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

It works, however if admins ghosts while GM is on screen, it remains some kind of "admin char" clone in GM Client;in Admin client this "clone" does not appear; also when GM steps into this "clone", gets debugged.

Also when Admin unghost while GM is on screen, GM client debugs.
 
Code:
1>------ Build started: Project: theforgottenserver, Configuration: Release Win32 ------
1>  player.cpp
1>  Generating code
1>  Finished generating code
1>  theforgottenserver.vcxproj -> C:\Users\Holiash\Desktop\Prismatic Engine\Tfs Custom Modifications V2\vc14\Release\theforgottenserver.exe
1>  theforgottenserver.vcxproj -> C:\Users\Holiash\Desktop\Prismatic Engine\Tfs Custom Modifications V2\vc14\Release\theforgottenserver.pdb (Full PDB)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

It works, however if admins ghosts while GM is on screen, it remains some kind of "admin char" clone in GM Client;in Admin client this "clone" does not appear; also when GM steps into this "clone", gets debugged.

Also when Admin unghost while GM is on screen, GM client debugs.

In luascript.cpp, in the function int LuaScriptInterface::luaPlayerSetGhostMode(lua_State* L) :
Change:
Code:
    for (Creature* spectator : list) {
        Player* tmpPlayer = spectator->getPlayer();
        if (tmpPlayer != player && !tmpPlayer->isAccessPlayer()) {
            if (enabled) {
                tmpPlayer->sendRemoveTileThing(position, tile->getStackposOfCreature(tmpPlayer, player));
            } else {
                tmpPlayer->sendCreatureAppear(player, position, true);
            }
        } else {
            tmpPlayer->sendCreatureChangeVisible(player, !enabled);
        }
    }

    if (player->isInGhostMode()) {
        for (const auto& it : g_game.getPlayers()) {
            if (!it.second->isAccessPlayer()) {
                it.second->notifyStatusChange(player, VIPSTATUS_OFFLINE);
            }
        }
        IOLoginData::updateOnlineStatus(player->getGUID(), false);
    } else {
        for (const auto& it : g_game.getPlayers()) {
            if (!it.second->isAccessPlayer()) {
                it.second->notifyStatusChange(player, VIPSTATUS_ONLINE);
            }
        }
        IOLoginData::updateOnlineStatus(player->getGUID(), true);
    }
To:
Code:
    for (Creature* spectator : list) {
        Player* tmpPlayer = spectator->getPlayer();
        if (tmpPlayer != player && tmpPlayer->getGroup()->id < player->getGroup()->id) {
            if (enabled) {
                tmpPlayer->sendRemoveTileThing(position, tile->getStackposOfCreature(tmpPlayer, player));
            } else {
                tmpPlayer->sendCreatureAppear(player, position, true);
            }
        } else {
            tmpPlayer->sendCreatureChangeVisible(player, !enabled);
        }
    }

    if (player->isInGhostMode()) {
        for (const auto& it : g_game.getPlayers()) {
            if (it.second->getGroup()->id < player->getGroup()->id) {
                it.second->notifyStatusChange(player, VIPSTATUS_OFFLINE);
            }
        }
        IOLoginData::updateOnlineStatus(player->getGUID(), false);
    } else {
        for (const auto& it : g_game.getPlayers()) {
            if (it.second->getGroup()->id < player->getGroup()->id) {
                it.second->notifyStatusChange(player, VIPSTATUS_ONLINE);
            }
        }
        IOLoginData::updateOnlineStatus(player->getGUID(), true);
    }
 
In luascript.cpp, in the function int LuaScriptInterface::luaPlayerSetGhostMode(lua_State* L) :
Change:
Code:
    for (Creature* spectator : list) {
        Player* tmpPlayer = spectator->getPlayer();
        if (tmpPlayer != player && !tmpPlayer->isAccessPlayer()) {
            if (enabled) {
                tmpPlayer->sendRemoveTileThing(position, tile->getStackposOfCreature(tmpPlayer, player));
            } else {
                tmpPlayer->sendCreatureAppear(player, position, true);
            }
        } else {
            tmpPlayer->sendCreatureChangeVisible(player, !enabled);
        }
    }

    if (player->isInGhostMode()) {
        for (const auto& it : g_game.getPlayers()) {
            if (!it.second->isAccessPlayer()) {
                it.second->notifyStatusChange(player, VIPSTATUS_OFFLINE);
            }
        }
        IOLoginData::updateOnlineStatus(player->getGUID(), false);
    } else {
        for (const auto& it : g_game.getPlayers()) {
            if (!it.second->isAccessPlayer()) {
                it.second->notifyStatusChange(player, VIPSTATUS_ONLINE);
            }
        }
        IOLoginData::updateOnlineStatus(player->getGUID(), true);
    }
To:
Code:
    for (Creature* spectator : list) {
        Player* tmpPlayer = spectator->getPlayer();
        if (tmpPlayer != player && tmpPlayer->getGroup()->id < player->getGroup()->id) {
            if (enabled) {
                tmpPlayer->sendRemoveTileThing(position, tile->getStackposOfCreature(tmpPlayer, player));
            } else {
                tmpPlayer->sendCreatureAppear(player, position, true);
            }
        } else {
            tmpPlayer->sendCreatureChangeVisible(player, !enabled);
        }
    }

    if (player->isInGhostMode()) {
        for (const auto& it : g_game.getPlayers()) {
            if (it.second->getGroup()->id < player->getGroup()->id) {
                it.second->notifyStatusChange(player, VIPSTATUS_OFFLINE);
            }
        }
        IOLoginData::updateOnlineStatus(player->getGUID(), false);
    } else {
        for (const auto& it : g_game.getPlayers()) {
            if (it.second->getGroup()->id < player->getGroup()->id) {
                it.second->notifyStatusChange(player, VIPSTATUS_ONLINE);
            }
        }
        IOLoginData::updateOnlineStatus(player->getGUID(), true);
    }

Amazing! Working perfectly, thank you very much!
 
Back
Top