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

The Forgotten Server 1.4

Almost 5 years after TFS 1.2 was released, we are happy to announce the immediate release of The Forgotten Server 1.4!

This release still targets 10.98 client protocol version, yet introduces countless features, bug fixes and improvements over 1.2.

Specific highlights include:
  • Improved build system (vcpkg) and CI integration (Github Actions)
  • Improved compatibility with 0.4 data packs to ease transition
  • RevScriptSys
  • Stability improvements and optimizations for high player count
  • Default data pack updates to showcase new features

Alphabetical list of contributors (since v1.2 release):
4mrcn4, amatria, andremiles1, BahamutxD, cezarguimaraes, Codinablack, Colandus, crizhon, DanielChabrowski, danyelvarejao, dbjorkholm, debone, diath, djarek, DSpeichert, emil92b, EPuncker, Erza, EvilHero90, forgee, gesior, gudan-garam, gugahoa, gunzino, HeavenIsLost, Herwi, idontreallywolf, jo3bingham, joseluis2g, josuedhg, kairion, Kamenuvol, kornholi, kygov, Leo32onGIT, lucasgrizante, lukka, LukSrT, lyuz1n, mackerel225, marksamman, marmichalski, Mateuso8, MillhioreBT, Mkalo, mrianura123, nekiro, nkzou, Oen44, omarcopires, pegason, PrinterLUA, pzaj2, ramon-bernardo, ranisalt, raymondtfr, Riverlance, rmalizia44, rookgaard, SeeingBlue, Shawak, slavidodo, slawkens, soul4soul, Sundance, t0kenz, theshibbies, TheSumm, vankk, wgrr, WibbenZ, Wirox, Xawx, Xikini, yamaken93, Zbizu, Znote

Release Notes (thanks to @zbizu for compiling it):

  • added support for POSIX signals (new: SIGINT, SIGTERM, SIGHUP and SIGUSR1)
  • better handling of configmanager class
  • better handling of item attribute types
  • improved dispatcher performance
  • improved OTBM loader performance
  • improved loading items.xml performance
  • improved getSpectators performance
  • improved XTEA performance
  • private RSA key is now being loaded from a PEM file
  • scheduler ignores empty tasks now

Source code
  • added override attribute wherever applicable
  • adjusted code formatting
  • adjusted construction of messages for dealt/received damage
  • anonymous namespaces are now being used wherever applicable
  • chaseMode uses bool now instead of enumeration
  • corrected many typos in strings and variable names
  • events (actions, talkactions, movements, etc.) use smart pointers now
  • guild rank now uses shared_ptr
  • improved blessings get/set code
  • improved LightInfo handling
  • map search for types and effects
  • monster loot now accepts count higher than 100
  • ProtocolGame::login now loads players by id instead of name
  • removed a lot of unused and unnecessary code
  • removed final attribute from final class methods
  • removed unused parameter mana from monsters and NPCs
  • replaced forward_list with vector in creature walking
  • replaced protected visibility with private for final classes
  • sendInventoryItems now uses a for loop
  • singletons now use return by reference
  • skill cache is no longer used as pow performance is fast enough
  • standardized class and variable names
  • standardized client viewport
  • STL algorithms are now being used for vocation search by id

Project tools
  • now compiling with C++17 by default
  • added appveyor
  • added docker
  • improvements to cmake and visual studio project files
  • moved from tfssdk to vcpkg
  • fixed various compiling issues across all supported platforms

