wraithseeker
Tired.
- Reaction score
- 122
Requires Table, UnitProperties, AutoIndex
Documention
JASS:
Customizable Item System
v1.04 Made by wraithseeker
Credits
Thanks to Pyrogasm for helping me.
Thanks to Litany for UnitProperties.
Thanks to Vexorian for Table.
Thanks to grim001 for AutoIndex.
Pros
- You do not have to do much OE editing as you only need to set stats in the Initialization function.
- Allows 12 inventory for units while carrying bonus in backpack
- MUI and leakless
- Allow custom item stats.
- Allows custom random item stats generating
- Configurable and useful
- Recipes
- Set Items
Cons
- Requires some importing
- Might take some time to get used to the system
- Uses ItemUserData
Changelog v1.00
- Initial release
Changelog v1.01
- Fixed a stupid bug
Changelog v1.02
- Ported some stuff and added a new function
Changelog v1.03
- Extra functions like recipes and SetItems.
Changelog v.104
- Fixed stuffs
Why was this system even created to begin with?
Blizzard made the item system for warcraft really limited by not having recipes,
set items and more inventory spaces so this was created. This system is designed to
take down the problems faced by many users with items that couldnt be possible. This
is a very useful system for people who want something to replace the item system of warcraft
but yet retain some of the features of it. This has a feature of creating item types in game but
you cannot change the icon due to the warcraft engine. If you have realised for items, you always
have to create new abilities in order to add stats to units but this system creates the abilities
already and you can just create a new ItemType bonus for a item. There are some function interface
for you to manipulate and there will be examples below.
Extra features that you might not know of as of
- Custom item stats for a item, you can have a item type that have the stats generated already but
if you create an item of that and give it a custom stat, the item type bonuses will be ignored.
This can be very useful for dungeon crawlers or other maps like a RPG.
- Recipes
Allows creation of recipes.
- Set Items
Maybe you played too many RPG games and liked those item sets so much that you want them to
be in warcraft. This is the right system for you!. Simply create the ingredients needed for
the event to fire off to get your bonuses when the unit has the items
- Random Item stats
Since with this system you can create a new set of stats for a item, you can generate them
randomly which can be good for RPGs that need randomness although icons cannot be changed.
- Function interface
This system allows you will call a function that you want when you set the correct fields
for the function to fire off. This was made as the user might want to do something to the
unit other then adding stats to it.
- Abilities
Now you can create abilities for items instead of just 1 which was limited but it uses
the slots for hero skills which you might not want. You might have to set abilities for
the item to click if you want to click a item to fire off a ability as doing this in the
warcraft engine is not possible.
Available function are as follow
static method Itemtype takes integer ItemId returns bonus
static method Item takes item whichItem returns bonus
static method Recipe takes integer i1, integer i2, integer i3,integer i4, integer i5, integer i6, integer result returns bonus
static method SetItem takes integer i1, integer i2, integer i3, integer i4, integer i5, integer i6 returns bonus
set d.[struct member] = value
How to use it?
integer ItemId = The ItemId of the item. Remember to use 039;____039; for your rawcodes.
integer Str = The amount of Strength.
integer Agi = The amount of Agility.
integer Int = The amount of Intelligence.
real Damage = The amount of Damage.
real Armor = The amount of Armour
real MaxLife = The max life that you want to increase meaning that you increase the base of the unit health.
real MaxMana = The max mana that you want to increase meaning that you increase the base of the unit mana.
real LifeRegen = The amount of life regen you want to give to the unit.
real ManaRegen = The amount of mana regen you want to give to the unit.
real AttackSpeed = The amount of attack speed you want to give to the unit.
real MoveSpeed = The amount of movement speed you want to give to the unit.
Abilities Section
integer array Abilities[MAX_ABILITIES]
integer array AbilityLevels[MAX_ABILITIES]
private constant integer MAX_ABILITIES = 6
The max amount of abilities you want to give per unit through one item.
integer array AbilityLevels[MAX_ABILITIES]
Whether you want the ability to have levels.
private constant integer BackpackId = 039;BAG1039;
This is the ID of the dummy spell that will be used to detect whether a unit whats to move it to the backpack.
static method Itemtype takes item whichItem returns bonus
You should only use this if you want to generate stats for an Itemtype.
Example of Usage
private function Stats takes unit u returns nothing
call KillUnit(u) (Unit u can be any naming but it must take a unit)
endfunction
set d = bonus.Itemtype(whichItem)
set d.Int = 300
set d.ItemTypePick = Stats
(Notice I do not add a function line infront as you cannot do that)
set d.Abilities[0] = 039;AHtb039; (adds the ability when picked up)
set d.AbilityLevels[0] = value (Note that if the value is 1, you do not have to do this)
It creates properties for the unit in the first line
and the second line generates 300 Int whenever you pickup the item
and removes bonus when you drop it. The third line gives u a function to do
whatever you want to the unit if that function is there else there will be
a syntax error.
static method Item takes item whichItem returns bonus
set d = bonus.Item(whichItem)
set d.Agi = 150
This is about the same as the itemtype but just creating stats for that specific item itself
and the itemtype stats will not be applied. function or struct members used in ItemType
can be used here as well.
static method Recipe takes integer i1, integer i2, integer i3,integer i4, integer i5, integer i6, integer result returns bonus
set d = bonus.Recipe(ingredient 1, ingredient 2 , ingredient 3, ingredient 4, ingredient 5, ingredient 6, your final item)
set d.Damage = 200
Creating recipes will be very simple, for example if you only need 3 items to form a item,
simply leave ingredient 4 to 6 set as 0.
static method SetItem takes integer i1, integer i2, integer i3, integer i4, integer i5, integer i6 returns bonus
set d = bonus.SetItem(ingredient 1, ingredient 2 , ingredient 3, ingredient 4, ingredient 5, ingredient 6)
Somewhat similar to the recipe usage but the items do not get removed and they give u bonuses when
the ingredients are together. You can only have a maximum SetItem type of 2 per unit, one in the
backpack while another in your inventory.
A illustration (for a set item type)
Your inventory Backpack
i1 | i2 i1 | i3
i3 | null i2 | null
null| null null| null
The order of the items do not matter but you must remember only 2 sets of a set itemtype can be
on a unit.
Last but not least, this system can be fatal if you do not create properties for the units picking
the items up. Notice that I do CreateUnitProperties(preplaced unit) for the system to function
properly. Remember this at all times if not the system will bug.
If you still do not get how to use the system, check CISInit, I included some examples on how to do
it.
Thanks for looking through the documention and have a nice day!
System
JASS:
library CIS initializer Init requires Table, UnitProperties, AutoIndex
globals
private constant integer BackpackId = 039;BAG1039;
private constant integer MAX_ABILITIES = 6
private constant string DEFAULTSFX = "Abilities\\Spells\\Items\\AIlm\\AIlmTarget.mdl"
endglobals
globals
private Table DataTable // stores the itemtype data
endglobals
function interface OnPick takes unit target returns nothing
function interface OnDrop takes unit target returns nothing
private function UnitHasItemOfType takes unit whichUnit, integer itemId returns boolean
local integer index = 0
local item indexItem
loop
set indexItem = UnitItemInSlot(whichUnit, index)
if indexItem != null and GetItemTypeId(indexItem) == itemId then
return true
endif
set index = index + 1
exitwhen index > 5
endloop
return false
endfunction
private function UnitHasItemOfTypeBackpack takes backpack d, integer itemId returns boolean
local integer index = 0 // something similar but checks backpack
local integer indexId = 0
loop
set indexId = d.ItemType[index]
if indexId != 0 and indexId == itemId then
return true
endif
set index = index + 1
exitwhen index > 5
endloop
return false
endfunction
struct bonus // just merged everything together, hope that it doesn't break MUI.
static integer Count = 0 // set item count
static bonus array D // set item count
static bonus array R // recipe count
static integer RCount = 0 // recipe count
Table COMBINED // needed so as to have a true or false inside a struct instance while making it MUI
Table Boolean
OnPick ItemTypePick
OnPick CustomItemPick
OnPick SetItemPick
OnPick RecipeCombine
OnDrop ItemTypeDrop
OnDrop CustomItemDrop
OnDrop SetItemDrop
integer ItemId = 0
integer Str = 0
integer Agi = 0
integer Int = 0
real Damage = 0.00
real Armor = 0.00
real MaxLife = 0.00
real MaxMana = 0.00
real LifeRegen = 0.00
real ManaRegen = 0.00
real AttackSpeed = 0.00
real MoveSpeed = 0.00
string SFX
integer array Items[6]
integer result = 0
integer array Abilities[MAX_ABILITIES]
integer array AbilityLevels[MAX_ABILITIES]
static method Itemtype takes integer ItemId returns bonus
local bonus d = bonus.create()
local integer i = 0
loop
set d.Abilities<i> = 0
set d.AbilityLevels<i> = 1
set i = i+1
exitwhen i >= MAX_ABILITIES
endloop
set d.ItemId = ItemId
set DataTable[ItemId] = d
return d
endmethod
static method Item takes item whichItem returns bonus
local bonus d = bonus.create()
local integer i = 0
loop
set d.Abilities<i> = 0
set d.AbilityLevels<i> = 1
set i = i+1
exitwhen i >= MAX_ABILITIES
endloop
call SetItemUserData(whichItem,d)
return d
endmethod
static method SetItem takes integer i1, integer i2, integer i3, integer i4, integer i5, integer i6 returns bonus
local bonus d = bonus.create()
local integer i = 0
set d.Items[0] = i1
set d.Items[1] = i2
set d.Items[2] = i3
set d.Items[3] = i4
set d.Items[4] = i5
set d.Items[5] = i6
loop
set d.Abilities<i> = 0
set d.AbilityLevels<i> = 1
set i = i+1
exitwhen i >= MAX_ABILITIES
endloop
set d.D[d.Count] = d
set d.Count = d.Count + 1
set d.COMBINED = Table.create()
set d.Boolean = Table.create()
return d
endmethod
static method Recipe takes integer i1, integer i2, integer i3,integer i4, integer i5, integer i6, integer result returns bonus
local bonus d = bonus.create()
local integer i = 0
set d.Items[0] = i1
set d.Items[1] = i2
set d.Items[2] = i3
set d.Items[3] = i4
set d.Items[4] = i5
set d.Items[5] = i6
set d.result = result
set d.SFX = DEFAULTSFX
loop
set d.Abilities<i> = 0
set d.AbilityLevels<i> = 1
set i = i+1
exitwhen i >= MAX_ABILITIES
endloop
set d.R[d.RCount] = d
set d.RCount = d.RCount + 1
return d
endmethod
endstruct
//! textmacro CheckAndApply takes VALUE
if d.$VALUE$ != 0 then
set $VALUE$<u> = $VALUE$<u> + d.$VALUE$
endif
//! endtextmacro
//! textmacro CheckAndUnapply takes VALUE
if d.$VALUE$ != 0 then
set $VALUE$<u> = $VALUE$<u> + -1*d.$VALUE$
endif
//! endtextmacro
private function UnitApplyItem takes unit u, bonus d returns nothing
local integer i
//! runtextmacro CheckAndApply("Str")
//! runtextmacro CheckAndApply("Agi")
//! runtextmacro CheckAndApply("Int")
//! runtextmacro CheckAndApply("Damage")
//! runtextmacro CheckAndApply("Armor")
//! runtextmacro CheckAndApply("MaxLife")
//! runtextmacro CheckAndApply("MaxMana")
//! runtextmacro CheckAndApply("LifeRegen")
//! runtextmacro CheckAndApply("ManaRegen")
//! runtextmacro CheckAndApply("AttackSpeed")
//! runtextmacro CheckAndApply("MoveSpeed")
if d.Abilities[0] != 0 then
set i = 0
loop
call UnitAddAbility(u, d.Abilities<i>)
call SetUnitAbilityLevel(u, d.Abilities<i>, d.AbilityLevels<i>)
set i = i+1
exitwhen d.Abilities<i> == 0 or i >= MAX_ABILITIES
endloop
endif
endfunction
private function UnitUnapplyItem takes unit u, bonus d returns nothing
local integer i
//! runtextmacro CheckAndUnapply("Str")
//! runtextmacro CheckAndUnapply("Agi")
//! runtextmacro CheckAndUnapply("Int")
//! runtextmacro CheckAndUnapply("Damage")
//! runtextmacro CheckAndUnapply("Armor")
//! runtextmacro CheckAndUnapply("MaxLife")
//! runtextmacro CheckAndUnapply("MaxMana")
//! runtextmacro CheckAndUnapply("LifeRegen")
//! runtextmacro CheckAndUnapply("ManaRegen")
//! runtextmacro CheckAndUnapply("AttackSpeed")
//! runtextmacro CheckAndUnapply("MoveSpeed")
if d.Abilities[0] != 0 then
set i = 0
loop
call UnitRemoveAbility(u, d.Abilities<i>)
set i = i + 1
exitwhen d.Abilities<i> == 0 or i >= MAX_ABILITIES
endloop
endif
endfunction
private function UnitUnapplyAbilities takes unit u, bonus d returns nothing
local integer i
if d.Abilities[0] != 0 then
set i = 0
loop
call UnitRemoveAbility(u, d.Abilities<i>)
set i = i + 1
exitwhen d.Abilities<i> == 0 or i >= MAX_ABILITIES
endloop
endif
endfunction
private function UnitApplyAbilities takes unit u, bonus d returns nothing
local integer i
if d.Abilities[0] != 0 then
set i = 0
loop
call UnitAddAbility(u, d.Abilities<i>)
call SetUnitAbilityLevel(u, d.Abilities<i>, d.AbilityLevels<i>)
set i = i + 1
exitwhen d.Abilities<i> == 0 or i >= MAX_ABILITIES
endloop
endif
endfunction
private function Check takes bonus d, unit u returns boolean // for checking of SetItems
local integer i = 0
local integer array Items
loop
exitwhen i > 5
set Items<i> = d.Items<i>
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 5
if UnitHasItemOfType(u,Items<i>) then
set Items<i> = 0
endif
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 5
if Items<i> != 0 then
return false
endif
set i = i + 1
endloop
return true
endfunction
private function RecipeCheck takes bonus d, unit u returns boolean
local integer i = 0 // took some reference to artificial's code
local integer array Items
local item array ItemRetrieve
local integer it = 0
local integer j = 0
loop
exitwhen i > 5
set Items<i> = d.Items<i>
set i = i + 1
endloop
set i = 0
loop
set it = GetItemTypeId(UnitItemInSlot(u,i))
loop
if it == Items[j] and it != 0 then
set ItemRetrieve[j] = UnitItemInSlot(u,i)
set Items[j] = 0
exitwhen true
endif
set j = j + 1
exitwhen j > 5
endloop
set j = 0
set i = i + 1
exitwhen i > 5
endloop
set j = 0
set i = 0
loop
if Items<i> != 0 then
loop
exitwhen j > 5
set ItemRetrieve[j] = null
set j = j + 1
endloop
return false
endif
set i = i + 1
exitwhen i > 5
endloop
set i = 0
loop
exitwhen i > 5
if ItemRetrieve<i> != null then
call RemoveItem(ItemRetrieve<i>)
set ItemRetrieve<i> = null
endif
set i = i + 1
endloop
call DestroyEffect(AddSpecialEffect(d.SFX,GetUnitX(u),GetUnitY(u)))
call UnitAddItemById(u,d.result)
return true
endfunction
private function BackCheck takes bonus d,unit u returns boolean
local integer i = 0
local integer array Items
loop
exitwhen i > 5
set Items<i> = d.Items<i>
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 5
if UnitHasItemOfType(u,Items<i>) then
set Items<i> = 0
endif
set i = i + 1
endloop
set i = 0
loop
exitwhen i > 5
if Items<i> != 0 then
return false
endif
set i = i + 1
endloop
return true
endfunction
private function onPickup takes nothing returns nothing
local item t = GetManipulatedItem()
local bonus d = GetItemUserData(t)
local unit u = GetTriggerUnit()
local integer i = 0
local integer r = 0
local boolean UserItem = false
if d != 0 then
call d.CustomItemPick.execute(u)
call UnitApplyItem(u,d)
set UserItem = true
endif
set d = DataTable[GetItemTypeId(t)]
if d > 0 then
if not UserItem then
call d.ItemTypePick.execute(u)
call UnitApplyItem(u,d)
endif
endif
loop
exitwhen r >= d.Count
set d = d.D[r]
if Check(d,u) and d.COMBINED[GetUnitId(u)] == 0 then
call d.SetItemPick.execute(u)
call UnitApplyItem(u,d)
set d.COMBINED[GetUnitId(u)] = 1
endif
set r = r + 1
endloop
set r = 0
loop
exitwhen r >= d.RCount
set d = d.R[r]
if RecipeCheck(d,u) then
call d.RecipeCombine.execute(u)
call UnitApplyItem(u,d)
endif
set r = r + 1
endloop
set t = null
set u = null
endfunction
private struct UnitAttach
unit target
timer t
static method create takes nothing returns UnitAttach
local UnitAttach d = UnitAttach.allocate()
set d.target = GetTriggerUnit()
set d.t = NewTimer()
return d
endmethod
method onDestroy takes nothing returns nothing
call ReleaseTimer(.t)
endmethod
endstruct
private function SetCheck takes nothing returns nothing
local UnitAttach c = GetTimerData(GetExpiredTimer())
local integer r = 0
local bonus d
loop
exitwhen r >= d.Count
set d = d.D[r]
if d.COMBINED[GetUnitId(c.target)] == 1 and not Check(d,c.target) then
call d.SetItemDrop.execute(c.target)
call UnitUnapplyItem(c.target,d)
set d.COMBINED[GetUnitId(c.target)] = 0
endif
set r = r + 1
call c.destroy() // destroy after using
endloop
endfunction
private function onDrop takes nothing returns nothing
local item t = GetManipulatedItem()
local bonus d = GetItemUserData(t)
local unit u = GetTriggerUnit()
local boolean UserItem = false
local UnitAttach c = UnitAttach.create() // for the attaching of the 0. timer
if d != 0 then
call d.CustomItemDrop.execute(u)
call UnitUnapplyItem(u,d)
set UserItem = true
endif
set d = DataTable[GetItemTypeId(t)]
if d > 0 then
if not UserItem then
call d.ItemTypeDrop.execute(u)
call UnitUnapplyItem(u,d)// if there is no custom stats assigned for that unit then we apply the normal basic stats
endif
endif
call SetTimerData(c.t,c) // Stupid blizzard takes dropped item in inventory when the event is run.
call TimerStart(c.t,0.,false,function SetCheck)
set u = null
set t = null
endfunction
struct backpack
integer array ItemType[6]
integer array Charges[6]
integer array UserData[6]
static method create takes unit u returns backpack
local backpack d = backpack.allocate()
local backpack c
local UnitAttach p = UnitAttach.create()
local bonus a
local bonus r
local integer i = 0
local item it
local integer j = 0
local boolean UserData = false
loop
exitwhen j >= bonus.Count
set r = bonus.D[j]
if BackCheck(r,u) then
call UnitApplyItem(u,r)
set r.Boolean[GetUnitId(u)] = 1
endif
set j = j + 1
endloop
loop
set it = UnitItemInSlot(u, i)
set d.ItemType<i> = GetItemTypeId(it)
set d.Charges<i> = GetItemCharges(it)
set d.UserData<i> = GetItemUserData(it)
set c = DataTable[d.ItemType<i>]
set a = GetItemUserData(it)
if a != 0 then
call UnitApplyItem(u,a)
call RemoveItem(it)
call UnitApplyAbilities(u,a)
set UserData = true
endif
if not UserData then
call UnitApplyItem(u,c)
call RemoveItem(it)
call UnitApplyAbilities(u,c)
endif
set i = i + 1
exitwhen i > 5
endloop
call SetTimerData(p.t,p)
call TimerStart(p.t,0.,false,function backpack.apply)
set it = null
return d
endmethod
static method apply takes nothing returns nothing
local UnitAttach d = GetTimerData(GetExpiredTimer())
local bonus r
local integer j = 0
loop
exitwhen j >= bonus.Count
set r = bonus.D[j]
if r.Boolean[GetUnitId(d.target)] == 1 then
call UnitApplyAbilities(d.target,r)
call r.SetItemPick.execute(d.target)
set r.Boolean[GetUnitId(d.target)] = 0
endif
set j = j + 1
endloop
call d.destroy()
endmethod
implement AutoData
endstruct
function ActivateBackpack takes nothing returns nothing
local unit target = GetTriggerUnit()
local backpack d1
local backpack d2 = backpack[target]
local backpack d
local integer i = 0
local integer j = 0
local item it
local bonus a
local bonus r
local boolean done = false
set d1 = backpack.create(target)
if d2 != 0 then
loop
if d2.ItemType<i> != 0 then
set it = UnitAddItemById(target, d2.ItemType<i>)
call SetItemCharges(it, d2.Charges<i>)
call SetItemUserData(it, d2.UserData<i>)
set d = DataTable[d2.ItemType<i>]
call UnitUnapplyItem(target,d)
call UnitApplyAbilities(target,d)
endif
set i = i + 1
exitwhen i > 5
endloop
loop
exitwhen j >= bonus.Count
set r = bonus.D[j]
if BackCheck(r,target) then
call UnitUnapplyItem(target,r)
call UnitApplyAbilities(target,r)
endif
set j = j + 1
endloop
call d2.destroy()
endif
set backpack[target] = d1
set it = null
endfunction
private function BackpackCondition takes nothing returns boolean
return GetSpellAbilityId() == BackpackId
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_PICKUP_ITEM)
call TriggerAddAction(t,function onPickup)
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DROP_ITEM)
call TriggerAddAction(t,function onDrop)
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function BackpackCondition))
call TriggerAddAction(t,function ActivateBackpack)
set DataTable = Table.create()
endfunction
endlibrary</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></u></u></u></u></i></i></i></i></i></i></i></i>