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