• 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+ Promotion bug TFS 1.3

Vantoria

www.ClassicOT.us
Joined
Jun 6, 2014
Messages
186
Reaction score
16
Location
USA
hello recently i start working on my server based on TFS 1.3 7.72 downgraded by @Nekiro so my problem is after character reach level 8 and going to main throught the npc The Oracle after they relog they automatically become promotion i dont know if it a source bug or is my npc here is my npc script
Code:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
 
local Topic, vocation, town, destination = {}, {}, {}, {}
local TOWN_ISLANDOFDESTINY = 20
local islandOfDestinyEnabled = false
 
function onCreatureAppear(cid)                npcHandler:onCreatureAppear(cid) end
function onCreatureDisappear(cid)             npcHandler:onCreatureDisappear(cid) end
function onCreatureSay(cid, type, msg)     npcHandler:onCreatureSay(cid, type, msg) end
function onThink()                         npcHandler:onThink() end
 
function greetCallback(cid)
    if(getPlayerLevel(cid) < 8) then
        npcHandler:say("CHILD! COME BACK WHEN YOU HAVE GROWN UP!", cid)
        return false
    elseif(getPlayerLevel(cid) > 9) then
        npcHandler:say(getCreatureName(cid) .. ", I CAN'T LET YOU LEAVE - YOU ARE TOO STRONG ALREADY! YOU CAN ONLY LEAVE WITH LEVEL 9 OR LOWER.", cid)
        return false
    else
        local talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT and 0 or cid
        Topic[talkUser], vocation[talkUser], town[talkUser], destination[talkUser] = 0, 0, 0, 0
        return true
    end
end
 
