• 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!
  • New resources must be posted under Resources tab. A discussion thread will be created automatically, you can't open threads manually anymore.

Revscripts(1.3) Custom Equipment {SYC}

Codinablack

Dreamer
Content Editor
Joined
Dec 26, 2013
Messages
1,813
Solutions
12
Reaction score
1,106
Ok everyone, I have been working on something for a few weeks in my spare time, and I'm here to share with you, a "Custom Equipment" system, that loads all your custom equipment properties thru a single xml file.

Credits to : @azzkaban for original release this is based off of here
Special thanks to @forgee , @zbizu , @Sarah Wesker , @Evil Hero for helping me along the way.

This is for TFS 1.3+ only, it is considered a MOD as it utilizes many different events in one file.

Features

  • Standard Attributes
  • Buffs (conditions)
  • Skill buffs (conditions)
  • Penalties (conditions)
  • Damage Penalties (conditions)
  • Reflection
  • Absorption
  • Requirements
  • Reusable base items (make as many version of one item as you like)
  • Special skills (crit, lifeleech, manaleech)
  • Elemental Damage increase
  • Lootable (from item with baseItemId being dropped in corpse) with chance configuration
  • Extended description for condtions on custom equipment
Event's utilized
  • onLook
  • onEquip
  • onDeEquip
  • onHealthChange

Why would you prefer to use this over any other system out there? Perhaps for simplicity or convenience, however this isn't a system that is made to be in competition with other systems like it, it's intended purpose was to make up for what the source code doesn't already provide for us, you know, those "item abilities" that people are always looking for, well, they can easily be added to this system.

This system is extremely extensible, and since it is part of the {SYC} series I was discussing here I would like to see many people sharing their copies. It is not required, nor enforced, but it is highly encouraged, if you add say "Luck" to it for monsters to drop the loot, or "rarity" system, perhaps you want to make your 10 different copies of MPA as different "tier" levels, anything you feel you can add or want to add to this system, please share with the rest of us! That includes the xml file, if all you did was create an elaborate equipment list that you are proud of, share here and we will all appreciate it.

I plan on uploading a video to demonstrate the power of this system, perhaps even make it into a guide, but that will have to wait, I don't currently have the time, so I will probably update this main thread later with a video and perhaps a more complete version of the xml. If you have any questions about the acceptable xml tags, please don't be afraid to ask.

As part of the Share Your Copy series, I will be updating main post with links to shared version of this system
(PLEASE SHARE YOU VERSION HERE, NOT IN A NEW THREAD)

for now, lets get to the good stuff.

the customequipment.lua file just needs to be inside data/scripts folder, and the customequipment.xml file inside data/xml and viola! System is ready to use!

One thing to keep in mind while using this system, the information is based off of the "equipId" so please, once you start making the items, DO NOT CHANGE THE EQUIPID, it will cause problems for you, as the items that have already been created, will not register properly.

The only function you need to use in other scripts to utilize this system is player:addCustomEquipment() -- uses equipId

a demonstration

LUA:
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    player:addCustomEquipment(24001)
    player:addCustomEquipment(24002)
    player:addCustomEquipment(24003)
    player:addCustomEquipment(24721)
    player:addCustomEquipment(24722)
end

That is a test action I used for testing this system, contains all the equipId's of the starter xml file.

I tried to include some comments for the different types of xml tags used, but if anyone has any questions about ones not already demonstrated, please ask.
Oh and any equipment you use here, please remove requirements from other appropriate locations, movements.xml, weapons.xml, ect. As those will still be applied and can conflict with the system.

Doesn't support wands, or ammo types

Enjoy :D

Updated version 1.1 has the premmy bugfix, the descriptions for conditions, manashield working, mana event that works with reflects absorbs, no nil error from absorbs/reflects anymore, lootable customequipment with configs, configs for setting healthticks, manaticks, and soulticks, with soulgain fixed.
 

Attachments

Last edited:
I looks nice.

IMO it should also be in some public git repository (gitlab? github?).
Just in case of some bug fix or new killing feature in future.
 
Well I mean it looks like at least 15 people have downloaded it so far, anyone install and test it out?
 
I do on otservbr but not work, i already know that "This is for TFS 1.3+ only", but I wanted to give it a try.
From what I understand , otservbr is basically 1.3 with a few source modifications and alot of lua work... what kind of error do you get? Maybe we can get it to work on otservbr pretty easily
 
