Executor
I see you
- Reaction score
- 57
Effect
- Coding Style: vJass
- Interface: vJass and Wc3-native (Jass)
Description:
This library completely replaces the type effect with the new mightier type Effect.
Ground Effects can be timed,colored,scaled,moved (etc.) and Effects you attached to units can also be timed. No longer setting up timers or waits to kill effects delayed.
Code:
JASS:
library Effect requires optional AutoFly
// ========== Effect ==========
// Introduces the type "Effect"
// This type allows you to color,scale,move,time and hide ground effects
// And to time widget-attached effects.
// IMPORTANT:
// Do not color,scale,move or hide widget-attached effects, but you may time em
// Author: Executor alias Lord_Executor
// ====== Implementation ======
// Make a new trigger called "Effect"
// Convert it to custom text
// Paste the whole code in the empty page
// IMPORTANT:
// Import Vexorian's dummy.mdx
// adjust the "war3mapImported\dummy.mdl" (beneath) to your custom import path
// finally save the map once, close it, reopen it and AFTER that remove the '!' of the '//!' beneath this line
//! runtextmacro Effect_MergeDummy("Visible Dummy","vdum","war3mapImported\dummy.mdl")
// ========== Credits =========
// Vexorian: vJass & Dummy.mdx & recycle idea
// Azlier: Autofly
globals
private constant integer DUMMY_ID = 039;vdum039;
private constant real RECYCLE_DELAY = 2.
private player DUMMY_OWNER = Player(14) // neutral
private constant real RECYCLE_X = 5000.
private constant real RECYCLE_Y = 5000.
endglobals
// ================================================================================
// ================ Do not modify code beneath this line ==========================
// ================================================================================
globals
private location L = Location(0,0)
endglobals
private function GetTerrainZ takes real x, real y returns real
call MoveLocation(L,x,y)
return GetLocationZ(L)
endfunction
struct Effect
integer userData
private unit carrier
private effect sfx
private real oz
private real cx
private real cy
private real cz
private thistype next
private thistype prev
private real schedule
private boolean timed
private static group DUMMIES
private static timer NOW
private static timer recycleTimer
private static timer removeTimer
private static thistype recycleStart
private static thistype recycleEnd
private static thistype removeStart
private static thistype removeEnd
private static method onInit takes nothing returns nothing
set .DUMMIES = CreateGroup()
set .NOW = CreateTimer()
set .recycleTimer = CreateTimer()
set .removeTimer = CreateTimer()
set .recycleStart = 0
set .recycleEnd = 0
set .removeStart = 0
set .removeEnd = 0
call TimerStart(.NOW,999999999.,false,null)
endmethod
method scale takes real size returns nothing
call SetUnitScale(.carrier,size,1.,1.)
endmethod
method scalePercent takes real size returns nothing
set size = size * 0.01
call SetUnitScale(.carrier,size,1.,1.)
endmethod
method color takes integer r, integer g, integer b, integer alpha returns nothing
call SetUnitVertexColor(.carrier,r,g,b,alpha)
endmethod
method moveTo takes real x, real y , real z returns nothing
set .cx = x
set .cy = y
set .cz = z
set .oz = GetTerrainZ(x,y)
call SetUnitX(.carrier,x)
call SetUnitY(.carrier,y)
call SetUnitFlyHeight(.carrier,z,0.)
endmethod
method moveBy takes real x, real y ,real z returns nothing
set .cx = .cx + x
set .cy = .cy + y
set .cz = .cz + z
call SetUnitX(.carrier,.cx)
call SetUnitY(.carrier,.cy)
call SetUnitFlyHeight(.carrier,.cz+.oz-GetTerrainZ(.cx,.cy),0.)
endmethod
method operator dummy takes nothing returns unit
return .carrier
endmethod
method operator xyAngle takes nothing returns real
return GetUnitFacing(.carrier)
endmethod
method operator x takes nothing returns real
return .cx
endmethod
method operator y takes nothing returns real
return .cy
endmethod
method operator z takes nothing returns real
return GetUnitFlyHeight(.carrier)
endmethod
method operator x= takes real x returns nothing
set .cx = x
call SetUnitFlyHeight(.carrier,.cz+.oz-GetTerrainZ(.cx,.cy),0.)
call SetUnitX(.carrier,x)
endmethod
method operator y= takes real y returns nothing
set .cy = y
call SetUnitFlyHeight(.carrier,.cz+.oz-GetTerrainZ(.cx,.cy),0.)
call SetUnitY(.carrier,y)
endmethod
method operator z= takes real z returns nothing
set .cz = z
call SetUnitFlyHeight(.carrier,z+.oz-GetTerrainZ(.cx,.cy),0.)
endmethod
method operator visibility takes nothing returns boolean
return not IsUnitHidden(.carrier)
endmethod
method operator xyAngle= takes real f returns nothing
call SetUnitFacing(.carrier,f)
endmethod
method operator visibility= takes boolean vis returns nothing
call ShowUnit(.carrier,vis)
endmethod
method operator zAngleRad= takes real value returns nothing
local integer i=R2I(value*bj_RADTODEG+90.5)
if(i>=180) then
set i=179
elseif(i<0) then
set i=0
endif
call SetUnitAnimationByIndex(.carrier, i )
endmethod
method operator zAngleDeg= takes integer value returns nothing
set value = value + 90
if value >= 180 then
set value = 179
elseif value < 0 then
set value = 0
endif
call SetUnitAnimationByIndex(.carrier,value)
endmethod
method remove takes nothing returns nothing
if .timed then // we have to erase the instance in the lifespawn queue
if .removeStart == this then // if instance equals the starting element
call PauseTimer(.removeTimer)
set .removeStart = .next // the next element becomes the starting element
set .removeStart.prev = 0
call TimerStart(.removeTimer,TimerGetRemaining(.NOW)-.removeStart.schedule,false,function thistype.onRemoveTimer)
else
set .prev.next = .next // instance is not the starting element, so we can access .prev
endif
if .removeEnd == this then // if instance equals ending element
set .removeEnd = .prev // previous element becomes ending element
set .removeEnd.next = 0
else
set .next.prev = .prev // instance is noth the ending element, so we can access .next
endif
endif
call .recycle()
endmethod
private method onDestroy takes nothing returns nothing
set .next = 0
set .prev = 0
set .schedule = 0
if .carrier != null then // if the effect used a dummy unit ...
call SetUnitScale(.carrier,1.,1.,1.)
call SetUnitVertexColor(.carrier,255,255,255,255)
call SetUnitX(.carrier,RECYCLE_X)
call SetUnitY(.carrier,RECYCLE_Y)
call GroupAddUnit(DUMMIES,.carrier) // recycle the dummy
set .carrier = null
endif
endmethod
private static method onRecycleTimer takes nothing returns nothing
// recycle one instance and start the timer to recycle the next one ...
local thistype this = .recycleStart
set .recycleStart = .recycleStart.next
call .destroy()
if .recycleStart != 0 then
call TimerStart(.recycleTimer,TimerGetRemaining(.NOW)-.recycleStart.schedule,false,function thistype.onRecycleTimer)
else
set .recycleEnd = 0
endif
endmethod
private method recycle takes nothing returns nothing
// add this instance to the recycle queue
call DestroyEffect(.sfx)
set .sfx = null
set .schedule = TimerGetRemaining(.NOW)-RECYCLE_DELAY
if .recycleStart == 0 then
set .recycleStart = this
set .recycleEnd = this
set .next = 0
call TimerStart(.recycleTimer,RECYCLE_DELAY,false,function thistype.onRecycleTimer)
else
set .recycleEnd.next = this
set .next = 0
set .recycleEnd = this
endif
endmethod
private static method onRemoveTimer takes nothing returns nothing
// the lifespawn of one instance is over.. so it is recycled and the timer focuses the next element
local thistype this = .removeStart
set .removeStart = .removeStart.next
set .removeStart.prev = 0
call DestroyEffect(.sfx)
set .timed = false
call .recycle()
if .removeStart != 0 then
call TimerStart(.removeTimer,TimerGetRemaining(.NOW)-.removeStart.schedule,false,function thistype.onRemoveTimer)
else
set .removeEnd = 0
endif
endmethod
static method newGroundEffect takes string modelName, real x, real y, real z returns thistype
local thistype this = thistype.allocate()
set .carrier = FirstOfGroup(DUMMIES)
if .carrier == null then
set .carrier = CreateUnit(DUMMY_OWNER,DUMMY_ID,x,y,0.)
call SetUnitPathing(.carrier,false)
static if not AutoFly then
call UnitAddAbility(.carrier,039;Amrf039;)
call UnitRemoveAbility(.carrier,039;Amrf039;)
endif
else
call GroupRemoveUnit(DUMMIES,.carrier)
endif
set .cx = x
set .cy = y
set .cz = z
set .oz = GetTerrainZ(x,y)
call SetUnitX(.carrier,x)
call SetUnitY(.carrier,y)
call SetUnitFlyHeight(.carrier, z, 0.)
set .sfx = AddSpecialEffectTarget(modelName,.carrier, "origin")
return this
endmethod
static method newTargetEffect takes string modelName, widget target, string attachPoint returns thistype
local thistype this = thistype.allocate()
set .carrier = null
set .sfx = AddSpecialEffectTarget(modelName,target,attachPoint)
return this
endmethod
method operator lifespawn= takes real t returns nothing
local thistype lp = 0
set .schedule = TimerGetRemaining(.NOW)-t
if .timed then // if instance already in the lifespawn list
if .removeStart == this then // if instance equals the starting element
call PauseTimer(.removeTimer)
if .schedule > .removeStart.schedule then // if instance still scheduled earliest
call TimerStart(.removeTimer,t,false,function thistype.onRemoveTimer) // restart timer with new duration
return // instance stays
else // instance is scheduled later than the next element
set .removeStart = .next // the next element becomes the starting element
set .removeStart.prev = 0
call TimerStart(.removeTimer,TimerGetRemaining(.NOW)-.removeStart.schedule,false,function thistype.onRemoveTimer)
endif
else
set .prev.next = .next // instance is not the starting element, so we can access .prev
endif
if .removeEnd == this then // if instance equals ending element
if .schedule < .removeEnd.prev.schedule then
return // instance stays
else
set .removeEnd = .prev // previous element becomes ending element
set .removeEnd.next = 0
endif
else
set .next.prev = .prev // instance is noth the ending element, so we can access .next
endif
else
set .timed = true // now it is a timed effect
endif
// instances which get here were either not timed yet or have to get a new spot in the list
if .removeStart == 0 then // list is empty?
set .removeStart = this
set .removeEnd = this
call TimerStart(.removeTimer,t,false,function thistype.onRemoveTimer)
return
elseif .removeStart.schedule<.schedule then // earlier then starting element?
call PauseTimer(.removeTimer)
call TimerStart(.removeTimer,t,false,function thistype.onRemoveTimer)
set .next = .removeStart
set .removeStart.prev = this
set .removeStart = this
return
else
loop
exitwhen (lp == 0) or (lp == .removeEnd)
if lp.schedule < .schedule then
set lp.prev.next = this
set lp.prev = this
set .next = lp
set .prev = lp.prev
return
endif
set lp = lp.next
endloop
set .prev = .removeEnd
set .removeEnd.next = this
set .removeEnd = this
endif
endmethod
method operator lifespawn takes nothing returns real
return TimerGetRemaining(.NOW)-.schedule
endmethod
//! textmacro Effect_MergeDummy takes NAME, ID, MODELPATH
//! external ObjectMerger w3u ushd $ID$ unam "$NAME$" uabi "Aeth,Avul,Aloc" umvs "520" umvr 1 umvt foot umvh -500 uhpm 99999 uhom 1 ucol -10 umdl "$MODELPATH$" ucbs 0 ucpt 0 ushu "" umvh 0 ufoo 0
//! endtextmacro
endstruct
function AddEffect takes string modelName, real x, real y, real z returns Effect
return Effect.newGroundEffect(modelName,x,y,z)
endfunction
function AddTimedEffect takes string modelName, real x, real y, real z, real duration returns Effect
local Effect e = Effect.newGroundEffect(modelName,x,y,z)
set e.lifespawn = duration
return e
endfunction
function AddEffectTarget takes string modelName, widget target, string attachPoint returns Effect
return Effect.newTargetEffect(modelName,target,attachPoint)
endfunction
function AddTimedEffectTarget takes string modelName, widget target, string attachPoint, real duration returns Effect
local Effect e = Effect.newTargetEffect(modelName,target,attachPoint)
set e.lifespawn = duration
return e
endfunction
function EffectScale takes Effect e, real scale returns nothing
call e.scale(scale)
endfunction
function EffectScaleByPercent takes Effect e, real scale returns nothing
call e.scalePercent(scale)
endfunction
function EffectReColor takes Effect e, integer r, integer g, integer b, integer alpha returns nothing
call e.color(r,g,b,alpha)
endfunction
function EffectMoveTo takes Effect e, real x, real y, real z returns nothing
call e.moveTo(x,y,z)
endfunction
function EffectMoveBy takes Effect e, real x, real y, real z returns nothing
call e.moveBy(x,y,z)
endfunction
function EffectSetX takes Effect e, real x returns nothing
set e.x = x
endfunction
function EffectSetY takes Effect e, real y returns nothing
set e.y = y
endfunction
function EffectSetZ takes Effect e, real z returns nothing
set e.z = z
endfunction
function EffectGetX takes Effect e returns real
return e.x
endfunction
function EffectGetY takes Effect e returns real
return e.y
endfunction
function EffectGetZ takes Effect e returns real
return e.z
endfunction
function EffectSetZAngle takes Effect e, real f returns nothing
set e.zAngleRad = f
endfunction
function EffectSetXYAngle takes Effect e, real f returns nothing
set e.xyAngle = f
endfunction
function EffectGetXYAngle takes Effect e returns real
return e.xyAngle
endfunction
function EffectSetLifeSpawn takes Effect e, real t returns nothing
set e.lifespawn = t
endfunction
function EffectGetLifeSpawn takes Effect e returns real
return e.lifespawn
endfunction
function ShowEffect takes Effect e, boolean flag returns nothing
set e.visibility = flag
endfunction
function EffectIsVisible takes Effect e returns boolean
return e.visibility
endfunction
function RemoveEffect takes Effect e returns nothing
call e.remove()
endfunction
endlibrary
Interface:
JASS:
// Struct interface
static method newGroundEffect takes string modelName, real x, real y, real z returns thistype
static method newTargetEffect takes string modelName, widget target, string attachPoint returns thistype
method remove takes nothing returns nothing
method operator x takes nothing returns real
method operator y takes nothing returns real
method operator z takes nothing returns real
method operator x= takes real x returns nothing
method operator y= takes real x returns nothing
method operator z= takes real x returns nothing
method moveTo takes real x, real y, real z returns nothing
method moveBy takes real x, real y, real z returns nothing
method scale takes real size returns nothing
method scalePercent takes real size returns nothing
method color takes integer r, integer g, integer b, integer alpha returns nothing
method operator lifespawn takes nothing returns real // *
method operator lifespawn= takes real t returns nothing // *
method operator xyAngle takes nothing returns real
method operator xyAngle= takes real f returns nothing
method operator visibility takes nothing returns boolean
method operator visibility= takes boolean vis returns nothing
method operator zAngleRad= takes real value returns nothing
method operator zAngleDeg= takes integer value returns nothing
method operator dummy takes nothing returns unit // **
// * : the only method which can be used on target-effects
// ** : returns the effect carrier when used on a ground effect; returns null on a target-effect
// Wc3 native-fitting interface (TESH-able)
function AddEffect takes string modelName, real x, real y, real z returns Effect
function AddTimedEffect takes string modelName, real x, real y, real z, real duration returns Effect
function AddEffectTarget takes string modelName, widget target, string attachPoint returns Effect
function AddTimedEffectTarget takes string modelName, widget target, string attachPoint, real duration returns Effect
function EffectScale takes Effect e, real scale returns nothing
function EffectScaleByPercent takes Effect e, real scale returns nothing
function EffectReColor takes Effect e, integer r, integer g, integer b, integer alpha returns nothing
function EffectMoveTo takes Effect e, real x, real y, real z returns nothing
function EffectMoveBy takes Effect e, real x, real y, real z returns nothing
function EffectSetX takes Effect e, real x returns nothing
function EffectSetY takes Effect e, real y returns nothing
function EffectSetZ takes Effect e, real z returns nothing
function EffectGetX takes Effect e returns real
function EffectGetY takes Effect e returns real
function EffectGetZ takes Effect e returns real
function EffectSetZAngle takes Effect e, real f returns nothing
function EffectSetXYAngle takes Effect e, real f returns nothing
function EffectGetXYAngle takes Effect e returns real
function EffectSetLifeSpawn takes Effect e, real t returns nothing
function EffectGetLifeSpawn takes Effect e returns real
function ShowEffect takes Effect e, boolean flag returns nothing
function EffectIsVisible takes Effect e returns boolean
function RemoveEffect takes Effect e returns nothing
System Mechanics:
Example Usage:
TESH:
JASS:
//
// _____ ___ ___ _ _
// |_ _| __/ __| |_| |
// | | | _|\__ \ _ |
// |_| |___|___/_| |_| Highlighting:
// - Effect by Executor
//
// What is this?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Implementing this allows the TESH syntax highlighter in Jass NewGen
// to highlight the syntax for this system (and autocomplete the functions).
//
// How to import?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Copy this into a blank text file, and save it at:
// <Your Jass NewGen folder>\tesh\includes\Effect.j
//
function AddEffect takes string modelName, real x, real y, real z returns Effect
function AddTimedEffect takes string modelName, real x, real y, real z, real duration returns Effect
function AddEffectTarget takes string modelName, widget target, string attachPoint returns Effect
function AddTimedEffectTarget takes string modelName, widget target, string attachPoint, real duration returns Effect
function EffectScale takes Effect e, real scale returns nothing
function EffectScaleByPercent takes Effect e, real scale returns nothing
function EffectReColor takes Effect e, integer r, integer g, integer b, integer alpha returns nothing
function EffectMoveTo takes Effect e, real x, real y, real z returns nothing
function EffectMoveBy takes Effect e, real x, real y, real z returns nothing
function EffectSetX takes Effect e, real x returns nothing
function EffectSetY takes Effect e, real y returns nothing
function EffectSetZ takes Effect e, real z returns nothing
function EffectGetX takes Effect e returns real
function EffectGetY takes Effect e returns real
function EffectGetZ takes Effect e returns real
function EffectSetZAngle takes Effect e, real f returns nothing
function EffectSetXYAngle takes Effect e, real f returns nothing
function EffectGetXYAngle takes Effect e returns real
function EffectSetLifeSpawn takes Effect e, real t returns nothing
function EffectGetLifeSpawn takes Effect e returns real
function ShowEffect takes Effect e, boolean flag returns nothing
function EffectIsVisible takes Effect e returns boolean
function RemoveEffect takes Effect e returns nothing
Updates:
- 22.05.2010: Release
- 22.05.2010:
- Replaced ShowEffect()&HideEffect() with ShowEffect(boolean)
- Added TESH&Interface part
- 23.05.2010:
- Added global configuration boolean USE_TOTAL_Z
- Modified SetUnitScale to only use the x-part of the native.
- 23.05.2010:
- Added internal variables integer prev and boolean timed.
- Added operator lifespawn (write&readable)
- Changed Interface
- Allowed method remove to remove timed and non-timed Effects.
- Method removeTimed erased.
- 25.05.2010:
- Added system-mechanics diagram
- 26.05.2010:
- Added global configuration boolean AUTO_ADJUST_Z
- Removed set operators for x,y and z
- 26.05.2010:
- Reworked dynamic components and mechanics:
- VERSION =
- STANDARD
- XYZ_EXTENSION (adds real x, real y, real z to the struct allowing the methods "moveBy", "x(=)", "y(=)", "z(=)" to be faster)
- Z_TRANSFORMATION =
- NONE (z equals the distance between the effect and the ground beneath it)
- AUTO (on creation z equals the distance between the effect and the ground beneath it, but moving off cliffs via "moveBy", "x=" or "y=" will be compensated)
- TOTAL (all z values are total: totalZ = GetTerrainZ + GetFlyHeight)
- VERSION =
- Interface extended
- Reworked dynamic components and mechanics:
- 31.05.2010:
- Determined the library to XYZ_EXTENSION + AUTO
Notes: Didn't test the current version much, so errors are possible.
Hope you enjoy it.