function creatureSayCallback(cid, type, msg)
    local talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT and 0 or cid
    if(not npcHandler:isFocused(cid)) then
        return false
    elseif msgcontains(msg, "yes") and Topic[talkUser] == 0 then
        npcHandler:say(islandOfDestinyEnabled and "I WILL BRING YOU TO THE ISLAND OF DESTINY AND YOU WILL BE UNABLE TO RETURN HERE! ARE YOU SURE?" or "IN WHICH TOWN DO YOU WANT TO LIVE: {CARLIN}, {AB'DENDRIEL}, {KAZORDOON}" .. (isPremium(cid) == TRUE and ", {THAIS}, {VENORE}, {DARASHIA}, {ANKRAHMUN}, OR {EDRON}?" or " OR {THAIS}?"), cid)
        Topic[talkUser] = islandOfDestinyEnabled and 4 or 1
    elseif Topic[talkUser] == 0 then
        npcHandler:unGreet(cid)
    elseif msgcontains(msg, "carlin") and Topic[talkUser] == 1 then
        npcHandler:say("IN CARLIN! AND WHAT PROFESSION HAVE YOU CHOSEN: {KNIGHT}, {PALADIN}, {SORCERER}, OR {DRUID}?", cid)
        Topic[talkUser] = 2
        town[talkUser] = 5
        destination[talkUser] = {x=32360, y=31782, z=7}
    elseif msgcontains(msg, "ab'dendriel") and Topic[talkUser] == 1 then
        npcHandler:say("IN AB'DENDRIEL! AND WHAT PROFESSION HAVE YOU CHOSEN: {KNIGHT}, {PALADIN}, {SORCERER}, OR {DRUID}?", cid)
        Topic[talkUser] = 2
        town[talkUser] = 1
        destination[talkUser] = {x=32732, y=31634, z=7}
    elseif msgcontains(msg, "kazordoon") and Topic[talkUser] == 1 then
        npcHandler:say("IN KAZORDOON! AND WHAT PROFESSION HAVE YOU CHOSEN: {KNIGHT}, {PALADIN}, {SORCERER}, OR {DRUID}?", cid)
        Topic[talkUser] = 2
        town[talkUser] = 2
        destination[talkUser] = {x=32649, y=31925, z=11}
    elseif msgcontains(msg, "thais") and Topic[talkUser] == 1 then
        npcHandler:say("IN THAIS! AND WHAT PROFESSION HAVE YOU CHOSEN: {KNIGHT}, {PALADIN}, {SORCERER}, OR {DRUID}?", cid)
        Topic[talkUser] = 2
        town[talkUser] = 3
        destination[talkUser] = {x=32369, y=32241, z=7}
    elseif msgcontains(msg, "venore") and Topic[talkUser] == 1 then
        npcHandler:say("IN VENORE! AND WHAT PROFESSION HAVE YOU CHOSEN: {KNIGHT}, {PALADIN}, {SORCERER}, OR {DRUID}?", cid)
        Topic[talkUser] = 2
        town[talkUser] = 4
        destination[talkUser] = {x=32957, y=32076, z=7}
    elseif msgcontains(msg, "darashia") and Topic[talkUser] == 1 then
        if isPremium(cid) == TRUE then
            npcHandler:say("IN DARASHIA! AND WHAT PROFESSION HAVE YOU CHOSEN: {KNIGHT}, {PALADIN}, {SORCERER}, OR {DRUID}?", cid)
            Topic[talkUser] = 2
            town[talkUser] = 7
            destination[talkUser] = {x=33213, y=32454, z=1}
        else
            npcHandler:say("YOU NEED A PREMIUM ACCOUNT IN ORDER TO GO THERE!", cid)
            Topic[talkUser] = 1
        end
    elseif msgcontains(msg, "ankrahmun") and Topic[talkUser] == 1 then
        if isPremium(cid) == TRUE then
            npcHandler:say("IN ANKRAHMUN! AND WHAT PROFESSION HAVE YOU CHOSEN: {KNIGHT}, {PALADIN}, {SORCERER}, OR {DRUID}?", cid)
            Topic[talkUser] = 2
            town[talkUser] = 6
            destination[talkUser] = {x=33194, y=32853, z=8}
        else
            npcHandler:say("YOU NEED A PREMIUM ACCOUNT IN ORDER TO GO THERE!", cid)
            Topic[talkUser] = 1
        end
    elseif msgcontains(msg, "edron") and Topic[talkUser] == 1 then
        if isPremium(cid) == TRUE then
            npcHandler:say("IN EDRON! AND WHAT PROFESSION HAVE YOU CHOSEN: {KNIGHT}, {PALADIN}, {SORCERER}, OR {DRUID}?", cid)
            Topic[talkUser] = 2
            town[talkUser] = 8
            destination[talkUser] = {x=33217, y=31814, z=8}
        else
            npcHandler:say("YOU NEED A PREMIUM ACCOUNT IN ORDER TO GO THERE!", cid)
            Topic[talkUser] = 1
        end
    elseif Topic[talkUser] == 1 then
        npcHandler:say("{CARLIN}, {AB'DENDRIEL}, {KAZORDOON}" .. (isPremium(cid) == TRUE and ", {THAIS}, {VENORE}, {DARASHIA}, {ANKRAHMUN}, {EDRON}?" or " OR {THAIS}?"), cid)
        Topic[talkUser] = 1
    elseif msgcontains(msg, "sorcerer") and Topic[talkUser] == 2 then
        npcHandler:say("A SORCERER! ARE YOU SURE? THIS DECISION IS IRREVERSIBLE!", cid)
        Topic[talkUser] = 3
        vocation[talkUser] = 1
    elseif msgcontains(msg, "druid") and Topic[talkUser] == 2 then
        npcHandler:say("A DRUID! ARE YOU SURE? THIS DECISION IS IRREVERSIBLE!", cid)
        Topic[talkUser] = 3
        vocation[talkUser] = 2
    elseif msgcontains(msg, "paladin") and Topic[talkUser] == 2 then
        npcHandler:say("A PALADIN! ARE YOU SURE? THIS DECISION IS IRREVERSIBLE!", cid)
        Topic[talkUser] = 3
        vocation[talkUser] = 3
    elseif msgcontains(msg, "knight") and Topic[talkUser] == 2 then
        npcHandler:say("A KNIGHT! ARE YOU SURE? THIS DECISION IS IRREVERSIBLE!", cid)
        Topic[talkUser] = 3
        vocation[talkUser] = 4
    elseif Topic[talkUser] == 2 then
        npcHandler:say("{KNIGHT}, {PALADIN}, {SORCERER}, OR {DRUID}?", cid)
        Topic[talkUser] = 2
    elseif msgcontains(msg, "yes") and Topic[talkUser] == 3 then
        npcHandler:say("SO BE IT!", cid)
        Topic[talkUser] = 0
        doPlayerSetVocation(cid, vocation[talkUser])
        doPlayerSetTown(cid, town[talkUser])
        npcHandler:releaseFocus(cid)
        doSendMagicEffect(getCreaturePosition(cid), CONST_ME_TELEPORT)
        doTeleportThing(cid, destination[talkUser])
        doPlayerAddItem(cid, 1988, 1) -- Backpack
        doPlayerAddItem(cid, 2480) -- legion helmet
        doPlayerAddItem(cid, 2484) -- studded armor
        doPlayerAddItem(cid, 2530) -- cooper shield
        doPlayerAddItem(cid, 2649) -- leather legs
        doPlayerAddItem(cid, 2643) -- leather boots
        doPlayerAddItem(cid, 2120, 1) -- rope
        doPlayerAddItem(cid, 2554, 1) -- shovel
        doPlayerAddItem(cid, 2789, 5) -- brown mushroom
        doPlayerAddItem(cid, 2160, 1) -- Crystal coin
        doSendMagicEffect(destination[talkUser], CONST_ME_TELEPORT)
    elseif Topic[talkUser] == 3 then
        npcHandler:unGreet(cid)
    elseif Topic[talkUser] == 4 then
        if msgcontains(msg, "yes") then
            npcHandler:say("SO BE IT!", cid)
            Topic[talkUser] = 0
            doPlayerSetTown(cid, TOWN_ISLANDOFDESTINY)
            npcHandler:releaseFocus(cid)
            doSendMagicEffect(getCreaturePosition(cid), CONST_ME_TELEPORT)
            doTeleportThing(cid, {x=32091,y=32027,z=7})
            doSendMagicEffect({x=32091,y=32027,z=7}, CONST_ME_TELEPORT)
            doPlayerSendTextMessage(cid, MESSAGE_EVENT_ADVANCE, "Welcome to the Island of Destiny. Walk north to find trainers who will help you find a suitable vocation.")
            doPlayerSendTextMessage(cid, MESSAGE_EVENT_ADVANCE, "The surface of this island is a protection zone. You can't attack or regain health here. If you need healing, talk to Yandur.")
            doAddMapMark(cid, {x=32091,y=32027,z=7}, MAPMARK_EXCLAMATION, "Island of Destiny - Training Centre")
            doAddMapMark(cid, {x=32091,y=32027,z=7}, MAPMARK_GREENNORTH, "Ship to Mainland")
        else
            npcHandler:unGreet(cid)
        end
    end
    return TRUE