how to proceed in this part?
in case my server doesn't have this eventcallback
LUA:
local lookEvent = EventCallback

lookEvent.onLook = function(self, thing, position, distance, description)
    if thing:isItem() then
        if thing:getCustomEquipId() then
            local eq = customEquipment[thing:getCustomEquipId()]
            if eq then
                if eq.requirements["level"] and type(eq.requirements["level"]) == "number" then
                    description = string.format("%s\nLevel Required: %d", description, eq.requirements["level"])
                end
                if eq.requirements["magiclevel"] and type(eq.requirements["magiclevel"]) == "number" then
                    description = string.format("%s\nMagic Level Required: %d", description, eq.requirements["magiclevel"])
                end
                if eq.requirements["premium"] and eq.requirements["premium"] > 0 then
                    description = string.format("%s\nPremium Required", description)
                end
                if eq.requirements["vocation"] then
                    description = string.format("%s\nVocation Required: " ..eq.requirements["vocation"].. "", description)
                end
                --- attributes reload onLook
                if attributeReload then
                    if reloadOnLook then
                        for attr, val in pairs(eq.attributes) do
                            item:setAttribute(attr, val)
                        end
                    end
                end
            end
        end
    end
    return description
end

lookEvent:register(1)


for key , id in pairs(baseItemList) do
    local equipEvent = MoveEvent()
    local deEquipEvent = MoveEvent()
    
    equipEvent:id(id)
    deEquipEvent:id(id)

    function equipEvent.onEquip(player, item, slot, isCheck)
        if isCheck == true then
            local eq = customEquipment[item:getCustomEquipId()]
            if eq then
                if eq.requirements["level"] and eq.requirements["level"] > player:getLevel() then
                    player:sendTextMessage(MESSAGE_INFO_DESCR,"You don't have the proper level required to equip that item!")
                    return false
                end
                if eq.requirements["magiclevel"] and eq.requirements["magiclevel"] > player:getMagicLevel() then
                    player:sendTextMessage(MESSAGE_INFO_DESCR,"You don't have the proper magic level required to equip that item!")
                    return false
                end
                if eq.requirements["premium"] and eq.requirements["premium"] > 0 then
                    if not player:getPremiumEndsAt() then
                        player:sendTextMessage(MESSAGE_INFO_DESCR,"You must have premium to equip that item!")
                        return false
                    end
                end
                if eq.requirements["vocation"] then
                    local vocation = Vocation(eq.requirements["vocation"])
                    if vocation then
                        if vocation ~= (player:getVocation() or player:getVocation():getDemotion()) then
                            player:sendTextMessage(MESSAGE_INFO_DESCR,"You don't have the proper vocation to equip that item!")
                            return false
                        end
                    end
                end
            end
        end

        if isCheck == false then
            if customEquipment[item:getCustomEquipId()] then
                player:applyEquipmentConditions(item, slot)
                player:applyEquipmentPentalties(item, slot)
                player:applyDamagePenalties(item, slot)
                player:registerEvent("HealthProcessor")
                player:registerEvent("DamageProcessor")
                --- attributes reload onEquip
                if attributeReload then
                    if reloadOnEquip then
                        for attr, val in pairs(customEquipment[item:getCustomEquipId()].attributes) do
                            item:setAttribute(attr, val)
                        end
                    end
                end

                return true
            end
        end
        return true
    end

    function deEquipEvent.onDeEquip(player, item, slot, isCheck)
        if isCheck == false then
            if customEquipment[item:getCustomEquipId()] then
                player:removeEquipmentConditions(item, slot)
                player:removeEquipmentPentalties(item, slot)
                player:removeDamagePenalties(item, slot)
                player:unregisterEvent("HealthProcessor")
                player:unregisterEvent("DamageProcessor")
                return true
            end
        end
        return true
    end

    equipEvent:register()
    deEquipEvent:register()
end
 
how to proceed in this part?
in case my server doesn't have this eventcallback
LUA:
local lookEvent = EventCallback

