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

Lua GHOST Script

archer32

Member
Joined
Feb 3, 2011
Messages
88
Solutions
1
Reaction score
9
Hey, I have a ghost script here
It works very well.

I want to know if there is a way that
if Vocation 1 goes ghost, people who are also vocation 1 can see the ghost still?

So example;
VocationID 1 goes ghost, VocationID 2 cannot see him, however Vocation 1 can still see the ghost guy?
kind of doing a vocation vs vocation thing to test out

Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_EFFECT, 63)
combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false)

local condition = Condition(CONDITION_INVISIBLE)
condition:setParameter(CONDITION_PARAM_TICKS, 5000)
combat:setCondition(condition)

function onCastSpell(creature, variant, isHotkey)
local player = Player(creature)

local function OMG()
    player:setGhostMode(isGhost)
         return true
  end
    addEvent(OMG, 5 * 1000)
    local position = player:getPosition()
    local isGhost = not player:isInGhostMode()
    player:setGhostMode(isGhost)
    return combat:execute(creature, variant)
end
 
On TFS 1.4+ it should be controlled by these 2 functions ( forgottenserver/player.cpp at master · otland/forgottenserver (https://github.com/otland/forgottenserver/blob/master/src/player.cpp#L765-L781) ):
C++:
bool Player::canSeeCreature(const Creature* creature) const
{
    if (creature == this) {
        return true;
    }

    if (creature->isInGhostMode() && !canSeeGhostMode(creature)) {
        return false;
    }

    if (!creature->getPlayer() && !canSeeInvisibility() && creature->isInvisible()) {
        return false;
    }
    return true;
}

bool Player::canSeeGhostMode(const Creature*) const { return group->access; }
This:
C++:
bool Player::canSeeGhostMode(const Creature*) const { return group->access; }
means that if player has access > 0 (is GM/CM/GOD), he can see other GM/CM/GOD.

You must adjust it, to check if const Creature* (add creature as parameter name to check what is Creature) is Player* and what is vocation of that Player.
C++:
bool Player::canSeeGhostMode(const Creature* creature) const {
    Player* player = creature->getPlayer();
    if (player) {
        // players have same vocation (fails if Sorcerer looks on Master Sorcerer)
        return player->getVocationId() == getVocationId();
    }
    return group->access; // wtf, Monster/NPC is in ghost mode? ok, it's allowed by engine - only GM+ can see them
}
 
Last edited:
Hey, I have a ghost script here
It works very well.

I want to know if there is a way that
if Vocation 1 goes ghost, people who are also vocation 1 can see the ghost still?

So example;
VocationID 1 goes ghost, VocationID 2 cannot see him, however Vocation 1 can still see the ghost guy?
kind of doing a vocation vs vocation thing to test out

Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_EFFECT, 63)
combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false)

local condition = Condition(CONDITION_INVISIBLE)
condition:setParameter(CONDITION_PARAM_TICKS, 5000)
combat:setCondition(condition)

function onCastSpell(creature, variant, isHotkey)
local player = Player(creature)

local function OMG()
    player:setGhostMode(isGhost)
         return true
  end
    addEvent(OMG, 5 * 1000)
    local position = player:getPosition()
    local isGhost = not player:isInGhostMode()
    player:setGhostMode(isGhost)
    return combat:execute(creature, variant)
end
only with source edit
 
that is fine, any idea where i would be able to do this particular change?
there are a few functions that checks ghost mode, like VIP (to show online or not), pm, push player, see player, walk through, attack.. i'm pretty sure that if you search for "ghost" in your source files you gonna find it all.. so i recommend that you do this at first, and bring here more specific questions that you may find...
and don't forget.. ghost mode is the way you can move around with god/gm without been seen.. if you start changing this function, you may not be able to use it as it should be.
 