end
 
npcHandler:setMessage(MESSAGE_GREET, "|PLAYERNAME|, ARE YOU PREPARED TO FACE YOUR DESTINY?")
npcHandler:setMessage(MESSAGE_WALKAWAY, "COME BACK WHEN YOU ARE PREPARED TO FACE YOUR DESTINY!")
npcHandler:setMessage(MESSAGE_FAREWELL, "COME BACK WHEN YOU ARE PREPARED TO FACE YOUR DESTINY!")
 
npcHandler:setCallback(CALLBACK_GREET, greetCallback)
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
 
Solution
i search in all files and the promotion storage is on Global.lua in this engine nekiro/forgottenserver (https://github.com/nekiro/forgottenserver/tree/7.72-downgrade) there are no more 30018 in all the datapack

Irrelevant.
You need to find if 30018 is being used in your DATAPACK files, not the engine files.
Or your ACC Maker, if you use an old achievements script:

Then use a test char.
  1. What is test chars ID.
  2. Go through rook and use oracle to set vocation.
  3. Logout and login, are they automatically promoted?
Then look for their ID in player_storage and see if they have 30018 set for...
hmm
Lua:
-- Promotion
    local vocation = player:getVocation()
    local promotion = vocation:getPromotion()
    if player:isPremium() then
        local value = player:getStorageValue(PlayerStorageKeys.promotion)
        if not promotion and value ~= 1 then -- maybe this is wrong logically speaking
            player:setStorageValue(PlayerStorageKeys.promotion, 1)
        elseif value == 1 then
            player:setVocation(promotion)
        end
    elseif not promotion then
        player:setVocation(vocation:getDemotion())
    end

Lua:
-- Promotion
    local vocation = player:getVocation()
    local promotion = vocation:getPromotion()
    if player:isPremium() then
        local value = player:getStorageValue(PlayerStorageKeys.promotion)
        if not promotion and value >= 1 then
            player:setStorageValue(PlayerStorageKeys.promotion, 1)
        elseif value == 1 then
            player:setVocation(promotion)
        end
    elseif not promotion then
        player:setVocation(vocation:getDemotion())
    end

Just changed that and seems to fix the issue. I'm no coder so have no idea what side effects this might have but from what I've been able to test I can no longer reproduce the issue.
 
Lua:
-- Promotion
    local vocation = player:getVocation()
    local promotion = vocation:getPromotion()
    if player:isPremium() then
        local value = player:getStorageValue(PlayerStorageKeys.promotion)
        if not promotion and value >= 1 then
            player:setStorageValue(PlayerStorageKeys.promotion, 1)
        elseif value == 1 then
            player:setVocation(promotion)
        end
    elseif not promotion then
        player:setVocation(vocation:getDemotion())
    end

Just changed that and seems to fix the issue. I'm no coder so have no idea what side effects this might have but from what I've been able to test I can no longer reproduce the issue.

I don't know if this is right since for the code to run we would need to login twice (?)
Lua:
-- Promotion
    local vocation = player:getVocation()
    local promotion = vocation:getPromotion()
    if player:isPremium() then
        local value = player:getStorageValue(PlayerStorageKeys.promotion) -- returns 1 if promoted, -1 if not
        if not promotion and value == -1 then -- if not promoted AND value equals -1 (not set)
            player:setStorageValue(PlayerStorageKeys.promotion, 1) -- set value = 1
        elseif value == 1 then -- if value == 1, set promotion
            player:setVocation(promotion)
        end
    elseif not promotion then
        player:setVocation(vocation:getDemotion())
    end
 
I don't know if this is right since for the code to run we would need to login twice (?)
Lua:
-- Promotion
    local vocation = player:getVocation()
    local promotion = vocation:getPromotion()
    if player:isPremium() then
        local value = player:getStorageValue(PlayerStorageKeys.promotion) -- returns 1 if promoted, -1 if not
        if not promotion and value == -1 then -- if not promoted AND value equals -1 (not set)
            player:setStorageValue(PlayerStorageKeys.promotion, 1) -- set value = 1
        elseif value == 1 then -- if value == 1, set promotion
            player:setVocation(promotion)
        end
    elseif not promotion then
        player:setVocation(vocation:getDemotion())
    end

That seems to be working aswell but may need more testing just incase. I'm no coder so other than trial and error I can't do much :)

Things I tested are (with a clear db/character/datapack)
· Create character with no vocation - login/logout/login (no promotion storage)
· Get him a vocation - logout/login (still no promotion storage)
· Get him promotion - logout/login (now it got promoted and the storage is = 1)
· Remove Premium (still have storage = 1 but due to not premium -> no promotion)
· Add Premium again (as it has storage = 1 it gets promoted)

Will reopen github issue again as it seems to be an issue with this code - a bit surprising that such a thing has gone unnoticed for so long. Hopefully others can confirm the issue if there really is something wrong here and so we can fix this.

And might aswell ping OP incase it didn't get to solve this @Vantoria for bringing this up. Such a coincidence I was toying with storages/achievements and found this.
 
Last edited:
Irrelevant.
You need to find if 30018 is being used in your DATAPACK files, not the engine files.
Or your ACC Maker, if you use an old achievements script:



Or add print(player:getStorageValue(30018)) to your login.lua script.
Confirm the issue before trying to fix anything.



👇
100% working for me thanks ;-)
 
Back
Top