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

What's the best current route to creating a 7.72 server?

Nostalgian

Member
Joined
Mar 17, 2018
Messages
66
Reaction score
15
Hey everyone. I've noticed lately that there are quite a few 7.72 servers popping up, and I have been kicking around working on one.

As the title infers, what is currently the best route to take with the fewest pain points?

I've found 2 different contenders in my search: otx3 and othire

Othire looks great, but my concern is the lack of resources for it. (Scripts, etc.)

I'm not sure about otx3. Is it a good distro for 7.7? Are there any major bugs I'll have to deal with right out of the gate?



Another idea I have been thinking about doing is to work on downgrading the new tfs.

I've kicked it around for a while and I'm in need of some guidance from those of you who have done it. I will only be using otcliend, so I feel that there is no need to remove things like modal windows.

Is there a simple(ish) way to use a 7.72 items.xml +otb from another distro like otx or othire, or will I have to completely redo both of them?

Would it be best to just replace new sprites with old ones and only use those, and then just go in and pick and choose what to change(like spell formulas)?

I thought about doing it that way, but my ocd drives me nuts trying to navigate 20,000+ randomly assorted sprites from a newer client, so I've been trying to think of the simplest way to narrow it down to just old sprites.

What do you think?
 
@Peonso can probably answer better than me, but I think Othire is based on an older version of TFS. You will need to change some stuff in new scripts (e.g the config file has some renamed entries). Starting from scratch sounds like a nightmare. It doesn't seem right to start over when someone already made you a foundation – even if you'd need to do some work to make what you want with Othire.
 
I guess that if you got enough knowledge the very best start is to downgrade the actual version of TFS to 7.72.
That would be my way to do it, anyways OTHire seems to be fine nowadays with all the work Peonso has made.
 
If you are totally lost and want to implement custom content, OTX is probably more customizable and will have more ready to be used scripts here in OtLand since it's based in TFS. OTHire is based in the good old OtServ, but despite having an ancient code base, it mimics better the oldschool mechanics of 7.72, and if you don't wanna flourish it too much you will have a much more accurate old school gameplay, and if you can script yourself you will be able to do nearby all he same stuff you can do with OTX.
 
Actually I've used OTX to rebuild a whole new 7.4 server.
It was hell of work but I could finally manage it, even tho I will never host these files probably.
My older 7.4 server took around 1-2 minute to restart the whole server, the newer files take about 10 seconds max.
A friend of mine could manage to get whole real map files from leaked tibia files.
We could manage to have every single AID and UID but no houses, even the map looks cleans as fk.

I modified a part of the source code for RME and could manage to delete every single AID and UID because I would have to re-create a whole new datapack, so my idea was actually to have a awesome datapack without havin alot of work.
Also I modified the RME part for "Import Map" so it took AID and UID from ORTS datapack (8.6 version) also I rewrote another part so it checks if the tile is a house tile and check if this tile (to avoid adding houses which came after 7.7+) exist in this map - if so, it copied the whole house tiles. It's pretty cool everything worked like a charm so I could use ORTS datapack for 7.4 without having alot of work to do.

I assume this was a part of RME source edit:
C++:
        if (old_tile) {
            for (ItemVector::iterator iter = import_tile->items.begin(); iter != import_tile->items.end(); ++iter) {
                Item* item = *iter;
                if (item->getActionID() != 0) {
                    //gui.PopupDialog(wxT("Success"), wxT("Found item with action id ") + i2ws(item->getActionID()), wxOK);
                    map.setTile(new_pos, import_tile, false);
                }
                else if (item->getUniqueID() != 0) {
                    //gui.PopupDialog(wxT("Success"), wxT("Found item with unique id ") + i2ws(item->getActionID()), wxOK);
                    map.setTile(new_pos, import_tile, false);
                }
            }
        }
  

  
        if (old_tile && import_tile->isHouseTile()){
        map.setTile(new_pos, import_tile, true);
        }

o2g7C9Q.png


xiuI6hu.jpg


Lxti4f8.jpg


OzgqgDq.jpg

hQejijs.jpg


These tiles in the corner of the last screenshot was a custom part made for test purposes, they did not exist before.


