• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Learning Jass Need Help ^^

Status
Not open for further replies.

ABM

ABM

Level 7
Joined
Jul 13, 2005
Messages
279
Hi everyone
I am using The_Witcher equipment system, but my jass knowledge is too low to understand how it works, so i would like to request some help from the pro VJass user from this forum to explain with //text tag what each structure and function does, so i can graps the concept of this system, and how to adapt it to my needs, and to learn from it to code VJass....

This is not the whole system but the part wich actually do most of the things, the other parts are a setup for items to input data, and a LinkedList and a RegisterPlayerUnitEvent.

Equipment System:
[Jass=System]
library AdvancedEquipmentSystem requires LinkedListModule, RegisterPlayerUnitEvent

// The_Witcher's Equipment System
//
// Requirements:
// JASS knowledge
// LinkedList (http://www.hiveworkshop.com/forums/jass-resources-412/snippet-linkedlistmodule-206552/)
// RegisterPlayerUnitEvent (http://www.hiveworkshop.com/forums/jass-resources-412/snippet-registerplayerunitevent-203338/)
//
// have fun^^

//**************************************************
//********************SETUP PART********************
//**************************************************

globals
// this is the rawcode of the unit which works as inventory
public constant integer INVENTORY_DUMMY = 'h007'

// this is the class you selected as mainhand class
public constant integer MAINHAND_CLASS = 0

// this is the class you selected as offhand class
public constant integer OFFHAND_CLASS = 1

// this is the amount of total classes you have
public constant integer CLASSES = 9

// this is the ability to close the inventory
public constant integer EXIT_ABILITY = 'A00G'

// this is the ability to open the inventory
public constant integer OPEN_ABILITY = 'A003'

// this is the ability which gives the dummy the same inventory as your hero has
public constant integer INVENTORY_ABILITY = 'AInv'

// this is the icon ability shown in the offhand slot when a twhoanded weapon is equipeed
public constant integer TWOHAND_ABILITY = 'A00Z'
public constant boolean SHOW_TWOHAND_ABILITY = true

// this is the text shown when a unit is trying to equip an item which it isnt allowed to
// example: " can't equip " becomes ingame something like Soldier can't equip Giant Sword
public constant string UNABLE_TO_EQUIP_STRING = " can't equip "
endglobals

//************************************************************
//********************SETUP PART ENDS HERE********************
//************************************************************
//*****************Don't edit anything below******************
//************************************************************

globals
private trigger OnEquip
private trigger OnUnequip
private integer TriggeringItem
private unit EquippingUnit
private hashtable table
endglobals

private struct AbilityList extends array
integer abi
implement LinkedList

static method create takes nothing returns thistype
return .createNode()
endmethod

method remove takes nothing returns nothing
call .removeNode()
call .deallocate()
endmethod

method add takes integer abi returns nothing
local thistype new = .allocate()
set new.abi = abi
call .insertNode(new)
endmethod
endstruct


// **** struct EquipmentItem ****
private struct EquipmentItem extends array
readonly integer id
readonly integer class
readonly AbilityList abilities
readonly integer icon
readonly boolean twohanded
readonly string tag

static method operator [] takes integer itemid returns EquipmentItem
return itemid - 'I000' + CLASSES + 1
endmethod

static method create takes integer id, integer icon, integer class, boolean twohanded, string animation returns EquipmentItem
local EquipmentItem this = id - 'I000' + CLASSES + 1
if id - 'I000' >= 0 then
call SaveBoolean(table, id - 'I000', 0, true)
endif
set .id = id
set .class = class
set .icon = icon
if id >= CLASSES + 1 then
set .abilities = AbilityList.create()
if class == MAINHAND_CLASS then
set .twohanded = twohanded
else
set .twohanded = false
endif
if (class == MAINHAND_CLASS or class == OFFHAND_CLASS) and id != 0 then
set .tag = animation
else
set .tag = ""
endif
endif
return this
endmethod

method addAbility takes integer abi returns nothing
call .abilities.add( abi)
endmethod

method applyAbilities takes unit u, boolean add returns nothing
local AbilityList node = .abilities.next
loop
exitwhen node.head
if add then
call UnitAddAbility(u, node.abi)
else
call UnitRemoveAbility(u, node.abi)
endif
set node = node.next
endloop
endmethod
endstruct

public function RegisterNewClass takes integer emptyicon, integer class returns nothing
call EquipmentItem.create('I000' - CLASSES - 1 + class, emptyicon, class, false, "")
endfunction

// **** struct Equipment ****
struct Equipment
private static EquipmentItem twohandIcon

private unit u
private unit dummy
readonly string animtag = ""
readonly EquipmentItem array Item [12]

static method operator [] takes unit u returns Equipment
return LoadInteger(table, GetHandleId(u), 0)
endmethod

method operator owner takes nothing returns unit
return .u
endmethod

method operator owner= takes unit new returns nothing
local integer i = 0
loop
exitwhen i >= CLASSES
if .Item != 0 then
call .Item.applyAbilities(.u, false)
call .Item.applyAbilities(new, true)
endif
set i = i + 1
endloop
call AddUnitAnimationProperties(.u, .animtag, false)
call UnitRemoveAbility(.u, OPEN_ABILITY)
call AddUnitAnimationProperties(new, .animtag, true)
call UnitAddAbility(new, OPEN_ABILITY)
set .u = new
call SaveInteger(table, GetHandleId(.u), 0, this)
call SaveInteger(table, GetHandleId(.dummy), 0, this)
endmethod

method syncInventories takes nothing returns nothing
local integer i = 0
loop
exitwhen i >= 6
call RemoveItem(UnitItemInSlot(.dummy, i))
call UnitAddItemToSlotById(.dummy, GetItemTypeId(UnitItemInSlot(.u, i)), i)
call SetItemDroppable(UnitItemInSlot(.dummy, i), false)
set i = i + 1
endloop
endmethod

private method refreshAnimation takes nothing returns nothing
local string a = .Item[MAINHAND_CLASS].tag
if .Item[OFFHAND_CLASS] != 0 and .Item[OFFHAND_CLASS] != twohandIcon then
set a = .Item[OFFHAND_CLASS].tag
endif
call AddUnitAnimationProperties(.u, .animtag, false)
call AddUnitAnimationProperties(.u, a, true)
set .animtag = a
endmethod

method equipEmptyClass takes integer class returns nothing
call UnitAddAbility(.dummy, EquipmentItem(class).icon)
set .Item[class] = 0
endmethod

method equipTwohandIcon takes nothing returns nothing
call UnitAddAbility(.dummy, twohandIcon.icon)
set .Item[OFFHAND_CLASS] = twohandIcon
endmethod

method unequip takes integer class returns nothing
local integer i = 0
local EquipmentItem toRemove = .Item[class]
if toRemove != 0 then
if toRemove.twohanded then
call UnitRemoveAbility(.dummy, TWOHAND_ABILITY)
call .equipEmptyClass(OFFHAND_CLASS)
endif
call toRemove.applyAbilities(.u, false)
call UnitAddItemById(.u, toRemove.id)
set TriggeringItem = toRemove.id
set EquippingUnit = .u
call TriggerEvaluate(OnUnequip)
call UnitRemoveAbility(.dummy, toRemove.icon)
else
call UnitRemoveAbility(.dummy, EquipmentItem(class).icon)
endif
set .Item[class] = 0
call .refreshAnimation()
endmethod