On TFS 1.4+ it should be controlled by these 2 functions ( forgottenserver/player.cpp at master · otland/forgottenserver (https://github.com/otland/forgottenserver/blob/master/src/player.cpp#L765-L781) ):
C++:
bool Player::canSeeCreature(const Creature* creature) const
{
    if (creature == this) {
        return true;
    }

    if (creature->isInGhostMode() && !canSeeGhostMode(creature)) {
        return false;
    }

    if (!creature->getPlayer() && !canSeeInvisibility() && creature->isInvisible()) {
        return false;
    }
    return true;
}

bool Player::canSeeGhostMode(const Creature*) const { return group->access; }
This:
C++:
bool Player::canSeeGhostMode(const Creature*) const { return group->access; }
means that if player has access > 0 (is GM/CM/GOD), he can see other GM/CM/GOD.

You must adjust it, to check if const Creature* (add creature as parameter name to check what is Creature) is Player* and what is vocation of that Player.
C++:
bool Player::canSeeGhostMode(const Creature* creature) const {
    Player* player = creature->getPlayer();
    if (player) {
        // players have same vocation (fails if Sorcerer looks on Master Sorcerer)
        return player->getVocationId() == getVocationId();
    }
    return group->access; // wtf, Monster/NPC is in ghost mode? ok, it's allowed by engine - only GM+ can see them
}
Thank you for that info! Much appreciated.
 
Also you may want to disable the possibility to see [GM / CM / GOD] if they are the same vocation
C++:
if (player && !player->isAccessPlayer()) {
    // players have same vocation (fails if Sorcerer looks on Master Sorcerer)
    return player->getVocationId() == getVocationId();
}
 
On TFS 1.4+ it should be controlled by these 2 functions ( forgottenserver/player.cpp at master · otland/forgottenserver (https://github.com/otland/forgottenserver/blob/master/src/player.cpp#L765-L781) ):
C++:
bool Player::canSeeCreature(const Creature* creature) const
{
    if (creature == this) {
        return true;
    }

    if (creature->isInGhostMode() && !canSeeGhostMode(creature)) {
        return false;
    }

    if (!creature->getPlayer() && !canSeeInvisibility() && creature->isInvisible()) {
        return false;
    }
    return true;
}

bool Player::canSeeGhostMode(const Creature*) const { return group->access; }
This:
C++:
bool Player::canSeeGhostMode(const Creature*) const { return group->access; }
means that if player has access > 0 (is GM/CM/GOD), he can see other GM/CM/GOD.

You must adjust it, to check if const Creature* (add creature as parameter name to check what is Creature) is Player* and what is vocation of that Player.
C++:
bool Player::canSeeGhostMode(const Creature* creature) const {
    Player* player = creature->getPlayer();
if (player && !player->isAccessPlayer()) {
    // players have same vocation (fails if Sorcerer looks on Master Sorcerer)
    return player->getVocationId() == getVocationId();
}
    return group->access; // wtf, Monster/NPC is in ghost mode? ok, it's allowed by engine - only GM+ can see them
}
thank you for response, in tfs 1.3 it is a bit different

however i added lines and get error in player.h and compile

C++:
bool canSeeGhostMode(const Creature* creature) const override;

bool Player::canSeeGhostMode(const Creature *creature) const override
member function declared with 'override' does not override a base class memberC/C++(1455)

if i try to remove override it compiles fine but does not work then

same code in player.cpp
C++:
bool Player::canSeeGhostMode(const Creature* creature) const {
    const Player* player = creature->getPlayer();
    if (player) {
        // players have same vocation (fails if Sorcerer looks on Master Sorcerer)
        return player->getVocationId() == getVocationId();
    }
    return group->access; // wtf, Monster/NPC is in ghost mode? ok, it's allowed by engine - only GM+ can see them
}
Post automatically merged:

seems my creature.h was missing

C++:
virtual bool canSeeGhostMode(const Creature*) const { return false; }

adding this after dinner and trying again
Post automatically merged:

after adding that to creature.h it still doesnt work, but compiles with no errors .. any idea?
Post automatically merged:

player.cpp
C++:
bool Player::canSeeGhostMode(const Creature* creature) const {
    const Player* player = creature->getPlayer();
    if (!player && !player->isAccessPlayer()) {
    // players have same vocation (fails if Sorcerer looks on Master Sorcerer)
    return player->getVocationId() == getVocationId();
}
    return group->access; // wtf, Monster/NPC is in ghost mode? ok, it's allowed by engine - only GM+ can see them
}

player.h
C++:
bool canSeeGhostMode(const Creature* creature) const override;

creature.h
C++:
virtual bool canSeeGhostMode(const Creature*) const { return false; }

creature.cpp
C++:
bool Creature::canSeeCreature(const Creature* creature) const
{
    if (!canSeeGhostMode(creature) && creature->isInGhostMode()) {
        return false;
    }
    return true;
}

these are changes I have made, obv. added your code in player.cpp but had to add const in front of Player * player
been poking around, cannot get it to work, it compiles fine.. probably missing something dumb :( any help appreciated :)
 
Last edited:
probably double lined here.. but tried something like

C++:
bool Player::canSeeGhostMode(const Creature* creature) const {
    const Player* player = creature->getPlayer();
    if (player) {
            // players with vocation ID 1 can see each other if invisible
            if (player->getVocationId() == 1 && getVocationId() == 1) {
                return true;
            }
            // players with vocation ID 2 can see each other if invisible
            if (player->getVocationId() == 2 && getVocationId() == 2) {
                return true;
            }
            // players with vocation ID 1 cannot see vocation ID 2 if invisible
            if (player->getVocationId() == 1 && getVocationId() == 2) {
                return false;
            }
            // players with vocation ID 2 cannot see vocation ID 1 if invisible
            if (player->getVocationId() == 2 && getVocationId() == 1) {
                return false;
            }
       
        return group->access; // wtf, Monster/NPC is in ghost mode? ok, it's allowed by engine - only GM+ can see them
    }
    return false;
}

did not seem to work though
 
player.cpp
C++:
bool Player::canSeeGhostMode(const Creature* creature) const {
    const Player* player = creature->getPlayer();
    if (player && !player->isAccessPlayer()) {
        // players have same vocation (fails if Sorcerer looks on Master Sorcerer)
        return player->getVocationId() == getVocationId();
    }
    return group->access; // wtf, Monster/NPC is in ghost mode? ok, it's allowed by engine - only GM+ can see them
}

luascript.cpp

Find
C++:
int LuaScriptInterface::luaPlayerSetGhostMode(lua_State* L)

Replace
C++:
if (tmpPlayer != player && !tmpPlayer->isAccessPlayer()) {

With
Lua:
if (tmpPlayer != player && !tmpPlayer->canSeeGhostMode(player)) {

There is no need to edit Creature::canSeeCreature - so leave it as it is

@EDIT: Also your spell script will inevitably crash the server, use this one instead
Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_EFFECT, 63)
combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false)

local function revertGhostMode(pid)
    local player = Player(pid)
    if not player then
        return
    end
    player:setGhostMode(false)
end

function onCastSpell(player, variant, isHotkey)

    if player:isInGhostMode() then
        return player:getPosition():sendMagicEffect(CONST_ME_POFF)
    end

    player:setGhostMode(true)
    addEvent(revertGhostMode, 5 * 1000, player:getId())
    return combat:execute(player, variant)
end
 
Last edited:
player.cpp
C++:
bool Player::canSeeGhostMode(const Creature* creature) const {
    const Player* player = creature->getPlayer();
    if (player && !player->isAccessPlayer()) {
        // players have same vocation (fails if Sorcerer looks on Master Sorcerer)
        return player->getVocationId() == getVocationId();
    }
    return group->access; // wtf, Monster/NPC is in ghost mode? ok, it's allowed by engine - only GM+ can see them
}

luascript.cpp

Find
C++:
int LuaScriptInterface::luaPlayerSetGhostMode(lua_State* L)

Replace
C++:
if (tmpPlayer != player && !tmpPlayer->isAccessPlayer()) {

With
Lua:
if (tmpPlayer != player && !tmpPlayer->canSeeGhostMode(player)) {

There is no need to edit Creature::canSeeCreature - so leave it as it is

@EDIT: Also your spell script will inevitably crash the server, use this one instead
Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_EFFECT, 63)
combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false)

local function revertGhostMode(pid)
    local player = Player(pid)
    if not player then
        return
    end
    player:setGhostMode(false)
end

function onCastSpell(creature, variant, isHotkey)

    if player:isInGhostMode() then
        return player:getPosition():sendMagicEffect(CONST_ME_POFF)
    end

    player:setGhostMode(true)
    addEvent(revertGhostMode, 5 * 1000, player:getId())
    return combat:execute(creature, variant)
end
it is progress, that new script for invis won't run.. yet, need to check into that.. complains about player nil, etc etc
Code:
Lua Script Error: [Spell Interface]
tfs  | data/spells/scripts/support/invisible.lua:onCastSpell
tfs  | data/spells/scripts/support/invisible.lua:15: attempt to index global 'player' (a nil value)
tfs  | stack traceback:
tfs  |  [C]: in function '__index'
tfs  |  data/spells/scripts/support/invisible.lua:15: in function <data/spells/scripts/support/invisible.lua:13>

but when i do go into invisible, it shows character but just them standing there.. they dont move back and forth, and if you run into them it locks up client, ahahah

kind of a funny bug.. hm
 
Back
Top