RaiJin
New Member
- Reaction score
- 40
JASS:
//***************************************************************************
//** OD ** OrderCast ** By RaiJin ** Version 1.21 **
//***************************************************************************
//
// What is Order Cast?
// - OrderCast is a system that reuses dummies instead of constantly
// creating new ones and destroy them.
// - You can register an order cast string to an ability code.
//
// Pros
// - Very easy to use
// - GUI'ers could easily use this
// - Faster to code with, doing it manually would take much longer than this
// - If done right then only one dummy will be needed to cast everything (instant spells)
//
// Cons
// - If the dummy is overloaded with a number of abilities it may bug
//
// Functions:
// - function OD_CastTarget takes player p, unit target, integer abilicode, integer level returns boolean
// - function OD_CastImmediate takes player p, real x, real y, integer abilicode, integer level returns boolean
// - function OD_CastPoint takes player p, real x, real y, real x2, real y2, integer abilicode, integer level returns boolean
// - function OD_CastChannel takes player p, unit target, integer abilicode, integer level returns boolean
// - function OD_CastOnGroup takes player p, integer abilicode, integer level, group g returns boolean
// - function OD_CastOnGroupDamage takes unit p, real dmg, attacktype attackType, damagetype damageType, weapontype weaponType, integer abilicode, integer level, group g returns boolean
// - function OD_CastOnAOE takes player p, real AOE, real x, real y, boolexpr filter, integer abilicode, integer level returns boolean
// - function OD_CastOnAOEDamage takes unit p, real AOE, real x, real y, boolexpr filter, real dmg, attacktype attackType, damagetype damageType, weapontype weaponType, integer abilicode, integer level returns boolean
// - function OD_RegisterOrder takes string s, integer abilicode returns nothing
// - function OD_RegisterOrderEx takes string s, integer abilicode, integer level returns nothing
// - all Above functions can have Ex(EXCEPT FOR CHANNEL) at the end of them, Meaning that it will use the instant dummy registered
// (below for more details)
//
// Details:
// - OD is a system I created because I heard its slow to create units.
// This system preloads dummies on initialization and then reuses them whenever there not needed
//
// - function OD_RegisterOrder, Registers strings to the abilicode so the system can call it directly instead of the users
// manually putting them in
//
// - function OD_CastPoint is taking 2 x and y's because there might be a need for angle so I put it in there
//
// - function OD_RegisterOrderEx, Works like OD_RegisterOrder except it Registers 1 dummy to the skill
// this means that all casts will be used by that 1 dummy, meaning it will be faster
// *NOTE: Only use the "Ex" functions if you know your dummy skills are instant
//
//
// Thanks:
// - Jesus4Lyf for adding in some extra functions and for the idea of Hashing the strings <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite1" alt=":)" title="Smile :)" loading="lazy" data-shortname=":)" />
//
// How to import:
// - Create a trigger named OD.
// - Convert it to custom text and replace the whole trigger text with this.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library OD initializer INIT requires KT
globals
private constant integer DUMMY_ID = 039;h000039; //DUMMYS ID
private constant integer HASH_NEXT = 53
private constant integer MAX_HASH_VALUE = 8191
private constant real HOLD = 0.35 //How long it takes to recycle the dummy after being used
//Setting it to 0 would be best if you know how to set the dummy
//ability corrently
private constant string STOP = "stop"
private integer COUNT = 1 // number of dummy's you start off with
private integer ORDER
private integer array HashedInt
private integer array CAST_IDS
private unit array UNITS
private unit array INSTANT_UNITS
endglobals
globals
//locals
private group castgroup = CreateGroup()
private integer HASH = 0
private player OWNER = null
private unit FIRST = null
endglobals
private function Hash takes integer int returns integer
local integer hash=int-(int/MAX_HASH_VALUE)*MAX_HASH_VALUE
loop
exitwhen HashedInt[hash]==int
if HashedInt[hash]==0 then
set HashedInt[hash]=int
return hash
endif
set hash=hash+HASH_NEXT
if hash>=MAX_HASH_VALUE then
set hash=hash-MAX_HASH_VALUE
endif
endloop
return hash
endfunction
private struct Data
unit dummy
integer Code
integer orderID
static method create takes unit which, integer CODE returns Data
local Data d = Data.allocate()
set d.dummy = which
set d.Code = CODE
set d.orderID = GetUnitCurrentOrder( which )
return d
endmethod
private method onDestroy takes nothing returns nothing
call UnitRemoveAbility( .dummy, .Code )
endmethod
endstruct
private function RemoveDummy takes nothing returns boolean
local Data d = KT_GetData()
local integer i = 0
loop
exitwhen i == COUNT
set i = i + 1
if d.dummy == UNITS<i> then
call IssueImmediateOrder( UNITS<i>, STOP )
exitwhen true
endif
endloop
call d.destroy()
return true
endfunction
private function ChannelEnd takes nothing returns boolean
local Data d = KT_GetData()
if GetUnitCurrentOrder( d.dummy ) != d.orderID then
call IssueImmediateOrder( d.dummy, STOP )
call d.destroy()
return true
endif
return false
endfunction
private function NewDummy takes nothing returns unit
local integer i = 0
loop
exitwhen i == COUNT
set i = i + 1
if GetUnitCurrentOrder( UNITS<i> ) == ORDER then
return UNITS<i>
endif
endloop
debug call BJDebugMsg("SYSTEM WARNING - ORDERDUMMY: Exceeded Max Dummies, Extending the number of Max Dummies!!")
set COUNT = COUNT + 1
set UNITS[COUNT] = CreateUnit( Player(14), DUMMY_ID, 0, 0, bj_UNIT_FACING )
return UNITS[COUNT]
endfunction
public function CastTarget takes player p, unit Widget, integer abilicode, integer level returns boolean
local unit d
if Widget == null then
debug call BJDebugMsg("Widget unit is NULL skipping the OrderCast")
return false
endif
set d = NewDummy()
call SetUnitOwner( d, p, false )
call UnitAddAbility( d, abilicode )
if level > 1 then
call SetUnitAbilityLevel( d, abilicode, level )
endif
call SetUnitX( d, GetUnitX( Widget ) )
call SetUnitY( d, GetUnitY( Widget ) )
call IssueTargetOrderById( d, CAST_IDS[Hash(abilicode)], Widget )
call KT_Add( function RemoveDummy, Data.create( d, abilicode ), HOLD )
return true
endfunction
public function CastTargetEx takes player p, unit Widget, integer abilicode, integer level returns boolean
if Widget == null then
debug call BJDebugMsg("Widget unit is NULL skipping the OrderCast")
return false
endif
set HASH = Hash(abilicode)
if INSTANT_UNITS[HASH] == null then
debug call BJDebugMsg("The ability "+I2S(abilicode)+" was not registered as an instant cast skipping actions")
return CastTarget(p,Widget,abilicode,level)
endif
if level > 1 then
call SetUnitAbilityLevel(INSTANT_UNITS[HASH],abilicode,level)
endif
call SetUnitOwner( INSTANT_UNITS[HASH], p, false )
call IssueTargetOrderById(INSTANT_UNITS[HASH], CAST_IDS[HASH], Widget)
return true
endfunction
public function CastPoint takes player p, real x, real y, real x2, real y2, integer abilicode, integer level returns boolean
local unit d = NewDummy()
call SetUnitOwner( d, p, false )
call SetUnitX( d, x2 )
call SetUnitY( d, y2 )
call UnitAddAbility( d, abilicode )
if level > 1 then
call SetUnitAbilityLevel( d, abilicode, level )
endif
call IssuePointOrderById( d, CAST_IDS[Hash(abilicode)], x, y )
call KT_Add( function RemoveDummy, Data.create( d, abilicode ), HOLD )
return false
endfunction
public function CastPointEx takes player p, real x, real y, real x2, real y2, integer abilicode, integer level returns boolean
set HASH = Hash(abilicode)
if INSTANT_UNITS[HASH] == null then
debug call BJDebugMsg("The ability "+I2S(abilicode)+" was not registered as an instant cast skipping actions")
return CastPoint(p,x,y,x2,y2,abilicode,level)
endif
if level > 1 then
call SetUnitAbilityLevel(INSTANT_UNITS[HASH],abilicode,level)
endif
call SetUnitOwner( INSTANT_UNITS[HASH], p, false )
call SetUnitX( INSTANT_UNITS[HASH], x2 )
call SetUnitY( INSTANT_UNITS[HASH], y2 )
call IssuePointOrderById( INSTANT_UNITS[HASH], CAST_IDS[HASH], x, y )
return false
endfunction
public function CastImmediate takes player p, real x, real y, integer abilicode, integer level returns boolean
local unit d = NewDummy()
call SetUnitOwner( d, p, false )
call UnitAddAbility( d, abilicode )
if level > 1 then
call SetUnitAbilityLevel( d, abilicode, level )
endif
call SetUnitX( d, x )
call SetUnitY( d, y )
call IssueImmediateOrderById( d, CAST_IDS[Hash(abilicode)] )
call KT_Add( function RemoveDummy, Data.create( d, abilicode ), HOLD )
return false
endfunction
public function CastImmediateEx takes player p, real x, real y, integer abilicode, integer level returns boolean
set HASH = Hash(abilicode)
if INSTANT_UNITS[HASH] == null then
debug call BJDebugMsg("The ability "+I2S(abilicode)+" was not registered as an instant cast skipping actions")
return CastImmediate(p,x,y,abilicode,level)
endif
if level > 1 then
call SetUnitAbilityLevel(INSTANT_UNITS[HASH],abilicode,level)
endif
call SetUnitOwner(INSTANT_UNITS[HASH],p,false)
call SetUnitX(INSTANT_UNITS[HASH],x)
call SetUnitY(INSTANT_UNITS[HASH],y)
call IssueImmediateOrderById(INSTANT_UNITS[HASH],CAST_IDS[HASH])
return true
endfunction
public function CastChannel takes player p, unit target, integer abilicode, integer level returns boolean
local unit d
if target == null then
debug call BJDebugMsg("Requested to cast a spell on a null unit, SKIPPING ACTIONS")
return false
endif
set d = NewDummy()
call SetUnitOwner( d, p, false )
call UnitAddAbility( d, abilicode )
if level > 1 then
call SetUnitAbilityLevel( d, abilicode, level )
endif
call SetUnitX( d, GetUnitX(target) )
call SetUnitY( d, GetUnitY(target) )
call IssueTargetOrderById( d, CAST_IDS[Hash(abilicode)], target )
call KT_Add( function ChannelEnd, Data.create( d, abilicode ), HOLD )
return true
endfunction
public function CastOnGroup takes player p, integer abilicode, integer level, group g returns boolean
if g == null then
debug call BJDebugMsg("NULL GROUP")
return false
endif
loop
set FIRST=FirstOfGroup(g)
exitwhen FIRST==null
call CastTarget(p,FIRST,abilicode,level)
call GroupRemoveUnit(g,FIRST)
endloop
return true
endfunction
public function CastOnGroupEx takes player p, integer abilicode, integer level, group g returns boolean
if g == null then
debug call BJDebugMsg("NULL GROUP")
return false
endif
loop
set FIRST=FirstOfGroup(g)
exitwhen FIRST==null
call CastTargetEx(p,FIRST,abilicode,level)
call GroupRemoveUnit(g,FIRST)
endloop
return true
endfunction
public function CastOnGroupDamage takes unit p, real dmg, attacktype attackType, damagetype damageType, weapontype weaponType, integer abilicode, integer level, group g returns boolean
set OWNER = GetOwningPlayer(p)
if g == null then
debug call BJDebugMsg("NULL GROUP")
return false
endif
loop
set FIRST=FirstOfGroup(g)
exitwhen FIRST == null
call CastTarget(OWNER,FIRST,abilicode,level)
call UnitDamageTarget(p,FIRST,dmg,false,false,attackType,damageType,weaponType)
call GroupRemoveUnit(g,FIRST)
endloop
return true
endfunction
public function CastOnGroupDamageEx takes unit p, real dmg, attacktype attackType, damagetype damageType, weapontype weaponType, integer abilicode, integer level, group g returns boolean
set OWNER = GetOwningPlayer(p)
if g == null then
debug call BJDebugMsg("NULL GROUP")
return false
endif
loop
set FIRST=FirstOfGroup(g)
exitwhen FIRST == null
call CastTargetEx(OWNER,FIRST,abilicode,level)
call UnitDamageTarget(p,FIRST,dmg,false,false,attackType,damageType,weaponType)
call GroupRemoveUnit(g,FIRST)
endloop
return true
endfunction
public function CastOnAOE takes player p, real AOE, real x, real y, boolexpr filter, integer abilicode, integer level returns boolean
call GroupEnumUnitsInRange( castgroup, x, y, AOE, filter )
loop
set FIRST=FirstOfGroup(castgroup)
exitwhen FIRST == null
call CastTarget(p,FIRST,abilicode,level)
call GroupRemoveUnit(castgroup,FIRST)
endloop
return true
endfunction
public function CastOnAOEEx takes player p, real AOE, real x, real y, boolexpr filter, integer abilicode, integer level returns boolean
call GroupEnumUnitsInRange( castgroup, x, y, AOE, filter )
loop
set FIRST=FirstOfGroup(castgroup)
exitwhen FIRST == null
call CastTargetEx(p,FIRST,abilicode,level)
call GroupRemoveUnit(castgroup,FIRST)
endloop
return false
endfunction
public function CastOnAOEDamage takes unit p, real AOE, real x, real y, boolexpr filter, real dmg, attacktype attackType, damagetype damageType, weapontype weaponType, integer abilicode, integer level returns boolean
call GroupEnumUnitsInRange(castgroup,x,y,AOE,filter)
return CastOnGroupDamage(p,dmg,attackType,damageType,weaponType,abilicode,level,castgroup)
endfunction
public function CastOnAOEDamageEx takes unit p, real AOE, real x, real y, boolexpr filter, real dmg, attacktype attackType, damagetype damageType, weapontype weaponType, integer abilicode, integer level returns boolean
call GroupEnumUnitsInRange(castgroup,x,y,AOE,filter)
return CastOnGroupDamageEx(p,dmg,attackType,damageType,weaponType,abilicode,level,castgroup)
endfunction
public function RegisterOrder takes string s, integer abilicode returns nothing
set CAST_IDS[Hash(abilicode)] = OrderId(s)
endfunction
public function RegisterOrderEx takes string s, integer abilicode, integer level returns boolean
set HASH = Hash(abilicode)
set CAST_IDS[HASH] = OrderId(s)
set INSTANT_UNITS[HASH] = CreateUnit( Player(13), DUMMY_ID, 0, 0, bj_UNIT_FACING )
call UnitAddAbility( INSTANT_UNITS[HASH], abilicode )
if level > 1 then
call SetUnitAbilityLevel( INSTANT_UNITS[HASH], abilicode, level )
endif
return false
endfunction
private function INIT takes nothing returns nothing
local integer i = 0
loop
exitwhen i == COUNT
set i = i + 1
set UNITS<i> = CreateUnit( Player(14), DUMMY_ID, 0, 0, bj_UNIT_FACING )
call IssueImmediateOrder( UNITS<i>, "stop" )
endloop
set ORDER = GetUnitCurrentOrder( UNITS<i> )
endfunction
endlibrary</i></i></i></i></i></i></i>
GUI Example
*NOTE: Remember to Register the Ability Code first
or even
Trigger:
- Untitled Trigger 001
- Events
- Unit - A unit Starts the effect of an ability
- Conditions
- (Ability being cast) Equal to Acid Bomb
- Actions
- Set TriggerUnit = (Triggering unit)
- Set TargetUnit = (Target unit of ability being cast)
- Custom script: call OD_CastTarget( GetOwningPlayer(udg_TriggerUnit), udg_TargetUnit, 'A001', 1 )
- Events
or even
Trigger:
- Untitled Trigger 001
- Events
- Unit - A unit Starts the effect of an ability
- Conditions
- (Ability being cast) Equal to Acid Bomb
- Actions
- Custom script: call OD_CastTarget( GetOwningPlayer(GetTriggerUnit()), GetSpellTargetUnit(), 'A001', 1 )
- Events
JASS:
scope Skill initializer i
private function ACT takes nothing returns nothing
call OD_CastImmediate( GetOwningPlayer(GetTriggerUnit()), GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), 039;A001039;, 1 )
endfunction
private function i takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddAction( t, function ACT )
call OD_RegisterOrder( "thunderclap", 039;A001039; )
endfunction
endscope
CHANGELOG:
Code:
//*******************************
//** ChangeLog
//*******************************
v1.21
-Readjusted Instant Casts
v.1.20
-11 new amazing functions !!
-You can Now Register 1 dummy to a skill(use it for casts that are instant)
v1.02
- The Dummies now Cast by Id's instead of strings ( faster now )
v1.01
-Changed some function names
-Increases Amount of Dummies instead of destroying them
-Added function OD_CastChannel
-Added function OD_CastPoint
v1.00
-Initial Release