• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[Trigger] Script: Advanced Inventory System

Status
Not open for further replies.
Level 10
Joined
Feb 7, 2005
Messages
409
Hey guys, I'm looking for a way of creating a specialized inventory system for a map I'm working on, here's the basic Idea I had and an idea on how it might, but probably wont work.

If anyone is able to produce such a specialized system for me it would be much appreciated!

Idea: When certain items are acquired (weapons or armour) they will not appear in your inventory slots, but you will still gain all the item bonuses from them, then, you can buy upgrades for your weapons or armour, that will add spells or increase the bonuses provided by them, these bonuses should also be saved to the item itself, or the character (so if the character drops the item it loses all the bonuses, but when picked up retains all bonuses) but if not, it's no big deal

These weapons or armour must also be able to be referenced, so it can be made that you can only have one chest piece, helmet, two handed weapon, two one handed weapons or a one handed weapon and a shield.

It would also be preferred if although they do not appear in your inventory, they can be seen elsewhere (i.e. press escape to view currently equipped items)

This system must also not take up any ability slots on the unit itself

How it Could Be Done (maybe): an item that is preset in the unit's inventory called "Equipment" that works as a spellbook, and stores the abilities and weapons you've purchased, however the problem with this is the limit, which may be too low for containing the upgrades on each item.

The production of such a system is as of yet beyond my knowledge, but I do believe it can be done, somehow...
 
Level 11
Joined
Feb 22, 2006
Messages
752
I created a custom inventory system a while back for an rpg I was making. It allows you to have multiple pages of inventory and equippable items. I didn't add in anything about upgrading your armor, but that can be easily added on. Also, I do use ONE ability on the unit (to show the equipment slots, but that's all it does). I've pasted the code below, and it's a bit messy...this was a while ago, before I truly embraced OOP to the fullest. If you can just take the code that's already here and build on it, great. If not, PM me and I'll see what I can do.


JASS:
library RPGSystem initializer RPGSystem_Init requires CasterSystem, BonusMod

globals

//Configuration

private constant integer NEXTPAGE_ID = 'I000'
private constant integer PREVPAGE_ID = 'I001'
private constant integer NOSLOT_ID = 'I002'
private constant integer DUMMYFILLER_ID = 'I003'

private constant integer EQUIP_NEXTPAGE_ID = 'I005'
private constant integer EQUIP_PREVPAGE_ID = 'I006'

private constant integer CANCEL_ID = 'I004'

private constant integer EQUIPMENU_ABIL_ID = 'A016'

private constant integer ITEM_STAT_BASE = 0x49313030
private constant integer ITEM_STACK_BASE = 0x49323030

//End Configuration

private rpgdata array rpgdata_array
private integer rpgdata_array_count = 0

private item_stat array item_stat_array

private item_stack array item_stack_array

endglobals

struct timerdata
    unit array unit_array[8]
    item array item_array[8]
    real array real_array[8]
    integer array integer_array[8]
endstruct

struct attrdata
    string name = ""
    integer level = 0
    
    static method create takes string name, integer startinglevel returns attrdata
        local attrdata data = attrdata.allocate()
        
        set data.name = name
        set data.level = startinglevel
        
        return data
    endmethod
endstruct

struct skilldata
    string name = ""
    integer level = 0
    real xp = 0.00
    
    static method create takes string name, integer startinglevel, real startingxp returns skilldata
        local skilldata data = skilldata.allocate()
        
        set data.name = name
        set data.level = startinglevel
        set data.xp = startingxp
        
        return data
    endmethod
endstruct

struct item_stack
    integer charge_max = 1
    
    static method create takes integer itemid, integer charge returns item_stack
        local item_stack data = item_stack.allocate()
        
        set item_stack_array[itemid - ITEM_STACK_BASE] = data
        
        set data.charge_max = charge
        
        return data
    endmethod
endstruct

struct item_stat
    integer itemId = 0
    string class = ""
    string itemClass = ""

    integer damageBonus = 0
    integer speedBonus = 0
    integer armorBonus = 0
    integer hpBonus = 0
    integer mindBonus = 0
    
    integer array attrBonus[8]
    integer array skillBonus[16]
    
    string array classRestr[4]
    
    integer array abilBonusId[4]
    
    string onEquip = ""
    string onUnequip = ""
    
    static method addAttributeBonus takes integer id, integer index, integer bonus returns boolean
        local item_stat data = item_stat_array[id - ITEM_STAT_BASE]
        
        if ( index > 7 ) then
            return false
        endif
        
        set data.attrBonus[index] = bonus
        
        return true
    endmethod
    
    static method addSkillBonus takes integer id, integer index, integer bonus returns boolean
        local item_stat data = item_stat_array[id - ITEM_STAT_BASE]
        
        if ( index > 15 ) then
            return false
        endif
        
        set data.skillBonus[index] = bonus
        
        return true
    endmethod
    
    static method addClassRestriction takes integer id, string class returns boolean
        local item_stat data = item_stat_array[id - ITEM_STAT_BASE]
        local integer i = 0
        
        loop
            exitwhen ( i > 3 )
            
            if ( data.classRestr[i] == "" ) then
                set data.classRestr[i] = class
                
                return true
            endif
            
            set i = i + 1
        endloop
        
        return false
    endmethod
    
    static method addAbilityBonus takes integer id, integer abil_id returns boolean
        local item_stat data = item_stat_array[id - ITEM_STAT_BASE]
        local integer i = 0
        
        loop
            exitwhen ( i > 3 )
            
            if ( data.abilBonusId[i] == 0 ) then
                set data.abilBonusId[i] = abil_id
                
                return true
            endif
            
            set i = i + 1
        endloop
        
        return false
    endmethod
    
    static method create takes integer id, string class, string itemclass, integer damage, integer speed, integer armor, integer hp, integer mind, string equip, string unequip returns item_stat
        local item_stat data = item_stat.allocate()
        local integer i = 0
        
        set data.itemId = id
        set data.class = class
        set data.itemClass = itemclass
        set data.damageBonus = damage
        set data.speedBonus = speed
        set data.armorBonus = armor
        set data.hpBonus = hp
        set data.mindBonus = mind
        
        set data.onEquip = equip
        set data.onUnequip = unequip
        
        loop
            exitwhen ( i > 15 )
            
            if ( i < 4 ) then
                set data.classRestr[i] = ""
                set data.abilBonusId[i] = 0
            endif
            
            if ( i < 8 ) then
                set data.attrBonus[i] = 0
            endif
            
            set data.skillBonus[i] = 0
            
            set i = i + 1
        endloop
        
        set item_stat_array[id - ITEM_STAT_BASE] = data
        
        return data
    endmethod
endstruct

struct rpgdata_equip_slot
    string class = "" //The type of equipment slot
    item equip = null //Current item in slot
    integer id = 0
    integer slotId = 0
    
    integer emptyItemId = 0
    
    static method create takes integer id, string class, integer emptyItemId returns rpgdata_equip_slot
        local rpgdata_equip_slot data = rpgdata_equip_slot.allocate()
        
        set data.class = class
        set data.id = id
        
        set data.slotId = ModuloInteger( id, 3 )
        
        set data.emptyItemId = emptyItemId
        
        return data
    endmethod
