• 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 [TFS 1.3] Refactor rust remover script

E

Evil Puncker

Guest
its me again, going to make a PR to tfs with the rust remover script found on this thread by @tokenzz I guess, but I need someone to make it look better, specially the table.contains part lmao, everything else is working fine:

Lua:
local config = {
    [9808] = { -- Common Rusty Armor
        [1] = {id = 2464, chance = 6994}, -- Chain Armor
        [2] = {id = 2483, chance = 3952}, -- Scale Armor
        [3] = {id = 2465, chance = 1502}, -- Brass Armor
        [4] = {id = 2463, chance = 197} -- Plate Armor
    },
    [9809] = { -- Semi-rare Rusty Armor
        [1] = {id = 2483, chance = 6437}, -- Scale Armor
        [2] = {id = 2464, chance = 4606}, -- Chain Armor
        [3] = {id = 2465, chance = 3029}, -- Brass Armor
        [4] = {id = 2463, chance = 1559}, -- Plate Armor
        [5] = {id = 2476, chance = 595}, -- Knight Armor
        [6] = {id = 8891, chance = 283}, -- Paladin Armor
        [7] = {id = 2487, chance = 49} -- Crown Armor
    },
    [9810] = { -- Rare Rusty Armor
        [1] = {id = 2465, chance = 6681}, -- Brass Armor
        [2] = {id = 2463, chance = 3767}, -- Plate Armor
        [3] = {id = 2476, chance = 1832}, -- Knight Armor
        [4] = {id = 2487, chance = 177}, -- Crown Armor
        [5] = {id = 8891, chance = 31}, -- Paladin Armor
        [6] = {id = 2466, chance = 10} -- Golden Armor
    },
    [9811] = { -- Common Rusty Legs
        [1] = {id = 2648, chance = 6949}, -- Chain Legs
        [2] = {id = 2468, chance = 3692}, -- Studded Legs
        [3] = {id = 2478, chance = 1307}, -- Brass Legs
        [4] = {id = 2647, chance = 133} -- Plate Legs
    },
    [9812] = { -- Semi-Rare Rusty Legs
        [1] = {id = 2468, chance = 5962}, -- Studded Legs
        [2] = {id = 2648, chance = 4037}, -- Chain Legs
        [3] = {id = 2478, chance = 2174}, -- Brass Legs
        [4] = {id = 2647, chance = 1242}, -- Plate Legs
        [5] = {id = 2477, chance = 186}, -- Knight Legs
    },
    [9813] = { -- Rare Rusty Legs
        [1] = {id = 2478, chance = 6500}, -- Brass Legs
        [2] = {id = 2647, chance = 3800}, -- Plate Legs
        [3] = {id = 2477, chance = 200}, -- Knight Legs
        [4] = {id = 2488, chance = 52}, -- Crown Legs
        [5] = {id = 2470, chance = 30} -- Golden Legs
    },
    [9814] = { -- Heavily Rusted Shield
    },
    [9815] = { -- Rusted Shield
    },
    [9816] = { -- Slightly Rusted Shield
        [1] = {id = 2510, chance = 3137}, -- Plate Shield
        [2] = {id = 2532, chance = 2887}, -- Ancient Shield
        [3] = {id = 7460, chance = 929}, -- Norse Shield
        [4] = {id = 2519, chance = 23}, -- Crown Shield
        [5] = {id = 2534, chance = 10} -- Vampire Shield
    },
    [9820] = { -- Heavily Rusted Helmet
    },
    [9821] = { -- Rusted Helmet
        [1] = {id = 2460, chance = 2200}, -- Brass Helmet
        [2] = {id = 2482, chance = 1870}, -- Studded Helmet
        [3] = {id = 2459, chance = 1490}, -- Iron Helmet
        [4] = {id = 2457, chance = 1010}, -- Steel Helmet
        [5] = {id = 2491, chance = 190}, -- Crown Helmet
        [6] = {id = 2497, chance = 10} -- Crusader Helmet
    },
    [9822] = { -- Slightly Rusted Helmet
        [1] = {id = 2459, chance = 3156}, -- Iron Helmet
        [2] = {id = 2457, chance = 2976}, -- Steel Helmet
        [3] = {id = 2491, chance = 963}, -- Crown Helmet
        [4] = {id = 2497, chance = 210}, -- Crusader Helmet
        [5] = {id = 2498, chance = 7} -- Royal Helmet
    },
    [9817] = { -- Heavily Rusted Boots
    },
    [9818] = { -- Rusted Boots
    },
    [9819] = { -- Slightly Rusted Boots
    },
}

local rustRemover = Action()