method equip takes integer id returns nothing
local EquipmentItem toEquip = EquipmentItem[id]
local EquipmentItem mainEquip = .Item[MAINHAND_CLASS]
// remove existing
if mainEquip != 0 then
if toEquip.twohanded or (mainEquip.twohanded and (toEquip.class == OFFHAND_CLASS or toEquip.class == MAINHAND_CLASS)) then
call .unequip(MAINHAND_CLASS)
call .unequip(OFFHAND_CLASS)
if toEquip.class == MAINHAND_CLASS and not toEquip.twohanded then
call .equipEmptyClass(OFFHAND_CLASS)
elseif toEquip.class == OFFHAND_CLASS then
call .equipEmptyClass(MAINHAND_CLASS)
endif
endif
endif
call .unequip(toEquip.class)
// new is twohanded ?
if toEquip.twohanded then
call .unequip(OFFHAND_CLASS)
call .equipTwohandIcon()
if not SHOW_TWOHAND_ABILITY then
call UnitRemoveAbility(.dummy, twohandIcon.icon)
endif
endif
// equip new
call toEquip.applyAbilities(.u, true)
call UnitAddAbility(.dummy, toEquip.icon)
set .Item[toEquip.class] = toEquip
call .refreshAnimation()
// fire trigger
set EquippingUnit = .u
set TriggeringItem = id
call TriggerEvaluate(OnEquip)
endmethod

static method disable takes integer itemId, integer unitType, boolean flag returns nothing
call SaveBoolean(table, itemId - 'I000', unitType, flag)
endmethod

private method onDestroy takes nothing returns nothing
local integer i = 0
call RemoveUnit(.dummy)
loop
exitwhen i > 12
if .Item != 0 then
call .Item.applyAbilities(.u, false)
endif
set i = i + 1
endloop
call AddUnitAnimationProperties(.u, .animtag, false)
call UnitRemoveAbility(.u, OPEN_ABILITY)
endmethod

static method create takes unit u returns Equipment
local Equipment this = Equipment
local integer i = 0
local integer id = GetPlayerId(GetOwningPlayer(u))
if this != 0 then
call RemoveUnit(.dummy)
else
set this = Equipment.allocate()
call SaveInteger(table, GetHandleId(u), 0, this)
endif
set .u = u
set .dummy = CreateUnit(GetOwningPlayer(u), INVENTORY_DUMMY, GetUnitX(u), GetUnitY(u), 0)
call SaveInteger(table, GetHandleId(.dummy), 0, this)
call UnitAddAbility(.dummy, INVENTORY_ABILITY)
call UnitAddAbility(.dummy, EXIT_ABILITY)
call UnitAddAbility(.u, OPEN_ABILITY)
loop
exitwhen i >= CLASSES
call .equipEmptyClass(i)
set i = i + 1
endloop
return this
endmethod


// **** Other Stuff ****
private static method Access takes nothing returns boolean
local unit u = GetTriggerUnit()
local Equipment inv = Equipment
local integer class
local integer i = 0
if GetSpellAbilityId() == EXIT_ABILITY then
if GetLocalPlayer() == GetOwningPlayer(inv.u) then
call ClearSelection()
call SelectUnit(inv.u, true)
endif
elseif GetSpellAbilityId() == OPEN_ABILITY then
call SetUnitX(inv.dummy, GetUnitX(inv.u))
call SetUnitY(inv.dummy, GetUnitY(inv.u))
if GetLocalPlayer() == GetOwningPlayer(inv.u) then
call ClearSelection()
call SelectUnit(inv.dummy, true)
endif
call inv.syncInventories()
elseif GetUnitTypeId(u) == INVENTORY_DUMMY then
loop
exitwhen i >= CLASSES
if inv.Item.icon == GetSpellAbilityId() then
set class = i
set i = CLASSES
endif
set i = i + 1
endloop
call inv.unequip(class)
call inv.equipEmptyClass(class)
call inv.syncInventories()
endif
set u = null
return false
endmethod

private static method ItemEquip takes nothing returns boolean
local unit u = GetTriggerUnit()
local item ite = GetManipulatedItem()
local integer i = 0
local Equipment inv = Equipment
local EquipmentItem invIte = EquipmentItem[GetItemTypeId(ite)]
if GetItemTypeId(ite) - 'I000' >= 0 then
if LoadBoolean(table, GetItemTypeId(ite) - 'I000', 0) then
if invIte != 0 and inv != 0 then
if not LoadBoolean(table, GetItemTypeId(ite) - 'I000', GetUnitTypeId(inv.u)) then
if u == inv.u then
call inv.equip(GetItemTypeId(ite))
call RemoveItem(ite)
call inv.syncInventories()
elseif u == inv.dummy then
loop
exitwhen i >= 6
if invIte.id == GetItemTypeId(UnitItemInSlot(inv.u, i)) then
call UnitUseItem(inv.u, UnitItemInSlot(inv.u, i))
call RemoveItem(ite)
set i = 7
endif
set i = i + 1
endloop
endif
else
call DisplayTextToPlayer(GetOwningPlayer(inv.u), 0, 0, GetUnitName(inv.u) + UNABLE_TO_EQUIP_STRING + GetItemName(ite))
endif
endif
endif
endif
set u = null
set ite = null
return false
endmethod

private static method onInit takes nothing returns nothing
set OnEquip = CreateTrigger()
set OnUnequip = CreateTrigger()
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_USE_ITEM, function Equipment.ItemEquip)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_CAST, function Equipment.Access)
set .twohandIcon = EquipmentItem.create('I000' - 1, TWOHAND_ABILITY, 0, false, "")
set table = InitHashtable()
endmethod

implement optional SaveLoadPlugin

endstruct

// **** Trigger Events ****
function RegisterItemEquipEvent takes code func returns nothing
call TriggerAddCondition(OnEquip, Filter(func))
endfunction

function RegisterItemUnequipEvent takes code func returns nothing
call TriggerAddCondition(OnUnequip, Filter(func))
endfunction

function GetTriggeringItemId takes nothing returns integer
return TriggeringItem
endfunction

function GetEquippingUnit takes nothing returns unit
return EquippingUnit
endfunction

//wrappers
function InitEquipment takes unit whichunit returns nothing
call Equipment.create(whichunit)
endfunction

public function RegisterItem takes integer itemid, integer icon, integer class, boolean twohanded, string animation returns nothing
call EquipmentItem.create(itemid, icon, class, twohanded, animation)
endfunction

public function AddItemAbility takes integer itemid, integer abi returns nothing
call EquipmentItem[itemid].addAbility(abi)
endfunction

function EnableItemEquip takes integer itemId, integer unitType, boolean flag returns nothing
call Equipment.disable(itemId, unitType, not flag)
endfunction

function IsEquipmentClassEmpty takes unit u, integer class returns boolean
return Equipment.Item[class] == 0
endfunction

function EquipItem takes unit u, item ite returns nothing
call Equipment.equip(GetItemTypeId(ite))
call RemoveItem(ite)
endfunction
function EquipItemById takes unit u, integer itemId returns nothing
call Equipment.equip(itemId)
endfunction

function UnequipItemById takes unit u, integer itemid returns nothing
local integer class = EquipmentItem[itemid].class
if Equipment.Item[class].id == itemid then
call Equipment.unequip(EquipmentItem[itemid].class)
call Equipment.equipEmptyClass(class)
endif
endfunction