endstruct

struct rpgdata
    private unit hero = null //the unit that this struct is attached to
    
    private string class = "" //the hero class of the unit
    
    private BonusData bonusMod = 0
    
    //Inventory stuff
    
    private integer slot_total = 6 //the total number of slots in the inventory (max = 64)
    private item array slot_item_array[64] //tracks all items in the inventory
    private integer slot_perpage = 6 //tracks the number of useable slots per (normal) inventory page
    
    private integer equip_total = 0 //the total number of equipment slots (max = 8)
    private rpgdata_equip_slot array equip_slot_array[8] //Tracks all equipment slot structs
    
    private integer currpage = 0 //tracks current page of inventory player is viewing
                                 //-1 indicates equipment page(s)
                                 //-2 indicates socket page
    private integer lastcurrpage = 0 //tracks the last inventory page the player viewed
    private integer currequippage = 0 //tracks current equipment page of inventory
    
    private trigger manipulateitem = null
    private triggeraction manipulateitem_action = null
    
    private trigger itemclick = null
    private triggeraction itemclick_action = null
    
    private timer ordertimer = CreateTimer()
    private timerdata ordertimerdata
    
    //Stats and skills stuff
    
    private integer attr_total = 0 //number of attributes (max = 8)
    private attrdata array attrset[8] //tracks all attributes
    
    private integer skill_total = 0 //number of skills (max = 16)
    private skilldata array skillset[16] //tracks all skills
    
    //Private Methods
    
    static method retrieveData takes unit u returns rpgdata
        local rpgdata data = 0
        local integer i = 0
    
        loop
            exitwhen ( i >= rpgdata_array_count )
            
            set data = rpgdata_array[i]
            
            if ( data.hero == u ) then
                return data
            endif
            
            set i = i + 1
        endloop
        
        return 0
    endmethod
    
    static method retrieveData_Timer takes timer t returns rpgdata
        local rpgdata data = 0
        local integer i = 0
    
        loop
            exitwhen ( i >= rpgdata_array_count )
            
            set data = rpgdata_array[i]
            
            if ( data.ordertimer == t ) then
                set i = 9000
            else
                set data = 0
            endif
            
            set i = i + 1
        endloop
        
        return data
    endmethod
    
    //#GetItemSlotId: returns the slot number a particular item is located in (either standard or extended)
    
    private method GetItemSlotId takes item item_query, boolean extended returns integer
        local integer i = 0
        
        if ( extended ) then
            loop
                exitwhen ( i > .slot_total - 1 )
                
                if ( .slot_item_array[i] == item_query ) then
                    return i
                endif
                
                set i = i + 1
            endloop
            
            return -1
        endif
        
        loop
            exitwhen ( i > 5 )
            
            if ( UnitItemInSlot( .hero, i ) == item_query ) then
                return i
            endif
            
            set i = i + 1
        endloop
        
        return -1
    endmethod
    
    //#GetSlotPage: returns the page number a particular slot is located in
    
    private method GetSlotPage takes integer slot returns integer
        if ( slot > .slot_total ) then
            return -5
        else
            return ( slot / .slot_perpage )
        endif    
    endmethod
    
    //#IsInventoryFull: checks whether a unit's ENTIRE inventory is full
    
    private method IsInventoryFull takes nothing returns boolean
        local integer i = 0
        
        loop
            exitwhen ( i >= .slot_total )
            
            if ( .slot_item_array[i] == null ) then
                return false
            endif
            
            set i = i + 1
        endloop
        
        return true
    endmethod
    
    //#IsPageFull: checks whether a page is full
    
    private method IsPageFull takes integer page returns boolean
        local integer firstslot
        local integer lastslot
        local integer i = 0

        set firstslot = page * .slot_perpage
        set lastslot = ( page + 1 ) * .slot_perpage - 1
            
        if ( lastslot > .slot_total - 1 ) then
            set lastslot = .slot_total - 1
        endif 

        set i = firstslot        
        loop
            exitwhen ( i > lastslot )
                
            if ( .slot_item_array[i] == null ) then
                return false
            endif
                
            set i = i + 1
        endloop
        
        return true
    endmethod
    
    //#MoveItem_Order: handles all "silent" move orders (usually to fix things when a player moves an item he isn't supposed to)
    
    private static method MoveItem_Order takes nothing returns nothing
        local rpgdata data = rpgdata.retrieveData_Timer( GetExpiredTimer() )
        
        call DisableTrigger( data.manipulateitem )
        
        call IssueTargetOrderById( data.hero, data.ordertimerdata.integer_array[0], data.ordertimerdata.item_array[0] )
        
        call EnableTrigger( data.manipulateitem )
    endmethod
    
    //#PageUpdate: updates the currently viewed page and stores the information into array
    
    private method PageUpdate takes nothing returns nothing
        local integer firstslot
        local integer lastslot
        local integer i = 0
        
        if ( .slot_total <= 6 ) then
            loop
                exitwhen ( i > 5 )
                
                set .slot_item_array[i] = UnitItemInSlot( .hero, i )
                
                set i = i + 1
            endloop
            
            return
        endif
        
        set firstslot = .currpage * 4
        set lastslot = .currpage * 4 + 3
        if ( lastslot > .slot_total - 1 ) then
            set lastslot = .slot_total - 1
        endif
        
        loop
            exitwhen ( i > lastslot - firstslot )
                
            set .slot_item_array[.currpage * 4 + i] = UnitItemInSlot( .hero, i )
                
            set i = i + 1
        endloop
    endmethod
    
    //#JumpToPage: most important function; handles all page switching
    
    private method JumpToPage takes integer page returns integer
        local integer firstslot
        local integer lastslot
        local integer i = 0
        
        if ( .slot_total <= 6 ) then //there is only one inventory page
            return .currpage
        endif
        
        if ( page * 4 > .slot_total - 1 ) then //page number is too large
            return .currpage
        endif
        
        if ( .currpage == page ) then //player is already viewing that page
            return .currpage
        endif
        
        call DisableTrigger( .manipulateitem )
        
        if ( page >= 0 ) then //jumping to inventory page
            if ( .currpage == -1 ) then //currently in equipment page
                loop
                    exitwhen ( i > 2 )
                    
                    if ( .equip_slot_array[.currequippage * 3 + i].equip == null ) then //equip slot is empty
                        call RemoveItem( UnitItemInSlot( .hero, i ) )
                    else //equip slot is filled
                        call SetItemDroppable( UnitItemInSlot( .hero, i ), true )
                    
                        call CS_SetItemVisible( UnitItemInSlot( .hero, i ), false )
                    endif
                    
                    set i = i + 1
                endloop
                
                //remove equip menu navigation items
                
                call RemoveItem( UnitItemInSlot( .hero, 3 ) )
                call RemoveItem( UnitItemInSlot( .hero, 4 ) )
                call RemoveItem( UnitItemInSlot( .hero, 5 ) )
                
                set .currpage = page
                set .lastcurrpage = page
                
                if ( .slot_total > 6 ) then
                    call UnitAddItemToSlotById( .hero, PREVPAGE_ID, 4 )
                    call UnitAddItemToSlotById( .hero, NEXTPAGE_ID, 5 )
                    
                    call SetItemCharges( UnitItemInSlot( .hero, 5 ), .currpage + 1 )
                endif
                
                set firstslot = .currpage * .slot_perpage
                set lastslot = ( .currpage + 1 ) * .slot_perpage - 1
                if ( lastslot > .slot_total - 1 ) then
                    set lastslot = .slot_total - 1
                endif
                
                set i = 0
                loop
                    exitwhen ( i > lastslot - firstslot )
                    
                    call CS_SetItemVisible( .slot_item_array[page * .slot_perpage + i], true ) //unhide stored items
                    call UnitAddItem( .hero, .slot_item_array[page * .slot_perpage + i] ) //add item back to unit inventory
                    
                    if ( .slot_item_array[page * .slot_perpage + i] == null ) then //if there is no item to be "unhid", add a dummy item that takes up the space so other items get put into the correct slot
                        call UnitAddItemToSlotById( .hero, DUMMYFILLER_ID, i )
                    endif
                    
                    //call TimerStart( .ordertimer, 0.00, false, function rpgdata.MoveItem_Order ) 
                    //set .ordertimerdata.item_array[0] = .slot_item_array[page * 4 + i]
                    //set .ordertimerdata.integer_array[0] = 852002 + i
                    
                    set i = i + 1
                endloop
                
                set i = 0
                loop
                    exitwhen ( i > lastslot - firstslot )
                    
                    if ( GetItemTypeId( UnitItemInSlot( .hero, i ) ) == DUMMYFILLER_ID ) then //clean up filler items
                        call RemoveItem( UnitItemInSlot( .hero, i ) )
                    endif
                    
                    set i = i + 1
                endloop
                
                if ( ( .currpage + 1 ) * .slot_perpage - 1 > .slot_total - 1 ) then //need to set up inventory slot fillers
                    set i = 1
                    
                    loop
                        exitwhen ( i > ( ( .currpage + 1 ) * .slot_perpage - 1 ) - ( .slot_total - 1 ) )
                        
                        call UnitAddItemToSlotById( .hero, NOSLOT_ID, .slot_perpage - i )
                        
                        set i = i + 1
                    endloop
                endif
                
            else //currently in inventory page  
                set firstslot = .currpage * 4
                set lastslot = .currpage * 4 + 3
                if ( lastslot > .slot_total - 1 ) then
                    set lastslot = .slot_total - 1
                endif
                
                call .PageUpdate() //Just in case...
                
                loop
                    exitwhen ( i > lastslot - firstslot )
                    
                    call CS_SetItemVisible( UnitItemInSlot( .hero, i ), false ) //hide current items
                    
                    set i = i + 1
                endloop
                
                set i = 0
                loop
                    exitwhen ( i > 3 )
                    
                    call RemoveItem( UnitItemInSlot( .hero, i ) ) //remove all items that may be left over (basically slot fillers)
                    
                    set i = i + 1
                endloop
                
                set .currpage = page
                set .lastcurrpage = page
                call SetItemCharges( UnitItemInSlot( .hero, 5 ), .currpage + 1 )
                
                set firstslot = .currpage * 4
                set lastslot = .currpage * 4 + 3
                if ( lastslot > .slot_total - 1 ) then
                    set lastslot = .slot_total - 1
                endif
                
                set i = 0
                loop
                    exitwhen ( i > lastslot - firstslot )
                    
                    call CS_SetItemVisible( .slot_item_array[page * 4 + i], true ) //unhide stored items
                    call UnitAddItem( .hero, .slot_item_array[page * 4 + i] ) //add item back to unit inventory
                    
                    if ( .slot_item_array[page * 4 + i] == null ) then //if there is no item to be "unhid", add a dummy item that takes up the space so other items get put into the correct slot
                        call UnitAddItemToSlotById( .hero, DUMMYFILLER_ID, i )
                    endif
                    
                    //call TimerStart( .ordertimer, 0.00, false, function rpgdata.MoveItem_Order ) 
                    //set .ordertimerdata.item_array[0] = .slot_item_array[page * 4 + i]
                    //set .ordertimerdata.integer_array[0] = 852002 + i
                    
                    set i = i + 1
                endloop
                
                set i = 0
                loop
                    exitwhen ( i > lastslot - firstslot )
                    
                    if ( GetItemTypeId( UnitItemInSlot( .hero, i ) ) == DUMMYFILLER_ID ) then //clean up filler items
                        call RemoveItem( UnitItemInSlot( .hero, i ) )
                    endif
                    
                    set i = i + 1
                endloop
                
                if ( .currpage * 4 + 3 > .slot_total - 1 ) then //need to set up inventory slot fillers
                    set i = 1
                    
                    loop
                        exitwhen ( i > ( .currpage * 4 + 3 ) - ( .slot_total - 1 ) )
                        
                        call UnitAddItemToSlotById( .hero, NOSLOT_ID, 4 - i )
                        
                        set i = i + 1
                    endloop
                endif
                
                call EnableTrigger( .manipulateitem )
                
                return .currpage
            endif
        endif
        
        call EnableTrigger( .manipulateitem )
        
        return .currpage
    endmethod
    
    private method JumpToEquipPage takes integer page returns integer
        local integer newpage = page
        local integer firstslot
        local integer lastslot
        local integer i = 0
        
        if ( .currpage == -1 ) then
            if ( page == -1 ) then
                return .currequippage
            endif
            
            call DisableTrigger( .manipulateitem )
            
            loop
                exitwhen ( i > 2 )
                    
                if ( .equip_slot_array[i] == 0 ) then //that slot position has no equipment slot...
                    call RemoveItem( UnitItemInSlot( .hero, i ) )
                else
                    if ( .equip_slot_array[.currequippage * 3 + i].equip == null ) then //equip slot is empty
                        call RemoveItem( UnitItemInSlot( .hero, i ) )
                    else //equip slot is filled
                        call SetItemDroppable( UnitItemInSlot( .hero, i ), true )
                    
                        call CS_SetItemVisible( UnitItemInSlot( .hero, i ), false )
                    endif
                endif
                    
                set i = i + 1
            endloop
            
            set i = newpage * 3
            loop
                exitwhen ( i > ( newpage + 1 ) * 3 - 1 )
            
                if ( .equip_slot_array[i] == 0 ) then //that slot position has no equipment slot...
                    call UnitAddItemToSlotById( .hero, NOSLOT_ID, ModuloInteger( i, 3 ) )
                else
                    if ( .equip_slot_array[i].equip == null ) then //equipment slot is empty
                        call UnitAddItemToSlotById( .hero, .equip_slot_array[i].emptyItemId, .equip_slot_array[i].slotId )
                    else //equipment slot is filled
                        call CS_SetItemVisible( .equip_slot_array[i].equip, true )
                        call UnitAddItem( .hero, .equip_slot_array[i].equip )
                        call SetItemDroppable( .equip_slot_array[i].equip, false )
                    endif
                endif
            
                set i = i + 1
            endloop
            
            set .currequippage = newpage
            
            call SetItemCharges( UnitItemInSlot( .hero, 5 ), .currequippage + 1 )
            
            call EnableTrigger( .manipulateitem )
            
            return .currequippage
        endif
        
        set firstslot = .currpage * .slot_perpage
        set lastslot = (.currpage + 1 ) * .slot_perpage - 1
        if ( lastslot > .slot_total - 1 ) then
            set lastslot = .slot_total - 1
        endif
                
        call .PageUpdate() //Just in case...
        
        call DisableTrigger( .manipulateitem )
                
        loop
            exitwhen ( i > lastslot - firstslot )
                    
            call CS_SetItemVisible( UnitItemInSlot( .hero, i ), false ) //hide current items
                    
            set i = i + 1
        endloop
                
        set i = 0
        loop
            exitwhen ( i > 3 )
                    
            call RemoveItem( UnitItemInSlot( .hero, i ) ) //remove all items that may be left over (basically slot fillers)
                    
            set i = i + 1
        endloop
        
        if ( .slot_total > 6 ) then //remove next/prev page items
            call RemoveItem( UnitItemInSlot( .hero, 4 ) )
            call RemoveItem( UnitItemInSlot( .hero, 5 ) )
        endif
        
        //add the equipment menu navigation items
        
        call UnitAddItemToSlotById( .hero, CANCEL_ID, 3 )
        call UnitAddItemToSlotById( .hero, EQUIP_PREVPAGE_ID, 4 )
        call UnitAddItemToSlotById( .hero, EQUIP_NEXTPAGE_ID, 5 )
        
        if ( page == -1 ) then
            set newpage = .currequippage
        endif
        
        set i = newpage * 3
        loop
            exitwhen ( i > ( newpage + 1 ) * 3 - 1 )
            
            if ( .equip_slot_array[i] == 0 ) then //that slot position has no equipment slot...
                call UnitAddItemToSlotById( .hero, NOSLOT_ID, ModuloInteger( i, 3 ) )
            else
                if ( .equip_slot_array[i].equip == null ) then //equipment slot is empty
                    call UnitAddItemToSlotById( .hero, .equip_slot_array[i].emptyItemId, .equip_slot_array[i].slotId )
                else //equipment slot is filled
                    call CS_SetItemVisible( .equip_slot_array[i].equip, true )
                    call UnitAddItem( .hero, .equip_slot_array[i].equip )
                    call SetItemDroppable( .equip_slot_array[i].equip, false )
                endif
            endif
            
            set i = i + 1
        endloop
        
        call SetItemCharges( UnitItemInSlot( .hero, 5 ), .currequippage + 1 )
        
        call EnableTrigger( .manipulateitem )
        
        set .currpage = -1
        
        return .currequippage
    endmethod
    
    private method Equip_Bonuses_Add takes item equipitem returns nothing
        local item_stat data = item_stat_array[GetItemTypeId( equipitem ) - 0x49313030]
        local integer damage = 0
        local integer speed = 0
        local integer armor = 0
        local integer hp = 0
        local integer mind = 0
        local integer i = 0
        
        //add attribute and skill bonuses first
        loop
            exitwhen ( i > 15 )
            
            if ( i < 8 ) then
                set .attrset[i].level = .attrset[i].level + data.attrBonus[i]
            endif
            
            set .skillset[i].level = .skillset[i].level + data.skillBonus[i]
            
            set i = i + 1
        endloop
        
        //adjust bonus for attribute and skills
        if ( data.itemClass == "blade" ) then
            set damage = data.damageBonus + R2I( data.damageBonus * .attrset[0].level * 0.01 ) + R2I( data.damageBonus * .skillset[0].level * 0.02 )
            set speed = data.speedBonus + R2I( 1 * .attrset[2].level ) + R2I( data.speedBonus * .skillset[0].level * 0.02 )
            set armor = data.armorBonus
            set hp = data.hpBonus
            set mind = data.mindBonus
        elseif ( data.itemClass == "blunt" ) then
            set damage = data.damageBonus + R2I( data.damageBonus * .attrset[0].level * 0.01 ) + R2I( data.damageBonus * .skillset[1].level * 0.04 )
            set speed = data.speedBonus + R2I( 1 * .attrset[2].level ) + R2I( data.speedBonus * .skillset[1].level * 0.01 )
            set armor = data.armorBonus
            set hp = data.hpBonus
            set mind = data.mindBonus
        elseif ( data.itemClass == "ranged" ) then
            set damage = data.damageBonus + R2I( data.damageBonus * .attrset[2].level * 0.01 ) + R2I( data.damageBonus * .skillset[1].level * 0.04 )
            set speed = data.speedBonus + R2I( 1 * .attrset[2].level ) + R2I( data.speedBonus * .skillset[4].level * 0.015 )
            set armor = data.armorBonus
            set hp = data.hpBonus
            set mind = data.mindBonus
        elseif ( data.itemClass == "martial" ) then
            set damage = data.damageBonus + R2I( data.damageBonus * .attrset[0].level * 0.01 ) + R2I( data.damageBonus * .skillset[1].level * 0.01 )
            set speed = data.speedBonus + R2I( 1 * .attrset[2].level ) + R2I( data.speedBonus * .skillset[5].level * 0.04 )
            set armor = data.armorBonus
            set hp = data.hpBonus
            set mind = data.mindBonus
        else
            set damage = data.damageBonus
            set speed = data.speedBonus
            set armor = data.armorBonus
            set hp = data.hpBonus
            set mind = data.mindBonus
        endif
        
        call SetHeroStr( .hero, GetHeroStr( .hero, false ) + damage, true )
        call SetHeroAgi( .hero, GetHeroAgi( .hero, false ) + speed, true )
        call SetHeroInt( .hero, GetHeroInt( .hero, false ) + mind, true )
        
        call .bonusMod.addBonus( .hero, 1, armor )
        call .bonusMod.addBonus( .hero, 2, hp )            
    endmethod
    
    private method Equip_Bonuses_Remove takes item equipitem returns nothing
        local item_stat data = item_stat_array[GetItemTypeId( equipitem ) - ITEM_STAT_BASE]
        local integer damage = 0
        local integer speed = 0
        local integer armor = 0
        local integer hp = 0
        local integer mind = 0
        local integer i = 0
        
        //adjust bonus for attribute and skills
        if ( data.itemClass == "blade" ) then
            set damage = data.damageBonus + R2I( data.damageBonus * .attrset[0].level * 0.01 ) + R2I( data.damageBonus * .skillset[0].level * 0.02 )
            set speed = data.speedBonus + R2I( 1 * .attrset[2].level ) + R2I( data.speedBonus * .skillset[0].level * 0.02 )
            set armor = data.armorBonus
            set hp = data.hpBonus
            set mind = data.mindBonus
        elseif ( data.itemClass == "blunt" ) then
            set damage = data.damageBonus + R2I( data.damageBonus * .attrset[0].level * 0.01 ) + R2I( data.damageBonus * .skillset[1].level * 0.04 )
            set speed = data.speedBonus + R2I( 1 * .attrset[2].level ) + R2I( data.speedBonus * .skillset[1].level * 0.01 )
            set armor = data.armorBonus
            set hp = data.hpBonus
            set mind = data.mindBonus
        elseif ( data.itemClass == "ranged" ) then
            set damage = data.damageBonus + R2I( data.damageBonus * .attrset[2].level * 0.01 ) + R2I( data.damageBonus * .skillset[1].level * 0.04 )
            set speed = data.speedBonus + R2I( 1 * .attrset[2].level ) + R2I( data.speedBonus * .skillset[4].level * 0.015 )
            set armor = data.armorBonus
            set hp = data.hpBonus
            set mind = data.mindBonus
        elseif ( data.itemClass == "martial" ) then
            set damage = data.damageBonus + R2I( data.damageBonus * .attrset[0].level * 0.01 ) + R2I( data.damageBonus * .skillset[1].level * 0.01 )
            set speed = data.speedBonus + R2I( 1 * .attrset[2].level ) + R2I( data.speedBonus * .skillset[5].level * 0.04 )
            set armor = data.armorBonus
            set hp = data.hpBonus
            set mind = data.mindBonus
        else
            set damage = data.damageBonus
            set speed = data.speedBonus
            set armor = data.armorBonus
            set hp = data.hpBonus
            set mind = data.mindBonus
        endif
        
        call SetHeroStr( .hero, GetHeroStr( .hero, false ) - damage, true )
        call SetHeroAgi( .hero, GetHeroAgi( .hero, false ) - speed, true )
        call SetHeroInt( .hero, GetHeroInt( .hero, false ) - mind, true )
        
        call .bonusMod.addBonus( .hero, 1, 0 - armor )
        call .bonusMod.addBonus( .hero, 2, 0 - hp )
        
        //subtract attribute and skill bonuses first
        loop
            exitwhen ( i > 15 )
            
            if ( i < 8 ) then
                set .attrset[i].level = .attrset[i].level - data.attrBonus[i]
            endif
            
            set .skillset[i].level = .skillset[i].level - data.skillBonus[i]
            
            set i = i + 1
        endloop
    endmethod
    
    private method Equip_Bonuses_Update takes nothing returns nothing
    endmethod
    
    private method Item_Equip_Swap takes item equipitem, integer equip_slot, integer slot returns nothing
        call DisableTrigger( .manipulateitem )
        
        call CS_SetItemVisible( equipitem, false )
        
        call CS_SetItemVisible( .equip_slot_array[equip_slot].equip, true )
        call UnitAddItem( .hero, .equip_slot_array[equip_slot].equip )
        
        call EnableTrigger( .manipulateitem )
        
        call .Equip_Bonuses_Remove( .equip_slot_array[equip_slot].equip )
        
        call TimerStart( .ordertimer, 0.00, false, function rpgdata.MoveItem_Order )
        set .ordertimerdata.item_array[0] = .equip_slot_array[equip_slot].equip
        set .ordertimerdata.integer_array[0] = 852002 + ModuloInteger( slot, .slot_perpage )
        
        set .slot_item_array[slot] = .equip_slot_array[equip_slot].equip
        set .equip_slot_array[equip_slot].equip = equipitem
        
        call .Equip_Bonuses_Add( equipitem )
    endmethod
    
    //#Item_Unequip: gets called when a player clicks on an item to unequip
    
    private method Item_Unequip takes item equipitem, integer slot returns nothing
        local integer i = 0
        local integer i2 = 0
        local boolean exit = false
        
        loop
            exitwhen ( i > .equip_total - 1 )
            
            if ( .equip_slot_array[i].equip == equipitem ) then
                if ( slot == -1 ) then //unequip item to the first open inventory slot
                    if ( .IsInventoryFull() ) then //inventory is currently full
                        call DisableTrigger( .manipulateitem )
                        
                        call SetItemDroppable( equipitem, true )
                        
                        call UnitRemoveItem( .hero, equipitem )
                        call SetItemPosition( equipitem, GetUnitX( .hero ), GetUnitY( .hero ) )
                        
                        call UnitAddItemToSlotById( .hero, .equip_slot_array[i].emptyItemId, .equip_slot_array[i].slotId )
                        
                        call EnableTrigger( .manipulateitem )
                        
                        set .equip_slot_array[i].equip = null
                        
                        call CS_Error( GetOwningPlayer( .hero ), "Inventory is full; your item has been dropped on the ground." )
                    else //inventory is not full
                        call DisableTrigger( .manipulateitem )
                        
                        call SetItemDroppable( equipitem, true )
                        
                        call CS_SetItemVisible( equipitem, false )
                        
                        call UnitAddItemToSlotById( .hero, .equip_slot_array[i].emptyItemId, .equip_slot_array[i].slotId )
                        
                        call EnableTrigger( .manipulateitem )
                        
                        set .equip_slot_array[i].equip = null
                        loop
                            exitwhen ( i2 > .slot_total - 1 or exit )
                            
                            if ( .slot_item_array[i2] == null ) then //inventory slot is empty
                                set .slot_item_array[i2] = equipitem
                                
                                set exit = true
                            endif
                            
                            set i2 = i2 + 1
                        endloop
                    endif
                else
                endif
                
                call .Equip_Bonuses_Remove( equipitem )
            endif
            
            set i = i + 1
        endloop
        
    endmethod
    
    //#Item_Equip: gets called when a player clicks an item to equip
    
    private method Item_Equip takes item equipitem, integer itemid returns nothing
        local item_stat itemdata = item_stat_array[itemid - ITEM_STAT_BASE]
        local integer firstslot = -1
        local integer i = 0
        local boolean exit = false
            
            //check to see if unit can equip the item
            
            if ( itemdata.classRestr[0] != "" ) then
                loop
                    exitwhen ( i > 3 or exit )
                    
                    if ( itemdata.classRestr[i] == .class ) then
                        set exit = true
                    endif
                    
                    set i = i + 1
                endloop
                
                if ( exit == false ) then //unit cannot equip item
                    call CS_Error( GetOwningPlayer( .hero ), "You cannot equip this item." )
                    
                    return
                endif
            endif
            
            //check to see if unit has appropriate equipment slot for the item
            
            set i = 0
            set exit = false
            loop
                exitwhen ( i > .equip_total - 1 )
                
                if ( .equip_slot_array[i].class == itemdata.class ) then
                    if ( .equip_slot_array[i].equip == null ) then //equipment slot is empty
                        call DisableTrigger( .manipulateitem )
                        
                        set .slot_item_array[.GetItemSlotId( equipitem, true )] = null
                        set .equip_slot_array[i].equip = equipitem
                        call CS_SetItemVisible( equipitem, false )
                        
                        call .Equip_Bonuses_Add( equipitem )
                        
                        call EnableTrigger( .manipulateitem )
                        
                        return
                    else //equipment slot is full
                        if ( firstslot == -1 ) then
                            set firstslot = i
                        endif
                    endif
                endif
                
                set i = i + 1
            endloop
            
            if ( firstslot == -1 ) then //for some reason the unit does not have the right type of equipment slot
                call CS_Error( GetOwningPlayer( .hero ), "You cannot equip this item." )
                
                return
            endif
            
            //If method has not returned at this point, it means the unit has the correct type of equipment slot, but they are all full, so we take the first one we found, remove the currently equipped item, and then equip the new item
            call .Item_Equip_Swap( equipitem, firstslot, .GetItemSlotId( equipitem, true ) )            
    endmethod
    
    //#Item_Stack: runs when a player moves a stackable item on top of another stackable item
    
    private method Item_Stack takes item sourceitem, integer itemid, integer orderid returns nothing
        local item_stack data = item_stack_array[itemid - ITEM_STACK_BASE]
        local item targetitem = UnitItemInSlot( .hero, orderid - 852002 )
        local integer slot = orderid - 852002
        local integer source_charge
        local integer target_charge
        
        if ( slot == .GetItemSlotId( sourceitem, false ) ) then //player moved item onto the same slot        
            set targetitem = null
            
            return
        endif
        
        if ( itemid == GetItemTypeId( targetitem ) ) then //the two itemtypes are the same
            set source_charge = GetItemCharges( sourceitem )
            set target_charge = GetItemCharges( targetitem )
            
            if ( source_charge == data.charge_max or target_charge == data.charge_max ) then
                set targetitem = null
            
                return
            endif
            
            if ( source_charge + target_charge <= data.charge_max ) then
                call DisableTrigger( .manipulateitem )
                
                call RemoveItem( targetitem )
                
                call SetItemCharges( sourceitem, source_charge + target_charge )
                
                call EnableTrigger( .manipulateitem )
            else
                call SetItemCharges( sourceitem, data.charge_max )
                call SetItemCharges( targetitem, source_charge + target_charge - data.charge_max )
            endif
        elseif ( targetitem == null ) then //there is no item in the target slot
            if ( GetItemCharges( sourceitem ) > 1 ) then
                call DisableTrigger( .manipulateitem )
                
                call UnitAddItemToSlotById( .hero, itemid, slot )
                call SetItemCharges( UnitItemInSlot( .hero, slot ), GetItemCharges( sourceitem ) - 1 )
                call SetItemCharges( sourceitem, 1 )
                
                call EnableTrigger( .manipulateitem )
            endif
        endif
        
        set targetitem = null
    endmethod
    
    //#ItemClick_Actions: run when a player clicks on an item (or the Equip Menu ability)
    
    private static method ItemClick_Actions takes nothing returns nothing
        local integer itemid = GetItemTypeId( GetManipulatedItem() )
        local integer newpage
        local rpgdata data = rpgdata.retrieveData( GetTriggerUnit() )
        
        if ( GetTriggerEventId() == EVENT_UNIT_SPELL_EFFECT and GetSpellAbilityId() == EQUIPMENU_ABIL_ID ) then //player clicked on Equip Menu ability
            if ( data.currpage == -1 ) then //player is already in equipment menu
            
                return
            else
                call data.JumpToEquipPage( -1 )
                
                return
            endif
        endif
        
        if ( itemid == PREVPAGE_ID ) then //player clicked on "previous page" item        
            if ( data.currpage - 1 < 0 ) then
                set newpage = data.GetSlotPage( data.slot_total - 1 )
            else
                set newpage = data.currpage - 1
            endif
            
            call data.JumpToPage( newpage )
            
            return
        elseif ( itemid == NEXTPAGE_ID ) then //player clicked on "next page" item
            if ( data.currpage + 1 > data.GetSlotPage( data.slot_total - 1 ) ) then
                set newpage = 0
            else
                set newpage = data.currpage + 1
            endif
            
            call data.JumpToPage( newpage )
            
            return
        elseif ( itemid == EQUIP_PREVPAGE_ID ) then //player clicked on equip menu "prev page" item
            if ( data.currequippage - 1 < 0 ) then
                set newpage = 2
            else
                set newpage = data.currequippage - 1
            endif
            
            call data.JumpToEquipPage( newpage )
            
            return
        elseif ( itemid == EQUIP_NEXTPAGE_ID ) then //player clicked on equip menu "next page" item
            if ( data.currequippage + 1 > 2 ) then
                set newpage = 0
            else
                set newpage = data.currequippage + 1
            endif
            
            call data.JumpToEquipPage( newpage )
            
            return
        elseif ( itemid == CANCEL_ID ) then //player clicked on "cancel" item
            call data.JumpToPage( data.lastcurrpage )
            
            return
        endif
        
        if ( itemid >= ITEM_STAT_BASE and itemid < ITEM_STACK_BASE ) then //player clicked on an equippable item  
            if ( data.currpage >= 0 ) then //player is in normal inventory
                call data.Item_Equip( GetManipulatedItem(), itemid )
            else //player is in equipment page
                call data.Item_Unequip( GetManipulatedItem(), -1 )
            endif
        endif
    endmethod
    
    //#TargetOrder_Child: run by ManipulateItem_Actions when a player moves an item around in an inventory
    
    private static method TargetOrder_Child takes nothing returns nothing
        local rpgdata data = rpgdata.retrieveData_Timer( GetExpiredTimer() )
        
        call data.PageUpdate()

    endmethod
    
    //#DropItem_Child: run by ManipulateItem_Actions when a unit drops an item
    
    private static method DropItem_Child takes nothing returns nothing
        local rpgdata data = rpgdata.retrieveData_Timer( GetExpiredTimer() )
        local item targetitem = data.ordertimerdata.item_array[0]
        
        if ( GetItemTypeId( targetitem ) == PREVPAGE_ID or GetItemTypeId( targetitem ) == NEXTPAGE_ID ) then //player is trying to drop item he is not supposed to drop
            call DisableTrigger( data.manipulateitem )
                
            if ( GetItemTypeId( targetitem ) == PREVPAGE_ID ) then
                call UnitAddItemToSlotById( data.hero, PREVPAGE_ID, 4 )
            else
                call UnitAddItemToSlotById( data.hero, NEXTPAGE_ID, 5 )
                call SetItemCharges( GetItemOfTypeFromUnitBJ( data.hero, NEXTPAGE_ID ), data.currpage + 1 )
            endif
            
            call RemoveItem( targetitem )
                
            call EnableTrigger( data.manipulateitem )
            
            set targetitem = null
            
            return
        endif
        
        call data.PageUpdate()
        
        set targetitem = null
    endmethod
    
    //#ManipulateItem_Actions: runs when a player does something to an item (except click)
    
    private static method ManipulateItem_Actions takes nothing returns nothing
        local eventid trigevent = GetTriggerEventId()
        local unit hero = GetTriggerUnit()
        local item targetitem
        local rpgdata data = rpgdata.retrieveData( hero )
        local integer i = 0
        local integer prevslot
        local boolean exit = false
        
        if ( trigevent == EVENT_UNIT_ISSUED_TARGET_ORDER and GetOrderTargetItem() != null ) then //unit is trying to pick up item or move item in inventory
            set targetitem = GetOrderTargetItem()
            
            if ( IsItemOwned( targetitem ) ) then //unit is moving item in inventory
                if ( GetItemTypeId( targetitem ) == PREVPAGE_ID or GetItemTypeId( targetitem ) == NEXTPAGE_ID ) then //player is trying to move item he is not supposed to move
                    if ( GetIssuedOrderId() == 852006 and GetItemTypeId( targetitem ) == PREVPAGE_ID ) then //player moved previous page item onto same slot
                        call EnableTrigger( data.manipulateitem )
                        
                        set trigevent = null
                        set hero = null
                        set targetitem = null
                        
                        return
                    elseif ( GetIssuedOrderId() == 852007 and GetItemTypeId( targetitem ) == NEXTPAGE_ID ) then //player moved next page item onto same slot
                        call EnableTrigger( data.manipulateitem )
                        
                        set trigevent = null
                        set hero = null
                        set targetitem = null
                    
                        return
                    endif
                
                    call TimerStart( data.ordertimer, 0.00, false, function rpgdata.MoveItem_Order )
                    set data.ordertimerdata.item_array[0] = targetitem
                    
                    if ( GetItemTypeId( targetitem ) == PREVPAGE_ID ) then
                        set data.ordertimerdata.integer_array[0] = 852006
                    else
                        set data.ordertimerdata.integer_array[0] = 852007
                    endif
                    
                    set trigevent = null
                    set hero = null
                    set targetitem = null
                    
                    return
                endif
                
                if ( GetIssuedOrderId() == 852006 and data.slot_total > 6 ) then //player moved item onto previous page item
                    set prevslot = data.GetItemSlotId( targetitem, true )
                    
                    if ( data.currpage - 1 < 0 ) then
                        set i = data.slot_total - 1
                    else
                        set i = data.currpage * data.slot_perpage - 1
                    endif
                    
                    loop
                        exitwhen ( i < 0 or exit )
                        
                        if ( data.slot_item_array[i] == null ) then
                            set i = i + 1
                            set exit = true
                        endif
                        
                        set i = i - 1
                    endloop
                    
                    if ( exit == false ) then
                        set i = data.slot_total - 1
                        loop
                            exitwhen ( i < ( ( data.currpage + 1 ) * data.slot_perpage ) or exit )
                        
                            if ( data.slot_item_array[i] == null ) then
                                set i = i + 1
                                set exit = true
                            endif
                        
                            set i = i - 1
                        endloop
                    endif
                    
                    if ( exit == false ) then //there are no open inventory slots on other pages
                        call CS_Error( GetOwningPlayer( data.hero ), "There are no open inventory slots." )
                        
                        call TimerStart( data.ordertimer, 0.00, false, function rpgdata.MoveItem_Order )
                        set data.ordertimerdata.item_array[0] = GetItemOfTypeFromUnitBJ( data.hero, PREVPAGE_ID )
                        set data.ordertimerdata.integer_array[0] = 852006
                        
                        set trigevent = null
                        set hero = null
                        set targetitem = null
                        
                        return
                    endif
                    
                    call DisableTrigger( data.manipulateitem )
                    
                    call CS_SetItemVisible( targetitem, false )
                    
                    call EnableTrigger( data.manipulateitem )
                    
                    call TimerStart( data.ordertimer, 0.00, false, function rpgdata.MoveItem_Order )
                    set data.ordertimerdata.item_array[0] = GetItemOfTypeFromUnitBJ( data.hero, PREVPAGE_ID )
                    set data.ordertimerdata.integer_array[0] = 852006
                    
                    set data.slot_item_array[i] = targetitem
                    set data.slot_item_array[prevslot] = null
                    
                    set trigevent = null
                    set hero = null
                    set targetitem = null
                        
                    return                    
                elseif ( GetIssuedOrderId() == 852007 and data.slot_total > 6 ) then //player moved item onto next page item
                    set prevslot = data.GetItemSlotId( targetitem, true )
                    
                    if ( data.currpage + 1 > data.GetSlotPage( data.slot_total - 1 ) ) then
                        set i = 0
                    else
                        set i = ( data.currpage + 1 ) * data.slot_perpage
                    endif
                    
                    loop
                        exitwhen ( i > data.slot_total or exit )
                        
                        if ( data.slot_item_array[i] == null ) then
                            set i = i - 1
                            set exit = true
                        endif
                        
                        set i = i + 1
                    endloop
                    
                    if ( exit == false ) then
                        set i = 0
                        loop
                            exitwhen ( i > ( data.currpage * data.slot_perpage - 1 ) or exit )
                        
                            if ( data.slot_item_array[i] == null ) then
                                set i = i - 1
                                set exit = true
                            endif
                        
                            set i = i + 1
                        endloop
                    endif
                    
                    if ( exit == false ) then //there are no open inventory slots on other pages
                        call CS_Error( GetOwningPlayer( data.hero ), "There are no open inventory slots." )
                        
                        call TimerStart( data.ordertimer, 0.00, false, function rpgdata.MoveItem_Order )
                        set data.ordertimerdata.item_array[0] = GetItemOfTypeFromUnitBJ( data.hero, NEXTPAGE_ID )
                        set data.ordertimerdata.integer_array[0] = 852007
                        
                        set trigevent = null
                        set hero = null
                        set targetitem = null
                        
                        return
                    endif
                    
                    call DisableTrigger( data.manipulateitem )
                    
                    call CS_SetItemVisible( targetitem, false )
                    
                    call EnableTrigger( data.manipulateitem )
                    
                    call TimerStart( data.ordertimer, 0.00, false, function rpgdata.MoveItem_Order )
                    set data.ordertimerdata.item_array[0] = GetItemOfTypeFromUnitBJ( data.hero, NEXTPAGE_ID )
                    set data.ordertimerdata.integer_array[0] = 852007
                    
                    set data.slot_item_array[i] = targetitem
                    set data.slot_item_array[prevslot] = null
                    
                    set trigevent = null
                    set hero = null
                    set targetitem = null
                        
                    return
                else //player moved item from one slot to another
                    if ( GetItemTypeId( targetitem ) >= 0x49323030 and GetItemTypeId( targetitem ) < 0x49333030 ) then //player moved a stackable item
                        call data.Item_Stack( targetitem, GetItemTypeId( targetitem ), GetIssuedOrderId() )
                    endif
                    
                    call TimerStart( data.ordertimer, 0.02, false, function rpgdata.TargetOrder_Child )
                    
                    set trigevent = null
                    set hero = null
                    set targetitem = null
                    
                    return
                endif
            else //Unit is trying to pick up item
                if ( data.IsInventoryFull() ) then //unit's inventory is full (ACTUALLY full)
                    call CS_Error( GetOwningPlayer( hero ), "Inventory is full" )
                    
                    set trigevent = null
                    set hero = null
                    set targetitem = null
                    
                    return
                endif
                
                if ( data.currpage < 0 ) then //player is not viewing normal inventory
                    set i = 0
                    loop
                        exitwhen ( i > data.slot_total )
                        
                        if ( data.slot_item_array[i] == null ) then
                            call data.JumpToPage( data.GetSlotPage( i ) )
                            
                            call IssueTargetOrder( hero, "pickup", targetitem )
                            
                            set trigevent = null
                            set hero = null
                            set targetitem = null
                            
                            return
                        endif
                        
                        set i = i + 1
                    endloop
                endif
            
                if ( data.IsPageFull( data.currpage ) ) then //current page is full; jump to next page with empty slot
                    set i = data.currpage * 4 + 4
                    loop
                        exitwhen ( i > data.slot_total )
                        
                        if ( data.slot_item_array[i] == null ) then
                            call data.JumpToPage( data.GetSlotPage( i ) )
                            
                            call IssueTargetOrder( hero, "pickup", targetitem )
                            
                            set trigevent = null
                            set hero = null
                            set targetitem = null
                            
                            return
                        endif
                        
                        set i = i + 1
                    endloop
                    
                    set i = 0
                    loop
                        exitwhen ( i > data.currpage * 4 - 1 )
                        
                        if ( data.slot_item_array[i] == null ) then
                            call data.JumpToPage( data.GetSlotPage( i ) )
                            
                            call IssueTargetOrder( hero, "pickup", targetitem )
                            
                            set trigevent = null
                            set hero = null
                            set targetitem = null
                            
                            return
                        endif
                        
                        set i = i + 1
                    endloop
                endif
            endif
            
        elseif ( trigevent == EVENT_UNIT_PICKUP_ITEM ) then  //unit has picked up item
            call data.PageUpdate()
        elseif ( trigevent == EVENT_UNIT_DROP_ITEM ) then //unit has dropped item from inventory
            set targetitem = GetManipulatedItem()
            
            call TimerStart( data.ordertimer, 0.01, false, function rpgdata.DropItem_Child )
            set data.ordertimerdata.item_array[0] = targetitem
                
            set trigevent = null
            set hero = null
            set targetitem = null
                
            return
        endif
        
        set trigevent = null
        set hero = null
        set targetitem = null
    endmethod
    
    method onDestroy takes nothing returns nothing
        local integer i = 0
        
        loop
            exitwhen ( i >= rpgdata_array_count )
            
            if ( rpgdata_array[i].hero == .hero ) then
                set rpgdata_array[i] = rpgdata_array[rpgdata_array_count - 1]
                set rpgdata_array[rpgdata_array_count - 1] = 0
                set rpgdata_array_count = rpgdata_array_count - 1
                
                set i = 9000
            endif
            
            set i = i + 1
        endloop        
    
        call TriggerRemoveAction( .manipulateitem, .manipulateitem_action )
        call DestroyTrigger( .manipulateitem )
        call DestroyTimer( .ordertimer )
    endmethod
    
    //Public Methods
    
    static method addAttribute takes unit hero, string name, integer startinglevel returns boolean
        local rpgdata data = rpgdata.retrieveData( hero )
        
        if ( data.attr_total >= 8 ) then
            return false
        endif
        
        set data.attrset[data.attr_total] = attrdata.create( name, startinglevel )
        set data.attr_total = data.attr_total + 1
        
        return true
    endmethod
    
    static method addSkill takes unit hero, string name, integer startinglevel, real startingxp returns boolean
        local rpgdata data = rpgdata.retrieveData( hero )
        
        if ( data.skill_total >= 16 ) then
            return false
        endif
        
        set data.skillset[data.skill_total] = skilldata.create( name, startinglevel, startingxp )
        set data.skill_total = data.skill_total + 1
        
        return true
    endmethod
    
    static method addEquipSlot takes unit hero, integer id, string class, integer emptyitem_id returns boolean
        local rpgdata data = rpgdata.retrieveData( hero )
        
        if ( id > 7 ) then
            return false
        endif
        
        if ( data.equip_total == 0 ) then
            call UnitAddAbility( data.hero, EQUIPMENU_ABIL_ID )
        endif
        
        set data.equip_slot_array[id] = rpgdata_equip_slot.create( id, class, emptyitem_id )
        set data.equip_total = data.equip_total + 1
        
        return true
    endmethod
    
    static method create takes unit u, string class, integer slots returns rpgdata
        local rpgdata data = rpgdata.allocate()
        local item tempitem
        local integer i = 0
        
        //call BJDebugMsg( "Method runs" )

        if ( rpgdata.retrieveData( u ) != 0 ) then //Unit already has struct attached
            return 0
        endif
        
        //call BJDebugMsg( "Pass multiples check" )
        
        set data.hero = u
        set data.class = class
        set data.slot_total = slots
        
        if ( slots > 6 ) then
            set data.slot_perpage = 4
        endif
        
        //Initialize array members
        
        loop
            exitwhen ( i > 63 )
            
            set data.slot_item_array[i] = null
            
            if ( i <= 7 ) then
                set data.equip_slot_array[i] = 0
            endif
            
            set i = i + 1
        endloop
        
        //call BJDebugMsg( "Pass initializing arrays" )
        
        //set up items
        if ( slots > 6 ) then
            //call BJDebugMsg( "Starting item setup" )
            
            call UnitAddItemToSlotById( u, PREVPAGE_ID, 4 ) //previous page item
            call UnitAddItemToSlotById( u, NEXTPAGE_ID, 5 ) //next page item
            call SetItemCharges( GetItemOfTypeFromUnitBJ( u, NEXTPAGE_ID ), data.currpage + 1 )
        endif
        
        //call BJDebugMsg( "Pass item setup" )
        
        //set up BonusMod
        
        set data.bonusMod = BonusData.create(u)
        
        //set up triggers
        
        set data.manipulateitem = CreateTrigger()
        
        call TriggerRegisterUnitEvent( data.manipulateitem, u, EVENT_UNIT_ISSUED_TARGET_ORDER )
        call TriggerRegisterUnitEvent( data.manipulateitem, u, EVENT_UNIT_PICKUP_ITEM )
        call TriggerRegisterUnitEvent( data.manipulateitem, u, EVENT_UNIT_DROP_ITEM )
        
        set data.manipulateitem_action = TriggerAddAction( data.manipulateitem, function rpgdata.ManipulateItem_Actions )
        
        set data.itemclick = CreateTrigger()
        call TriggerRegisterUnitEvent( data.itemclick, u, EVENT_UNIT_USE_ITEM )
        call TriggerRegisterUnitEvent( data.itemclick, u, EVENT_UNIT_SPELL_EFFECT )
        
        set data.itemclick_action = TriggerAddAction( data.itemclick, function rpgdata.ItemClick_Actions )
        
        //set up timer struct
        set data.ordertimerdata = timerdata.create()
        
        set rpgdata_array[rpgdata_array_count] = data
        set rpgdata_array_count = rpgdata_array_count + 1
        
        return data
    endmethod
endstruct

function RPGSystem_Init takes nothing returns nothing
endfunction

endlibrary


EDIT: As far as I know, the system as is doesn't have any major bugs in it, though I never got around to actually hardcore testing it.
 
Status
Not open for further replies.
Top