function rustRemover.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local targetItem = config[target.itemid]
    if not targetItem then
        return true
    end

    local randChance = math.random(10000)
    local index = false

    if targetItem[1].chance >= randChance then -- implying first item in the table index always has the highest chance.
        while not index do
            randomIndex = math.random(#targetItem)
            if targetItem[randomIndex].chance >= randChance then
                index = randomIndex
            end
        end
    end

    if not index then
        if table.contains({9808, 9809, 9810}, target.itemid) then msg = "The armor was already damaged so badly that it broke when you tried to clean it." end
        if table.contains({9811, 9812, 9813}, target.itemid) then msg = "The legs were already damaged so badly that they broke when you tried to clean them." end
        if table.contains({9814, 9815, 9816}, target.itemid) then msg = "The shield was already damaged so badly that it broke when you tried to clean it." end
        if table.contains({9817, 9818, 9819}, target.itemid) then msg = "The boots were already damaged so badly that they broke when you tried to clean them." end  
        if table.contains({9820, 9821, 9822}, target.itemid) then msg = "The helmet was already damaged so badly that it broke when you tried to clean it." end
        player:say(msg, TALKTYPE_MONSTER_SAY)
        target:getPosition():sendMagicEffect(CONST_ME_BLOCKHIT)
        target:remove()
    else
        target:transform(targetItem[index].id)
        target:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
    end
    return item:remove(1)
end

rustRemover:id(9930)
rustRemover:register()
 
Solution
If I restarted refactoring TFS code and doing PRs I'd probably get extremely irritated by the acceptance delays 😂

But let's see about this guy...


Pass 1
Break all that repeated string out into a closure;
Lua:
    function missed(item)
        local text = {
            ["armor"]  = { pverb = 'was',  pnoun = "it",   plur = "it"   },
            ["legs"]   = { pverb = 'were', pnoun = "they", plur = "them" },
            ["shield"] = { pverb = 'was',  pnoun = "it",   plur = "it"   },
            ["boots"]  = { pverb = 'were', pnoun = "they", plur = "them" },
            ["helmet"] = { pverb = 'was',  pnoun = "it",   plur = "it"   },
        }
        local pverb = text[item].pverb
        local pnoun = text[item].pnoun
        local plur  =...
Simple test cast in local Lua interpreter proves to me that your access syntax is correctly formed for this table function.

Lua:
table.contains = function(array, value)
    for _, targetColumn in pairs(array) do
        if targetColumn == value then
            return true
        end
    end
    return false
end

do
    local testTarget = {
        ["itemid"] = 9808
    }

    function testRefactor(target)
        if table.contains({9808, 9809, 9810}, target.itemid) then 
            msg = "Your rust refactoring should work" 
        else 
            msg = "Well that's unfortunate"
        end
        print(msg)
    end

    testRefactor(testTarget)
end


This test code seems to produce varying output, and I ran it enough to see a Royal Helmet roll
Lua:
math.randomseed(os.time())

local config = {
    [9822] = { -- Slightly Rusted Helmet
        [1] = {id = 2459, chance = 3156}, -- Iron Helmet
        [2] = {id = 2457, chance = 2976}, -- Steel Helmet
        [3] = {id = 2491, chance = 963}, -- Crown Helmet
        [4] = {id = 2497, chance = 210}, -- Crusader Helmet
        [5] = {id = 2498, chance = 7} -- Royal Helmet
    }
}

local testTarget = {
    ["itemid"] = 9822
}

do
    function randomShiny(target)
        local targetItem = config[target.itemid]
        local randChance = math.random(10000)
        local index = false

        if targetItem[1].chance >= randChance then -- implying first item in the table index always has the highest chance.
            while not index do
                randomIndex = math.random(#targetItem)
                if targetItem[randomIndex].chance >= randChance then
                    index = randomIndex
                end
            end
        end

        if(index) then
            print('Random shiny! You got:' .. index)
        else
            print('No error')
        end
    end

    randomShiny(testTarget)
end

69 runs:
Code:
47x -- No error
11x -- Random shiny! You got:1
7x  -- Random shiny! You got:2
3x  -- Random shiny! You got:3
1x  -- Random shiny! You got:5

LGTM.
 
Simple test cast in local Lua interpreter proves to me that your access syntax is correctly formed for this table function.

Lua:
table.contains = function(array, value)
    for _, targetColumn in pairs(array) do
        if targetColumn == value then
            return true
        end
    end
    return false
end

do
    local testTarget = {
        ["itemid"] = 9808
    }

    function testRefactor(target)
        if table.contains({9808, 9809, 9810}, target.itemid) then
            msg = "Your rust refactoring should work"
        else
            msg = "Well that's unfortunate"
        end
        print(msg)
    end

    testRefactor(testTarget)
end


This test code seems to produce varying output, and I ran it enough to see a Royal Helmet roll
Lua:
math.randomseed(os.time())

local config = {
    [9822] = { -- Slightly Rusted Helmet
        [1] = {id = 2459, chance = 3156}, -- Iron Helmet
        [2] = {id = 2457, chance = 2976}, -- Steel Helmet
        [3] = {id = 2491, chance = 963}, -- Crown Helmet
        [4] = {id = 2497, chance = 210}, -- Crusader Helmet
        [5] = {id = 2498, chance = 7} -- Royal Helmet
    }
}

local testTarget = {
    ["itemid"] = 9822
}

do
    function randomShiny(target)
        local targetItem = config[target.itemid]
        local randChance = math.random(10000)
        local index = false

        if targetItem[1].chance >= randChance then -- implying first item in the table index always has the highest chance.
            while not index do
                randomIndex = math.random(#targetItem)
                if targetItem[randomIndex].chance >= randChance then
                    index = randomIndex
                end
            end
        end

        if(index) then
            print('Random shiny! You got:' .. index)
        else
            print('No error')
        end
    end

    randomShiny(testTarget)
end

69 runs:
Code:
47x -- No error
11x -- Random shiny! You got:1
7x  -- Random shiny! You got:2
3x  -- Random shiny! You got:3
1x  -- Random shiny! You got:5

LGTM.
I'm wondering if there is a less ugly way of doing this part tho:

Lua:
        if table.contains({9808, 9809, 9810}, target.itemid) then msg = "The armor was already damaged so badly that it broke when you tried to clean it." end
        if table.contains({9811, 9812, 9813}, target.itemid) then msg = "The legs were already damaged so badly that they broke when you tried to clean them." end
        if table.contains({9814, 9815, 9816}, target.itemid) then msg = "The shield was already damaged so badly that it broke when you tried to clean it." end
        if table.contains({9817, 9818, 9819}, target.itemid) then msg = "The boots were already damaged so badly that they broke when you tried to clean them." end 
        if table.contains({9820, 9821, 9822}, target.itemid) then msg = "The helmet was already damaged so badly that it broke when you tried to clean it." end
 
If I restarted refactoring TFS code and doing PRs I'd probably get extremely irritated by the acceptance delays 😂

But let's see about this guy...


Pass 1
Break all that repeated string out into a closure;
Lua:
    function missed(item)
        local text = {
            ["armor"]  = { pverb = 'was',  pnoun = "it",   plur = "it"   },
            ["legs"]   = { pverb = 'were', pnoun = "they", plur = "them" },
            ["shield"] = { pverb = 'was',  pnoun = "it",   plur = "it"   },
            ["boots"]  = { pverb = 'were', pnoun = "they", plur = "them" },
            ["helmet"] = { pverb = 'was',  pnoun = "it",   plur = "it"   },
        }
        local pverb = text[item].pverb
        local pnoun = text[item].pnoun
        local plur  = text[item].plur
        return ("The "..item.." "..pverb.." already damaged so badly that "..pnoun.." broke when you tried to clean "..plur..".")
    end
    if not index then
        if table.contains({9808, 9809, 9810}, target.itemid) then msg = missed("armor") end
        if table.contains({9811, 9812, 9813}, target.itemid) then msg = missed("legs") end
        if table.contains({9814, 9815, 9816}, target.itemid) then msg = missed("shield") end
        if table.contains({9817, 9818, 9819}, target.itemid) then msg = missed("boots") end
        if table.contains({9820, 9821, 9822}, target.itemid) then msg = missed("helmet") end
        player:say(msg, TALKTYPE_MONSTER_SAY)
        target:getPosition():sendMagicEffect(CONST_ME_BLOCKHIT)
        target:remove()
    else

Pass 2:
Only two sets of verbs/pronouns: is the article a single or a pair
Lets use the C string formatter since it's available
Lua:
    function missed(item)
        local single = { pverb = 'was',  pnoun = "it",   plur = "it"   }
        local pain = { pverb = 'were', pnoun = "they", plur = "them" }

        local text = {
            ["armor"]  = single, ["shield"] = single, ["helmet"] = single,
            ["boots"]  = pair, ["legs"]   = pair
        }
        local pverb = text[item].pverb
        local pnoun = text[item].pnoun
        local plur  = text[item].plur
        return string.format("The %s %s already damaged so badly that %s broke when you tried to clean %s.", item, pverb, pnoun, plur)
    end

Pass 3: Eh, the closure is not likely for any actual reusage. Gut it to just a formatter wrapper. Rename.
Lua:
    function broken(item, pverb, pnoun, plur)
        return string.format("The %s %s already damaged so badly that %s broke when you tried to clean %s.", item, pverb, pnoun, plur)
    end

    if not index then
        if table.contains({9808, 9809, 9810}, target.itemid) then msg = broken("armor", "was", "it",  "it"  ) end
        if table.contains({9811, 9812, 9813}, target.itemid) then msg = broken("legs",  "were","they","them") end
        if table.contains({9814, 9815, 9816}, target.itemid) then msg = broken("shield","was", "it",  "it"  ) end
        if table.contains({9817, 9818, 9819}, target.itemid) then msg = broken("boots", "were","they","them") end
        if table.contains({9820, 9821, 9822}, target.itemid) then msg = broken("helmet","was", "it",  "it"  ) end
        player:say(msg, TALKTYPE_MONSTER_SAY)
        target:getPosition():sendMagicEffect(CONST_ME_BLOCKHIT)
        target:remove()
    else

Any attempts to reduce the table.contains blocks into other formats would gain little since the appropriate syntax would be just as large to make it a lookup table. Dunno how this could get more elegant.
 
Solution
Back
Top