lookEvent.onLook = function(self, thing, position, distance, description)
    if thing:isItem() then
        if thing:getCustomEquipId() then
            local eq = customEquipment[thing:getCustomEquipId()]
            if eq then
                if eq.requirements["level"] and type(eq.requirements["level"]) == "number" then
                    description = string.format("%s\nLevel Required: %d", description, eq.requirements["level"])
                end
                if eq.requirements["magiclevel"] and type(eq.requirements["magiclevel"]) == "number" then
                    description = string.format("%s\nMagic Level Required: %d", description, eq.requirements["magiclevel"])
                end
                if eq.requirements["premium"] and eq.requirements["premium"] > 0 then
                    description = string.format("%s\nPremium Required", description)
                end
                if eq.requirements["vocation"] then
                    description = string.format("%s\nVocation Required: " ..eq.requirements["vocation"].. "", description)
                end
                --- attributes reload onLook
                if attributeReload then
                    if reloadOnLook then
                        for attr, val in pairs(eq.attributes) do
                            item:setAttribute(attr, val)
                        end
                    end
                end
            end
        end
    end
    return description
end

lookEvent:register(1)


for key , id in pairs(baseItemList) do
    local equipEvent = MoveEvent()
    local deEquipEvent = MoveEvent()
   
    equipEvent:id(id)
    deEquipEvent:id(id)

    function equipEvent.onEquip(player, item, slot, isCheck)
        if isCheck == true then
            local eq = customEquipment[item:getCustomEquipId()]
            if eq then
                if eq.requirements["level"] and eq.requirements["level"] > player:getLevel() then
                    player:sendTextMessage(MESSAGE_INFO_DESCR,"You don't have the proper level required to equip that item!")
                    return false
                end
                if eq.requirements["magiclevel"] and eq.requirements["magiclevel"] > player:getMagicLevel() then
                    player:sendTextMessage(MESSAGE_INFO_DESCR,"You don't have the proper magic level required to equip that item!")
                    return false
                end
                if eq.requirements["premium"] and eq.requirements["premium"] > 0 then
                    if not player:getPremiumEndsAt() then
                        player:sendTextMessage(MESSAGE_INFO_DESCR,"You must have premium to equip that item!")
                        return false
                    end
                end
                if eq.requirements["vocation"] then
                    local vocation = Vocation(eq.requirements["vocation"])
                    if vocation then
                        if vocation ~= (player:getVocation() or player:getVocation():getDemotion()) then
                            player:sendTextMessage(MESSAGE_INFO_DESCR,"You don't have the proper vocation to equip that item!")
                            return false
                        end
                    end
                end
            end
        end

        if isCheck == false then
            if customEquipment[item:getCustomEquipId()] then
                player:applyEquipmentConditions(item, slot)
                player:applyEquipmentPentalties(item, slot)
                player:applyDamagePenalties(item, slot)
                player:registerEvent("HealthProcessor")
                player:registerEvent("DamageProcessor")
                --- attributes reload onEquip
                if attributeReload then
                    if reloadOnEquip then
                        for attr, val in pairs(customEquipment[item:getCustomEquipId()].attributes) do
                            item:setAttribute(attr, val)
                        end
                    end
                end

                return true
            end
        end
        return true
    end

    function deEquipEvent.onDeEquip(player, item, slot, isCheck)
        if isCheck == false then
            if customEquipment[item:getCustomEquipId()] then
                player:removeEquipmentConditions(item, slot)
                player:removeEquipmentPentalties(item, slot)
                player:removeDamagePenalties(item, slot)
                player:unregisterEvent("HealthProcessor")
                player:unregisterEvent("DamageProcessor")
                return true
            end
        end
        return true
    end

    equipEvent:register()
    deEquipEvent:register()
end
Same here, Otservbr dont support eventcallback
 
Ok since otserve doesn't support onLook callback, and I can see clearly it does support the other events like onEquip as shown here


then to make it compatible, the only thing that would need done is to comment out the onLook part of this code, then it should work perfectly. The onLook is NOT a necessary part of this system, its just a little added hook to utilize. so from lines 322-355, comment them out or just delete them, and then check and see, the system should work fine, if you want the onLook to be utilized, would take a little more altering on the standard onLook for player event.

@jel @nefinoo
 
Did anyone ever try the otservbr with this system, commenting or deleting the onlook part?
 
already in revscript?
Not sure I understand the question... Are you asking about the main post, the whole system? Or are you referring to my last statement? The entire system is in two files, the lua file contains everything together as a mod utilizing revscripts
 
