- Joined
- May 19, 2004
- Messages
- 267
Hi all,
This is an equipment system used to simulate an equipment menu. I'm posting this here to hopefully get some feedback on the functionality, as well as the code. Note that this is just a testversion, the code is not properly commented, nor is there any full documentation.
Importing is not supported yet.
I embarked on this project April 2006, where it was uploaded at clancbs.com.
In January 2009 I made a remake of it, adding new functionality and redoing alot of the code.
Today, I'm hopefully rewriting it for the last time.
It now uses vJass and ObjectMerger for easy importing and a clean code structure. So the system requires NewGen/JassHelper. The new system should support any kind of item bonuses you may want with some Jass knowledge.
It currently only functions as a template, however, I will later add modules to simplify adding basic stats.
Upcoming features:
Enjoy
This is an equipment system used to simulate an equipment menu. I'm posting this here to hopefully get some feedback on the functionality, as well as the code. Note that this is just a testversion, the code is not properly commented, nor is there any full documentation.
Importing is not supported yet.
I embarked on this project April 2006, where it was uploaded at clancbs.com.
In January 2009 I made a remake of it, adding new functionality and redoing alot of the code.
Today, I'm hopefully rewriting it for the last time.
It now uses vJass and ObjectMerger for easy importing and a clean code structure. So the system requires NewGen/JassHelper. The new system should support any kind of item bonuses you may want with some Jass knowledge.
It currently only functions as a template, however, I will later add modules to simplify adding basic stats.
Upcoming features:
- Documentation
- Set bonuses
- Two handed weapons
- Dualwield
- Easy managing for basic stats
- Proper customized stat/level requirements.
- Option to drop items on death
- A "validate" function if a unit delevels or looses stats etc.
- Temporarily enabling/disabling itemtypes and units from the system.
- Locking/Hiding slots for specific units.
- Waffles?
Enjoy
JASS:
library TEEquip initializer Init requires Table, Stack, UnitIndexingUtils, SimError
//***********************************************************************************************************************
//* TEEquip
//*
//* Author: Thunder_Eye
//*
//* Credits:
//* * Vexorian for vJass, JassHelper, and the finding of the spellbook trick
//* * PitzerMike for the ObjectMerger
//* * PipeDream for Grimoire
//* * SFilip for TESH
//* * MindWorX for maintaining NewGen
//*
//* Required Libraries:
//* * Table by Vexorian
//* * Stack by Anitarf
//* * UnitIndexingUtils by Rising Dusk
//* * SimError by Vexorian
//*
//* Optional Libraries:
//* * UnitMaxState by Earth-Fury
//* * BonusMod by Earth-Fury
//*
//* This is an equipment system which is easy to implent, and outputs a smooth
//* userinterface for the endgame user. However, it requires some massive Object
//* Editor use, and if used incorrectly, may clutter up your Ability section.
//* It supports up to 8191 different allocated itemtypes, and the same amount of
//* units utilizing the system.
//*
//* The basic system only works as a template with the addition that it handles
//* item requirements for you.
//*
//* In a future version however, there will be additional modules that can manage
//* changing the basic stats for you.
//*
//* Note that using UnitIndexingUtils will render you unable to use UnitUserData().
//*
//* To initialize a unit, call InitUnit (with the TEEquip prefix)
//* To add an itemtype, call AddItemType (again, with the TEEquip prefix)
//* Note that these are just wrapper functions, I suggest creating the structs
//* directly.
//*
//* Function list:
//* function InitUnit takes unit u returns nothing
//* function AddItemType takes integer iType, integer aId, integer sbId, integer slot, code eF, code uF returns nothing
//* function AddRestriction takes string restriction returns nothing
//* function AddRequirement takes string requirement returns nothing
//* function SetRequiredLevel takes integer value returns nothing
//* function SetRequiredStr takes integer value returns nothing
//* function SetRequiredAgi takes integer value returns nothing
//* function SetRequiredInt takes integer value returns nothing
//* function AddFunction takes code eF, code uF returns nothing
//* function GetSlotId takes string s returns integer
//*
//* Initialize a unit and give it an equipment menu.
//* This is just a wrapper function, I suggest creating the struct directly instead.
//* function InitUnit takes unit u returns nothing
//* unit u: The unit to initialize
//*
//* Add an itemtype to the system, making it equippable
//* This is just a wrapper function, I suggest creating the struct directly instead.
//* function AddItemType takes integer iType, integer aId, integer sbId, integer slot, code eF, code uF returns nothing
//* integer iType: The rawid of the itemtype.
//* integer aId: The rawid of the UI ability.
//* integer sbId: The rawid of the spellbook holding ability aId.
//* integer slot: The slot where the item is placed when equipped.
//* Can be anything between 0-10.
//* code eF: The function which runs when the item is equipped.
//* By passing null no function will run on equip.
//* code uF: The function which runs when the item is unequipped.
//* By passing null no function will run on unequip.
//*
//* Add a restriction to a unit, enabling it to use items with the proper requirement.
//* Note that units with no restrictions may only equip items with no requirements.
//* Member of: equipunit
//* function AddRestriction takes string restriction returns nothing
//* string restriction: The key of the restrictiontype, upper- or lowercase does not matter.
//*
//* Add a requirement to an item, requiring units to have the proper restrictions to use it.
//* Note that items with no requirements may be equipped by any initialized unit.
//* Units must match ALL requirements to equip item.
//* Member of: equipitem
//* function AddRequirement takes string requirement returns nothing
//* string requirement: The key of the requirementtype, upper- or lowercase does not matter.
//*
//* Temporary function to set a required level on itemtypes.
//* Member of: equipitem
//* function SetRequiredLevel takes integer value returns nothing
//* integer value: The required level.
//*
//* Temporary function to set a required strength on itemtypes.
//* Member of: equipitem
//* function SetRequiredStr takes integer value returns nothing
//* integer value: The required strength.
//*
//* Temporary function to set a required agility on itemtypes.
//* Member of: equipitem
//* function SetRequiredAgi takes integer value returns nothing
//* integer value: The required agility.
//*
//* Temporary function to set a required intelligence on itemtypes.
//* Member of: equipitem
//* function SetRequiredInt takes integer value returns nothing
//* integer value: The required intelligence.
//*
//* Adds an additional function (including the one when you add an itemtype) to an itemtype.
//* Member of: equipitem
//* function AddFunction takes code eF, code uF returns nothing
//* code eF: The function which runs when the item is equipped.
//* code uF: The function which runs when the item is unequipped.
//*
//* Gets the id of a slot.
//* Can be used if you want to clarify the slot when using AddItemType.
//* function GetSlotId takes string slot returns integer
//* string slot: The slot you want the id from.
//* "shoulder" = 0, "head" = 1, "neck" = 2, "finger" = 3,
//* "mainhand" = 4, "chest" = 5, "offhand" = 6, "wrists" = 7
//* "feet" = 8, "legs" = 9, "hands" = 10
//*
//***********************************************************************************************************************
globals
private constant integer MenuId = 'ES00'
endglobals
globals
//equipItemTable = key is itemtype-id, value is struct-id
//equipUnitTable = key is id of unit, value is struct-id
private Table equipItemTable
private Table equipUnitTable
//requirementTable = key is the name of the requirement, value is the id (requirementTable["plate"] = 1)
//requirementKey = key is the id of the requirement, value is the name (requirementKey[1] = "plate")
//requirementTotal = Amount of requirements and key for new requirements (requirementTotal = 2)
private StringTable requirementTable
private string array requirementKey
private integer requirementTotal = 0
//itemTypesAtP[11] = Stack pointing to struct-ids
//emptySlot[11] = Array with the "unequipped" spellbooks
private Stack array itemTypesAtP[11]
private integer array emptySlot[11]
//slotId = key is the name of the slot, value is the id
//hasInited = set to true when a unit is initialized
//hasRun = set to true when the first unit has been initialized.
private StringTable slotId
private boolean hasInited = false
private boolean hasRun = false
//passUnit = triggering unit passed for equip/unequip functions
//passItem = manipulated item passed for equip/unequip functions
public unit passUnit
public item passItem
endglobals
struct equipitem
private integer itemTypeId
private integer abilityId
private integer spellbookId
private integer slot
private Stack requirements = Stack.create()
private trigger equipTrigger = CreateTrigger()
private trigger unequipTrigger = CreateTrigger()
//Temporary until I add some kind of table to handle this.
private integer statReq
private integer levelReq = 0
private integer strReq = 0
private integer agiReq = 0
private integer intReq = 0
//************************************************************************************
//******************************Call functions (public)*******************************
//************************************************************************************
public method AddRequirement takes string requirement returns nothing
local integer i
set requirement = StringCase(requirement, false)
//Check so that it doesn't create duplicate keys of requirements.
if not .requirements.contains(requirementTable[requirement]) then
if requirementTable.exists(requirement) then
//Item requirement type already exists.
set i = requirementTable[requirement]
else
//Item requirement type does not exist, so add it to the table.
set requirementTotal = requirementTotal + 1
set i = requirementTotal
set requirementTable[requirement] = i
set requirementKey[i] = requirement
endif
//Add the key for the requirement type to the itemtype
call .requirements.push(i)
endif
endmethod
public method SetRequiredLevel takes integer value returns nothing
set .levelReq = value
endmethod
public method SetRequiredStr takes integer value returns nothing
set .strReq = value
endmethod
public method SetRequiredAgi takes integer value returns nothing
set .agiReq = value
endmethod
public method SetRequiredInt takes integer value returns nothing
set .intReq = value
endmethod
public method AddFunction takes code eF, code uF returns nothing
call .AddEquipFunc(eF)
call .AddUnequipFunc(uF)
endmethod
public method GetItemTypeId takes nothing returns integer
return .itemTypeId
endmethod
public method GetAbilityId takes nothing returns integer
return .abilityId
endmethod
public method GetSpellbookId takes nothing returns integer
return .spellbookId
endmethod
public method GetRequirementList takes nothing returns Stack
return .requirements
endmethod
public method GetSlot takes nothing returns integer
return .slot
endmethod
//************************************************************************************
//*****************************System functions (private)*****************************
//************************************************************************************
public method TryStats takes integer level, integer str, integer agi, integer int returns boolean
if level >= .levelReq and str >= .strReq and agi >= .agiReq and int >= .intReq then
return true
endif
return false
endmethod
private method AddEquipFunc takes code f returns nothing
if f != null then
call TriggerAddAction(.equipTrigger, f)
endif
endmethod
private method AddUnequipFunc takes code f returns nothing
if f != null then
call TriggerAddAction(.unequipTrigger, f)
endif
endmethod
public method Equip takes unit u, item i returns nothing
set passUnit = u
set passItem = i
call TriggerExecute(.equipTrigger)
endmethod
public method Unequip takes unit u, item i returns nothing
set passUnit = u
set passItem = i
call TriggerExecute(.unequipTrigger)
endmethod
method onDestroy takes nothing returns nothing
//Not added yet
endmethod
static method create takes integer itemTypeId, integer abilityId, integer spellbookId, integer slot, code eF, code uF returns equipitem
local equipitem new
//If no unit has been registered, create the itemtype.
if not hasInited then
set new = equipitem.allocate()
set new.itemTypeId = itemTypeId
set new.abilityId = abilityId
set new.spellbookId = spellbookId
set new.slot = slot
call new.AddEquipFunc(eF)
call new.AddUnequipFunc(uF)
call itemTypesAtP[slot].push(new)
set equipItemTable[itemTypeId] = new
set equipItemTable[abilityId] = new
return new
endif
return 0
endmethod
endstruct
struct equipunit
private unit u
integer array equippedItem[11]
Stack res = Stack.create()
static group equipUnits = CreateGroup()
static trigger onEquip = CreateTrigger()
static trigger onUnequip = CreateTrigger()
//************************************************************************************
//******************************Call functions (public)*******************************
//************************************************************************************
method AddRestriction takes string restriction returns nothing
local integer i
set restriction = StringCase(restriction, false)
if requirementTable.exists(restriction) then
//Item requirement type already exists.
set i = requirementTable[restriction]
else
//Item requirement type does not exist, so add it to the table.
set requirementTotal = requirementTotal + 1
set i = requirementTotal
set requirementTable[restriction] = i
set requirementKey[i] = restriction
endif
//Add the key for the requirement type to the unit
call .res.push(i)
endmethod
method onDestroy takes nothing returns nothing
local integer i = 0
call UnitRemoveAbility(.u, MenuId)
loop
exitwhen i > 10
call UnitRemoveAbility(.u, emptySlot[i])
set i = i + 1
endloop
call .res.destroy()
set .u = null
endmethod
method Reset takes nothing returns nothing
call .destroy()
endmethod
//************************************************************************************
//*****************************System functions (private)*****************************
//************************************************************************************
private static method condition takes nothing returns boolean
return IsUnitInGroup(GetTriggerUnit(), equipunit.equipUnits)
endmethod
private static method onequip takes nothing returns nothing
local unit u = GetTriggerUnit()
local item i = GetManipulatedItem()
local equipitem ei = equipItemTable[GetItemTypeId(i)]
local equipunit eu = equipUnitTable[GetUnitId(u)]
local integer slot = ei.GetSlot()
local Stack unitRes = Stack.create()
local Stack itemReq = Stack.create()
local integer l
local boolean b = true
if ei != 0 and eu.equippedItem[slot] == 0 and eu != 0 then
//Check requirements by looping through them.
set unitRes = eu.res.copy()
set itemReq = ei.GetRequirementList().copy()
loop
set l = itemReq.pop()
exitwhen l == Stack.EMPTY
if not unitRes.contains(l) then
set b = false
endif
endloop
//If unit can equip item.
if b and ei.TryStats(GetHeroLevel(u),GetHeroStr(u, false),GetHeroAgi(u, false),GetHeroInt(u, false)) then
set eu.equippedItem[slot] = ei.GetItemTypeId()
call UnitRemoveAbility(u, emptySlot[slot])
call UnitAddAbility(u, ei.GetSpellbookId())
call RemoveItem(i)
if GetLocalPlayer() == GetOwningPlayer(u) then
call ForceUIKey("I")
endif
call ei.Equip(u, i)
else
call SimError(GetOwningPlayer(u), "You do not meet the requirements for that item.")
endif
elseif ei != 0 and eu != 0 then
call SimError(GetOwningPlayer(u), "You already have an item equipped.")
else
call SimError(GetOwningPlayer(u), "You cannot equip that item.")
endif
call unitRes.destroy()
call itemReq.destroy()
set u = null
set i = null
endmethod
private static method onunequip takes nothing returns nothing
local unit u = GetTriggerUnit()
local item i
local integer a = GetSpellAbilityId()
local equipitem ei = equipItemTable[a]
local equipunit eu = equipUnitTable[GetUnitId(u)]
local integer slot = ei.GetSlot()
if ei != 0 and eu.equippedItem[slot] != 0 then
//Check if inventory is full, if so halt trigger.
if UnitInventoryCount(u) == UnitInventorySize(u) then
call SimError(GetOwningPlayer(u), "Inventory is full")
set u = null
return
endif
set eu.equippedItem[slot] = 0
set i = CreateItem(ei.GetItemTypeId(), 0, 0)
call UnitRemoveAbility(u, ei.GetSpellbookId())
call UnitAddAbility(u, emptySlot[slot])
call UnitAddItem(u, i)
if GetLocalPlayer() == GetOwningPlayer(u) then
call ForceUIKey("I")
endif
call ei.Unequip(u, i)
endif
set u = null
endmethod
private static method onInit takes nothing returns nothing
call TriggerRegisterAnyUnitEventBJ(equipunit.onEquip, EVENT_PLAYER_UNIT_USE_ITEM)
call TriggerAddCondition(equipunit.onEquip, Condition(function equipunit.condition))
call TriggerAddAction(equipunit.onEquip, function equipunit.onequip)
call TriggerRegisterAnyUnitEventBJ(equipunit.onUnequip, EVENT_PLAYER_UNIT_SPELL_CAST)
call TriggerAddCondition(equipunit.onUnequip, Condition(function equipunit.condition))
call TriggerAddAction(equipunit.onUnequip, function equipunit.onunequip)
endmethod
static method create takes unit u returns equipunit
local equipunit new = equipunit.allocate()
local player p = GetOwningPlayer(u)
local Stack s = Stack.create()
local equipitem ei
local integer sbId
local integer i
local integer pi
set new.u = u
call GroupAddUnit(equipunit.equipUnits, u)
call UnitAddAbility(u, MenuId)
set i = 0
loop
exitwhen i > 10
set new.equippedItem[i] = 0
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 10
call UnitAddAbility(u, emptySlot[i])
call SetPlayerAbilityAvailable(p, emptySlot[i], false)
if not hasRun then
set s = itemTypesAtP[i].copy()
loop
exitwhen s.peek()==Stack.EMPTY
set ei = s.peek()
set sbId = ei.GetSpellbookId()
call UnitAddAbility(u, sbId)
call UnitRemoveAbility(u, sbId)
set pi = 0
loop
exitwhen pi > 11
call SetPlayerAbilityAvailable(Player(pi), sbId, false)
set pi = pi + 1
endloop
call s.pop()
endloop
endif
set i = i + 1
endloop
//Add the unit to the table and make sure no more itemtypes are registered.
set equipUnitTable[GetUnitId(u)] = new
set hasInited = true
set hasRun = true
call s.destroy()
return new
endmethod
endstruct
public function InitUnit takes unit u returns equipunit
return equipunit.create(u)
endfunction
public function AddItemType takes integer itemTypeId, integer abilityId, integer spellbookId, integer slot, code eF, code uF returns equipitem
return equipitem.create(itemTypeId, abilityId, spellbookId, slot, eF, uF)
endfunction
function GetSlotId takes string s returns integer
return slotId[StringCase(s, false)]
endfunction
private function Init takes nothing returns nothing
local integer i = 0
set equipItemTable = Table.create()
set equipUnitTable = Table.create()
set requirementTable = Table.create()
set slotId = StringTable.create()
loop
exitwhen i > 10
set itemTypesAtP[i] = Stack.create()
set i = i + 1
endloop
set slotId["shoulders"] = 0
set slotId["head"] = 1
set slotId["neck"] = 2
set slotId["finger"] = 3
set slotId["mainhand"] = 4
set slotId["chest"] = 5
set slotId["offhand"] = 6
set slotId["wrists"] = 7
set slotId["feet"] = 8
set slotId["legs"] = 9
set slotId["hands"] = 10
set emptySlot[0] = 'ES01'
set emptySlot[1] = 'ES02'
set emptySlot[2] = 'ES03'
set emptySlot[3] = 'ES04'
set emptySlot[4] = 'ES05'
set emptySlot[5] = 'ES06'
set emptySlot[6] = 'ES07'
set emptySlot[7] = 'ES08'
set emptySlot[8] = 'ES09'
set emptySlot[9] = 'ES0A'
set emptySlot[10] = 'ES0B'
endfunction
endlibrary
JASS:
library TEEquip initializer Init requires Table, Stack, UnitIndexingUtils, SimError
//***********************************************************************************************************************
//* TEEquip
//*
//* Author: Thunder_Eye
//*
//* Credits:
//* * Vexorian for vJass, JassHelper, and the finding of the spellbook trick
//* * PitzerMike for the ObjectMerger
//* * PipeDream for Grimoire
//* * SFilip for TESH
//* * MindWorX for maintaining NewGen
//*
//* Required Libraries:
//* * Table by Vexorian
//* * Stack by Anitarf
//* * UnitIndexingUtils by Rising Dusk
//* * SimError by Vexorian
//*
//* Optional Libraries:
//* * UnitMaxState by Earth-Fury
//* * BonusMod by Earth-Fury
//*
//* This is an equipment system which is easy to implent, and outputs a smooth
//* userinterface for the endgame user. However, it requires some massive Object
//* Editor use, and if used incorrectly, may clutter up your Ability section.
//* It supports up to 8191 different allocated itemtypes, and the same amount of
//* units utilizing the system.
//*
//* The basic system only works as a template with the addition that it handles
//* item requirements for you.
//*
//* In a future version however, there will be additional modules that can manage
//* changing the basic stats for you.
//*
//* Note that using UnitIndexingUtils will render you unable to use UnitUserData().
//*
//* To initialize a unit, call InitUnit (with the TEEquip prefix)
//* To add an itemtype, call AddItemType (again, with the TEEquip prefix)
//* Note that these are just wrapper functions, I suggest creating the structs
//* directly.
//*
//* Function list:
//* function InitUnit takes unit u returns nothing
//* function AddItemType takes integer iType, integer aId, integer sbId, integer slot, code eF, code uF returns nothing
//* function AddRestriction takes string restriction returns nothing
//* function AddRequirement takes string requirement returns nothing
//* function SetRequiredLevel takes integer value returns nothing
//* function SetRequiredStr takes integer value returns nothing
//* function SetRequiredAgi takes integer value returns nothing
//* function SetRequiredInt takes integer value returns nothing
//* function AddFunction takes code eF, code uF returns nothing
//* function GetSlotId takes string s returns integer
//*
//* Initialize a unit and give it an equipment menu.
//* This is just a wrapper function, I suggest creating the struct directly instead.
//* function InitUnit takes unit u returns nothing
//* unit u: The unit to initialize
//*
//* Add an itemtype to the system, making it equippable
//* This is just a wrapper function, I suggest creating the struct directly instead.
//* function AddItemType takes integer iType, integer aId, integer sbId, integer slot, code eF, code uF returns nothing
//* integer iType: The rawid of the itemtype.
//* integer aId: The rawid of the UI ability.
//* integer sbId: The rawid of the spellbook holding ability aId.
//* integer slot: The slot where the item is placed when equipped.
//* Can be anything between 0-10.
//* code eF: The function which runs when the item is equipped.
//* By passing null no function will run on equip.
//* code uF: The function which runs when the item is unequipped.
//* By passing null no function will run on unequip.
//*
//* Add a restriction to a unit, enabling it to use items with the proper requirement.
//* Note that units with no restrictions may only equip items with no requirements.
//* Member of: equipunit
//* function AddRestriction takes string restriction returns nothing
//* string restriction: The key of the restrictiontype, upper- or lowercase does not matter.
//*
//* Add a requirement to an item, requiring units to have the proper restrictions to use it.
//* Note that items with no requirements may be equipped by any initialized unit.
//* Units must match ALL requirements to equip item.
//* Member of: equipitem
//* function AddRequirement takes string requirement returns nothing
//* string requirement: The key of the requirementtype, upper- or lowercase does not matter.
//*
//* Temporary function to set a required level on itemtypes.
//* Member of: equipitem
//* function SetRequiredLevel takes integer value returns nothing
//* integer value: The required level.
//*
//* Temporary function to set a required strength on itemtypes.
//* Member of: equipitem
//* function SetRequiredStr takes integer value returns nothing
//* integer value: The required strength.
//*
//* Temporary function to set a required agility on itemtypes.
//* Member of: equipitem
//* function SetRequiredAgi takes integer value returns nothing
//* integer value: The required agility.
//*
//* Temporary function to set a required intelligence on itemtypes.
//* Member of: equipitem
//* function SetRequiredInt takes integer value returns nothing
//* integer value: The required intelligence.
//*
//* Adds an additional function (including the one when you add an itemtype) to an itemtype.
//* Member of: equipitem
//* function AddFunction takes code eF, code uF returns nothing
//* code eF: The function which runs when the item is equipped.
//* code uF: The function which runs when the item is unequipped.
//*
//* Gets the id of a slot.
//* Can be used if you want to clarify the slot when using AddItemType.
//* function GetSlotId takes string slot returns integer
//* string slot: The slot you want the id from.
//* "shoulder" = 0, "head" = 1, "neck" = 2, "finger" = 3,
//* "mainhand" = 4, "chest" = 5, "offhand" = 6, "wrists" = 7
//* "feet" = 8, "legs" = 9, "hands" = 10
//*
//***********************************************************************************************************************
globals
//equipItemTable = key is itemtype-id, value is struct-id
//equipUnitTable = key is id of unit, value is struct-id
private Table equipItemTable
private Table equipUnitTable
//requirementTable = key is the name of the requirement, value is the id (requirementTable["plate"] = 1)
//requirementKey = key is the id of the requirement, value is the name (requirementKey[1] = "plate")
//requirementTotal = Amount of requirements and key for new requirements (requirementTotal = 2)
private StringTable requirementTable
private string array requirementKey
private integer requirementTotal = 0
//itemTypesAtP[11] = Stack pointing to struct-ids
//emptySlot[11] = Array with the "unequipped" spellbooks
private Stack array itemTypesAtP[11]
private integer array emptySlot[11]
//slotId = key is the name of the slot, value is the id
//hasInited = set to true when a unit is initialized
private StringTable slotId
private boolean hasInited = false
//passUnit = triggering unit passed for equip/unequip functions
//passItem = manipulated item passed for equip/unequip functions
public unit passUnit
public item passItem
endglobals
struct equipitem
private integer itemTypeId
private integer abilityId
private integer spellbookId
private integer slot
private Stack requirements = Stack.create()
private trigger equipTrigger = CreateTrigger()
private trigger unequipTrigger = CreateTrigger()
//Temporary until I add some kind of table to handle this.
private integer statReq
private integer levelReq = 0
private integer strReq = 0
private integer agiReq = 0
private integer intReq = 0
//************************************************************************************
//******************************Call functions (public)*******************************
//************************************************************************************
public method AddRequirement takes string requirement returns nothing
local integer i
set requirement = StringCase(requirement, false)
//Check so that it doesn't create duplicate keys of requirements.
if not .requirements.contains(requirementTable[requirement]) then
if requirementTable.exists(requirement) then
//Item requirement type already exists.
set i = requirementTable[requirement]
else
//Item requirement type does not exist, so add it to the table.
set requirementTotal = requirementTotal + 1
set i = requirementTotal
set requirementTable[requirement] = i
set requirementKey[i] = requirement
endif
//Add the key for the requirement type to the itemtype
call .requirements.push(i)
endif
endmethod
public method SetRequiredLevel takes integer value returns nothing
set .levelReq = value
endmethod
public method SetRequiredStr takes integer value returns nothing
set .strReq = value
endmethod
public method SetRequiredAgi takes integer value returns nothing
set .agiReq = value
endmethod
public method SetRequiredInt takes integer value returns nothing
set .intReq = value
endmethod
public method AddFunction takes code eF, code uF returns nothing
call .AddEquipFunc(eF)
call .AddUnequipFunc(uF)
endmethod
public method GetItemTypeId takes nothing returns integer
return .itemTypeId
endmethod
public method GetAbilityId takes nothing returns integer
return .abilityId
endmethod
public method GetSpellbookId takes nothing returns integer
return .spellbookId
endmethod
public method GetRequirementList takes nothing returns Stack
return .requirements
endmethod
public method GetSlot takes nothing returns integer
return .slot
endmethod
//************************************************************************************
//*****************************System functions (private)*****************************
//************************************************************************************
public method TryStats takes integer level, integer str, integer agi, integer int returns boolean
if level >= .levelReq and str >= .strReq and agi >= .agiReq and int >= .intReq then
return true
endif
return false
endmethod
private method AddEquipFunc takes code f returns nothing
if f != null then
call TriggerAddAction(.equipTrigger, f)
endif
endmethod
private method AddUnequipFunc takes code f returns nothing
if f != null then
call TriggerAddAction(.unequipTrigger, f)
endif
endmethod
public method Equip takes unit u, item i returns nothing
set passUnit = u
set passItem = i
call TriggerExecute(.equipTrigger)
endmethod
public method Unequip takes unit u, item i returns nothing
set passUnit = u
set passItem = i
call TriggerExecute(.unequipTrigger)
endmethod
static method create takes integer itemTypeId, integer abilityId, integer spellbookId, integer slot, code eF, code uF returns equipitem
local equipitem new
//If no unit has been registered, create the itemtype.
if not hasInited then
set new = equipitem.allocate()
set new.itemTypeId = itemTypeId
set new.abilityId = abilityId
set new.spellbookId = spellbookId
set new.slot = slot
call new.AddEquipFunc(eF)
call new.AddUnequipFunc(uF)
call itemTypesAtP[slot].push(new)
endif
set equipItemTable[itemTypeId] = new
set equipItemTable[abilityId] = new
return new
endmethod
endstruct
struct equipunit
private unit u
integer array equippedItem[11]
Stack res = Stack.create()
static group equipUnits = CreateGroup()
static trigger onEquip = CreateTrigger()
static trigger onUnequip = CreateTrigger()
//************************************************************************************
//******************************Call functions (public)*******************************
//************************************************************************************
method AddRestriction takes string restriction returns nothing
local integer i
set restriction = StringCase(restriction, false)
if requirementTable.exists(restriction) then
//Item requirement type already exists.
set i = requirementTable[restriction]
else
//Item requirement type does not exist, so add it to the table.
set requirementTotal = requirementTotal + 1
set i = requirementTotal
set requirementTable[restriction] = i
set requirementKey[i] = restriction
endif
//Add the key for the requirement type to the unit
call .res.push(i)
endmethod
method onDestroy takes nothing returns nothing
local integer i = 0
call UnitRemoveAbility(.u, 'A000')
loop
exitwhen i > 10
call UnitAddAbility(.u, emptySlot[i])
set i = i + 1
endloop
call .res.destroy()
set .u = null
endmethod
method Reset takes nothing returns nothing
call .destroy()
endmethod
//************************************************************************************
//*****************************System functions (private)*****************************
//************************************************************************************
private static method condition takes nothing returns boolean
return IsUnitInGroup(GetTriggerUnit(), equipunit.equipUnits)
endmethod
private static method onequip takes nothing returns nothing
local unit u = GetTriggerUnit()
local item i = GetManipulatedItem()
local equipitem ei = equipItemTable[GetItemTypeId(i)]
local equipunit eu = equipUnitTable[GetUnitId(u)]
local integer slot = ei.GetSlot()
local Stack unitRes = Stack.create()
local Stack itemReq = Stack.create()
local integer l
local boolean b = true
if ei != 0 and eu.equippedItem[slot] == 0 and eu != 0 then
//Check requirements by looping through them.
set unitRes = eu.res.copy()
set itemReq = ei.GetRequirementList().copy()
loop
set l = itemReq.pop()
exitwhen l == Stack.EMPTY
if not unitRes.contains(l) then
set b = false
endif
endloop
//If unit can equip item.
if b and ei.TryStats(GetHeroLevel(u),GetHeroStr(u, false),GetHeroAgi(u, false),GetHeroInt(u, false)) then
set eu.equippedItem[slot] = ei.GetItemTypeId()
call UnitRemoveAbility(u, emptySlot[slot])
call UnitAddAbility(u, ei.GetSpellbookId())
call RemoveItem(i)
if GetLocalPlayer() == GetOwningPlayer(u) then
call ForceUIKey("I")
endif
call ei.Equip(u, i)
else
call SimError(GetOwningPlayer(u), "You do not meet the requirements for that item.")
endif
elseif ei != 0 and eu != 0 then
call SimError(GetOwningPlayer(u), "You already have an item equipped.")
else
call SimError(GetOwningPlayer(u), "You cannot equip that item.")
endif
call unitRes.destroy()
call itemReq.destroy()
set u = null
set i = null
endmethod
private static method onunequip takes nothing returns nothing
local unit u = GetTriggerUnit()
local item i
local integer a = GetSpellAbilityId()
local equipitem ei = equipItemTable[a]
local equipunit eu = equipUnitTable[GetUnitId(u)]
local integer slot = ei.GetSlot()
if ei != 0 and eu.equippedItem[slot] != 0 then
//Check if inventory is full, if so halt trigger.
if UnitInventoryCount(u) == UnitInventorySize(u) then
call SimError(GetOwningPlayer(u), "Inventory is full")
set u = null
return
endif
set eu.equippedItem[slot] = 0
set i = CreateItem(ei.GetItemTypeId(), 0, 0)
call UnitRemoveAbility(u, ei.GetSpellbookId())
call UnitAddAbility(u, emptySlot[slot])
call UnitAddItem(u, i)
if GetLocalPlayer() == GetOwningPlayer(u) then
call ForceUIKey("I")
endif
call ei.Unequip(u, i)
endif
set u = null
endmethod
private static method onInit takes nothing returns nothing
call TriggerRegisterAnyUnitEventBJ(equipunit.onEquip, EVENT_PLAYER_UNIT_USE_ITEM)
call TriggerAddCondition(equipunit.onEquip, Condition(function equipunit.condition))
call TriggerAddAction(equipunit.onEquip, function equipunit.onequip)
call TriggerRegisterAnyUnitEventBJ(equipunit.onUnequip, EVENT_PLAYER_UNIT_SPELL_CAST)
call TriggerAddCondition(equipunit.onUnequip, Condition(function equipunit.condition))
call TriggerAddAction(equipunit.onUnequip, function equipunit.onunequip)
endmethod
static method create takes unit u returns equipunit
local equipunit new = equipunit.allocate()
local player p = GetOwningPlayer(u)
local Stack s = Stack.create()
local equipitem ei
local integer sbId
local integer i
set new.u = u
call GroupAddUnit(equipunit.equipUnits, u)
call UnitAddAbility(u, 'A000')
set i = 0
loop
exitwhen i > 10
set new.equippedItem[i] = 0
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 10
call UnitAddAbility(u, emptySlot[i])
call SetPlayerAbilityAvailable(p, emptySlot[i], false)
set s = itemTypesAtP[i].copy()
loop
exitwhen s.peek()==Stack.EMPTY
set ei = s.peek()
set sbId = ei.GetSpellbookId()
call UnitAddAbility(u, sbId)
call UnitRemoveAbility(u, sbId)
call SetPlayerAbilityAvailable(p, sbId, false)
call s.pop()
endloop
set i = i + 1
endloop
//Add the unit to the table and make sure no more itemtypes are registered.
set equipUnitTable[GetUnitId(u)] = new
set hasInited = true
call s.destroy()
return new
endmethod
endstruct
public function InitUnit takes unit u returns equipunit
return equipunit.create(u)
endfunction
public function AddItemType takes integer itemTypeId, integer abilityId, integer spellbookId, integer slot, code eF, code uF returns equipitem
return equipitem.create(itemTypeId, abilityId, spellbookId, slot, eF, uF)
endfunction
function GetSlotId takes string s returns integer
return slotId[StringCase(s, false)]
endfunction
private function Init takes nothing returns nothing
local integer i = 0
set equipItemTable = Table.create()
set equipUnitTable = Table.create()
set requirementTable = Table.create()
set slotId = StringTable.create()
loop
exitwhen i > 10
set itemTypesAtP[i] = Stack.create()
set i = i + 1
endloop
set slotId["shoulders"] = 0
set slotId["head"] = 1
set slotId["neck"] = 2
set slotId["finger"] = 3
set slotId["mainhand"] = 4
set slotId["chest"] = 5
set slotId["offhand"] = 6
set slotId["wrists"] = 7
set slotId["feet"] = 8
set slotId["legs"] = 9
set slotId["hands"] = 10
set emptySlot[0] = 'ES01'
set emptySlot[1] = 'ES02'
set emptySlot[2] = 'ES03'
set emptySlot[3] = 'ES04'
set emptySlot[4] = 'ES05'
set emptySlot[5] = 'ES06'
set emptySlot[6] = 'ES07'
set emptySlot[7] = 'ES08'
set emptySlot[8] = 'ES09'
set emptySlot[9] = 'ES0A'
set emptySlot[10] = 'ES0B'
endfunction
endlibrary
JASS:
library TEEquip initializer Init requires Table, Stack, UnitIndexingUtils, SimError
//***********************************************************************************************************************
//* TEEquip
//*
//* Author: Thunder_Eye
//*
//* Credits:
//* * Vexorian for vJass, JassHelper, and the finding of the spellbook trick
//* * PitzerMike for the ObjectMerger
//* * PipeDream for Grimoire
//* * SFilip for TESH
//* * MindWorX for maintaining NewGen
//* * Earth-Fury for UnitMaxState and BonusMod
//*
//* Required Libraries:
//* * Table by Vexorian
//* * Stack by Anitarf
//* * UnitIndexingUtils by Rising Dusk
//* * SimError by Vexorian
//*
//* This is an equipment system which is easy to implent, and outputs a smooth
//* userinterface for the endgame user. However, it requires some massive Object
//* Editor use, and if used incorrectly, may clutter up your Ability section.
//* It supports up to 8191 different allocated itemtypes, and the same amount of
//* units utilizing the system.
//*
//* The basic system only works as a template with the addition that it handles
//* item requirements for you.
//*
//* In a future version however, there will be additional modules that can manage
//* changing the basic stats for you.
//*
//* Note that using UnitIndexingUtils will make you unable to use UnitUserData().
//*
//* To initialize a unit, call InitUnit (with the TEEquip prefix)
//* To add an itemtype, call AddItemType (again, with the TEEquip prefix)
//*
//* Function list:
//* function InitUnit takes unit u returns nothing
//* function AddItemType takes integer iType, integer aId, integer sbId, integer slot, code eF, code uF returns nothing
//* function UnitAddRestriction takes unit u, string restriction returns nothing
//* function ItemTypeAddRequirement takes integer iType, string requirement returns nothing
//* function SetItemTypeLevel takes integer iType, integer level returns nothing
//* function ItemTypeAddFunction takes integer iType, code eF, code uF returns nothing
//* function GetSlotId takes string s returns integer
//*
//* Initialize a unit and give it an equipment menu.
//* function InitUnit takes unit u returns nothing
//* unit u: The unit to initialize
//*
//* Add an itemtype to the system, making it equippable
//* function AddItemType takes integer iType, integer aId, integer sbId, integer slot, code eF, code uF returns nothing
//* integer iType: The rawid of the itemtype.
//* integer aId: The rawid of the UI ability.
//* integer sbId: The rawid of the spellbook holding ability aId.
//* integer slot: The slot where the item is placed when equipped.
//* Can be anything between 0-10.
//* code eF: The function which runs when the item is equipped.
//* code uF: The function which runs when the item is unequipped.
//*
//* Add a restriction to a unit, enabling it to use items with the proper requirement.
//* Note that units with no restrictions may only equip items with no requirements.
//* function UnitAddRestriction takes unit u, string restriction returns nothing
//* unit u: The unit to add a restriction to.
//* string restriction: The key of the restrictiontype, upper- or lowercase does not matter.
//*
//* Add a requirement to an item, requiring units to have the proper restrictions to use it.
//* Note that items with no requirements may be equipped by any initialized unit.
//* Units must match ALL requirements to equip item.
//* function ItemTypeAddRequirement takes integer iType, string requirement returns nothing
//* integer iType: The rawid of the itemtype.
//* string requirement: The key of the requirementtype, upper- or lowercase does not matter.
//*
//* Temporary function to set a required level on itemtypes.
//* function SetItemTypeLevel takes integer iType, integer level returns nothing
//* integer iType: The rawid of the itemtype.
//* integer level: The required level.
//*
//* Adds an additional function (including the one when you add an itemtype) to an itemtype.
//* function ItemTypeAddFunction takes integer iType, code eF, code uF returns nothing
//* integer iType: The rawid of the itemtype.
//* code eF: The function which runs when the item is equipped.
//* code uF: The function which runs when the item is unequipped.
//*
//* Gets the id of a slot.
//* Can be used if you want to clarify the slot when using AddItemType.
//* function GetSlotId takes string slot returns integer
//* string slot: The slot you want the id from.
//* "shoulder" = 0, "head" = 1, "neck" = 2, "finger" = 3,
//* "mainhand" = 4, "chest" = 5, "offhand" = 6, "wrists" = 7
//* "feet" = 8, "legs" = 9, "hands" = 10
//*
//***********************************************************************************************************************
globals
private Table itemTypeTable
private Table unitTable
private Stack array itemTypesAtP[11]
private integer array emptySlot[11]
private StringTable requirementTable
private string array requirementKey
private integer requirementCount = 0
private StringTable slotId
private boolean hasInited = false
public unit passUnit
public item passItem
endglobals
private struct itemType
private integer iType
private integer aId
private integer sbId
private integer slot
private Stack req = Stack.create()
private trigger eT = CreateTrigger()
private trigger uT = CreateTrigger()
//Temporary until I add some kind of table to handle this.
public integer levelReq = 0
public method AddEquipFunc takes code f returns nothing
if f != null then
call TriggerAddAction(.eT, f)
endif
endmethod
public method AddUnequipFunc takes code f returns nothing
if f != null then
call TriggerAddAction(.uT, f)
endif
endmethod
public method Equip takes unit u, item i returns nothing
set passUnit = u
set passItem = i
call TriggerExecute(.eT)
endmethod
public method Unequip takes unit u, item i returns nothing
set passUnit = u
set passItem = i
call TriggerExecute(.uT)
endmethod
public method GetItemTypeId takes nothing returns integer
return .iType
endmethod
public method GetSlot takes nothing returns integer
return .slot
endmethod
public method GetSpellbookId takes nothing returns integer
return .sbId
endmethod
public method GetAbilityId takes nothing returns integer
return .aId
endmethod
public method GetRequirementList takes nothing returns Stack
return .req
endmethod
static method create takes integer iType, integer aId, integer sbId, integer slot returns itemType
local itemType new = itemType.allocate()
set new.iType = iType
set new.aId = aId
set new.sbId = sbId
set new.slot = slot
set itemTypeTable[iType] = new
set itemTypeTable[aId] = new
return new
endmethod
endstruct
private struct equipunit
private unit u
integer array equippedItem[11]
Stack res = Stack.create()
static group equipUnits = CreateGroup()
static trigger onEquip = CreateTrigger()
static trigger onUnequip = CreateTrigger()
private static method condition takes nothing returns boolean
return IsUnitInGroup(GetTriggerUnit(), equipunit.equipUnits)
endmethod
private static method onequip takes nothing returns nothing
local unit u = GetTriggerUnit()
local item i = GetManipulatedItem()
local itemType iT = itemTypeTable[GetItemTypeId(i)]
local equipunit eu = unitTable[GetUnitId(u)]
local integer slot = iT.GetSlot()
local Stack unitRes = Stack.create()
local Stack itemReq = Stack.create()
local integer l
local boolean b = true
if iT != 0 and eu.equippedItem[slot] == 0 and eu != 0 then
//Check requirements by looping through them.
set unitRes = eu.res.copy()
set itemReq = iT.GetRequirementList().copy()
loop
set l = itemReq.pop()
exitwhen l == Stack.EMPTY
if not unitRes.contains(l) then
set b = false
endif
endloop
//If unit can equip item.
if b and iT.levelReq <= GetHeroLevel(u) then
set eu.equippedItem[slot] = iT.GetItemTypeId()
call UnitRemoveAbility(u, emptySlot[slot])
call UnitAddAbility(u, iT.GetSpellbookId())
call RemoveItem(i)
if GetLocalPlayer() == GetOwningPlayer(u) then
call ForceUIKey("I")
endif
call iT.Equip(u, i)
else
call SimError(GetOwningPlayer(u), "You do not meet the requirements for that item.")
endif
elseif iT != 0 and eu != 0 then
call SimError(GetOwningPlayer(u), "You already have an item equipped.")
else
call SimError(GetOwningPlayer(u), "You cannot equip that item.")
endif
call unitRes.destroy()
call itemReq.destroy()
set u = null
set i = null
endmethod
private static method onunequip takes nothing returns nothing
local unit u = GetTriggerUnit()
local item i
local integer a = GetSpellAbilityId()
local itemType iT = itemTypeTable[a]
local equipunit eu = unitTable[GetUnitId(u)]
local integer slot = iT.GetSlot()
if iT != 0 and eu.equippedItem[slot] != 0 then
//Check if inventory is full, if so halt trigger.
if UnitInventoryCount(u) == UnitInventorySize(u) then
call SimError(GetOwningPlayer(u), "Inventory is full")
set u = null
return
endif
set eu.equippedItem[slot] = 0
set i = CreateItem(iT.GetItemTypeId(), 0, 0)
call UnitRemoveAbility(u, iT.GetSpellbookId())
call UnitAddAbility(u, emptySlot[slot])
call UnitAddItem(u, i)
if GetLocalPlayer() == GetOwningPlayer(u) then
call ForceUIKey("I")
endif
call iT.Unequip(u, i)
endif
set u = null
endmethod
method onDestroy takes nothing returns nothing
call .res.destroy()
set .u = null
endmethod
static method create takes unit u returns equipunit
local equipunit new = equipunit.allocate()
local integer i = 0
set new.u = u
call GroupAddUnit(equipunit.equipUnits, u)
loop
exitwhen i > 10
set new.equippedItem[i] = 0
set i = i + 1
endloop
return new
endmethod
static method onInit takes nothing returns nothing
call TriggerRegisterAnyUnitEventBJ(equipunit.onEquip, EVENT_PLAYER_UNIT_USE_ITEM)
call TriggerAddCondition(equipunit.onEquip, Condition(function equipunit.condition))
call TriggerAddAction(equipunit.onEquip, function equipunit.onequip)
call TriggerRegisterAnyUnitEventBJ(equipunit.onUnequip, EVENT_PLAYER_UNIT_SPELL_CAST)
call TriggerAddCondition(equipunit.onUnequip, Condition(function equipunit.condition))
call TriggerAddAction(equipunit.onUnequip, function equipunit.onunequip)
endmethod
endstruct
public function InitUnit takes unit u returns nothing
local player p = GetOwningPlayer(u)
local integer i = 0
local itemType iT
local Stack s = Stack.create()
local equipunit eu = equipunit.create(u)
local integer sbId
//Equipment spellbook ability
call UnitAddAbility(u, 'A000')
set i = 0
loop
exitwhen i > 10
call UnitAddAbility(u, emptySlot[i])
call SetPlayerAbilityAvailable(p, emptySlot[i], false)
set s = itemTypesAtP[i].copy()
loop
exitwhen s.peek()==Stack.EMPTY
set iT = s.peek()
set sbId = iT.GetSpellbookId()
call UnitAddAbility(u, sbId)
call UnitRemoveAbility(u, sbId)
call SetPlayerAbilityAvailable(p, sbId, false)
call s.pop()
endloop
set i = i + 1
endloop
//Add the unit to the table and make sure no more itemtypes are registered.
set unitTable[GetUnitId(u)] = eu
set hasInited = true
call s.destroy()
endfunction
public function AddItemType takes integer iType, integer aId, integer sbId, integer slot, code eF, code uF returns nothing
local itemType i
//If no unit has been registered, create the itemtype.
if not hasInited then
set i = itemType.create(iType, aId, sbId, slot)
call i.AddEquipFunc(eF)
call i.AddUnequipFunc(uF)
call itemTypesAtP[slot].push(i)
endif
endfunction
public function ResetUnit takes unit u returns nothing
local equipunit eu = unitTable[GetUnitId(u)]
local integer i = 0
call UnitRemoveAbility(u, 'A000')
loop
exitwhen i > 10
call UnitAddAbility(u, emptySlot[i])
set i = i + 1
endloop
call eu.destroy()
endfunction
public function UnitAddRestriction takes unit u, string restriction returns nothing
local equipunit eu = unitTable[GetUnitId(u)]
local integer count
set restriction = StringCase(restriction, false)
if requirementTable.exists(restriction) then
//Item requirement type already exists.
set count = requirementTable[restriction]
else
//Item requirement type does not exist, so add it to the table.
set requirementCount = requirementCount + 1
set count = requirementCount
set requirementTable[restriction] = count
set requirementKey[count] = restriction
endif
//Add the key for the requirement type to the unit
call eu.res.push(count)
endfunction
public function ItemTypeAddRequirement takes integer iType, string requirement returns nothing
local itemType i = itemTypeTable[iType]
local integer count
set requirement = StringCase(requirement, false)
if requirementTable.exists(requirement) then
//Item requirement type already exists.
set count = requirementTable[requirement]
else
//Item requirement type does not exist, so add it to the table.
set requirementCount = requirementCount + 1
set count = requirementCount
set requirementTable[requirement] = count
set requirementKey[count] = requirement
endif
//Add the key for the requirement type to the itemtype
call i.GetRequirementList().push(count)
endfunction
public function ItemTypeAddStatRequirement takes integer iType, string requirement, integer level returns nothing
local itemType i = itemTypeTable[iType]
local integer count
set requirement = StringCase(requirement, false)
if requirementTable.exists(requirement) then
//Item requirement type already exists.
set count = requirementTable[requirement]
else
//Item requirement type does not exist, so add it to the table.
set requirementCount = requirementCount + 1
set count = requirementCount
set requirementTable[requirement] = count
set requirementKey[count] = requirement
endif
//Add the key for the requirement type to the itemtype
call i.GetRequirementList().push(count)
endfunction
public function SetItemTypeLevel takes integer iType, integer level returns nothing
local itemType i = itemTypeTable[iType]
set i.levelReq = level
endfunction
public function ItemTypeAddFunction takes integer iType, code eF, code uF returns nothing
local itemType i = itemTypeTable[iType]
call i.AddEquipFunc(eF)
call i.AddUnequipFunc(uF)
endfunction
public function GetSlotId takes string s returns integer
return slotId[StringCase(s, false)]
endfunction
private function Init takes nothing returns nothing
local integer i = 0
set itemTypeTable = Table.create()
set unitTable = Table.create()
set requirementTable = Table.create()
set slotId = StringTable.create()
loop
exitwhen i > 10
set itemTypesAtP[i] = Stack.create()
set i = i + 1
endloop
set slotId["shoulders"] = 0
set slotId["head"] = 1
set slotId["neck"] = 2
set slotId["finger"] = 3
set slotId["mainhand"] = 4
set slotId["chest"] = 5
set slotId["offhand"] = 6
set slotId["wrists"] = 7
set slotId["feet"] = 8
set slotId["legs"] = 9
set slotId["hands"] = 10
set emptySlot[0] = 'ES01'
set emptySlot[1] = 'ES02'
set emptySlot[2] = 'ES03'
set emptySlot[3] = 'ES04'
set emptySlot[4] = 'ES05'
set emptySlot[5] = 'ES06'
set emptySlot[6] = 'ES07'
set emptySlot[7] = 'ES08'
set emptySlot[8] = 'ES09'
set emptySlot[9] = 'ES0A'
set emptySlot[10] = 'ES0B'
endfunction
endlibrary
Attachments
Last edited: