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

Rare, Epic and Legendary Loot Rolls

Mana Drain protection done, renamed to Mana Shield: +XX% which just reduces all incoming damage when you're using mana shield/energy rings.
Tweaked the Stun attribute too so it's a bit more clear and can react when you actually stun a creature:

ENIyScK.gif


I'm happy enough with this to finish up wands and rods.

They can currently roll:
+Mana Leech %, +Mana Shield%, +Spell Damage%, +Stun Chance%

Which matches the count on melee weapons:
+Attack, +Defense/Extra Defense, +Critical Chance, *(Elemental Damage)
 
that 10.76 web client can be used in 10.98? i mean with last tfs

It can, yeah.
There's flash files for 10.98 sitting around on github.

But because flash is deprecated in all browser nowadays you have to enable flash manually when you launch:

1577841892004.png

So it's a bad user experience and isn't something you'd really want to be using in production.
 
It can, yeah.
There's flash files for 10.98 sitting around on github.

But because flash is deprecated in all browser nowadays you have to enable flash manually when you launch:

View attachment 41464

So it's a bad user experience and isn't something you'd really want to be using in production.
thanks for response, i was trying to use it not for production just for me because i always liked the flash client.
i tried to find how to use the flash client but nothing. i just find swf files, but i dont know hot to proceed. :(
 
The next piece of work is a crafting system that revolves around these rarity mechanics, here it is:

The forge:
9S1UUlI.png


How-to books:
9EqKuL6.png

kSQuvzK.png


The Workbench, destroy rare/epic/legendary items for Magic Sulphur:
S2JH2JW.gif
QD27x2s.gif


The Anvil, attempt to roll rare/epic/legendary on a regular item:
U3Wclb0.gif
tnE75dw.gif


Originally I wanted to place the items ON TOP of the workbench/anvil, but this will require client edits:
  • To give the workbench/anvil HEIGHT (items arn't positioned correctly on top at the moment).
  • To remove the BLOCKING flag or whatever so you can actually place items on them.
Because of the required client edits, I've settled for making them 1 slot containers for now.
Lua:
function onStartup()

    local workbenchpos = Position(1148, 633, 6)
    local anvilpos = Position(1151, 633, 6)
    local workbench = Tile(workbenchpos):getItemById(23660)
    local anvil = Tile(anvilpos):getItemById(8671)
   
    -- Replace normal workbench and anvil with one that has a 1 slot container
    if (not workbench:isContainer()) then
        workbench:remove()
        Game.createContainer(23660, 1, workbenchpos)
    end
   
    if (not anvil:isContainer()) then
        anvil:remove()
        Game.createContainer(8671, 1, anvilpos)
    end
   
    return true
end
I'll cut them over once I've settled on a client.

I like the fact that the whole process is transparent to other users.
They can see what other people are destroying or enchanting - it just gives it that level of OOF.

There are safeguards in-place so you can't steal other players items while they're crafting:
On adding:
Lua:
item:setAttribute(ITEM_ATTRIBUTE_OWNER, self:getGuid())

On removing:
Lua:
item:removeAttribute(ITEM_ATTRIBUTE_OWNER)

Why you theivin bruh?
Lua:
...
...
else
    self:sendCancelMessage("This item does not belong to you.")
    return false
end

And there is code in-place so if a user leaves an item in the workbench or anvil for XX amount of time, it is sent to their depot.
(This is so users can't block using the forge by leaving items in there.)
Lua:
itemtosend:moveTo(depot)
player:sendTextMessage(MESSAGE_INFO_DESCR, "You have left an item unattended in the smithing " .. anvilorworkbench .. " in the forge, it has been sent to your depot.")

The only edge-case here is if a player logs out and leaves an item in the workbench or anvil.
In those cases the ITEM_ATTRIBUTE_OWNER is removed and anyone can take it.
Lua:
self:sendTextMessage(MESSAGE_INFO_DESCR, "This item has been abandoned, it's now yours!")
 
Last edited:
Made some more changes to these items.

Mainly to try and make use of all rare/obscure items and make specific monsters valuable to hunt.
Extra drops similar to world drops in mmos like WoW, except the loot isn't global - it's tailored to the theme of the monster.
Lua:
local jewel = 0
local jewelCorpse = {
    [5995] = { -- Demon
        2493, -- Demon Helmet
        2494, -- Demon Armor
        2495, -- Demon Legs
        2400, -- Magic Sword
        2431, -- SCA
        2421, -- Thunder Hammer
        16112,-- Spellbook of Arcana
        8852, -- The Devileye
        8905,  -- Rainbow Shield
        2131  -- Star Amulet
    },
    -- Example
}
if jewelCorpse[corpse:getId()] then
    if math.random(1,50) == 1 then -- 1/50 = 2%
        local jewelCase = corpse:addItem(6104, 1)
        if jewelCase then
            local jewelItem = jewelCase:addItem(jewelCorpse[corpse:getId()][math.random(1,#jewelCorpse[corpse:getId()])], 1)
            if checkrollable(jewelItem) then
                rollItems(jewelItem, true) -- Force roll a rarity
            end
            jewel = 1
        end
    end
end

SDg3KPN.png


These items are always rare, epic or legendary.
I've also re-envisioned the Rainbow Shield to make it useful again:
XML:
<item id="8905" article="a" name="rainbow shield">
    <attribute key="description" value="Strange elemental magic flows over this shield." />
    <attribute key="weight" value="6900" />
    <attribute key="defense" value="39" />
    <attribute key="weaponType" value="shield" />
    <attribute key="speed" value="80" />
    <attribute key="skillShield" value="3" />
</item>
<item id="8906" article="a" name="fiery rainbow shield">
    <attribute key="description" value="It has been temporarily imbued with fire magic and boosts your regeneration." />
    <attribute key="weight" value="6900" />
    <attribute key="defense" value="36" />
    <attribute key="weaponType" value="shield" />
    <attribute key="absorbPercentFire" value="10" />
    <attribute key="duration" value="60" />
    <attribute key="decayTo" value="8905" />
    <attribute key="healthGain" value="1" />
    <attribute key="healthTicks" value="3000" />
    <attribute key="manaGain" value="4" />
    <attribute key="manaTicks" value="3000" />
    <attribute key="skillShield" value="3" />
</item>
<item id="8907" article="an" name="icy rainbow shield">
    <attribute key="description" value="It has been temporarily imbued with ice magic and boosts your regeneration." />
    <attribute key="weight" value="6900" />
    <attribute key="defense" value="36" />
    <attribute key="weaponType" value="shield" />
    <attribute key="absorbPercentIce" value="10" />
    <attribute key="duration" value="60" />
    <attribute key="decayTo" value="8905" />
    <attribute key="healthGain" value="1" />
    <attribute key="healthTicks" value="3000" />
    <attribute key="manaGain" value="4" />
    <attribute key="manaTicks" value="3000" />
    <attribute key="skillShield" value="3" />
</item>
<item id="8908" article="a" name="sparking rainbow shield">
    <attribute key="description" value="It has been temporarily imbued with energy magic and boosts your regeneration." />
    <attribute key="weight" value="6900" />
    <attribute key="defense" value="36" />
    <attribute key="weaponType" value="shield" />
    <attribute key="absorbPercentEnergy" value="10" />
    <attribute key="duration" value="60" />
    <attribute key="decayTo" value="8905" />
    <attribute key="healthGain" value="1" />
    <attribute key="healthTicks" value="3000" />
    <attribute key="manaGain" value="4" />
    <attribute key="manaTicks" value="3000" />
    <attribute key="skillShield" value="3" />
</item>
<item id="8909" article="a" name="terran rainbow shield">
    <attribute key="description" value="It has been temporarily imbued with earth magic and boosts your regeneration." />
    <attribute key="weight" value="6900" />
    <attribute key="defense" value="36" />
    <attribute key="weaponType" value="shield" />
    <attribute key="absorbPercentEarth" value="10" />
    <attribute key="duration" value="60" />
    <attribute key="decayTo" value="8905" />
    <attribute key="healthGain" value="1" />
    <attribute key="healthTicks" value="3000" />
    <attribute key="manaGain" value="4" />
    <attribute key="manaTicks" value="3000" />
    <attribute key="skillShield" value="3" />
</item>


Regen and elemental protection has been added to all elemental transformations so none are better than the others:
It transforms on taking elemental damage and the transformations last a minute:

uGv42RB.gif


So it's basically just an adaptable elemental protection shield, with soft boots-esque regen.
 
Last edited:
Love it. Systems like this that draws players from mindlessly killing monsters are in my opinion what this game always lacked.

Something lke this could even use a level cap for players and leave progression for crafting/upgrading or better item drops.

Good job!
 
Its a nice system you got. My only problem is that it goes all the way up to legendary, why can all items be legendary? know what i mean?
isnt normal, common, uncommon, rare and epic enough?

It doesnt really need +25% crit chance or w/e. 1, 2, 3% is enough to make a good difference.
 
is it possible to download this system? or is this thread just a showoff?

This sytem has been released here:

The only thing missing is the forge functionality...

Forge:
The next piece of work is a crafting system that revolves around these rarity mechanics, here it is:

The forge:
9S1UUlI.png


How-to books:
9EqKuL6.png

kSQuvzK.png


The Workbench, destroy rare/epic/legendary items for Magic Sulphur:
S2JH2JW.gif
QD27x2s.gif


The Anvil, attempt to roll rare/epic/legendary on a regular item:
U3Wclb0.gif
tnE75dw.gif


Originally I wanted to place the items ON TOP of the workbench/anvil, but this will require client edits:
  • To give the workbench/anvil HEIGHT (items arn't positioned correctly on top at the moment).
  • To remove the BLOCKING flag or whatever so you can actually place items on them.
Because of the required client edits, I've settled for making them 1 slot containers for now.

Here it is:

globalevents.xml
(Get forge/anvil items on map position and convert them to 1 slot containers)
add:
XML:
<globalevent type="startup" name="LoadForge" script="forge.lua" />

globalevents/scripts/forge.lua
Lua:
function onStartup()

    local workbenchpos = Position(1148, 633, 6) -- WORKBENCH POSITION
    local anvilpos = Position(1151, 633, 6) -- ANVIL POSITION
    local workbench = Tile(workbenchpos):getItemById(23660) -- WORKBENCH ITEMID
    local anvil = Tile(anvilpos):getItemById(8671) -- ANVIL ITEMID
 
    -- Replace normal workbench and anvil with one that has a 1 slot container
    if (not workbench:isContainer()) then
        workbench:remove()
        Game.createContainer(23660, 1, workbenchpos)
    end
 
    if (not anvil:isContainer()) then
        anvil:remove()
        Game.createContainer(8671, 1, anvilpos)
    end
 
    return true
end

actions.xml
(Use hammer on workbench/anvil code + book text)
XML:
<action uniqueid="30020" script="other/forge.lua" />
<action uniqueid="30021" script="other/forge.lua" />
<action itemid="4846" script="other/forge.lua" />

scripts/other/forge.lua
Lua:
function onUse(player, item, fromPosition, item2, toPosition)
 
    if item:getUniqueId() == 30020 then -- BOOK 1
        local text = "Disenchanting items using the Workbench:"
        text = text .. "\r\r" .. "1. Place rare, epic or legendary items in the Workbench."
        text = text .. "\r" .. "2. Use a Smithing Hammer on the Workbench."
        text = text .. "\r\r" .. "This will DESTROY the item and extract some magic powder."
        text = text .. "\r\r" .. "   Rare\t\t1 Magic Powder"
        text = text .. "\r" .. "   Epic\t\t3 Magic Powder"
        text = text .. "\r" .. "   Legendary\t5 Magic Powder"
        text = text .. "\r\r" .. "(Smithing Hammers can be purchased from Dixi)"
        player:showTextDialog(item:getId(), text)
    elseif item:getUniqueId() == 30021 then -- BOOK 2
        local text = "Enchanting items using the Anvil:"
        text = text .. "\r\r" .. "1. Place a regular item in the Anvil."
        text = text .. "\r" .. "2. Use a Smithing Hammer on the Anvil."
        text = text .. "\r\r" .. "This requires 25 Magic Powder and will attempt to enchant the item."
        text = text .. "\r\r" .. "10 Magic Powder is wasted if your enchantment fails."
        player:showTextDialog(item:getId(), text)
    elseif item:getId() == 4846 then
        local workbenchpos = Position(1148, 633, 6)
        local anvilpos = Position(1151, 633, 6)
        local workbench = Tile(workbenchpos):getItemById(23660)
        local anvil = Tile(anvilpos):getItemById(8671)
        if toPosition == workbenchpos then -- WORKBENCH
            if workbench:isContainer() then
                local disenchantItem = Container(workbench.uid):getItem(0)
                local disenchantOwner = disenchantItem:getAttribute(ITEM_ATTRIBUTE_OWNER)
                local smithUser = player:getId()
                if disenchantItem then
                    if disenchantOwner == smithUser then
                        local disenchantDesc = disenchantItem:getAttribute(ITEM_ATTRIBUTE_ARTICLE)
                        local sulfurcount = 0
                        if disenchantDesc:find "rare" then
                            sulfurcount = 1
                        elseif disenchantDesc:find "epic" then
                            sulfurcount = 3
                        elseif disenchantDesc:find "legendary" then
                            sulfurcount = 5
                        elseif disenchantDesc:find "dawnbreaker" then
                            sulfurcount = 100
                        end
                        if sulfurcount ~= 0 then
                            disenchantItem:remove()
                            player:addItem(23453, sulfurcount)
                            workbenchpos:sendMagicEffect(CONST_ME_FIREAREA)
                            -- Stop the event that would send unattended items to players depot (events/scripts/player.lua)
                            -- function Player.onMoveItem(self, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
                            if Game.getStorageValue(30020) then
                                stopEvent(Game.getStorageValue(30020))
                                Game.setStorageValue(30020, -1)
                            end
                            -- Destroy item or just remove rarity?
                            -- local vanillaitem = workbench:addItem(disenchantItem:getId())
                            -- vanillaitem:setAttribute(ITEM_ATTRIBUTE_OWNER, player:getGuid())
                        end
                    else
                        player:sendCancelMessage("The item on the workbench does not belong to you.")
                    end
                else
                    player:sendCancelMessage("There is nothing in the workbench to disenchant.")
                end
            end
        elseif toPosition == anvilpos then -- ANVIL
            if anvil:isContainer() then
                local enchantItem = Container(anvil.uid):getItem(0)
                local enchantOwner = enchantItem:getAttribute(ITEM_ATTRIBUTE_OWNER)
                local enchantDesc = enchantItem:getDescription()
                local smithUser = player:getId()
                if enchantItem then
                    if enchantOwner == smithUser then
                        if enchantDesc:find "rare" or enchantDesc:find "epic" or enchantDesc:find "legendary" then
                            player:sendCancelMessage("This item has already been enchanted, please remove it from the anvil.")
                        else
                            local sulfurcount = player:getItemCount(23453)
                            if sulfurcount >= 25 then
                                if math.random(1,2) == 2 then
                                    rollRarity(enchantItem, true)
                                    anvilpos:sendMagicEffect(73)
                                    player:removeItem(23453, 25)
                                else
                                    player:sendCancelMessage("Your attempt to enchant the item has failed.")
                                    anvilpos:sendMagicEffect(CONST_ME_POFF)
                                    player:removeItem(23453, 10)
                                end
                            else
                                player:sendCancelMessage("You do not have enough Magic Sulphurs to attempt an enchantment.")
                            end
                        end
                    else
                        player:sendCancelMessage("The item on the anvil does not belong to you.")
                    end
                end
            end
        end
    end
 return true
end

events.xml
(Code for when item placed/removed from workbench/anvil)
XML:
<event class="Player" method="onMoveItem" enabled="1" />

events/scripts/player.lua
update:
Lua:
function Player.onMoveItem(self, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
-- This is used to clean the forge and send contents to the players depot if they leave it there for X amount of time
    function abandonedItem(playerId, anvilorworkbench)
        local itemtosend = false
        if anvilorworkbench == "workbench" then
            local workbenchpos = Position(1148, 633, 6)
            local workbench = Tile(workbenchpos):getItemById(23660)
            if workbench:isContainer() then
                itemtosend = workbench:getItem(0)
            end
        elseif anvilorworkbench == "anvil" then
            local anvilpos = Position(1151, 633, 6)
            local anvil = Tile(anvilpos):getItemById(8671)
            if anvil:isContainer() then
                itemtosend = anvil:getItem(0)
            end
        end
        if itemtosend then
            local player = false
            -- see if player is online
            for _, playersearch in ipairs(Game.getPlayers()) do
                if playersearch:getId() == playerId then
                    player = Player(playerId)
                end
            end
            -- player is online
            if player then
                local depot = player:getDepotChest(0, true)
                itemtosend:moveTo(depot)
                player:sendTextMessage(MESSAGE_INFO_DESCR, "You have left an item unattended in the " .. anvilorworkbench .. " in the forge, it has been sent to your depot.")
                player:save()
                local resetstorage = 0
                if anvilorworkbench == "workbench" then
                    resetstorage = 30020
                elseif anvilorworkbench == "anvil" then
                    resetstorage = 30021
                end
                Game.setStorageValue(resetstorage, -1)
            else
                itemtosend:removeAttribute(ITEM_ATTRIBUTE_OWNER)
            end
        else
            return false
            -- Couldn't get item from anvil/forge for some reason
        end
    end
 
    if toCylinder and toCylinder:isItem() then
        if toCylinder:getId() == 23660 then
            local disenchantDesc = item:getAttribute(ITEM_ATTRIBUTE_ARTICLE)
            if disenchantDesc:find "rare" or disenchantDesc:find "epic" or disenchantDesc:find "legendary" or disenchantDesc:find "dawnbreaker" then -- dawnbreaker is a custom weapon that may not exist on your server
                item:setAttribute(ITEM_ATTRIBUTE_OWNER, self:getId())
                Game.setStorageValue(30020, addEvent(abandonedItem, 60000, self:getId(), "workbench"))
                return true
            else
                self:sendCancelMessage("You cannot disenchant regular items.")
                return false
            end
        elseif toCylinder:getId() == 8671 then
            local disenchantDesc = item:getAttribute(ITEM_ATTRIBUTE_ARTICLE)
            if disenchantDesc:find "rare" or disenchantDesc:find "epic" or disenchantDesc:find "legendary" or disenchantDesc:find "dawnbreaker" then
                self:sendCancelMessage("This item is already enchanted.")
                return false
            elseif rollCheck(item) == false then
                self:sendCancelMessage("This item cannot be enchanted here.")
                return false
            else
                item:setAttribute(ITEM_ATTRIBUTE_OWNER, self:getId())
                Game.setStorageValue(30021, addEvent(abandonedItem, 60000, self:getId(), "anvil"))
                return true
            end
        end
    end
    if fromCylinder and fromCylinder:isItem() then -- trying to move item from workbench
        if fromCylinder:getId() == 23660 then
            local ownerId = item:getAttribute(ITEM_ATTRIBUTE_OWNER) -- check owner
            if ownerId ~= 0 then
                local myId = self:getId()
                if myId == ownerId then -- owner is trying to move their item
                    item:removeAttribute(ITEM_ATTRIBUTE_OWNER)
                    if Game.getStorageValue(30020) then
                        stopEvent(Game.getStorageValue(30020))
                        Game.setStorageValue(30020, -1)
                    end
                    return true
                else -- someone is trying to move someone elses item
                    self:sendCancelMessage("This item does not belong to you.")
                    return false
                end
            else -- item has been abandoned in the workbench for a while, you can have it
                self:sendTextMessage(MESSAGE_INFO_DESCR, "This item has been abandoned, it's now yours!")
            end
        elseif fromCylinder:getId() == 8671 then -- trying to move item from anvil
            local ownerId = item:getAttribute(ITEM_ATTRIBUTE_OWNER)
            if ownerId ~= 0 then
                local myId = self:getId()
                if myId == ownerId then
                    item:removeAttribute(ITEM_ATTRIBUTE_OWNER)
                    if Game.getStorageValue(30021) then
                        stopEvent(Game.getStorageValue(30021))
                        Game.setStorageValue(30021, -1)
                    end
                    return true
                else
                    self:sendCancelMessage("This item does not belong to you.")
                    return false
                end
            else
                self:sendTextMessage(MESSAGE_INFO_DESCR, "This item has been abandoned, it's now yours!")
            end
        end
    end
 
    return true
end

items.xml
(new item names)
replace:
XML:
<!-- over-write these itemids if they exist already -->
<item id="8671" article="an" name="anvil" />
<item id="23453" name="magic powder">
        <attribute key="description" value="It can be used to enchant items at the town forge." />
        <attribute key="weight" value="10" />
        <attribute key="showcount" value="0" />
</item>
<item id="4846" article="a" name="smithing hammer">
        <attribute key="weight" value="1200" />
</item>
<item id="23660" article="a" name="workbench">
        <attribute key="description" value="You can disenchant rare, epic and legendary items here." />
</item>
 
Hey Leo32, amazing system. Managed to import it without any console errors. Only problem I'm getting is "The item on the anvil does not belong to you." (killed cyclops - put in short sword & have enough dust to enchant) same error when using workbench. Currently on TFS 1.4.1, know of any solutions? Much appreciated <3
 
Back
Top