From what I understand , otservbr is basically 1.3 with a few source modifications and alot of lua work... what kind of error do you get? Maybe we can get it to work on otservbr pretty easily
[2021-04-08 21:53:10.088] [error] Lua script error: C:\ots\otservbr-global-develop\data\scripts\custom\customequpiment.lua
[2021-04-08 21:53:10.090] [error] ...r-global-develop\data\scripts\custom\customequpiment.lua:114: table index is nil
stack traceback:
[C]: in function '__newindex'
...r-global-develop\data\scripts\custom\customequpiment.lua:114: in main chunk
[2021-04-08 21:53:10.092] [error] customequpiment.lua
[2021-04-08 21:53:10.094] [error]
 
Can you post to me the error with the original script UNALTERED top half, or atleast show me the line you get the error on, because my version shared here has no table referenced on that line
@nefinoo , I'd like to figure out what's wrong to help you guys
 
[2021-04-08 21:53:10.088] [error] Lua script error: C:\ots\otservbr-global-develop\data\scripts\custom\customequpiment.lua
[2021-04-08 21:53:10.090] [error] ...r-global-develop\data\scripts\custom\customequpiment.lua:114: table index is nil
stack traceback:
[C]: in function '__newindex'
...r-global-develop\data\scripts\custom\customequpiment.lua:114: in main chunk
[2021-04-08 21:53:10.092] [error] customequpiment.lua
[2021-04-08 21:53:10.094] [error]
can you show me that line please? It doesn't match what I have, or shared... No table is referenced on that line in my copy. I think I can fix it if you will share, but I really don't want to go through the trouble of downloading new client, creating new database, downloading otservbr, and setting it all up just to be able to login and test it, so if you or anyone else like

@famosiin or @jel could you share your errors with the onLook event removed or commented out , please, someone, could have had this working already probably
 
can you show me that line please? It doesn't match what I have, or shared... No table is referenced on that line in my copy. I think I can fix it if you will share, but I really don't want to go through the trouble of downloading new client, creating new database, downloading otservbr, and setting it all up just to be able to login and test it, so if you or anyone else like

@famosiin or @jel could you share your errors with the onLook event removed or commented out , please, someone, could have had this working already probably
I'm using an out of date 1.3 downgrade for 7.6, i had that exact error but on another line.
/data/scripts/customequpiment.lua:123: table index is nil
It is because my server does not support bleeding which was on line 123.

I fixed all unsupported damage types and my next error was:
/data/scripts/customequpiment.lua:158: attempt to call method 'getGroup' (a nil value)
i just removed this check assuming it's my outdated tfs plus it didn't seem a very important check.

My next error was the onLook and again i removed this whole chunk of code assuming outdated tfs.
/data/scripts/customequpiment.lua:332: attempt to index local 'lookEvent' (a nil value)

Right now the system seems to be working fine and without errors but I haven't tested it extensively or made any modifications yet. Since i'm on an outdated downgrade and not otservbr i'm not sure how applicable any of this is for you in regard to their problems.

fyi line 114 on the unmodified file is [CONDITION_EXHAUST_WEAPON] = tonumber(i:match('penalty.-=.-"disableweapon".-enabled.-=.-"(.-)"')),
 
Last edited:
fyi line 114 on the unmodified file is [CONDITION_EXHAUST_WEAPON] = tonumber(i:match('penalty.-=.-"disableweapon".-enabled.-=.-"(.-)"')),
Yes, which is why I requested to see your version to identify the table that was registering a nil value.


I'm using an out of date 1.3 downgrade for 7.6, i had that exact error but on another line.
/data/scripts/customequpiment.lua:123: table index is nil
It is because my server does not support bleeding which was on line 123.
This doesn't really help me with figuring out which lines are which in your modified version, but it seems as though since you got it working that everything is well! I'm glad to see that! Since you haven't really gotten all super customized with the code yet, to specifically suit your server, mind sharing the working version you have with the specific client and server you are using? I'd really appreciate it, and i'm certain others would as well!

I'd still like to help any otservbr user as well
 
Yes, which is why I requested to see your version to identify the table that was registering a nil value.
I didn't post in here before, just trying to give some light because no one else was replying and I had similar errors.

I just had a look at otservbr and it doesn't look like it uses CONDITION_EXHAUST_WEAPON.

Since you haven't really gotten all super customized with the code yet, to specifically suit your server, mind sharing the working version you have with the specific client and server you are using? I'd really appreciate it, and i'm certain others would as well!
I'll have to test it more before uploading it, but sure
 
Last edited:
Back
Top