- Joined
- Feb 6, 2014
- Messages
- 2,466
Ok, I'll put the debug messages back. Anything else? So I can fix all the issues in one update.
//Refresh Rate of triggers
private constant real REFRESH_RATE = 120
Tried that before, if I recall correctly, that event will only run when DUMMY_OWNER is summoned not the summoner.
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)
endmethod
SetUnitAnimation(thistype.illu, "stand")
in case the illusion is a building so that users won't have to do it themselves because buildings play their birth animation upon being summoned.thistype.get()
is only referred to once.I'll check again.private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
set thistype.[COLOR=color: #666666]dummy[/COLOR] = CreateUnit(DUMMY_OWNER, DUMMY_ID, 0, 0, 0)
call TriggerRegisterUnitEvent(t, thistype.[COLOR=color: #666666]dummy[/COLOR], EVENT_UNIT_SUMMON)
endmethod
Ok.Also, maybe you could add a
SetUnitAnimation(thistype.[COLOR=color: #666666]illu[/COLOR], "stand")
in case the illusion is a building so that users won't have to do it themselves because buildings play their birth animation upon being summoned.
Right.And then under the onDamage method, you don't need the local thistype this.
thistype.[COLOR=color: #666666]get[/COLOR]()
is only referred to once.
I'm not sure if it's worth doing a specific unit event over a generic event though. Using a generic event would be as simple asInstead of periodic event refresh, I think it would be better to use a wasted event counter which increments everytime an illusion dies then refresh the trigger when the counter cap is reached because there're cases where the trigger needs not be refreshed within a certain duration (Like if an illusion is a map is only seldom used). I think a unit specific death event is more efficient than a generic death event.
if IsUnitInGroup(GetTriggerUnit(), thistype.g) then
call thistype.get(GetTriggerUnit()).destroy()
endif
This could be done by a DDS.What would could be cool, if I could define absolsut numbers for damage making/taking, instead of "only" relative factors.
Forgot to do this, but I've already updated so I'm just gonna leave it at that.852274 is clear what I expect it to be, thouh for readability it could be a constant integer, so it's just 100% clear what order command it is.
Not a fan of Unit Indexer. Plus I don't want to force users to import a Unit Indexer.Instead of using Table/hashtable UDex could be used, and then instead of onDeath onDeindex could fire. It's a tiny bit better imo.
And if it was imported, then also just a normal array can be used to bind the instance to a unit.
System is written good and is definitly useful. small notes:
|
if GetSummoningUnit() == thistype.dummy then
call SetUnitOwner(thistype.dummy, DUMMY_OWNER, false)
I think should be directly after the issue illusion order to the dummy since if the issue fails or if illusion is null, it will return 0 before the dummy will be set back to the neutral owner.Of course, how could I miss that :/you forgot to remove this check on onEnter
if GetSummoningUnit() == thistype.dummy then
Come to think of it, if that dummy does not return to DUMMY_OWNER, I don't see any game-breaking side effects.And thiscall SetUnitOwner(thistype.dummy, DUMMY_OWNER, false)
I think should be directly after the issue illusion order to the dummy since if the issue fails or if illusion is null, it will return 0 before the dummy will be set back to the neutral owner.
I'll test using plain JASS if that's the casethe onDeath function could be somewhere on top, as JassHelper will internaly have to create a copy function of it so it can be properly called, if it's under the caller function in the struct. And the original, actual onDeath function may become not used.
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
call ForGroup(thistype.g, function thistype.reAdd)
, it might matter.//TESH.scrollpos=0
//TESH.alwaysfold=0
library Illusion /*
Illusion v1.33
by Flux
Allows easy creation of Illusion with any damage factor.
*/ requires DamageEvent, DamageModify, UnitIndexerGUI /*
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 extends array
public real damageTaken
public real damageGiven
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
private static thistype illuId
method operator unit takes nothing returns unit
return GetUnitById(this)
endmethod
static method get takes unit u returns thistype
return GetUnitUserData(u)
endmethod
private static method reAdd takes nothing returns nothing
call TriggerRegisterUnitEvent(thistype.deathTrg, GetEnumUnit(), EVENT_UNIT_DEATH)
endmethod
method destroy takes nothing returns nothing
if UnitAlive(this.unit) then
call KillUnit(this.unit)
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
endmethod
private static method onDeath takes nothing returns boolean
call thistype(thistype.get(GetTriggerUnit())).destroy()
return false
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 nothing
set thistype.illu = GetIndexedUnit()
set thistype.illuId = udg_UDex
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 GetUnitTypeId(thistype.illu) != 0 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
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.illuId
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)
set thistype.illu = null
return this
endmethod
private static method onInit takes nothing returns nothing
set thistype.dummy = CreateUnit(DUMMY_OWNER, DUMMY_ID, 0, 0, 0)
call OnUnitIndex(function thistype.entered)
call TriggerAddCondition(thistype.deathTrg, Condition(function thistype.onDeath))
call UnitAddAbility(thistype.dummy, ILLUSION_SPELL)
call Damage.registerModifier(function thistype.onDamage)
endmethod
endstruct
endlibrary