New features
  • account storage key/value
  • buy with backpacks
  • classic attackspeed
  • configurable depot and vip limits
  • custom item attributes
  • customizable world light
  • event callbacks
  • hotkey equip
  • improved bank system
  • lua item description (disabled by defeault)
  • lua Party methods
  • monsters drop loot in lua
  • monsters walkback to spawn
  • more getters for ItemType class
  • NPC trade using bank account
  • NPC voice module (npc saying random lines, see #2932 for details)
  • player direction is now stored in the database
  • reintroduced /attr talkaction known from 0.4
  • separated group flags in groups.xml (no longer a single number)
  • spawns can now be set to create random monsters (see #3605 for details)
  • special skills (leech and crit)
  • store inbox
  • towns are now cached in the database
  • vocation specific kick times in case of lost connection

New options in config.lua
  • allowWalkthrough
  • classicAttackSpeed
  • cleanProtectionZones
  • defaultWorldLight
  • depotFreeLimit
  • depotPremiumLimit
  • forceMonsterTypesOnLoad
  • houseDoorShowPrice
  • houseOwnedByAccount
  • luaItemDesc
  • onlyInvitedCanMoveHouseItems
  • removeChargesFromPotions
  • removeOnDespawn
  • removeWeaponAmmunition
  • removeWeaponCharges
  • serverSaveCleanMap
  • serverSaveClose
  • serverSaveNotifyDuration
  • serverSaveNotifyMessage
  • serverSaveShutdown
  • showPlayerLogInConsole
  • vipFreeLimit
  • vipPremiumLimit
  • yellMinimumLevel
  • yellAlwaysAllowPremium

New enums



Magic effect

Fight mode

Item attribute

Item group

Item ids

Message types
  • MESSAGE_GUILD - White message in channel (+ channelId)
  • MESSAGE_PARTY_MANAGEMENT - White message in channel (+ channelId)
  • MESSAGE_PARTY - White message in channel (+ channelId)




New XML attributes

  • canwalkonenergy
  • canwalkonfire
  • canwalkonpoison
  • challengeable
  • ignoreSpawnBlock
  • isBoss


imbuements related:
  • criticalhitchance
  • criticalhitamount
  • lifeleechchance
  • lifeleechamount
  • manaleechchance
  • manaleechamount
  • forceserialize/forcesave - saves unmoveable items like beds and carpets when put in house
  • storeitem - allows putting the item in store inbox
  • initdamage - damage dealt when stepping on field
  • attackspeed - attack speed
  • elementholy - holy resistance
  • elementdeath - death resistance

  • ignoreendvalue - boolean for mission field. Enabling it will keep the mission displayed when mission storage is higher than endvalue.

  • allowPvp - (boolean) some vocations can have pvp disabled now
  • noPongKickTime - (unsigned int) amount of seconds to kick the player in case he loses the connection


A new way to create scripts has been implemented. It allows the developers to create mods they can drag and drop to data/scripts. Example mods can be found in the same folder. Every file from that folder will load automatically. To disable loading a certain file, add a # symbol at the beginning of file.

Supported constructors: - Action - CreatureEvent - GlobalEvent - MonsterType - MoveEvent - Party - Spell - TalkAction - Weapon

  • Added event callbacks. They’re hooks for things located in data/events folder. Examples can be found in data/scripts/eventcallbacks.

New events
  • Creature:onHear(speaker, words, type)
  • Monster:onDropLoot(corpse)
  • Monster:onSpawn(position, startup, artificial)
  • Player:onItemMoved(item, count, fromPosition, toPosition, fromCylinder, toCylinder)
  • Player:onTradeCompleted(target, item, targetItem, isSuccess)
  • Player:onWrapItem(item, position)

New functions
  • isNumber(str) - same as tonumber(str) but returns false instead of nil
  • isValidMoney(money)
  • getLootRandom()
  • getMoneyCount(string)
  • getMoneyWeight(money)
  • getSubTypeName(subType)
  • logCommand(player, words, param) - logs talkaction to a file
  • setWorldLight(level, color)

New methods

  • combat:getPositions(creature, variant)
  • combat:getTargets(creature, variant)
  • combat:clearConditions()
  • combat:getParameter(key)

  • condition:getParameter(key)

  • container:createLootItem(item)
  • container:getItems(recursive)

  • creature:isImmune()
  • creature:move(direction) - moves creature to selected direction
  • creature:hasCondition(conditionType[, subId = 0]) - checks if creature has specified condition
  • creature:isContainer()
  • creature:isTeleport()
  • creature:setHealth(health)
  • creature:canAccessPz()
  • creature:isMovementBlocked()
  • creature:setMovementBlocked(state)

  • Game.getClientVersion() - returns a table with fields min, max and string
  • Game.getMonsterTypes()
  • Game.getItemAttributeByName(name)
  • Game.getAccountStorageValue(accountId, key)
  • Game.setAccountStorageValue(accountId, key, value)
  • Game.saveAccountStorageValues()

  • group:hasFlag(flag)

  • house:getItems()
  • house:save()
  • house:getDoorIdByPosition(position)
  • house:canEditAccessList(listId, player)
  • house:kickPlayer(player, targetPlayer)

  • item:isLoadedFromMap()
  • item:isMonster()
  • item:isNpc()
  • item:isStoreItem()
  • item:setStoreItem(bool storeItem)
  • itemType:isStoreItem()
  • item:getCustomAttribute(key)
  • item:setCustomAttribute(key, value)
  • item:removeCustomAttribute(key)
  • item:getSpecialDescription()

  • itemType:isBlocking()
  • itemType:isGroundTile()
  • itemType:isMagicField()
  • itemType:isUseable()
  • itemType:isPickupable()
  • itemType:getAmmoType()
  • itemType:getCorpseType()
  • itemType:getGroup()
  • itemType:getAbilities()
  • itemType:hasShowAttributes()
  • itemType:hasShowCount()
  • itemType:hasShowCharges()
  • itemType:hasShowDuration()
  • itemType:hasAllowDistRead()
  • itemType:getWieldInfo()
  • itemType:getDuration()
  • itemType:getLevelDoor()
  • itemType:getVocationString()
  • itemType:getMinReqLevel()
  • itemType:getMinReqMagicLevel()

  • monster:rename(name[, nameDescription])

  • networkMessage:seek(position)
  • networkMessage:tell()
  • networkMessage:len()

  • Outfit(looktype) - meant to compare outfit1 == outfit2

  • player:hasChaseMode()
  • player:hasSecureMode()
  • player:getFightMode()
  • player:hasFlag(flag)
  • player:canWearOutfit(looktype)
  • player:getZone()
  • player:getSpecialSkill(specialSkillType)
  • player:addSpecialSkill(specialSkillType, value)
  • player:transferMoneyTo(target, amount)
  • player:withdrawMoney(amount)
  • player:depositMoney(amount)
  • player:getPremiumEndsAt()
  • player:setPremiumEndsAt(timestamp)
  • player:setPremiumTime(seconds)
  • player:addPremiumTime(seconds)
  • player:removePremiumTime(seconds)
  • player:getPremiumTime()
  • player:addLevel(amount, round)
  • player:addMagicLevel(value)
  • player:addSkill(skillId, value, round)
  • player:getWeaponType()
  • player:sendHouseWindow(house, listId)
  • player:setEditHouse(house, listId)
  • player:removeSkillTries(skillType, tries[, notify = true])
  • player:removeManaSpent(amount[, notify = true])

  • position:isWalkable(condition)
  • position:isInRange(fromPos, toPos)

  • spell:runeLevel(level)
  • spell:runeMagicLevel(magLevel)

  • string.splitTrimmed(string, separator) - works as a combination of string.split(str, sep) and string.trim(str), can also be called as text:splitTrimmed(sep)

  • table.contains(table, value) - same as isInArray(t, v)

  • tile:isWalkable(condition)
  • tile:addItem(itemId, count)
  • tile:addItemEx(item[, flags = 0])
  • tile:remove()

  • vocation:allowsPvp()

Changes in datapack
  • Added allowDistRead attribute to many signs and statues (items.xml)
  • Added more groups. To get full access now you need account type 6 and group id 6
  • Added spell words to runes when looking at them
  • Updated forgotten.otbm to version 10.98
  • Updated monsters and items.xml

Added and updated lots of Lua scripts up to version 10.98
  • added achievements system
  • added enchanting system
  • updated taming system
  • new weapons and equipment statistics
  • house carpets
  • ferumbras items
  • gold converter
  • scroll of ascension
  • costume bags
  • premium scroll
  • secret service tool gears
  • blessing charms
  • lootboxes (christmas bundles, surprise bags, gnomish package, etc)
  • skinning (obsidian knife, blessed wooden stake)
  • rust remover
  • juice squeezer
  • afflicted outfit related items
  • large seashell
  • wall mirror
  • snow heap
  • dolls
  • sweetheart ring
  • spider egg
  • fire bug
  • water pipe
  • music instruments
  • lottery ticket
  • clay lump
  • 8.1 april fools items
  • sugar oat
  • rum distilling
  • goldfish bowl
  • white deer death scripts
  • missing food ids
  • daily crate loot
  • muck remover
  • saw (for wooden ties)
  • watering flower pots
  • swamp digging
  • hive gate teleporting
  • gnomish vouchers
  • items displaying blessings
  • claw of the noxious spawn
  • roasting meat on campfire
  • ice flower harvesting
  • insectoid cell
  • banker npc
  • juicy roots harvesting
  • painted gourd rattle
  • perppermoon bells
  • ice fishing
  • beds (added “this bed cannot be used message”)

Adjusted Lua scripts
  • added a message to citizen teleport
  • added level and premium config for !buyhouse command
  • added missing astro clock, sundial and very noble looking watch to the watch script
  • added missing rope spots (up to 10.98)
  • added more swimmable tiles
  • added new potions up to 10.98
  • added isPremium check to ship captain NPC
  • code improvements for /looktype
  • fixed console warnings when the player is misusing rope
  • fixed post startup rng by calling math.randomseed(os.time()) as early as possible
  • fixed promotion.lua bug that made players with no vocation promoted
  • fixed wrong fluids behaviour when moving between fluid containers
  • improved ip ban system
  • improved the code behind curse condition
  • improved !online and fixed ghost mode handling
  • moved windows and doors to revscripts
  • NPC system now warns when a NPC sells something for lower price than he buys
  • pick now works with shiny stone
  • reworked utori spells
  • shortened and improved party spells code
  • spellbooks now show params if spells have one
  • updated door locking mechanism
  • updated healing/mana color and messages
  • updated message types for quests and doors

Code quality improvements (Lua)
  • changed nil checks to not checks
  • removed unnecessary nil checks
  • fixed typos and whitespaces
  • replaced isInArray with table.contains
  • renamed combat:setCondition to combat:addCondition
  • adjusted scripts to avoid using compat functions

Moved to lua

  • All commands are talkactions now. As commands.xml is no longer needed, it got removed.
  • /reload
  • /raid
  • !sellhouse

  • find person (exiva)
  • house access management spells
  • creature illusion (utevo res ina)
  • summon creature (utevo res)
  • levitate (exani hur)
  • chameleon rune (adevo ina)
  • convince creature rune (adeta sio)
  • runemaking

  • doSet...Outfit
  • table.contains (formerly known as isInArray)
  • bug reporting
  • rule violation reporting
  • transform
  • decay
  • party shared xp formula
  • monster loot dropping
  • experience stages
  • item descriptions (needs enabling in config.lua)


  • actions can now be grouped with ; separator
  • added a few missing lua_pop instructions to luascript.cpp
  • added a console warning when monster paralyze is trying to go above the limit
  • added a console warning when vocations.xml file has unrecognized XML attributes
  • added backwards compatibility for <inside> tag in monster loot
  • added pushable flag to NPCs
  • config.lua is now generated from config.lua.dist if the former can’t be loaded
  • creature:removeCondition now supports userdata
  • direction checking methods now read DIRECTION_NONE instead of DIRECTION_NORTHWEST when both positions are equal
  • enforced utf-8 encoding in the database
  • fixed a bug with items not being removed in Game::internalRemoveItem
  • fixed a crash caused by calling addEvent(function() end)
  • fixed a crash caused by closing the server on Windows
  • fixed a crash caused by creature:setMaster
  • fixed a crash caused by inability to find map specified in config.lua
  • fixed a crash caused by registering same creaturescript twice on a single creature
  • fixed a crash caused by relogging after putting an item on depot (Linux)
  • fixed a crash caused by targeting already removed creature in rare situations (see #2582 for details)
  • fixed a crash in token time parsing
  • fixed a crash on Windows when using 2FA
  • fixed a crash possible to happen during RSA decryption
  • fixed a crash related to monsters with onPrepareDeath event dying from a condition
  • fixed a crash related to map cleaning
  • fixed a crash when the spectator can’t see the position in removeTileCreature
  • fixed a crash with combat:execute(combat, variant)
  • fixed a login error caused by enabling freepremium
  • fixed a loop in player:getInstantSpells()
  • fixed a missing call to onTargetCombat in combat.cpp
  • fixed an issue with double onEquip execution. An extra parameter isCheck was added.
  • fixed an issue with house doors not being unique in the database
  • fixed an issue with LuaJIT being detected twice
  • fixed combatBlockHit not using ignoreResistances flag
  • fixed bugs, freezes and crashes related to /i talkaction and Game.createItem
  • fixed data race in scheduler
  • fixed handling creatures that fall into interlocked teleports
  • fixed memory leaks in talkactions and NPC system
  • fixed monsters with conditions not becoming idle
  • fixed multiple crashes, bugs and memory leaks caused by /reload
  • fixed multiple crashes caused by passing nil to some functions (see #3562 for details)
  • fixed waitlist getting stuck
  • fluids now use ids under 100 in items.xml
  • improved :getPluralName
  • improved premium time handling
  • monsters can no longer be set to have healthNow higher than healthMax in their XML file
  • new limits to spawn time: min 10 seconds, max 1 day
  • nonpvp walls and growths now disappear when stepped on
  • NPCs are now in idle state when no players are nearby
  • removed unnecessary shoplist update in NPC system

Lua functions:
  • doPlayerAddManaSpent and doPlayerAddSkillTry no longer multiply the amount by skill rates
  • fixed player:getClosestFreePosition behaviour
  • fixed incorrect gold stacks detection in player:removeMoney
  • container:addItem no longer limits subType to 100
  • fixed issues with pushMovement in creature:teleportTo
  • fixed Player:onMoveItem not being called when using items from the ground
  • fixed Player:onMoveItem not being called when switching items in the inventory
  • new implementation of onManaChange
  • new flags in target/tile combat: blockedByArmor, blockedByShield, ignoreResistances
  • player:addMount, player:hasMount and player:removeMount now support mount name string
  • Player constructor now allows GUID
  • player:showTextDialog now accepts Item userdata
  • premium time is now updated on character login
  • promoted vocations are no longer needed in weapons.xml

  • fixed a client crash when creature:say has missing type
  • fixed a client crash when displaying more than 7 players on one tile
  • fixed a client crash when opening unnamed (item of type …) containers
  • fixed incorrect distance effect path when player gets teleported with onPrepareDeath script
  • fixed issues with disabled action bars in some clients
  • fixed light sources not working in arrow slot
  • fixed multiple client crashes on “set outfit” window requests
  • premium status now displays correctly in character list
  • fixed market not recognizing items from cancelled offers
  • fixed mount issues with GM outfit (see #2028 for details)
  • fixed trade window being stuck in some situations

  • added black skull limitations
  • added stairhop exhaustion for spells
  • adjusted player corpse descriptions
  • blood splashes caused by physical damage no longer spill in PZ tiles
  • bonus magic level is no longer counted for %!m(MISSING)agic level buff condition
  • browse field no longer shows items marked with special uniqueId
  • challenged creatures no longer run away on low health
  • changed wrap/unwrap to be for house owners only
  • corrected inaccurate sight lines for throwing items and attacks
  • corrected intervals for bleeding and poison
  • default cap for new characters is 400 now
  • default townId for new characters is 1 now
  • fixed a bug that caused players to stay on trainers when they exit the client with targeted creature
  • fixed a bug with wall runes not working diagonally
  • fixed a bug with elemental damage reduction not working in some situations
  • fixed a pick being able to make holes anywhere
  • fixed aleta grav not working on closed doors
  • fixed allowfaruse not working
  • fixed an overflow in skullTicks
  • fixed blood rage spell behaviour
  • fixed bypassing disabled browse field with arrow up icon
  • fixed conditions not being applied when drinking fluids
  • fixed count message for hotkey actions
  • fixed decay not working in some scenarios
  • fixed direction not updating when changing floor using parcels trick
  • fixed disappearing depot items when player never opened his depot yet
  • fixed disappearing items after trade bug
  • fixed inability to cast spells in front of a wall
  • fixed inability to cast spells when muted
  • fixed inability to talk in NPC channel when muted
  • fixed inability to switch floors with stacked parcels in some situations
  • fixed inaccurate player defense formula
  • fixed inaccurate viplist behaviour
  • fixed incorrect behaviour of pyramid corners
  • fixed invisibility interaction with ghost mode
  • fixed issues related to buying fluids through NPC trade
  • fixed missing attributes display on bows crossbows
  • fixed monster lookDirection when facing the target diagonally
  • fixed monsters interaction with fields
  • fixed pagination in sendAddContainerItem
  • fixed potential yellow skull bug (see #2072)
  • fixed problems with opening containers on a tile with many of them
  • fixed problems with auto stacking system
  • fixed reading player skill values when equipped with weapons with ammo
  • fixed shared experience triggering and formula bugs
  • fixed skills not going up when being exactly at zero tries of starting level
  • fixed stacking items with modified attributes
  • fixed stored vocation regeneration not updating
  • fixed traps not dealing damage
  • fixed unintentionally reduced PVP healing
  • fixed “use” option not working in “browse field” after an item was moved
  • fluid containers in loot are now empty by default instead of having water
  • heal friend (exura sio) has proper range now
  • house access lists can now read guild ranks
  • improved two handed weapons equipping mechanic
  • improved experience formula - now allows 1034406 max level
  • improved player:getDeathPenalty() precision
  • keys now use four digits to display the number (eg 0021 instead of just 21)
  • magic fields are no longer impossible to replace
  • monster aggro no longer gets triggered through ground floor
  • monsters killed by other monsters now drop loot properly
  • monsters no longer hit you instantly when you enter and leave pz fast
  • monsters no longer paralyze themselves
  • mute condition now saves on logout
  • players can no longer invite themselves to a party
  • players with low level pvp protection can now be walked through
  • poison is no longer applied on missed hits
  • removed the ability to message to yourself
  • removed the ability to buy items from yourself at the market
  • removed delay on monster death
  • removed duplicate rent charge on !buyhouse
  • store outfits and mounts are no longer premium only
  • summons inherit canPushItems flag (see #3462 for details)
  • updated afk warning message
  • updated cancel messages
  • using items no longer cancels autowalk
  • war players no longer have green skull

Security updates
  • added token validation when connecting to the gameworld
  • dropped support for regular expressions in house access lists



  • tfs-v1.4-ubuntu-clang-Release-luajit.zip
    6.9 MB · Views: 134 · VirusTotal
  • tfs-v1.4-macos-clang-Release-luajit.zip
    6 MB · Views: 46 · VirusTotal
  • tfs-v1.4-windows-msvc-Release-luajit.zip
    6.2 MB · Views: 523 · VirusTotal
Anyone know why monsters don't respawn when the player is on screen?
I have seen 10.98 servers where this feature works perfectly.
I'm not mistaken, this is the tfs 1.4.3 version. It's good to check it out

Yes, but I could not compile it received numerous errors.
There are no approvals for everything, which is why it doesn't work as expected.
I'm not mistaken, this is the tfs 1.4.3 version. It's good to check it out
GitHub - otland/forgottenserver at 1.4 (https://github.com/otland/forgottenserver/tree/1.4) is the official TFS 1.4 GitHub repo.
Current version is 1.4.2 as can be seen in definitions.h.

EPuncker is part of the dev team, but his repo is a fork.
Most likely he uses his fork as a testing ground, which he can then use to push to the official repo.

Short and sweet; 1.4.3 isn't available yet officially.
Last edited:
GitHub - otland/forgottenserver at 1.4 (https://github.com/otland/forgottenserver/tree/1.4) is the official TFS 1.4 GitHub repo.
Current version is 1.4.2 as can be seen in definitions.h.

EPuncker is part of the dev team, but his repo is a fork.
Most likely he uses his fork as a testing ground, which he can then use to push to the official repo.

Short and sweet; 1.4.3 isn't available yet officially.
I have updated all the commits at once. Now it's on TFS 1.4.3, running smoothly and calmly. I'm quite pleased with it