A part of action.xml:
Lua:
    <!-- Quests -->
    <action actionid="2000" script="quests/system.lua"/>
    <action fromaid="30009" toaid="30011" script="quests/system.lua"/>
    <action actionid="30002" script="quests/system.lua"/>
    <action actionid="30039" script="quests/system.lua"/>
    <action uniqueid="30019" script="quests/systemNoContainer.lua"/>
    <action fromuid="30047" touid="30050" script="quests/systemNoContainer.lua"/>
    <action uniqueid="30063" script="quests/systemNoContainer.lua"/>
    <action uniqueid="30073" script="quests/systemNoContainer.lua"/>
    <action uniqueid="31005" script="quests/systemNoContainer.lua"/>
    <action uniqueid="31017" script="quests/systemNoContainer.lua"/>
    <action fromuid="31027" touid="31029" script="quests/systemNoContainer.lua"/>
    <action uniqueid="31043" script="quests/systemNoContainer.lua"/>
    <action uniqueid="31050" script="quests/systemNoContainer.lua"/>
    <action uniqueid="31053" script="quests/systemNoContainer.lua"/>
    <action uniqueid="31229" script="quests/theDesertDungeonQuest.lua"/>
    <action actionid="31248" script="quests/system.lua"/>
    <action actionid="31254" script="quests/systemNoContainer.lua"/>
    <action actionid="31256" script="quests/systemNoContainer.lua"/>

    <!-- The Ape City Quest -->
    <action actionid="31257" script="theApeCityQuest/theDeepestCatacombsLever.lua" />
    <action uniqueid="31291" script="theApeCityQuest/theDeepestCatacombsLever.lua" />

    <!-- Postman Quest -->
    <action itemid="2330" script="postmanQuest/deliverLetterbag.lua"/>
    <action itemid="2331" script="postmanQuest/openPresent.lua"/>

    <!-- The Djinn War Quest -->
    <action fromuid="31283" touid="31284" script="djinnWarQuest/exchangeLamp.lua"/>

    <!-- Thais Lighthouse Quest -->
    <action fromuid="31269" touid="31270" script="quests/thaisLighthouseLevers.lua"/>

    <!-- The Ancient Tombs Quest -->
    <action actionid="30042" script="theAncientTombsQuest/thalasSwitches.lua"/>
    <action actionid="30043" script="theAncientTombsQuest/diprathSwitches.lua"/>
    <action actionid="30044" script="theAncientTombsQuest/mahridsInstruments.lua"/>
    <action actionid="30045" script="theAncientTombsQuest/rahemosFindTheCarrot.lua"/>
    <action actionid="30046" script="theAncientTombsQuest/ashmunrahSwitches.lua"/>
    <action actionid="30047" script="theAncientTombsQuest/tombRewardSystem.lua"/>

    <!-- Pits Of Inferno Quest -->
    <action uniqueid="31082" script="pitsOfInfernoQuest/graveStonePortal.lua"/>
    <action uniqueid="31085" script="pitsOfInfernoQuest/oilLever.lua"/>
    <action fromuid="31087" touid="31090" script="pitsOfInfernoQuest/fireWallLever.lua"/>
    <action fromuid="31091" touid="31106" script="pitsOfInfernoQuest/levers.lua"/>
    <action fromuid="31108" touid="31109" script="pitsOfInfernoQuest/ladderLevers.lua"/>
    <action fromuid="31136" touid="31137" script="pitsOfInfernoQuest/mazeStoneRemoval.lua"/>
    <action uniqueid="31140" script="pitsOfInfernoQuest/secondTrapLever.lua"/>
    <action fromuid="31166" touid="31175" script="pitsOfInfernoQuest/bazirWrongLevers.lua"/>
    <action uniqueid="31176" script="pitsOfInfernoQuest/bazirMazeLever.lua"/>
    <action uniqueid="31177" script="pitsOfInfernoQuest/fireThroneLever.lua"/>
    <action fromuid="31178" touid="31179" script="pitsOfInfernoQuest/bazirMirror.lua"/>
    <action actionid="30040" script="pitsOfInfernoQuest/fountain.lua"/>

    <!-- The Queen Of The Banshees Quest -->
    <action fromuid="31059" touid="31060" script="theQueenOfTheBansheesQuest/magicWallLevers.lua"/>
    <action actionid="30000" script="theQueenOfTheBansheesQuest/theSixthSeal.lua"/>
    <action fromuid="31068" touid="31072" script="theQueenOfTheBansheesQuest/theThirdSeal.lua"/>
    <action actionid="30005" script="theQueenOfTheBansheesQuest/firstDoors.lua"/>

    <!-- Svargrond Arena Quest -->
    <action uniqueid="31078" script="svargrondArenaQuest/arenaDoor.lua"/>
    <action uniqueid="31079" script="svargrondArenaQuest/arenaDoor.lua"/>
    <action uniqueid="31080" script="svargrondArenaQuest/arenaDoor.lua"/>

    <!-- Annihilator -->
    <action uniqueid="30000" script="annihilatorQuest/annihilatorLever.lua"/>
 
    <!-- Silver Key Quest Lever 3003 -->
    <action uniqueid="30005" script="silverKeyQuest3003Lever/silverKeyQuestLever.lua"/>

    <!-- Silver Key Quest Lever 3304 -->
    <action uniqueid="31058" script="goldenKeyQuest3304Lever/goldenKeyQuestLever.lua"/>

    <!-- Senja Magic Wall Lever -->
    <action uniqueid="30028" script="senjaMagicWall/senjaMagicWallLever.lua"/>

    <!-- Demon Helmet Quest Lever -->
    <action uniqueid="30067" script="demonHelmetQuest/demonHelmetQuestLever.lua"/>