function UnequipItemByClass takes unit u, integer class returns nothing
call Equipment.unequip(class)
call Equipment.equipEmptyClass(class)
endfunction

function GetEquippedItemTypeId takes unit u, integer class returns integer
return Equipment.Item[class].id
endfunction

function ChangeEquipmentOwner takes unit u, unit newowner returns nothing
set Equipment.owner = newowner
endfunction

function UnequipAll takes unit u returns nothing
local integer i = 1
loop
call Equipment.unequip(i)
call Equipment.equipEmptyClass(i)
exitwhen i >= CLASSES
set i = i + 1
endloop
endfunction

endlibrary


//Code indented using The_Witcher's Script Language Aligner
//Download the newest version and report bugs at www.hiveworkshop.com[/code]

For example what the structure AbilityList extends array does?
maybe store ability? how?

it is also connected to LinkedList wich is used for a recycler i guess... but i don't really understand.


--------- 2) How to use this system (2 ---------
well its very simple to use:
call InitEquipment ( owner )
owner is the unit that gets the equipment
and thats all^^ whenever this unit uses a registered item, it will get equipped


so Owner is an unit variable?
is the unit stored after the call InitEquipment ( unit )?
and if i use it again i can store a new unit?
or should i use an unit array to store all units before to call InitEquipment ( unit(integer) )
or is the code programed to check the player associated with the unit designed and automatically allow 1 unit per player?, i though it was MUI?

thanks for your time and help.
i will try to edit if i have more precise question about specific part...

i understand what structure, member, function, method, private, static are, i have read almost all tutorial on VJass struct for begginner but seing it all like this in giant structure is a bit confusing...
it is hard to understand how they are linked to each other and how they work.

more questions:
when you call a function you need to input the needed take value but
when a function return something who use the returned value? how is it linked to other functions?

[Jass=EquipmentItem]
// **** struct EquipmentItem ****
private struct EquipmentItem extends array
readonly integer id
readonly integer class
readonly AbilityList abilities
readonly integer icon
readonly boolean twohanded
readonly string tag

static method operator [] takes integer itemid returns EquipmentItem
return itemid - 'I000' + CLASSES + 1
endmethod

static method create takes integer id, integer icon, integer class, boolean twohanded, string animation returns EquipmentItem
local EquipmentItem this = id - 'I000' + CLASSES + 1
if id - 'I000' >= 0 then
call SaveBoolean(table, id - 'I000', 0, true)
endif
set .id = id
set .class = class
set .icon = icon
if id >= CLASSES + 1 then
set .abilities = AbilityList.create()
if class == MAINHAND_CLASS then
set .twohanded = twohanded
else
set .twohanded = false
endif
if (class == MAINHAND_CLASS or class == OFFHAND_CLASS) and id != 0 then
set .tag = animation
else
set .tag = ""
endif
endif
return this
endmethod

method addAbility takes integer abi returns nothing
call .abilities.add( abi)
endmethod

method applyAbilities takes unit u, boolean add returns nothing
local AbilityList node = .abilities.next
loop
exitwhen node.head
if add then
call UnitAddAbility(u, node.abi)
else
call UnitRemoveAbility(u, node.abi)
endif
set node = node.next
endloop
endmethod
endstruct
[/code]


For example in EquipmentItem what does the operator do?
JASS:
static method operator [] takes integer itemid returns EquipmentItem
            return itemid - 'I000' + CLASSES + 1
        endmethod



DEMO MAP
 

Attachments

  • testingmod.w3x
    1.3 MB · Views: 382
Last edited:
Level 19
Joined
Aug 8, 2007
Messages
2,765
for 2), you can only have one owner per player. if u try to do a second it will wipe the inventory of the first one and init for te second
 

ABM

ABM

Level 7
Joined
Jul 13, 2005
Messages
279
are you sure Arhowk? the author specified that his system is MUI...

call InitEquipment ( owner )
is an order to access the function named InitEquipment wich require a value of unit.
owner doesn't refer to a player but to an unit wich own the equipment.
it can be replaced by an units variable or units.

[Jass=InitEquipment]
function InitEquipment takes unit whichunit returns nothing
call Equipment.create(whichunit)
endfunction
[/code]

this function take the unit and call another function structure called Equipment and method inside the structure called create and the method is associated with the unit value renamed wichunit

[Jass= Equipment.create]
static method create takes unit u returns Equipment
local Equipment this = Equipment
local integer i = 0
local integer id = GetPlayerId(GetOwningPlayer(u))
if this != 0 then
call RemoveUnit(.dummy)
else
set this = Equipment.allocate()
call SaveInteger(table, GetHandleId(u), 0, this)
endif
set .u = u
set .dummy = CreateUnit(GetOwningPlayer(u), INVENTORY_DUMMY, GetUnitX(u), GetUnitY(u), 0)
call SaveInteger(table, GetHandleId(.dummy), 0, this)
call UnitAddAbility(.dummy, INVENTORY_ABILITY)
call UnitAddAbility(.dummy, EXIT_ABILITY)
call UnitAddAbility(.u, OPEN_ABILITY)
loop
exitwhen i >= CLASSES
call .equipEmptyClass(i)
set i = i + 1
endloop
return this
endmethod[/code]

this create an instance which take "wichunit" and change its name to u, then the instance of the structure Equipment ( Equipment This) is associated with the unit = Equipment (u)
does it mean the unit (u) is the instance of this method?
then id store the player number associated with the unit [local integer id = GetPlayerId(GetOwningPlayer(u))]


this part i don't understand
[Jass=...]
if this != 0 then
call RemoveUnit(.dummy)[/code]
"this" is the instance, if the instance is different than 0? what does this mean? and what is the .Dummy unit wich is removed? and why?


then i am not sure, this (instance) = Equipment (structure)
i think .allocate is same as .create but used inside the structure but there is no call,
it just associate the instance with.... what, i don't know???

[Jass=...]set this = Equipment.allocate()
call SaveInteger(table, GetHandleId(u), 0, this)
endif[/code]
then it save the integer
"table" maybe refer to where to store the integer
GetHandleId(u) refer to the specific unit id
0 i don't know what it is??
this is the instance where all these things happened.


[Jass=...]
set .u = u
set .dummy = CreateUnit(GetOwningPlayer(u), INVENTORY_DUMMY, GetUnitX(u), GetUnitY(u), 0)
call SaveInteger(table, GetHandleId(.dummy), 0, this)
call UnitAddAbility(.dummy, INVENTORY_ABILITY)
call UnitAddAbility(.dummy, EXIT_ABILITY)
call UnitAddAbility(.u, OPEN_ABILITY)[/code]
set the variable .u to the value of u (unit) but is .u a variable or an instance "Equipment.u"?
set .dummy to a new "inventory_dummy" type unit create for the player owner of the instanciated unit (u) at location of unit (u)
call a function wich save integer to save the dummy unit value
call a function wich add an ability to dummy unit
call a function wich add an ability to dummy unit
call a function wich add an ability to (u) unit


[Jass=...]
loop
exitwhen i >= CLASSES
call .equipEmptyClass(i)
set i = i + 1
endloop
return this[/code]
a loop wich is based on total number of Item Class set in the setup
call method .equipEmptyClass(i) in the structure Equipment giving an iteger (i)
loop call from Class 0 to max class
the return this i am not to sure, it mean it return the instance, but to who and for what purpose i don't know....

