- Joined
- Feb 6, 2014
- Messages
- 2,466
JASS:
library Illusion /*
Illusion v1.33
by Flux
Allows easy creation of Illusion with any damage factor.
*/ requires DamageEvent, DamageModify/*
http://www.hiveworkshop.com/threads/damagepackage.287101/
Required to manipulate damage given and damage taken by illusions.
*/ optional Table /*
If not found, the system will create a hashtable. You cannot create more than 256 hashtable
per map.
********************************************************************************
*************************************** API ************************************
********************************************************************************
Illusion.create(player, unitSource, x, y)
- Create an Illusion based on <unitSource>, owned by <player>, positioned at (<x>, <y>)
this.duration = <timedLife>
- Add a timer to an illusion.
- Cannot be overwritten once set.
Illusion.get(unit)
- Return the 'Illusion instance' based on <unit> parameter.
this.unit
- Refers to the actual illusion unit
this.damageGiven
- Determines damage dealt factor.
this.damageTaken
- Determines damage received factor.
CREDITS:
Bribe - Table
Flux - DamageEvent and DamageModify
*/
//===================================================================
//========================= CONFIGURATION ===========================
//===================================================================
globals
//Rawcode of Illusion Ability based on "Item Illusions"
private constant integer ILLUSION_SPELL = 'AILS'
private constant integer DUMMY_ID = 'dumi'
private constant integer REFRESH_COUNT = 30
//Dummy unit owner
private constant player DUMMY_OWNER = Player(PLAYER_NEUTRAL_PASSIVE)
endglobals
//===================================================================
//======================= END CONFIGURATION =========================
//===================================================================
native UnitAlive takes unit u returns boolean
struct Illusion
readonly unit unit
public real damageTaken
public real damageGiven
static if LIBRARY_Table then
private static Table tb
else
private static hashtable hash = InitHashtable()
endif
private static trigger deathTrg = CreateTrigger()
private static group g = CreateGroup()
private static timer t = CreateTimer()
private static integer count = 0
private static unit dummy
private static unit illu
static method get takes unit u returns thistype
static if LIBRARY_Table then
return thistype.tb[GetHandleId(u)]
else
return LoadInteger(thistype.hash, GetHandleId(u), 0)
endif
endmethod
private static method reAdd takes nothing returns nothing
call TriggerRegisterUnitEvent(thistype.deathTrg, GetEnumUnit(), EVENT_UNIT_DEATH)
endmethod
private static method onDeath takes nothing returns boolean
call thistype(thistype.get(GetTriggerUnit())).destroy()
return false
endmethod
method destroy takes nothing returns nothing
if UnitAlive(this.unit) then
call KillUnit(this.unit)
endif
static if LIBRARY_Table then
call thistype.tb.remove(GetHandleId(this.unit))
else
call RemoveSavedInteger(thistype.hash, GetHandleId(this.unit), 0)
endif
call GroupRemoveUnit(thistype.g, this.unit)
//Death trigger refresh
set thistype.count = thistype.count + 1
if thistype.count >= REFRESH_COUNT then
call DestroyTrigger(thistype.deathTrg)
set thistype.deathTrg = CreateTrigger()
call TriggerAddCondition(thistype.deathTrg, Condition(function thistype.onDeath))
call ForGroup(thistype.g, function thistype.reAdd)
set thistype.count = 0
endif
set this.unit = null
call this.deallocate()
endmethod
private static method onDamage takes nothing returns nothing
//If source is illusion
if IsUnitInGroup(Damage.source, thistype.g) then
set Damage.amount = Damage.amount*thistype.get(Damage.source).damageGiven
endif
//If target is illusion
if IsUnitInGroup(Damage.target, thistype.g) then
set Damage.amount = Damage.amount*thistype.get(Damage.target).damageTaken
endif
endmethod
private static method entered takes nothing returns boolean
set thistype.illu = GetSummonedUnit()
return false
endmethod
method operator duration= takes real time returns nothing
call UnitApplyTimedLife(this.unit, 'BTLF', time)
endmethod
static method create takes player owner, unit source, real x, real y returns thistype
local thistype this
set thistype.illu = null
//Create the Illusion Unit
if source != null and UnitAlive(source) then
call SetUnitX(thistype.dummy, GetUnitX(source))
call SetUnitY(thistype.dummy, GetUnitY(source))
call SetUnitOwner(thistype.dummy, GetOwningPlayer(source), false)
if IssueTargetOrderById(thistype.dummy, 852274, source) then
if thistype.illu != null then
call SetUnitOwner(thistype.illu, owner, true)
if IsUnitType(source, UNIT_TYPE_STRUCTURE) then
call SetUnitPosition(thistype.illu, x, y)
else
call SetUnitX(thistype.illu, x)
call SetUnitY(thistype.illu, y)
endif
else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 3600, "[Illusion] No illusion created")
call SetUnitOwner(thistype.dummy, DUMMY_OWNER, false)
return 0
endif
else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 3600, "[Illusion] Issued illusion create order failed")
call SetUnitOwner(thistype.dummy, DUMMY_OWNER, false)
return 0
endif
call SetUnitOwner(thistype.dummy, DUMMY_OWNER, false)
else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 3600, "[Illusion] Source unit dead or non-existing")
return 0
endif
//Initialize struct
set this = thistype.allocate()
set this.unit = thistype.illu
set this.damageTaken = 1.0
set this.damageGiven = 1.0
call SetUnitAnimation(thistype.illu, "stand")
call GroupAddUnit(thistype.g, this.unit)
call TriggerRegisterUnitEvent(thistype.deathTrg, this.unit, EVENT_UNIT_DEATH)
static if LIBRARY_Table then
set thistype.tb[GetHandleId(this.unit)] = this
else
call SaveInteger(thistype.hash, GetHandleId(this.unit), 0, this)
endif
set thistype.illu = null
return this
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
set thistype.dummy = CreateUnit(DUMMY_OWNER, DUMMY_ID, 0, 0, 0)
call TriggerRegisterUnitEvent(t, thistype.dummy, EVENT_UNIT_SUMMON)
call TriggerAddCondition(t, Condition(function thistype.entered))
call TriggerAddCondition(thistype.deathTrg, Condition(function thistype.onDeath))
call UnitAddAbility(thistype.dummy, ILLUSION_SPELL)
static if LIBRARY_Table then
set thistype.tb = Table.create()
endif
call Damage.registerModifier(function thistype.onDamage)
endmethod
endstruct
endlibrary
Example of using the system:
JASS:
scope Test1 initializer Init
private function BeginTest takes nothing returns nothing
local Illusion illu1 = Illusion.create(Player(0), tinker, 0, 0)
local Illusion illu2 = Illusion.create(Player(0), firelord, 0, 0)
local Illusion illu3 = Illusion.create(Player(0), tank, 0, 0)
local Illusion illu4 = Illusion.create(Player(0), flying, 0, 0)
//Set Duration
set illu1.duration = 30
set illu2.duration = 30
set illu3.duration = 30
set illu4.duration = 30
//Set Damage Manipulation of each illusion
set illu1.damageTaken = 1 //Receives the same damage
set illu1.damageGiven = 10 //Deals 10 times the original damage
set illu2.damageTaken = 3 //Receives thrice damage
set illu2.damageGiven = 1.5 //Deals 1.5 times the original damage
set illu3.damageTaken = 0 //Will not receive any damage
set illu3.damageGiven = 0 //Will not deal any damage
set illu4.damageTaken = 0 //Will not receive any damage
set illu4.damageGiven = 2.0 //Deals twice the original damage
//Order the illusions to move to the corners of the map
call IssuePointOrder(illu1.unit, "move", 3000, 3000)
call IssuePointOrder(illu2.unit, "move", -3000, -3000)
call IssuePointOrder(illu3.unit, "move", -3000, 3000)
call IssuePointOrder(illu4.unit, "move", 3000, -3000)
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
local string s = "1"
call TriggerRegisterPlayerChatEvent(t, Player(0), s, true)
call TriggerAddAction(t, function BeginTest)
call BJDebugMsg("Type '" + s + "' to create 4 Illusions owned by Player(0) at (0,0)")
endfunction
endscope
Changelog:
v1.00 - [2 March 2016]
- Initial Release
v1.10 - [15 March 2016]
- Optimized the code.
- Made the Debug Messages more specific.
- Added RegisterPlayerUnitEvent as an optional requirement.
- Improved documentation.
v1.20 - [10 June 2016]
- Revised most of the code.
- Only one object editor ability based on Item Illusion is needed.
- Damage dealt, damage received and duration can now be manipulated dynamically.
v1.30 - [2 November 2016]
- Fixed bug involving damage source and damage target are both illusion.
- Now requires DamageEvent and DamageModify.
- Renamed "static method instance" to "static method get".
- Optimized refreshing system.
- Removed duration parameter in "static method create"
- Added "method operator duration="
v1.31 - [2 November 2016]
- Fixed potential leak with refresh system.
- Improved configuration.
v1.32 - [4 February 2017]
- Replaced periodic trigger cleanup with unused event counter cleanup.
- Added debug messages.
- Illusions created now automatically plays "stand" animation.
- Shortened onDamage function.
v1.33 - [11 February 2017]
- Reorder a function placement to avoid trigger evaluation.
- Removed unnecessary function call.
- Dummy changes ownership back to NEUTRAL upon failing creation of Illusion.
- Improved debug messages.
Attachments
Last edited: