Name | Type | is_array | initial_value |
Ahead_Decelerate | boolean | Yes | |
Ahead_Move | boolean | Yes | |
Backwards_Decelerate | boolean | Yes | |
Backwards_Move | boolean | Yes | |
braje | force | No | |
camera | boolean | No | |
CowBoy | force | No | |
cu | real | No | |
Current_Speed_Variable | real | Yes | |
dehors | boolean | No | |
demo | boolean | No | |
effect | effect | Yes | |
emplacement | location | No | |
endinggroup | group | No | |
EntierTemporaire | integer | No | |
fee | boolean | No | |
gogo | boolean | Yes | |
Group_Collision_Units | group | No | |
heal | effect | Yes | |
heroinv | group | No | |
Indians | force | No | |
INTEGER | integer | No | |
INTEGER2 | integer | No | |
intro | dialog | No | |
intro2 | boolean | No | |
introbutton | button | Yes | |
itemage | boolean | Yes | |
itemageind | boolean | Yes | |
Joue | force | No | |
Joueur | integer | No | |
JoueurDansMultitable | integer | Yes | |
LumberText | string | No | |
market | unit | Yes | |
mechanic | unit | No | |
My_Car | unit | Yes | |
number | integer | No | |
Orientation | integer | No | |
patrol | group | Yes | |
pilot | boolean | No | |
Player | player | No | |
Player_Number_of_Picked_Player | integer | No | |
Player_Number_of_Trig_Player | integer | No | |
POINT | location | No | |
Point_of_Creation | location | No | |
Point_of_Path | location | Yes | |
Point_of_Path2 | location | No | |
prime | integer | Yes | |
Region_Collision | rect | Yes | |
repair | boolean | No | |
revi | boolean | No | |
reward | integer | No | |
rifle | boolean | No | |
Rotation_Left | boolean | Yes | |
Rotation_Right | boolean | Yes | |
round | dialog | No | |
round2 | button | Yes | |
separator | boolean | No | |
smoke | effect | No | |
STATS_ACCELERATION | real | Yes | 0.00 |
STATS_BREAK | real | Yes | 0.00 |
STATS_HANDLING | real | Yes | 0.00 |
STATS_TOPSPEED | real | Yes | 0.00 |
The_Picked_Player | player | No | |
timer | timer | No | |
type | integer | No | |
u | unit | Yes | |
victoireGoal | integer | No | |
victoireInd | integer | No | |
victoireUSA | integer | No |
//TESH.scrollpos=0
//TESH.alwaysfold=0
/*~~~~~~~How to Import/Update this system~~~~~~~*\
1. Delete (if existing) the old Equipment System trigger
2. Copy the new Equipment system Trigger into your map
~~~~~~~How to Set Up~~~~~~~
1. Copy all the abilities used by this system (here they are all under "human") or create your own ones
they are one ability for opening the inventory, one for closing, one which makes items "clickable", and for each empty slot a ability
2. Create all your items which can be equipped and give them as ability ONLY the [clickable item] ability
3. For each equipable item create a icon ability (best if you use "channel" as base ability)
2 things to be careful with:
Make sure that the item icon's Spell ID for each type of item is distinct
i.e. Swords => acidbomb
shields => bloodlust
(be aware that the Cancel button has it's own Spell ID => absorb)
Make sure that every item ability icon has the X and Y button coordinates matching with the Type of item it is
i.e. Necklaces = 0,0 ; Helmets = 1,0 ; Gloves = 2,0
Necklace of Power = 0,0
Glory Necklace = 0,0
Bloodlust Helmet = 1,0
Green Cap = 1,0
Gloves of the IronDwarf = 2,0
4. Create abilities for each equipable item. DONT use the same ability twice on items of different equipment classes!!
Dont give those abilities to the items! They will be given to the equipping unit ingame by this system.
I advise you to take abilities which have no icon because it would show up on the owner
(of course this can be useful if an item should grant a active ability, for example!)
if you need an icon ability which should be invisible (aura for example), create a spellbook, add that ability to it,
disable the spellbook at map start and register the spellbook as an ability given by your item ;)
5. initialize your items and classes
6. make sure that all the adjustable variables in the setup part fit your map now
~~~~~~~Hints~~~~~~~
to show/hide the rawcode of anything in the object editor just press CTRL + D
to copy the systems abilities (open,close, empty offhand,...) you have to import all the BTN files importet in this map aswell!!
aaaaaand you are done :D
gl & hf
The_Witcher
*/
//TESH.scrollpos=93
//TESH.alwaysfold=0
\* */
/****************************************************************\
* *
* *
* Advanced Equipment System *
* *
* *
* by The_Witcher *
\****************************************************************/
/* *\
--------- Introduction ---------
what this is:
- Equipment System
- MUI
- in vJass
what this is not:
- Inventory System
- in GUI/normal Jass
- exportable to GUI or normal Jass
Content:
1) How to register items
2) How to use this system
3) Additional functions
4) Trigger Events
5) To all vJassers out there
--------- 1) How to register items (1 ---------
this system isn't that perfekt that it can do everything on its own ;D
At first you have to initialize your classes.
Do this by calling:
call AdvancedEquipmentSystem_RegisterNewClass( icon, class)
"icon" is the icon ability that indicates an empty slot
"class" is a simple integer that determines the class
You also have to register all items you want to be equipable to this system.
With the following function you can do that:
call AdvancedEquipmentSystem_RegisterItem(itemid, abilities, icon, class, twohanded, animation)
"itemid" is of course the rawcode of the item the rest is assigned to
"icon" is the ability shown inside the Equipment when the item is equipped
"class" is the slot the item jumps in (be sure to adjust the x/y coordinates inside the object editor according
to the coordinates of the "empty slot" icon ability of the same class)
"twohanded" is a boolean (i think self explaining) !!works only for mainhand items!!
"animation" is a string which indicates the animation tag added when this item is equipped
ATTENTION: offhand slot items animations always overwrite mainhand slot items animations
until now your items have no effect when equipped...
you can add countless abilities to one itemtype! (actually its limited to around 8000 abilities in total :D )
to add one use:
call AdvancedEquipmentSystem_AddItemAbility( integer itemid, integer abi )
"itemid" is the rawcode of the item the rest is assigned to
"abi" is the rawcode of the ability the unit gets when it equips this item
Example:
globals
integer AMULET_CLASS = 2
endglobals
...
call AdvancedEquipmentSystem_RegisterNewClass('A00A', AMULET_CLASS)
...
call AdvancedEquipmentSystem_RegisterItem('I004', 'A008', AMULET_CLASS, false, "Alternate")
call AdvancedEquipmentSystem_AddItemAbility('I004', 'A002')
--------- 2) How to use this system (2 ---------
well its very simple to use:
call InitEquipment ( owner )
owner is the unit that gets the equipment
and thats all^^ whenever this unit uses a registered item, it will get equipped
--------- 3) Additional functions (3 ---------
function IsEquipmentClassEmpty takes unit u, integer class returns boolean
function EquipItem takes unit u, item ite returns nothing
function EquipItemById takes unit u, integer itemId returns nothing
function UnequipItemById takes unit u, integer itemid returns nothing
function UnequipItemByClass takes unit u, integer class returns nothing
function GetEquippedItemTypeId takes unit u, integer class returns integer
function ChangeEquipmentOwner takes unit u, unit newowner returns nothing
function UnequipAll takes unit u returns nothing
function EnableItemEquip takes integer itemId, integer unitType, boolean flag returns nothing
--------- 4) Trigger Events (4 ---------
function RegisterItemEquipEvent takes code func returns nothing
function RegisterItemUnequipEvent takes code func returns nothing
//use GetTriggeringItemId and GetEquippingUnit to get the involved units
--------- 5) To all vJassers out there (5 ---------
well as we understand vJass we can do things much easier ^^
the above mentioned functions are all simple wrappers for the included structs methods:
struct Equipment
methods
create takes unit u returns Equipment => creates a new Equipment for unit u
destroy takes nothing returns nothing => destroys an existing Equipment
equip takes integer itemId returns nothing => equips the given item
unequip takes integer class returns nothing => unequips whatever is in the given class
static method disable takes integer itemId, integer unitType, boolean flag returns nothing
=> disables a itemtype for a unit type so it can't equip it anymore
members
unit owner => the equipment unit, use "set yourEquipment.owner = yourunit" to transfer the Equipment to another unit
readonly EquipmentItem array Item => the equipped EquipmentItem in a slot, specified by the array index
--------- Thanks to all who gave useful critism or tips for improvement ---------
The_Witcher
//TESH.scrollpos=0
//TESH.alwaysfold=0
library AdvancedEquipmentSystem requires LinkedListModule, RegisterPlayerUnitEvent
// The_Witcher's Equipment System
//
// This is my easy to use equipment system, which adds an equipment screen to any unit you want.
// equipped items can give up abilities to the owner and can change the animations of him...
//
//
// To learn how to use this system please read the "How To Use" delivered in the demo map
//
//
// Requirements:
// JASS knowledge
// LinkedList (http://www.hiveworkshop.com/forums/jass-resources-412/snippet-linkedlistmodule-206552/)
// RegisterPlayerUnitEvent (http://www.hiveworkshop.com/forums/jass-resources-412/snippet-registerplayerunitevent-203338/)
//
// have fun^^
//**************************************************
//********************SETUP PART********************
//**************************************************
globals
// this is the rawcode of the unit which works as inventory
public constant integer INVENTORY_DUMMY = 'h00T'
// this is the class you selected as mainhand class
public constant integer MAINHAND_CLASS = 0
// this is the class you selected as offhand class
public constant integer OFFHAND_CLASS = 1
// this is the amount of total classes you have
public constant integer CLASSES = 9
// this is the ability to close the inventory
public constant integer EXIT_ABILITY = 'A015'
// this is the ability to open the inventory
public constant integer OPEN_ABILITY = 'A016'
// this is the ability which gives the dummy the same inventory as your hero has
public constant integer INVENTORY_ABILITY = 'AInv'
// this is the icon ability shown in the offhand slot when a twhoanded weapon is equipeed
public constant integer TWOHAND_ABILITY = 'A01D'
public constant boolean SHOW_TWOHAND_ABILITY = true
// this is the text shown when a unit is trying to equip an item which it isnt allowed to
// example: " can't equip " becomes ingame something like Soldier can't equip Giant Sword
public constant string UNABLE_TO_EQUIP_STRING = " you can't equip this item "
endglobals
//************************************************************
//********************SETUP PART ENDS HERE********************
//************************************************************
//*****************Don't edit anything below******************
//************************************************************
globals
private trigger OnEquip
private trigger OnUnequip
private integer TriggeringItem
private unit EquippingUnit
private hashtable table
endglobals
private struct AbilityList extends array
integer abi
implement LinkedList
static method create takes nothing returns thistype
return .createNode()
endmethod
method remove takes nothing returns nothing
call .removeNode()
call .deallocate()
endmethod
method add takes integer abi returns nothing
local thistype new = .allocate()
set new.abi = abi
call .insertNode(new)
endmethod
endstruct
// **** struct EquipmentItem ****
private struct EquipmentItem extends array
readonly integer id
readonly integer class
readonly AbilityList abilities
readonly integer icon
readonly boolean twohanded
readonly string tag
static method operator [] takes integer itemid returns EquipmentItem
return itemid - 'I000' + CLASSES + 1
endmethod
static method create takes integer id, integer icon, integer class, boolean twohanded, string animation returns EquipmentItem
local EquipmentItem this = id - 'I000' + CLASSES + 1
if id - 'I000' >= 0 then
call SaveBoolean(table, id - 'I000', 0, true)
endif
set .id = id
set .class = class
set .icon = icon
if id >= CLASSES + 1 then
set .abilities = AbilityList.create()
if class == MAINHAND_CLASS then
set .twohanded = twohanded
else
set .twohanded = false
endif
if (class == MAINHAND_CLASS or class == OFFHAND_CLASS) and id != 0 then
set .tag = animation
else
set .tag = ""
endif
endif
return this
endmethod
method addAbility takes integer abi returns nothing
call .abilities.add( abi)
endmethod
method applyAbilities takes unit u, boolean add returns nothing
local AbilityList node = .abilities.next
loop
exitwhen node.head
if add then
call UnitAddAbility(u, node.abi)
else
call UnitRemoveAbility(u, node.abi)
endif
set node = node.next
endloop
endmethod
endstruct
public function RegisterNewClass takes integer emptyicon, integer class returns nothing
call EquipmentItem.create('I000' - CLASSES - 1 + class, emptyicon, class, false, "")
endfunction
// **** struct Equipment ****
struct Equipment
private static EquipmentItem twohandIcon
private unit u
private unit dummy
readonly string animtag = ""
readonly EquipmentItem array Item [12]
static method operator [] takes unit u returns Equipment
return LoadInteger(table, GetHandleId(u), 0)
endmethod
method operator owner takes nothing returns unit
return .u
endmethod
method operator owner= takes unit new returns nothing
local integer i = 0
loop
exitwhen i >= CLASSES
if .Item[i] != 0 then
call .Item[i].applyAbilities(.u, false)
call .Item[i].applyAbilities(new, true)
endif
set i = i + 1
endloop
call AddUnitAnimationProperties(.u, .animtag, false)
call UnitRemoveAbility(.u, OPEN_ABILITY)
call AddUnitAnimationProperties(new, .animtag, true)
call UnitAddAbility(new, OPEN_ABILITY)
set .u = new
call SaveInteger(table, GetHandleId(.u), 0, this)
call SaveInteger(table, GetHandleId(.dummy), 0, this)
endmethod
method syncInventories takes nothing returns nothing
local integer i = 0
loop
exitwhen i >= 6
call RemoveItem(UnitItemInSlot(.dummy, i))
call UnitAddItemToSlotById(.dummy, GetItemTypeId(UnitItemInSlot(.u, i)), i)
call SetItemDroppable(UnitItemInSlot(.dummy, i), false)
set i = i + 1
endloop
endmethod
private method refreshAnimation takes nothing returns nothing
local string a = .Item[MAINHAND_CLASS].tag
if .Item[OFFHAND_CLASS] != 0 and .Item[OFFHAND_CLASS] != twohandIcon then
set a = .Item[OFFHAND_CLASS].tag
endif
call AddUnitAnimationProperties(.u, .animtag, false)
call AddUnitAnimationProperties(.u, a, true)
set .animtag = a
endmethod
method equipEmptyClass takes integer class returns nothing
call UnitAddAbility(.dummy, EquipmentItem(class).icon)
set .Item[class] = 0
endmethod
method equipTwohandIcon takes nothing returns nothing
call UnitAddAbility(.dummy, twohandIcon.icon)
set .Item[OFFHAND_CLASS] = twohandIcon
endmethod
method unequip takes integer class returns nothing
local integer i = 0
local EquipmentItem toRemove = .Item[class]
if toRemove != 0 then
if toRemove.twohanded then
call UnitRemoveAbility(.dummy, TWOHAND_ABILITY)
call .equipEmptyClass(OFFHAND_CLASS)
endif
call toRemove.applyAbilities(.u, false)
call UnitAddItemById(.u, toRemove.id)
set TriggeringItem = toRemove.id
set EquippingUnit = .u
call TriggerEvaluate(OnUnequip)
call UnitRemoveAbility(.dummy, toRemove.icon)
else
call UnitRemoveAbility(.dummy, EquipmentItem(class).icon)
endif
set .Item[class] = 0
call .refreshAnimation()
endmethod
method equip takes integer id returns nothing
local EquipmentItem toEquip = EquipmentItem[id]
local EquipmentItem mainEquip = .Item[MAINHAND_CLASS]
// remove existing
if mainEquip != 0 then
if toEquip.twohanded or (mainEquip.twohanded and (toEquip.class == OFFHAND_CLASS or toEquip.class == MAINHAND_CLASS)) then
call .unequip(MAINHAND_CLASS)
call .unequip(OFFHAND_CLASS)
if toEquip.class == MAINHAND_CLASS and not toEquip.twohanded then
call .equipEmptyClass(OFFHAND_CLASS)
elseif toEquip.class == OFFHAND_CLASS then
call .equipEmptyClass(MAINHAND_CLASS)
endif
endif
endif
call .unequip(toEquip.class)
// new is twohanded ?
if toEquip.twohanded then
call .unequip(OFFHAND_CLASS)
call .equipTwohandIcon()
if not SHOW_TWOHAND_ABILITY then
call UnitRemoveAbility(.dummy, twohandIcon.icon)
endif
endif
// equip new
call toEquip.applyAbilities(.u, true)
call UnitAddAbility(.dummy, toEquip.icon)
set .Item[toEquip.class] = toEquip
call .refreshAnimation()
// fire trigger
set EquippingUnit = .u
set TriggeringItem = id
call TriggerEvaluate(OnEquip)
endmethod
static method disable takes integer itemId, integer unitType, boolean flag returns nothing
call SaveBoolean(table, itemId - 'I000', unitType, flag)
endmethod
private method onDestroy takes nothing returns nothing
local integer i = 0
call RemoveUnit(.dummy)
loop
exitwhen i > 12
if .Item[i] != 0 then
call .Item[i].applyAbilities(.u, false)
endif
set i = i + 1
endloop
call AddUnitAnimationProperties(.u, .animtag, false)
call UnitRemoveAbility(.u, OPEN_ABILITY)
endmethod
static method create takes unit u returns Equipment
local Equipment this = Equipment[u]
local integer i = 0
local integer id = GetPlayerId(GetOwningPlayer(u))
if this != 0 then
call RemoveUnit(.dummy)
else
set this = Equipment.allocate()
call SaveInteger(table, GetHandleId(u), 0, this)
endif
set .u = u
set .dummy = CreateUnit(GetOwningPlayer(u), INVENTORY_DUMMY, GetUnitX(u), GetUnitY(u), 0)
call SaveInteger(table, GetHandleId(.dummy), 0, this)
call UnitAddAbility(.dummy, INVENTORY_ABILITY)
call UnitAddAbility(.dummy, EXIT_ABILITY)
call UnitAddAbility(.u, OPEN_ABILITY)
loop
exitwhen i >= CLASSES
call .equipEmptyClass(i)
set i = i + 1
endloop
return this
endmethod
// **** Other Stuff ****
private static method Access takes nothing returns boolean
local unit u = GetTriggerUnit()
local Equipment inv = Equipment[u]
local integer class
local integer i = 0
if GetSpellAbilityId() == EXIT_ABILITY then
if GetLocalPlayer() == GetOwningPlayer(inv.u) then
call ClearSelection()
call SelectUnit(inv.u, true)
endif
elseif GetSpellAbilityId() == OPEN_ABILITY then
call SetUnitX(inv.dummy, GetUnitX(inv.u))
call SetUnitY(inv.dummy, GetUnitY(inv.u))
if GetLocalPlayer() == GetOwningPlayer(inv.u) then
call ClearSelection()
call SelectUnit(inv.dummy, true)
endif
call inv.syncInventories()
elseif GetUnitTypeId(u) == INVENTORY_DUMMY then
loop
exitwhen i >= CLASSES
if inv.Item[i].icon == GetSpellAbilityId() then
set class = i
set i = CLASSES
endif
set i = i + 1
endloop
call inv.unequip(class)
call inv.equipEmptyClass(class)
call inv.syncInventories()
endif
set u = null
return false
endmethod
private static method ItemEquip takes nothing returns boolean
local unit u = GetTriggerUnit()
local item ite = GetManipulatedItem()
local integer i = 0
local Equipment inv = Equipment[u]
local EquipmentItem invIte = EquipmentItem[GetItemTypeId(ite)]
if GetItemTypeId(ite) - 'I000' >= 0 then
if LoadBoolean(table, GetItemTypeId(ite) - 'I000', 0) then
if invIte != 0 and inv != 0 then
if not LoadBoolean(table, GetItemTypeId(ite) - 'I000', GetUnitTypeId(inv.u)) then
if u == inv.u then
call inv.equip(GetItemTypeId(ite))
call RemoveItem(ite)
call inv.syncInventories()
elseif u == inv.dummy then
loop
exitwhen i >= 6
if invIte.id == GetItemTypeId(UnitItemInSlot(inv.u, i)) then
call UnitUseItem(inv.u, UnitItemInSlot(inv.u, i))
call RemoveItem(ite)
set i = 7
endif
set i = i + 1
endloop
endif
else
call DisplayTextToPlayer(GetOwningPlayer(inv.u), 0, 0, GetUnitName(inv.u) + UNABLE_TO_EQUIP_STRING + GetItemName(ite))
endif
endif
endif
endif
set u = null
set ite = null
return false
endmethod
private static method onInit takes nothing returns nothing
set OnEquip = CreateTrigger()
set OnUnequip = CreateTrigger()
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_USE_ITEM, function Equipment.ItemEquip)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_CAST, function Equipment.Access)
set .twohandIcon = EquipmentItem.create('I000' - 1, TWOHAND_ABILITY, 0, false, "")
set table = InitHashtable()
endmethod
implement optional SaveLoadPlugin
endstruct
// **** Trigger Events ****
function RegisterItemEquipEvent takes code func returns nothing
call TriggerAddCondition(OnEquip, Filter(func))
endfunction
function RegisterItemUnequipEvent takes code func returns nothing
call TriggerAddCondition(OnUnequip, Filter(func))
endfunction
function GetTriggeringItemId takes nothing returns integer
return TriggeringItem
endfunction
function GetEquippingUnit takes nothing returns unit
return EquippingUnit
endfunction
//wrappers
function InitEquipment takes unit whichunit returns nothing
call Equipment.create(whichunit)
endfunction
public function RegisterItem takes integer itemid, integer icon, integer class, boolean twohanded, string animation returns nothing
call EquipmentItem.create(itemid, icon, class, twohanded, animation)
endfunction
public function AddItemAbility takes integer itemid, integer abi returns nothing
call EquipmentItem[itemid].addAbility(abi)
endfunction
function EnableItemEquip takes integer itemId, integer unitType, boolean flag returns nothing
call Equipment.disable(itemId, unitType, not flag)
endfunction
function IsEquipmentClassEmpty takes unit u, integer class returns boolean
return Equipment[u].Item[class] == 0
endfunction
function EquipItem takes unit u, item ite returns nothing
call Equipment[u].equip(GetItemTypeId(ite))
call RemoveItem(ite)
endfunction
function EquipItemById takes unit u, integer itemId returns nothing
call Equipment[u].equip(itemId)
endfunction
function UnequipItemById takes unit u, integer itemid returns nothing
local integer class = EquipmentItem[itemid].class
if Equipment[u].Item[class].id == itemid then
call Equipment[u].unequip(EquipmentItem[itemid].class)
call Equipment[u].equipEmptyClass(class)
endif
endfunction
function UnequipItemByClass takes unit u, integer class returns nothing
call Equipment[u].unequip(class)
call Equipment[u].equipEmptyClass(class)
endfunction
function GetEquippedItemTypeId takes unit u, integer class returns integer
return Equipment[u].Item[class].id
endfunction
function ChangeEquipmentOwner takes unit u, unit newowner returns nothing
set Equipment[u].owner = newowner
endfunction
function UnequipAll takes unit u returns nothing
local integer i = 1
loop
call Equipment[u].unequip(i)
call Equipment[u].equipEmptyClass(i)
exitwhen i >= CLASSES
set i = i + 1
endloop
endfunction
endlibrary
//Code indented using The_Witcher's Script Language Aligner
//Download the newest version and report bugs at www.hiveworkshop.com
//TESH.scrollpos=0
//TESH.alwaysfold=0
library SaveLoadPlugin
// create your custom save/load functions in here.
// if you don't need any simply delete this trigger
// WARNING: this is only for experienced users!
// the demo map save/load code is more an example
// than a useful system (but it works, too)
module SaveLoadPlugin
method getLoadCode takes nothing returns string
local integer i = 0
local string s = ""
loop
set i = i + 1
if .Item[i].id != 0 then
set s = s + I2S(.Item[i].id - 'I000')
endif
set s = s + "x"
exitwhen i >= AdvancedEquipmentSystem_CLASSES
endloop
return s
endmethod
method useLoadCode takes string LoadCode returns nothing
local integer i = 0
local integer i2 = 0
local integer i3 = 1
local string s
local string c = LoadCode
loop
set i = i + 1
set i2 = 1
loop
set s = SubString(c, 0, i2)
exitwhen SubString(s, StringLength(s) - 1, StringLength(s)) == "x"
set i2 = i2 + 1
endloop
set c = SubString(c, i2, 99999)
set s = SubString(s, 0, StringLength(s) - 1)
if s != "" then
call .equip('I000' + S2I(s))
endif
exitwhen i >= AdvancedEquipmentSystem_CLASSES or c == ""
endloop
endmethod
endmodule
function GetLoadCode takes unit u returns string
return Equipment[u].getLoadCode()
endfunction
function UseLoadCode takes unit u, string LoadCode returns nothing
call Equipment[u].useLoadCode( LoadCode)
endfunction
endlibrary
//Code indented using The_Witcher's Script Language Aligner
//Download the newest version and report bugs at www.hiveworkshop.com
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope SetupAdvancedEquipmentSystem initializer Initialize
globals
integer AMULET_CLASS = 2
integer ARMOR_CLASS = 3
integer BOOTS_CLASS = 4
integer GLOVES_CLASS = 5
integer RING_CLASS = 6
integer HELMET_CLASS = 7
integer SPECIAL_CLASS = 8
endglobals
private function Initialize takes nothing returns nothing
// here you have to give an icon ability for every empty slot
// this is my setup for the testmap
// WARNING: class 0 and 1 are taken as main and offhand slots! start with 2 for new indexes
call AdvancedEquipmentSystem_RegisterNewClass('A01F', AdvancedEquipmentSystem_MAINHAND_CLASS)//Mainhand
call AdvancedEquipmentSystem_RegisterNewClass('A01G', AdvancedEquipmentSystem_OFFHAND_CLASS)//Offhand
call AdvancedEquipmentSystem_RegisterNewClass('A018', AMULET_CLASS)//Pant
call AdvancedEquipmentSystem_RegisterNewClass('A019', ARMOR_CLASS)//Armor
call AdvancedEquipmentSystem_RegisterNewClass('A01A', BOOTS_CLASS)//Boots
call AdvancedEquipmentSystem_RegisterNewClass('A01B', GLOVES_CLASS)//Gloves
call AdvancedEquipmentSystem_RegisterNewClass('A01E', RING_CLASS)//Bracers
call AdvancedEquipmentSystem_RegisterNewClass('A01C', HELMET_CLASS)//Helmet
call AdvancedEquipmentSystem_RegisterNewClass('A01H', SPECIAL_CLASS)//Belt
//in this part set up the items
//you can do this anytime in your map (may cause bugs if not at initialization) by using
//call AdvancedEquipmentSystem_RegisterItem(itemid, abilities, icon, class, twohanded, animation)
// look into the HowToUse for further information
// itemid | icon | class | twohanded? | animationtag
//Revolver
call AdvancedEquipmentSystem_RegisterItem('I00V' , 'A01I', AdvancedEquipmentSystem_MAINHAND_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I00V', 'AItf')
//Spear
call AdvancedEquipmentSystem_RegisterItem('I018' , 'A02D', AdvancedEquipmentSystem_MAINHAND_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I018', 'A02G')
//Tomahawk
call AdvancedEquipmentSystem_RegisterItem('I01B' , 'A02E', AdvancedEquipmentSystem_MAINHAND_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I01B', 'A01K')
//Winchester
call AdvancedEquipmentSystem_RegisterItem('I00X', 'A01L', AdvancedEquipmentSystem_MAINHAND_CLASS, true, "")
call AdvancedEquipmentSystem_AddItemAbility('I00X', 'A01M')
//Springfield
call AdvancedEquipmentSystem_RegisterItem('I022', 'A031', AdvancedEquipmentSystem_MAINHAND_CLASS, true, "")
call AdvancedEquipmentSystem_AddItemAbility('I022', 'A030')
//Light Bow
call AdvancedEquipmentSystem_RegisterItem('I00Z', 'A015', AdvancedEquipmentSystem_MAINHAND_CLASS, true, "")
call AdvancedEquipmentSystem_AddItemAbility('I00Z', 'A01R')
//Composite Bow
call AdvancedEquipmentSystem_RegisterItem('I015', 'A024', AdvancedEquipmentSystem_MAINHAND_CLASS, true, "")
call AdvancedEquipmentSystem_AddItemAbility('I015', 'A01K')
//Revolver Secondary
call AdvancedEquipmentSystem_RegisterItem('I024', 'A034', AdvancedEquipmentSystem_OFFHAND_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I024', 'A01R')
//wooden shield
call AdvancedEquipmentSystem_RegisterItem('I01C', 'A02H', AdvancedEquipmentSystem_OFFHAND_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I01C', 'A02K')
//metal shield
call AdvancedEquipmentSystem_RegisterItem('I01D', 'A02I', AdvancedEquipmentSystem_OFFHAND_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I01D', 'A02J')
//Pant
call AdvancedEquipmentSystem_RegisterItem('I011', 'A01U', AMULET_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I011', 'A01T')
//Mail Pant
call AdvancedEquipmentSystem_RegisterItem('I013', 'A020', AMULET_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I013', 'A021')
//Kevlar Pant
call AdvancedEquipmentSystem_RegisterItem('I02B', 'A03H', AMULET_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I02B', 'A03G')
//Camo Pant
call AdvancedEquipmentSystem_RegisterItem('I02A', 'A03E', AMULET_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I02A', 'A03F')
//Agi Belt
call AdvancedEquipmentSystem_RegisterItem('I010', 'A01S', SPECIAL_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I010', 'AIa6')
//Str Belt
call AdvancedEquipmentSystem_RegisterItem('I014', 'A022', SPECIAL_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I014', 'AIs6')
//Int Belt
call AdvancedEquipmentSystem_RegisterItem('I028', 'A039', SPECIAL_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I028', 'AIi6')
//Puttee
call AdvancedEquipmentSystem_RegisterItem('I01G', 'A02Q', BOOTS_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I01G', 'A02S')
//Leather Boots
call AdvancedEquipmentSystem_RegisterItem('I01H', 'A02R', BOOTS_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I01H', 'A02T')
//Ceremonial Boots
call AdvancedEquipmentSystem_RegisterItem('I02Q', 'A03O', BOOTS_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I02Q', 'AI2m')
//Fur Boots
call AdvancedEquipmentSystem_RegisterItem('I02P', 'A03N', BOOTS_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I02P', 'A03M')
//Breastplate
call AdvancedEquipmentSystem_RegisterItem('I00W', 'A01J', ARMOR_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I00W', 'A02P')
//Armor Body
call AdvancedEquipmentSystem_RegisterItem('I023', 'A033', ARMOR_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I023', 'A032')
//Fur Armor
call AdvancedEquipmentSystem_RegisterItem('I01E', 'A02L', ARMOR_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I01E', 'A02O')
//Leather Armor
call AdvancedEquipmentSystem_RegisterItem('I01F', 'A02M', ARMOR_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I01F', 'A02N')
//Leather Gloves
call AdvancedEquipmentSystem_RegisterItem('I016', 'A026', GLOVES_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I016', 'A027')
//Metallic Gloves
call AdvancedEquipmentSystem_RegisterItem('I017', 'A025', GLOVES_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I017', 'A028')
//Reinforced Gloves
call AdvancedEquipmentSystem_RegisterItem('I027', 'A03A', GLOVES_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I027', 'A03B')
//Silk Gloves
call AdvancedEquipmentSystem_RegisterItem('I029', 'A03C', GLOVES_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I029', 'A03D')
//Adrian
call AdvancedEquipmentSystem_RegisterItem('I00Y', 'A01O', HELMET_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I00Y', 'A01P')
//German helmet
call AdvancedEquipmentSystem_RegisterItem('I01Z', 'A02Y', HELMET_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I01Z', 'A02Z')
//Leather helmet
call AdvancedEquipmentSystem_RegisterItem('I02G', 'A03I', HELMET_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I02G', 'A03J')
//Metal helmet
call AdvancedEquipmentSystem_RegisterItem('I03L', 'A03L', HELMET_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I03L', 'A03K')
//Fur Bracer
call AdvancedEquipmentSystem_RegisterItem('I019', 'A029', RING_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I019', 'A02B')
//Leather Bracer
call AdvancedEquipmentSystem_RegisterItem('I01A', 'A02A', RING_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I01A', 'A02C')
//Heavy Bracer
call AdvancedEquipmentSystem_RegisterItem('I025', 'A035', RING_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I025', 'A036')
//Light Bracer
call AdvancedEquipmentSystem_RegisterItem('I026', 'A038', RING_CLASS, false, "")
call AdvancedEquipmentSystem_AddItemAbility('I026', 'A037')
endfunction
endscope
//Code indented using The_Witcher's Script Language Aligner
//Download the newest version and report bugs at www.hiveworkshop.com
//TESH.scrollpos=44
//TESH.alwaysfold=0
library LinkedListModule /* v2.2.0
Easy implementation of linked lists into structs.
***********************************************************************
*
* module LinkedList
*
* - Implement at the top of your struct, must extend array
*
* thistype next
* thistype prev
* boolean head
*
* readonly static thistype base
* - Precreated head, useful for non-dynamic lists.
*
* static method allocate takes nothing returns thistype
* method deallocate takes nothing returns nothing
*
* static method createNode takes nothing returns thistype
* - Allocates a new node pointing towards itself.
* - These nodes are considered "heads" therefore it's head
* - boolean member is set to true.
* method insertNode takes thistype toInsert returns thistype
* - Inserts the node into the list after 'this' node.
* method removeNode takes nothing returns nothing
* - Removes the node from the list.
* method clearNode takes nothing returns nothing
* - Deallocates all the instances within the node's range
* method flushNode takes nothing returns nothing
* - Clears and deallocates the node.
*
********************************************************************* */
module LinkedList
//private static integer instanceCount = 0
readonly static integer instanceCount = 0
boolean head
thistype next
thistype prev
static method operator base takes nothing returns thistype
return 8190
endmethod
static method allocate takes nothing returns thistype
local thistype this=thistype(0).prev
if this == 0 then
debug if instanceCount == 8190 then
debug call BJDebugMsg("[LinkedList] Error: attempted to allocate too many instances.")
debug return 0
debug endif
set instanceCount=instanceCount+1
return instanceCount
endif
set thistype(0).prev=this.prev
return this
endmethod
method deallocate takes nothing returns nothing
set this.prev=thistype(0).prev
set thistype(0).prev=this
set this.head=false
endmethod
static method createNode takes nothing returns thistype
local thistype this=allocate()
set this.next=this
set this.prev=this
set this.head=true
return this
endmethod
method clearNode takes nothing returns nothing
if this != this.next then
set this.next.prev=thistype(0).prev
set thistype(0).prev=this.prev
set this.next=this
set this.prev=this
endif
endmethod
method flushNode takes nothing returns nothing
set this.next.prev=thistype(0).prev
set thistype(0).prev=this
set head=false
endmethod
method insertNode takes thistype toInsert returns nothing
set this.prev.next=toInsert
set toInsert.prev=this.prev
set this.prev=toInsert
set toInsert.next=this
endmethod
method removeNode takes nothing returns nothing
set this.prev.next=this.next
set this.next.prev=this.prev
endmethod
private static method onInit takes nothing returns nothing
set thistype(8190).next=8190
set thistype(8190).prev=8190
set thistype(8190).head=true
endmethod
static if DEBUG_MODE then
method print takes nothing returns nothing
local string s=""
local thistype exit=this
set this=this.next
loop
set s=s+I2S(this)
set this=this.next
exitwhen this == exit
set s=s+" - "
endloop
call BJDebugMsg("[ "+s+" ]")
endmethod
endif
endmodule
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
/**************************************************************
*
* RegisterPlayerUnitEvent
* v5.0.0.0
* By Magtheridon96
*
* I would like to give a special thanks to Bribe, azlier
* and BBQ for improving this library. For modularity, it only
* supports player unit events.
*
* Functions passed to RegisterPlayerUnitEvent must
* return false. They can return nothing as well. (Which is a Pro)
*
* Warning:
* --------
*
* - Don't use TriggerSleepAction inside registered code.
*
* API:
* ----
*
* - function RegisterPlayerUnitEvent
* takes
* playerunitevent whichEvent : The event you would like to register
* code whichFunction : The code you would like to register
* returns
* nothing
*
* - Registers code that will execute when an event fires.
*
* - function RegisterPlayerUnitEventForPlayer
* takes
* playerunitevent whichEvent : The event you would like to register
* code whichFunction : The code you would like to register
* player whichPlayer : The player you would like to register the event for
* returns
* nothing
*
* - Registers code that will execute when an event fires for a certain player.
*
**************************************************************/
library RegisterPlayerUnitEvent // Special Thanks to Bribe and azlier
globals
private trigger array t
endglobals
function RegisterPlayerUnitEvent takes playerunitevent p, code c returns nothing
local integer i = GetHandleId(p)
local integer k = 15
if t[i] == null then
set t[i] = CreateTrigger()
loop
call TriggerRegisterPlayerUnitEvent(t[i], Player(k), p, null)
exitwhen k == 0
set k = k - 1
endloop
endif
call TriggerAddCondition(t[i], Filter(c))
endfunction
function RegisterPlayerUnitEventForPlayer takes playerunitevent p, code c, player pl returns nothing
local integer i = 260 + 16 * GetHandleId(p) + GetPlayerId(pl)
if t[i] == null then
set t[i] = CreateTrigger()
call TriggerRegisterPlayerUnitEvent(t[i], pl, p, null)
endif
call TriggerAddCondition(t[i], Filter(c))
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_GoldBag1_Actions takes nothing returns nothing
local integer MAX_CHARGES = 99
local unit u = GetTriggerUnit()
local item picked_item = GetManipulatedItem()
local item slot_item = null
local integer picked_item_id = GetItemTypeId(picked_item)
local integer charges_source = GetItemCharges(picked_item)
local integer charges_target = 0
local integer i = 0
if(picked_item_id=='phea')then
loop
exitwhen i > 5 or charges_source <= 0
set slot_item = UnitItemInSlot(u,i)
set charges_target = GetItemCharges(slot_item)
if (slot_item!=picked_item) and (GetItemTypeId(slot_item)==picked_item_id) and (charges_target<MAX_CHARGES) then
if(charges_target+charges_source>MAX_CHARGES)then
call SetItemCharges(slot_item,MAX_CHARGES)
set charges_source = charges_source-(MAX_CHARGES-charges_target)
else
call SetItemCharges(slot_item,charges_target+charges_source)
set charges_source = 0
endif
endif
set i = i + 1
endloop
if charges_source == 0 then
call RemoveItem(picked_item)
else
call SetItemCharges(picked_item,charges_source)
endif
endif
set picked_item = null
set u = null
set slot_item = null
endfunction
//===========================================================================
function InitTrig_GoldBag1 takes nothing returns nothing
set gg_trg_GoldBag1 = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_GoldBag1, EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerAddAction( gg_trg_GoldBag1, function Trig_GoldBag1_Actions )
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_GoldBag2_Actions takes nothing returns nothing
local integer MAX_CHARGES = 99
local unit u = GetTriggerUnit()
local item picked_item = GetManipulatedItem()
local item slot_item = null
local integer picked_item_id = GetItemTypeId(picked_item)
local integer charges_source = GetItemCharges(picked_item)
local integer charges_target = 0
local integer i = 0
if(picked_item_id=='pman')then
loop
exitwhen i > 5 or charges_source <= 0
set slot_item = UnitItemInSlot(u,i)
set charges_target = GetItemCharges(slot_item)
if (slot_item!=picked_item) and (GetItemTypeId(slot_item)==picked_item_id) and (charges_target<MAX_CHARGES) then
if(charges_target+charges_source>MAX_CHARGES)then
call SetItemCharges(slot_item,MAX_CHARGES)
set charges_source = charges_source-(MAX_CHARGES-charges_target)
else
call SetItemCharges(slot_item,charges_target+charges_source)
set charges_source = 0
endif
endif
set i = i + 1
endloop
if charges_source == 0 then
call RemoveItem(picked_item)
else
call SetItemCharges(picked_item,charges_source)
endif
endif
set picked_item = null
set u = null
set slot_item = null
endfunction
//===========================================================================
function InitTrig_GoldBag2 takes nothing returns nothing
set gg_trg_GoldBag2 = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_GoldBag2, EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerAddAction( gg_trg_GoldBag2, function Trig_GoldBag2_Actions )
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_GoldBag3_Actions takes nothing returns nothing
local integer MAX_CHARGES = 99
local unit u = GetTriggerUnit()
local item picked_item = GetManipulatedItem()
local item slot_item = null
local integer picked_item_id = GetItemTypeId(picked_item)
local integer charges_source = GetItemCharges(picked_item)
local integer charges_target = 0
local integer i = 0
if(picked_item_id=='sman')then
loop
exitwhen i > 5 or charges_source <= 0
set slot_item = UnitItemInSlot(u,i)
set charges_target = GetItemCharges(slot_item)
if (slot_item!=picked_item) and (GetItemTypeId(slot_item)==picked_item_id) and (charges_target<MAX_CHARGES) then
if(charges_target+charges_source>MAX_CHARGES)then
call SetItemCharges(slot_item,MAX_CHARGES)
set charges_source = charges_source-(MAX_CHARGES-charges_target)
else
call SetItemCharges(slot_item,charges_target+charges_source)
set charges_source = 0
endif
endif
set i = i + 1
endloop
if charges_source == 0 then
call RemoveItem(picked_item)
else
call SetItemCharges(picked_item,charges_source)
endif
endif
set picked_item = null
set u = null
set slot_item = null
endfunction
//===========================================================================
function InitTrig_GoldBag3 takes nothing returns nothing
set gg_trg_GoldBag3 = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_GoldBag3, EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerAddAction( gg_trg_GoldBag3, function Trig_GoldBag3_Actions )
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
library DestructableLib initializer Initialization
//* ============================================================================ *
//* Made by PitzerMike *
//* *
//* I made this to detect if a destructable is a tree or not. It works not only *
//* for the standard trees but also for custom destructables created with the *
//* object editor. It uses a footie as a dummy with the goul's harvest ability. *
//* The dummy ids can be changed though. I also added the IsDestructableDead *
//* function for completeness. *
//* ============================================================================ *
globals
private constant integer DUMMY_UNIT_ID = 'hfoo' // footman
private constant integer HARVEST_ID = 'Ahrl' // ghouls harvest
private constant player OWNING_PLAYER = Player(15)
private unit dummy = null
endglobals
function IsDestructableDead takes destructable dest returns boolean
return GetDestructableLife(dest) <= 0.405
endfunction
function IsDestructableTree takes destructable dest returns boolean
local boolean result = false
if (dest != null) then
call PauseUnit(dummy, false)
set result = IssueTargetOrder(dummy, "harvest", dest)
call PauseUnit(dummy, true) // stops order
endif
return result
endfunction
private function Initialization takes nothing returns nothing
set dummy = CreateUnit(OWNING_PLAYER, DUMMY_UNIT_ID, 0.0, 0.0, 0.0)
call ShowUnit(dummy, false) // cannot enumerate
call UnitAddAbility(dummy, HARVEST_ID)
call UnitAddAbility(dummy, 'Aloc') // unselectable, invulnerable
call PauseUnit(dummy, true)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library RT initializer Init
globals
private trigger Trig = CreateTrigger()
private constant real RegrowTime = 20
endglobals
function RegrowTrees takes nothing returns nothing
local destructable d = GetTriggerDestructable()
call TriggerSleepAction(RegrowTime)
call DestructableRestoreLife( d, GetDestructableMaxLife(d), true )
set d=null
endfunction
function Revival takes nothing returns nothing
if IsDestructableTree(GetEnumDestructable())==true then
call TriggerRegisterDeathEvent( Trig, GetEnumDestructable() )
endif
endfunction
function Init takes nothing returns nothing
call EnumDestructablesInRect(bj_mapInitialPlayableArea,null,function Revival )
call TriggerAddAction(Trig,function RegrowTrees)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Init initializer Set
globals
private real MAP_MIN_X
private real MAP_MAX_X
private real MAP_MIN_Y
private real MAP_MAX_Y
endglobals
function IsInMapXY takes real x , real y returns boolean
return x > MAP_MIN_X and x < MAP_MAX_X and y > MAP_MIN_Y and y < MAP_MAX_Y
endfunction
private function Set takes nothing returns nothing
set MAP_MIN_X = GetRectMinX(bj_mapInitialPlayableArea)
set MAP_MAX_X = GetRectMaxX(bj_mapInitialPlayableArea)
set MAP_MIN_Y = GetRectMinY(bj_mapInitialPlayableArea)
set MAP_MAX_Y = GetRectMaxY(bj_mapInitialPlayableArea)
endfunction
endlibrary
//***************************************************************************
//*
//* SetUnitZ - By TriggerHappy187
//*
//***************************************************************************
//*
//* Installation
//* * All you need to do is copy this script into your map and you can use
//* the provided functions.
//*
//***************************************************************************
//*
//* Requirements
//* * This requires no external systems, all it requires is JassHelper.
//*
//***************************************************************************
//
// Precautions
// * If this function is used on a point with a terarin deformation
// A desync may occur.
//
//***************************************************************************
library SetUnitZ
globals
private location heightFixer = Location(0,0)
endglobals
function GetCoordZ takes real x, real y returns real
call MoveLocation(heightFixer, x, y)
return GetLocationZ(heightFixer)
endfunction
function SetUnitZ takes unit u, real h returns nothing
local location loc = GetUnitLoc(u)
local real z = GetLocationZ(loc)
call RemoveLocation(loc)
set loc = null
call SetUnitFlyHeight(u,h-z,0.)
endfunction
//function SetUnitZ takes unit whichUnit, real height, real rate returns nothing
// if GetUnitFlyHeight(whichUnit) == 0 then
// if UnitAddAbility(whichUnit, 'Arav') then
// call UnitRemoveAbility(whichUnit, 'Arav')
// endif
// endif
// //call MoveLocation(heightFixer, GetUnitX(whichUnit), GetUnitY(whichUnit))
// call SetUnitFlyHeight(whichUnit, height-GetCoordZ(GetUnitX(whichUnit), GetUnitY(whichUnit)), rate)
//endfunction
function GetUnitZ takes unit whichUnit returns real
call MoveLocation(heightFixer, GetUnitX(whichUnit), GetUnitY(whichUnit))
return GetUnitFlyHeight(whichUnit)+GetLocationZ(heightFixer)
endfunction
endlibrary
library GetTerrainZ
// How to Implement:
//
// by D.V.D
//
// Copy this code
// Create a trigger in your map
// Change the trigger to custom script
// Paste the code into the trigger
globals
location GL = Location(0,0)
endglobals
function GetTerrainZ takes real x, real y returns real
call MoveLocation(GL, x, y)
return GetLocationZ(GL)
endfunction
function GetTerrainZLoc takes location loc returns real
call MoveLocation(GL, GetLocationX(loc), GetLocationY(loc))
return GetLocationZ(GL)
endfunction
endlibrary
//TESH.scrollpos=-1
//TESH.alwaysfold=0
scope Grenade initializer Init
private keyword Data
globals
// Editable Globals
private constant integer GRENADE_ID = 'n008' // Grenade unit
private constant integer GRENADE_SFX1 = 'n006' // SFX 1
private constant integer GRENADE_SFX2 = 'n007' // SFX 2
private constant integer SPELL_ID = 'A00N' // Ability ID
private constant real MAX_RANGE = 1000
private constant real MIN_RANGE = 400
private constant real MAX_HEIGHT = 200
private constant attacktype AT = ATTACK_TYPE_NORMAL
private constant damagetype DT = DAMAGE_TYPE_NORMAL
private constant weapontype WT = WEAPON_TYPE_WHOKNOWS
private constant boolean DAMAGE_SELF = false// Can it hurt player units ?
private constant boolean DAMAGE_ALLY = false// Can it hurt ally units ?
// Editable Globals
// Don't change...
private constant real PERIOD = 0.04 // Depends on what period you like ... don't moan at me if your .0001 period lags though...
private constant real SPEED = 400 * PERIOD// How fast the grenade travels per second
private Data DATA //Temp Globals
private real X //Temp Globals
private real Y //Temp Globals
private real DIST //Temp Globals
private integer COUNT = 0
private Data array GData
private timer TIMER = CreateTimer()
private location LOC = Location(0,0)
//Don't change
endglobals
private constant function AOE_Range takes integer lvl returns real
return 50 + lvl*50 *1.0
endfunction
private function MinMax takes real val,real min,real max returns real
if(min>val) then
return min
elseif(val>max) then
return max
else
return val
endif
endfunction
private function GetParabolaZ takes real x,real d,real h returns real
return 4 * h * x * (d - x) / (d * d)
endfunction // By AceHart
private function GetDamage takes integer level returns real
return GetRandomReal (50,50) + 50 * (level-1)
endfunction// I guess Flare @ TH.net helped me with this O_o...
private struct Data
unit Grenade
unit caster
player p
real x
real y
real DistCur
real DistMax
real baseH
real aoe
integer level
real cos
real sin
static group GROUP = CreateGroup()
static method Damage takes nothing returns boolean
local unit u = GetFilterUnit()
local player p = GetOwningPlayer(u)
local Data d = DATA
local real damage = GetDamage(d.level)
local boolean dmg = false
if(DAMAGE_SELF and p==d.p)then
set dmg = true
elseif(DAMAGE_ALLY and IsPlayerAlly(p,d.p))then
set dmg = true
elseif(IsPlayerEnemy(p,d.p))then
set dmg = true
endif
if(dmg) then
call UnitDamageTarget(d.caster,u,damage,true,true,AT,DT,WT)
endif
set u = null
return false
endmethod
static method InCircle takes nothing returns boolean
local destructable d = GetFilterDestructable()
local real x = DATA.x - GetDestructableX(d)
local real y = DATA.y - GetDestructableY(d)
local real dist = x*x+y*y
set d = null
if(dist>DATA.aoe*DATA.aoe)then// or SquareRoot(dist) > AOE_RANGE either workz...
return false
else
return true
endif
endmethod
static method TreeDestroy takes nothing returns nothing
local destructable d = GetEnumDestructable()
if IsDestructableTree(d) then
call KillDestructable(d)
endif
set d = null
endmethod
method KillTrees takes real x,real y returns nothing
local rect r = Rect(x-.aoe,y-.aoe,x+.aoe,y+.aoe)
call EnumDestructablesInRect(r,Filter(function Data.InCircle),function Data.TreeDestroy)
call RemoveRect(r)
set r = null
endmethod
method Explode takes nothing returns nothing
call UnitApplyTimedLife(CreateUnit(.p,GRENADE_SFX1,.x,.y,0),0,1)
call UnitApplyTimedLife(CreateUnit(.p,GRENADE_SFX2,.x,.y,0),0,1)
set DATA = this
call GroupEnumUnitsInRange(.GROUP,.x,.y,this.aoe,Filter(function Data.Damage))
call .KillTrees(.x,.y)
call .destroy()
endmethod
method onDestroy takes nothing returns nothing
call ShowUnit(.Grenade,false)// Don't know wether this is neccesary ?
call RemoveUnit(.Grenade)
endmethod
endstruct
private function Execute takes nothing returns nothing
local integer i = 0
local Data d
local unit u
local boolean zhit
loop
exitwhen i == COUNT
set zhit = false
set d = GData[i]
set u = d.Grenade
set d.DistCur = d.DistCur + SPEED
set d.x = d.x + SPEED * d.cos
set d.y = d.y + SPEED * d.sin
if IsInMapXY(d.x,d.y) == true then
call SetUnitX(u,d.x)
call SetUnitY(u,d.y)
call SetUnitZ(u,d.baseH+GetParabolaZ(d.DistCur,d.DistMax,MAX_HEIGHT))
call MoveLocation(LOC,d.x,d.y)
if(R2I(GetUnitZ(u))==R2I(GetLocationZ(LOC)))then
// R2I because it gives me '0.001' and stuff ... so it isn't 'equal' unit height
set zhit=true
endif
if zhit==true then
set COUNT = COUNT - 1
set GData[i] = GData[COUNT]
call d.Explode()
else
set i = i + 1
endif
else
set COUNT = COUNT - 1
set GData[i] = GData[COUNT]
call d.destroy()
endif
endloop
set u = null
if COUNT == 0 then
call PauseTimer(TIMER)
endif
endfunction
private function Run takes nothing returns nothing
local Data d = Data.create()
local location l = GetSpellTargetLoc()
local real x = GetLocationX(l)
local real y = GetLocationY(l)
local real dist = 0
local real facing
call RemoveLocation(l)// do I need to 'set l = null' ?
set d.caster = GetTriggerUnit()
set l = GetUnitLoc(d.caster)
set d.baseH = GetLocationZ(l)
call RemoveLocation(l)
set l = null
set d.p = GetOwningPlayer(d.caster)
set d.x = GetUnitX(d.caster)
set d.y = GetUnitY(d.caster)
set d.level = GetUnitAbilityLevel(d.caster,SPELL_ID)
set d.aoe = AOE_Range(d.level)
set x = x - d.x
set y = y - d.y
set facing = Atan2(y,x)
set d.cos = Cos(facing)
set d.sin = Sin(facing)
set d.Grenade = CreateUnit(d.p,GRENADE_ID,d.x,d.y,facing)
call UnitAddAbility(d.Grenade,'Amrf')// I have to do this or else it goes buggy over raised terrain
call UnitRemoveAbility(d.Grenade,'Amrf')
set d.DistMax = MinMax(SquareRoot(x*x+y*y),MIN_RANGE,MAX_RANGE)
set d.DistCur = 0
set GData[COUNT] = d
set COUNT = COUNT + 1
if COUNT == 1 then
call TimerStart(TIMER,PERIOD,true,function Execute)
endif
endfunction
private function Cond takes nothing returns boolean
if GetSpellAbilityId() == SPELL_ID then
call Run()
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_CAST)
call TriggerAddCondition(t,Condition(function Cond))
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
//
//
// To Implement the spell
//
//
// Copy the following : UNITS
//
// Explosion -> 'xdum'
// Explosion SFX -> 'xsfx''
// Grenade -> ' gdum''
//
//
//
// Copy the following : ABILITy
//
// Grenade -> 'GAId'
//
//
// Copy the following : Triggers
//
// Regrow Trees
// IsDestructableTree
// InitLibrary
//
//
//
// You can change many of the grenades features, such as :
//
// max height , max/min range , aoe range
// damage , wether it can hurt allied or player units
//
//TESH.scrollpos=-1
//TESH.alwaysfold=0
scope BouncyGrenade initializer Init
private keyword Data
globals
// Editable Globals
private constant integer GRENADE_ID = 'gdum'
private constant integer GRENADE_SFX1 = 'xdum'
private constant integer GRENADE_SFX2 = 'xsfx'
private constant integer SPELL_ID = 'BGid'
private constant integer MAX_BOUNCES = 2// How many bounces ?
private constant real BOUNCE_DECREASE = 1.5// How much the range divises by per bounce
private constant real MAX_RANGE = 1200// max range of grenade
private constant real MIN_RANGE = 400// min range of grenade
private constant real MAX_HEIGHT = 400// maximum height reachable
private constant attacktype AT = ATTACK_TYPE_NORMAL // attack type..
private constant damagetype DT = DAMAGE_TYPE_NORMAL// damage type..
private constant weapontype WT = WEAPON_TYPE_WHOKNOWS// Weapon type..
private constant boolean DAMAGE_SELF = false// Can it hurt player units ?
private constant boolean DAMAGE_ALLY = false// Can it hurt ally units ?
//
// Don't change...
private constant real PERIOD = 0.04 // Depends on what period you like ... don't moan at me if your .0001 period lags though...
private constant real SPEED = 700 *PERIOD // How fast the grenade travels per second
private Data DATA// Temp Globals
private real X //Temp Globals
private real Y //Temp Globals
private real DIST //Temp Globals
private integer COUNT = 0
private Data array GData
private timer TIMER = CreateTimer()
//You can now continue to the rest of the code...
endglobals
private constant function AOE_Range takes integer lvl returns real
return 150 + lvl*50 *1.0// Find AoE for Grenade explosion
endfunction
private function MinMax takes real val,real min,real max returns real
if(min>val) then
return min
elseif(val>max) then
return max
else
return val
endif
endfunction
private function GetRange takes real range returns real
return range/BOUNCE_DECREASE// devise the range
endfunction
private function GetSpeed takes real range returns real
return (range/MAX_RANGE)*SPEED*2// find speed with this 'formula'
endfunction
private function GetHeight takes real range returns real// find the max height for that bounce
return MinMax((range/MAX_RANGE)*MAX_HEIGHT*3,0,MAX_HEIGHT)
endfunction
private function GetParabolaZ takes real x,real d,real h returns real
return 4 * h * x * (d - x) / (d * d)
endfunction // By AceHart
private function GetDamage takes integer level returns real
return GetRandomReal (10,20) + 15 * (level-1)
endfunction// I guess Flare @ TH.net helped me with this O_o...
private struct Data
unit Grenade
unit caster
player p
real x
real y
real DistCur
real DistMax
real HeightMax
real heightBase
real baseH
real aoe
real facing
integer level
real speed
real cos
real sin
integer bounce
boolean justBounced
static group GROUP = CreateGroup()
static method Damage takes nothing returns boolean// To damage the targets near grenade
local unit u = GetFilterUnit()
local player p = GetOwningPlayer(u)
local Data d = DATA
local real damage = GetDamage(d.level)
local boolean dmg = false
if(DAMAGE_SELF and p==d.p)then// damage the caster's and player units ... if possible ?
set dmg = true
elseif(DAMAGE_ALLY and IsPlayerAlly(p,d.p))then// hurt allies ?
set dmg = true
elseif(IsPlayerEnemy(p,d.p))then// or just enemies...
set dmg = true
endif
if(dmg) then
call UnitDamageTarget(d.caster,u,damage,true,true,AT,DT,WT)// the damage..
endif
set u = null
return false// return false to not add to global group..
endmethod
static method InCircle takes nothing returns boolean
local destructable d = GetFilterDestructable()
local real x = DATA.x - GetDestructableX(d)
local real y = DATA.y - GetDestructableY(d)
local real dist = x*x+y*y
// Check if the destructable is in range of the grenade AoE
set d = null
if(dist>DATA.aoe*DATA.aoe)then// or SquareRoot(dist) > AOE_RANGE either workz...
return false
else
return true
endif
endmethod
static method TreeDestroy takes nothing returns nothing
local destructable d = GetEnumDestructable()
if IsDestructableTree(d) then
call KillDestructable(d)// Destroy the tree if its a tree...
endif
set d = null//nulls...
endmethod
method KillTrees takes real x,real y returns nothing
local rect r = Rect(x-.aoe,y-.aoe,x+.aoe,y+.aoe)
// find trees within a rect then find within a circle...
call EnumDestructablesInRect(r,Filter(function Data.InCircle),function Data.TreeDestroy)
call RemoveRect(r)// nulls...
set r = null
endmethod
method Explode takes nothing returns nothing
call UnitApplyTimedLife(CreateUnit(.p,GRENADE_SFX1,.x,.y,0),0,1)
call UnitApplyTimedLife(CreateUnit(.p,GRENADE_SFX2,.x,.y,0),0,1)// Add each SFX for a second
set DATA = this
// global data for enums ...
call GroupEnumUnitsInRange(.GROUP,.x,.y,this.aoe,Filter(function Data.Damage))
call .KillTrees(.x,.y)
call .destroy()// kill trees then destroy self..
endmethod
method onDestroy takes nothing returns nothing
call ShowUnit(.Grenade,false)// Don't know wether this is neccesary ?
call RemoveUnit(.Grenade)
endmethod
method NewBounce takes nothing returns nothing// set new data for that bounce
local location l = GetUnitLoc(.Grenade)
set .bounce = .bounce + 1// increase bounce
set .DistMax = .DistCur/BOUNCE_DECREASE// find the distmax from the distance traveled / decrement
set .DistCur = 0// reset dist traveled
set .HeightMax = GetHeight(.DistMax)// formula for height
set .speed = GetSpeed(.DistMax)// find the speed for new bounce
set .baseH = GetLocationZ(l)//find 'this' bounce height again..
call RemoveLocation(l)// leaks
set l = null
endmethod
endstruct
private function Execute takes nothing returns nothing
local integer i = 0
local Data d
local unit u
local boolean zhit // Z - Hit if anyone has a weird font like me which looks like an s ...
local location l = Location(0,0)
loop
exitwhen i == COUNT
set zhit = false
set d = GData[i]
set u = d.Grenade
set d.DistCur = d.DistCur + d.speed
set d.x = d.x + d.speed * d.cos// moving data...
set d.y = d.y + d.speed * d.sin
if IsInMapXY(d.x,d.y) == true then// grenade in map
call SetUnitX(u,d.x)
call SetUnitY(u,d.y)// move the grenade
call SetUnitZ(u,d.baseH+GetParabolaZ(d.DistCur,d.DistMax,d.HeightMax))
// set unit Z
call MoveLocation(l,d.x,d.y)
if(R2I(GetUnitZ(u))==R2I(GetLocationZ(l)))then
// R2I because it gives me '0.001' and stuff ... so it isn't 'equal' unit height
set zhit=true
endif
// I dont think the dist current can go higher than the max... but just in case
if zhit==true then
if d.bounce==2 then
set COUNT = COUNT - 1
set GData[i] = GData[COUNT]// next instance
call d.Explode()
else
call d.NewBounce()// new bounce because of zhit
endif
else
set i = i + 1// just increase the value to the next instance
endif
else
set COUNT = COUNT - 1// change to next instance
set GData[i] = GData[COUNT]
call d.destroy()
endif
endloop
call RemoveLocation(l)
set u = null// leaks
set l = null
if COUNT == 0 then
call PauseTimer(TIMER)// pause
endif
endfunction
private function Run takes nothing returns nothing
local Data d = Data.create()
local location l = GetSpellTargetLoc()
local real x = GetLocationX(l)
local real y = GetLocationY(l)
local real dist = 0// locals for data
local real facing
call RemoveLocation(l)// do I need to 'set l = null' ?
set d.caster = GetTriggerUnit()
set l = GetUnitLoc(d.caster)
set d.baseH = GetLocationZ(l)
call RemoveLocation(l)
set l = null// leaks
set d.caster = GetTriggerUnit()
set d.p = GetOwningPlayer(d.caster)
set d.x = GetUnitX(d.caster)// caster data
set d.y = GetUnitY(d.caster)
set d.level = GetUnitAbilityLevel(d.caster,SPELL_ID)
set d.aoe = AOE_Range(d.level)
set d.bounce = 0
set x = x - d.x
set y = y - d.y
set facing = Atan2(y,x)
set d.cos = Cos(facing)
set d.sin = Sin(facing)// facing,,,
set d.Grenade = CreateUnit(d.p,GRENADE_ID,d.x,d.y,facing)
call UnitAddAbility(d.Grenade,'Amrf')// I have to do this or else it goes buggy over raised terrain
call UnitRemoveAbility(d.Grenade,'Amrf')
set d.DistMax = MinMax(SquareRoot(x*x+y*y)/Pow(BOUNCE_DECREASE,MAX_BOUNCES),0,MAX_RANGE)
set d.HeightMax = GetHeight(d.DistMax)// height, dist , speed data
set d.speed = GetSpeed(d.DistMax)
//MinMax(SquareRoot(x*x+y*y),MIN_RANGE,MAX_RANGE)
set d.DistCur = 0
set GData[COUNT] = d
set COUNT = COUNT + 1
if COUNT == 1 then
call TimerStart(TIMER,PERIOD,true,function Execute)
endif
endfunction
private function Cond takes nothing returns boolean
if GetSpellAbilityId() == SPELL_ID then
call Run()
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_CAST)
call TriggerAddCondition(t,Condition(function Cond))
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
//
//
// To Implement the spell
//
//
// Copy the following : UNITS
//
// Explosion -> 'xdum'
// Explosion SFX -> 'xsfx''
// Grenade -> ' gdum''
//
//
//
// Copy the following : ABILITy
//
// Grenade -> 'BGid'
//
//
// Copy the following : Triggers
//
// Regrow Trees
// IsDestructableTree
// InitLibrary
//
//
// You can change many of the grenades features, such as :
//
// max height , max/min range , aoe range
// damage , wether it can hurt allied or player units
// max bounces , how far each bounce ... bounces
//
// I tried to make the formulas even as if they were a real grenade...
// slowing down , not bouncing as high , and traveling less distance