[Jass=equipEmptyClass]
method equipEmptyClass takes integer class returns nothing
call UnitAddAbility(.dummy, EquipmentItem(class).icon)
set .Item[class] = 0
endmethod[/code]
this take the class integer and call the function UnitAddAbility giving unit and ability, i think...
.Item[Class] is probably an integer array, not sure why it need to be put to 0.

if someone could explain to me what i am missing that would be nice ^^
 
Last edited:
It is MUI... owner is a unit, which is the unit that will be registered for the system... Unless a unit is registered with the system, that unit won't have the custom inventory...

for the this != 0 then remove dummy... it's protection for those who might register a unit twice or more than that... if ever you register a unit more than once, it will remove the existing inventory for that unit first...

for the hashtable entry, 0 is a childkey... it's an arbitrary number set by the maker of the system, don't meddle with it...

.u is the unit registered to have a custom inventory (the "owner" on the InitEquipment part)

the create method must return the instance, that's why there is a return this at the end...


btw, I've been using that system and I need to tell you this... Unless you're planning to recreate that system, you don't really need to understand the whole code [most systems here are like that], you only need to know what was on the How To Use part and you should be fine...

There is a reason why we don't comment the main code, because normal users don't really need to understand how each line works... and normal users won't even bother anyway...

Most of your questions are something that shouldn't bother someone who is just focused on implementing the system, they are for someone who actually wants to recreate the system... But, curiosity is really nice too...


ultimately, If you really want to learn vJASS, I suggest trying to make your own spells/systems... You might learn faster if you take the hands-on approach...
 

ABM

ABM

Level 7
Joined
Jul 13, 2005
Messages
279
Thanks Nestharus,
actually i looked at some of your written tutorial and i am currently watching the video one, (currently video 5).

Thanks Adiktuz,
well i understand your opinion and you are right,
that's why i am doing some trial map Jass training with Gui converted to Jass to learn step by step...
well if i didn't care about learning Jass i would ask question and use the system...
i also know that this intermediate Jass coding is a little bit too advanced for me, but actually i need to re-do the system a little bit because it doesn't do what i need.

so maybe, some of you who understand how this system function will be able to help me adapt it, i asked the maker of this system and he told me the limitation...

i understand the limitation but i found out a way to circle them, but i don't have answer about that yet from The_Witcher, maybe what i want is not doable, but i think it is...


so let me explain you everything and then maybe you can tell me how to do it.

SYSTEM
it create a dummy inventory for registered unit.
normal unit have item when equiped item become ability on the dummy unit wich look like the item equiped.
every item need 1 ability (icon) to show on equipment dummy and other ability to do something (like increase damage or life)
all item equiped are position locked because the ability can have only 1 position x,y on the dummy, so each class item has 1 position only and can get 1 item only.

NEED
" I need to be able to equip 2 rings and if possible to allow dual weapon wielding"

with this system dual "mainhand class" wielding is impossible
and if i want 2 ring to equip i need class ring1 and class ring2 wich mean some ring only equip to position(ring1) and other only to position(ring2)
if i try to equip two ring of same class the new will remove the old and the other empty ring will still be empty


METHOD
create for each ring item 2 ability
(one associated with class ring1 and one with class ring2, thus 2 position avaiable for each ring)
....then when a ring is equiped
.........check if dummy ability ring1(position) is empty and equip ring,
....if not
.........check if ring2(position) is empty and equip ring using the ability associated with ring2,
....if ring1 and ring2 not empty,
.........then replace ring1 with the new ring and give back to unit inventory the old item like it is now in the system.

for dual wielding it is the same idea but the trigger would be much more complicated, because it will have to check if the herotype is able to use dual wielding or not.
because dual wielding is allowed only for certain Hero type.


if i had a good knowledge in Jass i would implement the change myself but i don't understand completly his system so i am unable to adapt it.
 
They are certainly doable if you can edit the system... But personally, I'd rather have The_Witcher do it for you... that, or you learn how to do it... :)

just focus on understanding how the equip and unequip parts work and you should be able to do the method you outlined... and maybe a bit of linking the two placer ability versions two...

most functions mean exactly what they say so you can maybe understand it bit by bit if you take time to understand the words...
 

ABM

ABM

Level 7
Joined
Jul 13, 2005
Messages
279
I Think i need help....
i have the basic idea on how to proceed but it is hard to modify the System because i don't graps everything about it...

here is what i added/modified

[Jass=setup]
// itemid | icon | icon2 | class | alter | twohanded? | animationtag
// itemid | abi |
//ItemName
call AdvancedEquipmentSystem_RegisterItem('I004', 'A008', 0, AdvancedEquipmentSystem_MAINHAND_CLASS, false, false, "Alternate")
call AdvancedEquipmentSystem_AddItemAbility('I004', 'A002')[/code]