Also I modified OTX sources to have some custom features such as:
Lua:
-- Promotion Price
promotionPrice = 10000
promotionLevel = 20

-- Demona Shortcut
demonaShortcutTeleporter = true

-- Food text above player if eats food
foodText = false

-- Desert Quest Settings
desertQuestTeleporter = true
desertQuestItemsNeeded = false

onlyOwnerCanOpenCorpse = false
travelForFree = true
npcSellsBackpack = true
npcSellWands = false
spawnDjinnsOnStartUp = true
needQuestForDjinns = false

rateConjureAmount = 2

--NPCs give random voices
npcVoices = false

On globalevents start up I had something like this:

Lua:
    if configManager.getBoolean(configKeys.DESERT_QUEST_TELEPORTER) then
       local desertQuestTeleporter = Game.createItem(1387, 1, { x = xxx, y = yyy, z = zzz })
        desertQuestTeleporter:setDestination({ x = xxx, y = yyy, z = zzz })
    end

    if configManager.getBoolean(configKeys.DEMONA_SHORTCUT_TELEPORTER) then
       local demonaShortcut = Game.createItem(1387, 1, { x = xxxx, y = yyy, z = zzzz})
        demonaShortcut:setDestination({ x = xx, y = yy, z = zz })
    end

Since I took ORTS NPC and their system which worked well (ofc I had to delete few lines inside npcs but most of them worked well) they had random voices and instead of delete these lines I thought about make a function inside config.lua so I could enable these random messages from npcs everytime I would like to

e.g Benjamin.lua
Lua:
local voices = {
    'Welcome to the post office!',
    'If you need help with letters or parcels, just ask me. I can explain everything.',
    'Hey, send a letter to your friend now and then. Keep in touch, you know.'
}

if configManager.getBoolean(configKeys.NPC_VOICES) then
    local lastSound = 0
    function onThink()
        if lastSound < os.time() then
            lastSound = (os.time() + 10)
            if math.random(100) < 20 then
                Npc():say(voices[math.random(#voices)], TALKTYPE_SAY)
            end
        end
        npcHandler:onThink()
    end
end

Also to make a server start easier I've made a small script also configureable inside config.lua
Lua:
-- Countdown settings
startServerClosed = true
--Year, month, day, hour, minute, second
timeToOpenServer = "2018, 12, 31, 24, 59, 59"
A globalevent script which looks something like this:
Lua:
local countDown = configManager.getString(configKeys.TIME_TO_OPEN_SERVER):split(',')
local SERVER_START = {year=countDown[1], month=countDown[2], day=countDown[3], hour=countDown[4], min=countDown[5], sec=countDown[6]}
local START_CALCULATOR = os.time(SERVER_START)

function onThink(interval)

   if Game.getGameState() == GAME_STATE_CLOSED then
       if configManager.getBoolean(configKeys.START_SERVER_CLOSED) then
           if START_CALCULATOR <= os.time() then
               Game.setGameState(GAME_STATE_NORMAL)
               print('>> WARNING: The Countdown is over, Gamestate is OPEN.')
           end
       end
   end

   if Game.getGameState() == GAME_STATE_NORMAL then
       if configManager.getBoolean(configKeys.START_SERVER_CLOSED) then
           if START_CALCULATOR >= os.time() then
               Game.setGameState(GAME_STATE_CLOSED)
               print('>> WARNING: The Server game state was OPEN it is now closed again - use /maintainserver to go into maintenance instead.')
           end
       end
   end

   return true
end

This was one of the first test scripts I had, this is not the final one, not sure if this one works 100% but the one inside datapack works exellent of course :p

So overall, if you know what to do and how to make the easiest way, I guess OTX will give you the best road for it.

PS: After I could find a clean and almost 100% real map of 8.0 I did the same with OTX to have a 8.0 which I might host sooner or later.
 
Last edited:
Thanks for all the replies guys.

I can script and would rank myself intermediate with c++. I guess I've just been racking my brain trying to figure out the most pain free way to get a good, stable 7.72 that's fairly modern. I was curious if my vague vision existed.

I think I'm going to mimic old mechanics on the new tfs, but keep things such as modal windows and mounts.

What would you guys want, Tfs 1.3 that plays like 7.72, or Tfs 1.3 that plays like 7.4?

It will be otclient only
 
Back
Top