Itemid = item (ASCII) code in the Object editor
icon = ability (ASCII) code, the ability wich will appear on the equipment menu (slot1)
icon1 = ability , the alternate version ability wich appear in a different position (slot2)
class = an integer wich separate item into class wich are reprented as a slot in the equipment menu
alter = a boolean to keep track of the item statut (is it in normal slot1 (icon) or alternate slot2 (icon1)
twohanded = a boolean to track weapon that need both hand to use
animationtag = animation (String) code wich modify the animation of the unit wearing the item

the modified items are in orange (right now i focus only on enabling to equip 2 rings)
to allow that item class must be able to be modified so the slot they equip in can be changed
// ex: GoldenRing by default will go to slot8 (RING1_CLASS) but if the slot is occupied it will go to slot9 (RING2_CLASS)
so the GoldenRing class can change from 8 to 9 and the icon ability will adapt too, but to keep track if the item need to use icon or icon1 we use "alter"
GoldenRing: normal, class = 8, abi = icon, alter = false
GoldenRing: alternate, class = 9, abi = icon1, alter = true


on the Jass setup the only item showed is a Main_Hand so icon1 = 0 , only the Ring will have an alternate position (because we can equip 2 ring at same time) (later i will try to add the dual wield)

Here is the Code modified but it doesn't work completly
i can equip 2 rings everything works but i can only unequip the one wich go to the normal spot, the alternate spot ring cannot be unequiped
[Jass=Setup]
scope SetupAdvancedEquipmentSystem initializer Initialize

globals
integer AMULET_CLASS = 2
integer ARMOR_CLASS = 3
integer BOOTS_CLASS = 4
integer GLOVES_CLASS = 5
integer SHOULDER_CLASS = 6
integer HELMET_CLASS = 7
integer RING1_CLASS = 8
integer RING2_CLASS = 9
endglobals

private function Initialize takes nothing returns nothing
// here you have to give an icon ability for every empty slot
// this is my setup for the testmap


// WARNING: class 0 and 1 are taken as main and offhand slots! start with 2 for new indexes
call AdvancedEquipmentSystem_RegisterNewClass('A00D', AdvancedEquipmentSystem_MAINHAND_CLASS)//Mainhand
call AdvancedEquipmentSystem_RegisterNewClass('A00E', AdvancedEquipmentSystem_OFFHAND_CLASS)//Offhand
call AdvancedEquipmentSystem_RegisterNewClass('A00A', AMULET_CLASS)//Amulet
call AdvancedEquipmentSystem_RegisterNewClass('A007', ARMOR_CLASS)//Armor
call AdvancedEquipmentSystem_RegisterNewClass('A00F', BOOTS_CLASS)//Boots
call AdvancedEquipmentSystem_RegisterNewClass('A004', GLOVES_CLASS)//Gloves
call AdvancedEquipmentSystem_RegisterNewClass('A00L', HELMET_CLASS)//Helmet
call AdvancedEquipmentSystem_RegisterNewClass('A00M', SHOULDER_CLASS)//Shoulder
call AdvancedEquipmentSystem_RegisterNewClass('A010', RING1_CLASS)//Ring(icon1)
call AdvancedEquipmentSystem_RegisterNewClass('A00C', RING2_CLASS)//Ring(icon2)


//in this part set up the items
//you can do this anytime in your map (may cause bugs if not at initialization) by using
//call AdvancedEquipmentSystem_RegisterItem(itemid, abilities, icon, class, twohanded, animation)
// look into the HowToUse for further information

// itemid | icon | icon2 | class | alter | twohanded? | animationtag
// itemid | abi | abi1 |
// itemid | unittype | equip? | dual?
//Silversword
call AdvancedEquipmentSystem_RegisterItem('I004', 'A008', 0, AdvancedEquipmentSystem_MAINHAND_CLASS, false, false, "Alternate")
call AdvancedEquipmentSystem_AddItemAbility('I004', 'A002')
call EnableItemEquip('I004','H001',true)
//leather cloak
call AdvancedEquipmentSystem_RegisterItem('I000', 'A00K', 0, SHOULDER_CLASS, false, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I000', 'A000')
call AdvancedEquipmentSystem_AddItemAbility('I000', 'A00Y')
//Slizer
call AdvancedEquipmentSystem_RegisterItem('I005' , 'A00H', 0, AdvancedEquipmentSystem_MAINHAND_CLASS, false, false, "Alternate")
call AdvancedEquipmentSystem_AddItemAbility('I005', 'A005')
//Razor
call AdvancedEquipmentSystem_RegisterItem('I006', 'A00J', 0, AdvancedEquipmentSystem_MAINHAND_CLASS, false, true, "Channel")
call AdvancedEquipmentSystem_AddItemAbility('I006', 'A00I')
//shield
call AdvancedEquipmentSystem_RegisterItem('I001', 'A009', 0, AdvancedEquipmentSystem_OFFHAND_CLASS, false, false, "defend")
call AdvancedEquipmentSystem_AddItemAbility('I001', 'A006')
//Amulet of darkness
call AdvancedEquipmentSystem_RegisterItem('I00A', 'A00B', 0, AMULET_CLASS, false, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I00A', 'A00S')
//Golems Skin
call AdvancedEquipmentSystem_RegisterItem('I003', 'A00N', 0, ARMOR_CLASS, false, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I003', 'A00U')
//Windwalkers
call AdvancedEquipmentSystem_RegisterItem('I002', 'A00O', 0, BOOTS_CLASS, false, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I002', 'A00X')
//Stonefists
call AdvancedEquipmentSystem_RegisterItem('I007', 'A00P', 0, GLOVES_CLASS, false, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I007', 'A00W')
//Arthuriel
call AdvancedEquipmentSystem_RegisterItem('I008', 'A00Q', 'A013', RING1_CLASS, false, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I008', 'A00T')
//Arthurion
call AdvancedEquipmentSystem_RegisterItem('I00B', 'A011', 'A014', RING1_CLASS, false, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I00B', 'A012')
//Mask of Horror
call AdvancedEquipmentSystem_RegisterItem('I009', 'A00R', 0, HELMET_CLASS, false, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I009', 'A00V')

endfunction

endscope


//Code indented using The_Witcher's Script Language Aligner
//Download the newest version and report bugs at www.hiveworkshop.com
[/code]


[Jass=Equipment]
library AdvancedEquipmentSystem requires LinkedListModule, RegisterPlayerUnitEvent

// The_Witcher's Equipment System
//
// This is my easy to use equipment system, which adds an equipment screen to any unit you want.
// equipped items can give up abilities to the owner and can change the animations of him...
//
//
// To learn how to use this system please read the "How To Use" delivered in the demo map
//
//
// Requirements:
// JASS knowledge
// LinkedList (http://www.hiveworkshop.com/forums/jass-resources-412/snippet-linkedlistmodule-206552/)
// RegisterPlayerUnitEvent (http://www.hiveworkshop.com/forums/jass-resources-412/snippet-registerplayerunitevent-203338/)
//
// have fun^^

//**************************************************
//********************SETUP PART********************
//**************************************************

globals
// this is the rawcode of the unit which works as inventory
public constant integer INVENTORY_DUMMY = 'h007'

// this is the class you selected as mainhand class
public constant integer MAINHAND_CLASS = 0

// this is the class you selected as offhand class
public constant integer OFFHAND_CLASS = 1

// this is the amount of total classes you have
public constant integer CLASSES = 10

// this is the ability to close the inventory
public constant integer EXIT_ABILITY = 'A00G'

// this is the ability to open the inventory
public constant integer OPEN_ABILITY = 'A003'

// this is the ability which gives the dummy the same inventory as your hero has
public constant integer INVENTORY_ABILITY = 'AInv'

// this is the icon ability shown in the offhand slot when a twhoanded weapon is equipeed
public constant integer TWOHAND_ABILITY = 'A00Z'
public constant boolean SHOW_TWOHAND_ABILITY = true

// this is the text shown when a unit is trying to equip an item which it isnt allowed to
// example: " can't equip " becomes ingame something like Soldier can't equip Giant Sword
public constant string UNABLE_TO_EQUIP_STRING = " can't equip "
endglobals

//************************************************************
//********************SETUP PART ENDS HERE********************
//************************************************************
//*****************Don't edit anything below******************
//************************************************************

globals
private trigger OnEquip
private trigger OnUnequip
private integer TriggeringItem
private unit EquippingUnit
private hashtable table
endglobals

private struct AbilityList extends array
integer abi
implement LinkedList

static method create takes nothing returns thistype
return .createNode()
endmethod

method remove takes nothing returns nothing
call .removeNode()
call .deallocate()
endmethod

method add takes integer abi returns nothing
local thistype new = .allocate()
set new.abi = abi
call .insertNode(new)
endmethod
endstruct


// **** struct EquipmentItem ****
private struct EquipmentItem extends array
readonly integer id
integer class
readonly AbilityList abilities
readonly integer icon
readonly integer icon1 //added icon1
boolean alter // added alter (is item in normal or alternate mode)
readonly boolean twohanded
readonly string tag

static method operator [] takes integer itemid returns EquipmentItem
return itemid - 'I000' + CLASSES + 1
endmethod

static method create takes integer id, integer icon, integer icon1, integer class, boolean alter, boolean twohanded, string animation returns EquipmentItem //added icon1
local EquipmentItem this = id - 'I000' + CLASSES + 1
if id - 'I000' >= 0 then
call SaveBoolean(table, id - 'I000', 0, true)
endif
set .id = id
set .class = class
set .icon = icon
set .icon1 = icon1 //added icon1
if id >= CLASSES + 1 then
set .abilities = AbilityList.create()
if class == MAINHAND_CLASS then
set .twohanded = twohanded
else
set .twohanded = false
endif
if (class == MAINHAND_CLASS or class == OFFHAND_CLASS) and id != 0 then
set .tag = animation
else
set .tag = ""
endif
endif
return this
endmethod

method addAbility takes integer abi returns nothing
call .abilities.add( abi)
endmethod

method applyAbilities takes unit u, boolean add returns nothing
local AbilityList node = .abilities.next
loop
exitwhen node.head
if add then
call UnitAddAbility(u, node.abi)
else
call UnitRemoveAbility(u, node.abi)
endif
set node = node.next
endloop
endmethod
endstruct

public function RegisterNewClass takes integer emptyicon, integer class returns nothing
call EquipmentItem.create('I000' - CLASSES - 1 + class, emptyicon, 0, class, false, false, "")
endfunction

// **** struct Equipment ****
struct Equipment
private static EquipmentItem twohandIcon

private unit u
private unit dummy
readonly string animtag = ""
readonly EquipmentItem array Item [12]

static method operator [] takes unit u returns Equipment
return LoadInteger(table, GetHandleId(u), 0)
endmethod

method operator owner takes nothing returns unit
return .u
endmethod

method operator owner= takes unit new returns nothing
local integer i = 0
loop
exitwhen i >= CLASSES
if .Item != 0 then
call .Item.applyAbilities(.u, false)
call .Item.applyAbilities(new, true)
endif
set i = i + 1
endloop
call AddUnitAnimationProperties(.u, .animtag, false)
call UnitRemoveAbility(.u, OPEN_ABILITY)
call AddUnitAnimationProperties(new, .animtag, true)
call UnitAddAbility(new, OPEN_ABILITY)
set .u = new
call SaveInteger(table, GetHandleId(.u), 0, this)
call SaveInteger(table, GetHandleId(.dummy), 0, this)
endmethod

method syncInventories takes nothing returns nothing
local integer i = 0
loop
exitwhen i >= 6
call RemoveItem(UnitItemInSlot(.dummy, i))
call UnitAddItemToSlotById(.dummy, GetItemTypeId(UnitItemInSlot(.u, i)), i)
call SetItemDroppable(UnitItemInSlot(.dummy, i), false)
set i = i + 1
endloop
endmethod

private method refreshAnimation takes nothing returns nothing
local string a = .Item[MAINHAND_CLASS].tag
if .Item[OFFHAND_CLASS] != 0 and .Item[OFFHAND_CLASS] != twohandIcon then
set a = .Item[OFFHAND_CLASS].tag
endif
call AddUnitAnimationProperties(.u, .animtag, false)
call AddUnitAnimationProperties(.u, a, true)
set .animtag = a
endmethod

method equipEmptyClass takes integer class returns nothing
call UnitAddAbility(.dummy, EquipmentItem(class).icon)
set .Item[class] = 0
endmethod

method equipTwohandIcon takes nothing returns nothing
call UnitAddAbility(.dummy, twohandIcon.icon)
set .Item[OFFHAND_CLASS] = twohandIcon
endmethod

method unequip takes integer class returns nothing
local integer i = 0
local EquipmentItem toRemove = .Item[class]
if toRemove != 0 then
if toRemove.twohanded then
call UnitRemoveAbility(.dummy, TWOHAND_ABILITY)
call .equipEmptyClass(OFFHAND_CLASS)
endif
call toRemove.applyAbilities(.u, false)
call UnitAddItemById(.u, toRemove.id)
set TriggeringItem = toRemove.id
set EquippingUnit = .u
call TriggerEvaluate(OnUnequip)
if toRemove.alter == false then
call UnitRemoveAbility(.dummy, toRemove.icon)
else
call UnitRemoveAbility(.dummy, toRemove.icon1)
set toRemove.alter = false
set toRemove.class = RING1_CLASS
endif
else
call UnitRemoveAbility(.dummy, EquipmentItem(class).icon)
endif
set .Item[class] = 0
call .refreshAnimation()
endmethod

method equip takes integer id returns nothing
local EquipmentItem toEquip = EquipmentItem[id]
local EquipmentItem mainEquip = .Item[MAINHAND_CLASS]
local EquipmentItem ring1Equip = .Item[RING1_CLASS]
local EquipmentItem ring2Equip = .Item[RING2_CLASS]
// remove existing
if mainEquip != 0 then
if toEquip.twohanded or (mainEquip.twohanded and (toEquip.class == OFFHAND_CLASS or toEquip.class == MAINHAND_CLASS)) then
call .unequip(MAINHAND_CLASS)
call .unequip(OFFHAND_CLASS)
if toEquip.class == MAINHAND_CLASS and not toEquip.twohanded then
call .equipEmptyClass(OFFHAND_CLASS)
elseif toEquip.class == OFFHAND_CLASS then
call .equipEmptyClass(MAINHAND_CLASS)
endif
endif
endif
if (toEquip.class == RING1_CLASS or toEquip.class == RING2_CLASS) then
if ring1Equip != 0 and ring2Equip == 0 then
set toEquip.class = RING2_CLASS
set toEquip.alter = true
call .unequip(RING2_CLASS)
else
set toEquip.class = RING1_CLASS
set toEquip.alter = false
call .unequip(RING1_CLASS)
endif
endif
call .unequip(toEquip.class)
// new is twohanded ?
if toEquip.twohanded then
call .unequip(OFFHAND_CLASS)
call .equipTwohandIcon()
if not SHOW_TWOHAND_ABILITY then
call UnitRemoveAbility(.dummy, twohandIcon.icon)
endif
endif
// equip new
call toEquip.applyAbilities(.u, true)
if toEquip.alter == false then
call UnitAddAbility(.dummy, toEquip.icon)
else
call UnitAddAbility(.dummy, toEquip.icon1)
endif
set .Item[toEquip.class] = toEquip
call .refreshAnimation()
// fire trigger
set EquippingUnit = .u
set TriggeringItem = id
call TriggerEvaluate(OnEquip)
endmethod

static method disable takes integer itemId, integer unitType, boolean flag returns nothing
call SaveBoolean(table, itemId - 'I000', unitType, flag)
endmethod

private method onDestroy takes nothing returns nothing
local integer i = 0
call RemoveUnit(.dummy)
loop
exitwhen i > 12
if .Item != 0 then
call .Item.applyAbilities(.u, false)
endif
set i = i + 1
endloop
call AddUnitAnimationProperties(.u, .animtag, false)
call UnitRemoveAbility(.u, OPEN_ABILITY)
endmethod

static method create takes unit u returns Equipment
local Equipment this = Equipment
local integer i = 0
local integer id = GetPlayerId(GetOwningPlayer(u))
if this != 0 then
call RemoveUnit(.dummy)
else
set this = Equipment.allocate()
call SaveInteger(table, GetHandleId(u), 0, this)
endif
set .u = u
set .dummy = CreateUnit(GetOwningPlayer(u), INVENTORY_DUMMY, GetUnitX(u), GetUnitY(u), 0)
call SaveInteger(table, GetHandleId(.dummy), 0, this)
call UnitAddAbility(.dummy, INVENTORY_ABILITY)
call UnitAddAbility(.dummy, EXIT_ABILITY)
call UnitAddAbility(.u, OPEN_ABILITY)
loop
exitwhen i >= CLASSES
call .equipEmptyClass(i)
set i = i + 1
endloop
return this
endmethod


// **** Other Stuff ****
private static method Access takes nothing returns boolean
local unit u = GetTriggerUnit()
local Equipment inv = Equipment
local integer class
local integer i = 0
if GetSpellAbilityId() == EXIT_ABILITY then
if GetLocalPlayer() == GetOwningPlayer(inv.u) then
call ClearSelection()
call SelectUnit(inv.u, true)
endif
elseif GetSpellAbilityId() == OPEN_ABILITY then
call SetUnitX(inv.dummy, GetUnitX(inv.u))
call SetUnitY(inv.dummy, GetUnitY(inv.u))
if GetLocalPlayer() == GetOwningPlayer(inv.u) then
call ClearSelection()
call SelectUnit(inv.dummy, true)
endif
call inv.syncInventories()
elseif GetUnitTypeId(u) == INVENTORY_DUMMY then
loop
exitwhen i >= CLASSES
if inv.Item.icon == GetSpellAbilityId() then
set class = i
set i = CLASSES
endif
set i = i + 1
endloop
call inv.unequip(class)
call inv.equipEmptyClass(class)
call inv.syncInventories()
endif
set u = null
return false
endmethod

private static method ItemEquip takes nothing returns boolean
local unit u = GetTriggerUnit()
local item ite = GetManipulatedItem()
local integer i = 0
local Equipment inv = Equipment
local EquipmentItem invIte = EquipmentItem[GetItemTypeId(ite)]
if GetItemTypeId(ite) - 'I000' >= 0 then
if LoadBoolean(table, GetItemTypeId(ite) - 'I000', 0) then
if invIte != 0 and inv != 0 then
if not LoadBoolean(table, GetItemTypeId(ite) - 'I000', GetUnitTypeId(inv.u)) then
if u == inv.u then
call inv.equip(GetItemTypeId(ite))
call RemoveItem(ite)
call inv.syncInventories()
elseif u == inv.dummy then
loop
exitwhen i >= 6
if invIte.id == GetItemTypeId(UnitItemInSlot(inv.u, i)) then
call UnitUseItem(inv.u, UnitItemInSlot(inv.u, i))
call RemoveItem(ite)
set i = 7
endif
set i = i + 1
endloop
endif
else
call DisplayTextToPlayer(GetOwningPlayer(inv.u), 0, 0, GetUnitName(inv.u) + UNABLE_TO_EQUIP_STRING + GetItemName(ite))
endif
endif
endif
endif
set u = null
set ite = null
return false
endmethod

private static method onInit takes nothing returns nothing
set OnEquip = CreateTrigger()
set OnUnequip = CreateTrigger()
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_USE_ITEM, function Equipment.ItemEquip)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_CAST, function Equipment.Access)
set .twohandIcon = EquipmentItem.create('I000' - 1, TWOHAND_ABILITY, 0, 0, false, false, "")
set table = InitHashtable()
endmethod

implement optional SaveLoadPlugin

endstruct

// **** Trigger Events ****
function RegisterItemEquipEvent takes code func returns nothing
call TriggerAddCondition(OnEquip, Filter(func))
endfunction

function RegisterItemUnequipEvent takes code func returns nothing
call TriggerAddCondition(OnUnequip, Filter(func))
endfunction

function GetTriggeringItemId takes nothing returns integer
return TriggeringItem
endfunction

function GetEquippingUnit takes nothing returns unit
return EquippingUnit
endfunction

//wrappers
function InitEquipment takes unit whichunit returns nothing
call Equipment.create(whichunit)
endfunction

public function RegisterItem takes integer itemid, integer icon, integer icon1, integer class, boolean alter, boolean twohanded, string animation returns nothing
call EquipmentItem.create(itemid, icon, icon1, class, alter, twohanded, animation)
endfunction

public function AddItemAbility takes integer itemid, integer abi returns nothing
call EquipmentItem[itemid].addAbility(abi)
endfunction

function EnableItemEquip takes integer itemId, integer unitType, boolean flag returns nothing
call Equipment.disable(itemId, unitType, not flag)
endfunction

function IsEquipmentClassEmpty takes unit u, integer class returns boolean
return Equipment.Item[class] == 0
endfunction

function EquipItem takes unit u, item ite returns nothing
call Equipment.equip(GetItemTypeId(ite))
call RemoveItem(ite)
endfunction
function EquipItemById takes unit u, integer itemId returns nothing
call Equipment.equip(itemId)
endfunction

function UnequipItemById takes unit u, integer itemid returns nothing
local integer class = EquipmentItem[itemid].class
if Equipment.Item[class].id == itemid then
call Equipment.unequip(EquipmentItem[itemid].class)
call Equipment.equipEmptyClass(class)
endif
endfunction

function UnequipItemByClass takes unit u, integer class returns nothing
call Equipment.unequip(class)
call Equipment.equipEmptyClass(class)
endfunction

function GetEquippedItemTypeId takes unit u, integer class returns integer
return Equipment.Item[class].id
endfunction

function ChangeEquipmentOwner takes unit u, unit newowner returns nothing
set Equipment.owner = newowner
endfunction

function UnequipAll takes unit u returns nothing
local integer i = 1
loop
call Equipment.unequip(i)
call Equipment.equipEmptyClass(i)
exitwhen i >= CLASSES
set i = i + 1
endloop
endfunction

endlibrary


//Code indented using The_Witcher's Script Language Aligner
//Download the newest version and report bugs at www.hiveworkshop.com
[/code]


[Jass=LinkedList]
library LinkedListModule /* v2.2.0

Easy implementation of linked lists into structs.

***********************************************************************
*
* module LinkedList
*
* - Implement at the top of your struct, must extend array
*
* thistype next
* thistype prev
* boolean head
*
* readonly static thistype base
* - Precreated head, useful for non-dynamic lists.
*
* static method allocate takes nothing returns thistype
* method deallocate takes nothing returns nothing
*
* static method createNode takes nothing returns thistype
* - Allocates a new node pointing towards itself.
* - These nodes are considered "heads" therefore it's head
* - boolean member is set to true.
* method insertNode takes thistype toInsert returns thistype
* - Inserts the node into the list after 'this' node.
* method removeNode takes nothing returns nothing
* - Removes the node from the list.
* method clearNode takes nothing returns nothing
* - Deallocates all the instances within the node's range
* method flushNode takes nothing returns nothing
* - Clears and deallocates the node.
*
********************************************************************* */

module LinkedList
//private static integer instanceCount = 0
readonly static integer instanceCount = 0

boolean head
thistype next
thistype prev

static method operator base takes nothing returns thistype
return 8190
endmethod

static method allocate takes nothing returns thistype
local thistype this=thistype(0).prev
if this == 0 then
debug if instanceCount == 8190 then
debug call BJDebugMsg("[LinkedList] Error: attempted to allocate too many instances.")
debug return 0
debug endif
set instanceCount=instanceCount+1
return instanceCount
endif
set thistype(0).prev=this.prev
return this
endmethod

method deallocate takes nothing returns nothing
set this.prev=thistype(0).prev
set thistype(0).prev=this
set this.head=false
endmethod

static method createNode takes nothing returns thistype
local thistype this=allocate()
set this.next=this
set this.prev=this
set this.head=true
return this
endmethod

method clearNode takes nothing returns nothing
if this != this.next then
set this.next.prev=thistype(0).prev
set thistype(0).prev=this.prev
set this.next=this
set this.prev=this
endif
endmethod

method flushNode takes nothing returns nothing
set this.next.prev=thistype(0).prev
set thistype(0).prev=this
set head=false
endmethod

method insertNode takes thistype toInsert returns nothing
set this.prev.next=toInsert
set toInsert.prev=this.prev
set this.prev=toInsert
set toInsert.next=this
endmethod

method removeNode takes nothing returns nothing
set this.prev.next=this.next
set this.next.prev=this.prev
endmethod

private static method onInit takes nothing returns nothing
set thistype(8190).next=8190
set thistype(8190).prev=8190
set thistype(8190).head=true
endmethod

static if DEBUG_MODE then
method print takes nothing returns nothing
local string s=""
local thistype exit=this
set this=this.next
loop
set s=s+I2S(this)
set this=this.next
exitwhen this == exit
set s=s+" - "
endloop
call BJDebugMsg("[ "+s+" ]")
endmethod
endif

endmodule

endlibrary[/code]


[Jass=RegisteredEvent]
/**************************************************************
*
* RegisterPlayerUnitEvent
* v5.0.0.0
* By Magtheridon96
*
* I would like to give a special thanks to Bribe, azlier
* and BBQ for improving this library. For modularity, it only
* supports player unit events.
*
* Functions passed to RegisterPlayerUnitEvent must
* return false. They can return nothing as well. (Which is a Pro)
*
* Warning:
* --------
*
* - Don't use TriggerSleepAction inside registered code.
*
* API:
* ----
*
* - function RegisterPlayerUnitEvent
* takes
* playerunitevent whichEvent : The event you would like to register
* code whichFunction : The code you would like to register
* returns
* nothing
*
* - Registers code that will execute when an event fires.
*
* - function RegisterPlayerUnitEventForPlayer
* takes
* playerunitevent whichEvent : The event you would like to register
* code whichFunction : The code you would like to register
* player whichPlayer : The player you would like to register the event for
* returns
* nothing
*
* - Registers code that will execute when an event fires for a certain player.
*
**************************************************************/
library RegisterPlayerUnitEvent // Special Thanks to Bribe and azlier
globals
private trigger array t
endglobals

function RegisterPlayerUnitEvent takes playerunitevent p, code c returns nothing
local integer i = GetHandleId(p)
local integer k = 15
if t == null then
set t = CreateTrigger()
loop
call TriggerRegisterPlayerUnitEvent(t, Player(k), p, null)
exitwhen k == 0
set k = k - 1
endloop
endif
call TriggerAddCondition(t, Filter(c))
endfunction

function RegisterPlayerUnitEventForPlayer takes playerunitevent p, code c, player pl returns nothing
local integer i = 260 + 16 * GetHandleId(p) + GetPlayerId(pl)
if t == null then
set t = CreateTrigger()
call TriggerRegisterPlayerUnitEvent(t, pl, p, null)
endif
call TriggerAddCondition(t, Filter(c))
endfunction
endlibrary[/code]



Here i will post the Jass script i changed and the script wich i think are concerned by the bug...

[Jass=Unequip]
method unequip takes integer class returns nothing
local integer i = 0
local EquipmentItem toRemove = .Item[class]
if toRemove != 0 then
if toRemove.twohanded then
call UnitRemoveAbility(.dummy, TWOHAND_ABILITY)
call .equipEmptyClass(OFFHAND_CLASS)
endif
call toRemove.applyAbilities(.u, false)
call UnitAddItemById(.u, toRemove.id)
set TriggeringItem = toRemove.id
set EquippingUnit = .u
call TriggerEvaluate(OnUnequip)
if toRemove.alter == false then
call UnitRemoveAbility(.dummy, toRemove.icon)
else
call UnitRemoveAbility(.dummy, toRemove.icon1)
set toRemove.alter = false
set toRemove.class = RING1_CLASS
endif
else
call UnitRemoveAbility(.dummy, EquipmentItem(class).icon)
endif
set .Item[class] = 0
call .refreshAnimation()
endmethod[/code]

[Jass=Equip]
method equip takes integer id returns nothing
local EquipmentItem toEquip = EquipmentItem[id]
local EquipmentItem mainEquip = .Item[MAINHAND_CLASS]
local EquipmentItem ring1Equip = .Item[RING1_CLASS]
local EquipmentItem ring2Equip = .Item[RING2_CLASS]
// remove existing
if mainEquip != 0 then
if toEquip.twohanded or (mainEquip.twohanded and (toEquip.class == OFFHAND_CLASS or toEquip.class == MAINHAND_CLASS)) then
call .unequip(MAINHAND_CLASS)
call .unequip(OFFHAND_CLASS)
if toEquip.class == MAINHAND_CLASS and not toEquip.twohanded then
call .equipEmptyClass(OFFHAND_CLASS)
elseif toEquip.class == OFFHAND_CLASS then
call .equipEmptyClass(MAINHAND_CLASS)
endif
endif
endif
if (toEquip.class == RING1_CLASS or toEquip.class == RING2_CLASS) then
if ring1Equip != 0 and ring2Equip == 0 then
set toEquip.class = RING2_CLASS
set toEquip.alter = true
call .unequip(RING2_CLASS)
else
set toEquip.class = RING1_CLASS
set toEquip.alter = false
call .unequip(RING1_CLASS)
endif
endif
call .unequip(toEquip.class)
// new is twohanded ?
if toEquip.twohanded then
call .unequip(OFFHAND_CLASS)
call .equipTwohandIcon()
if not SHOW_TWOHAND_ABILITY then
call UnitRemoveAbility(.dummy, twohandIcon.icon)
endif
endif
// equip new
call toEquip.applyAbilities(.u, true)
if toEquip.alter == false then
call UnitAddAbility(.dummy, toEquip.icon)
else
call UnitAddAbility(.dummy, toEquip.icon1)
endif
set .Item[toEquip.class] = toEquip
call .refreshAnimation()
// fire trigger
set EquippingUnit = .u
set TriggeringItem = id
call TriggerEvaluate(OnEquip)
endmethod

static method disable takes integer itemId, integer unitType, boolean flag returns nothing
call SaveBoolean(table, itemId - 'I000', unitType, flag)
endmethod

private method onDestroy takes nothing returns nothing
local integer i = 0
call RemoveUnit(.dummy)
loop
exitwhen i > 12
if .Item != 0 then
call .Item.applyAbilities(.u, false)
endif
set i = i + 1
endloop
call AddUnitAnimationProperties(.u, .animtag, false)
call UnitRemoveAbility(.u, OPEN_ABILITY)
endmethod

static method create takes unit u returns Equipment
local Equipment this = Equipment
local integer i = 0
local integer id = GetPlayerId(GetOwningPlayer(u))
if this != 0 then
call RemoveUnit(.dummy)
else
set this = Equipment.allocate()
call SaveInteger(table, GetHandleId(u), 0, this)
endif
set .u = u
set .dummy = CreateUnit(GetOwningPlayer(u), INVENTORY_DUMMY, GetUnitX(u), GetUnitY(u), 0)
call SaveInteger(table, GetHandleId(.dummy), 0, this)
call UnitAddAbility(.dummy, INVENTORY_ABILITY)
call UnitAddAbility(.dummy, EXIT_ABILITY)
call UnitAddAbility(.u, OPEN_ABILITY)
loop
exitwhen i >= CLASSES
call .equipEmptyClass(i)
set i = i + 1
endloop
return this
endmethod[/code]

The Equip part seems to work for the second ring but not the unequip...

Here is a Demo Map at the first post (beginning of thread)
 
Last edited:
Status
Not open for further replies.
Top