• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Snippet] Dummy (WIP)

Hi guys, for my new Caster System I am creating a collection of useful libraries.

Many of this stuff has already been created, but nothing fits my purpose to have a lot of features and still be safe...

Requires:

JASS:
library Position initializer init

    globals
        real POSITION_MIN_X = 0.
		real POSITION_MIN_Y = 0.
		real POSITION_MAX_X = 0.
		real POSITION_MAX_Y = 0.
		real POSITION_MIN_Z = 0.
		real POSITION_MAX_Z = 0.
                
        constant real POSITION_TWO_PI = 2 * bj_PI
		constant real POSITION_NEG_TWO_PI = -1 * POSITION_TWO_PI
		constant location POSITION_LOC = Location(0., 0.)
    endglobals
    
    function GetLocZ takes real x, real y returns real
		if x < POSITION_MIN_X or x > POSITION_MAX_X or y < POSITION_MIN_Y or y > POSITION_MAX_Y then
			return POSITION_MIN_Z -1.
		endif
	
		call MoveLocation(POSITION_LOC, x, y)
		return GetLocationZ(POSITION_LOC)
	endfunction
    
    function GetSafeX takes real x returns real
		if x > POSITION_MAX_X then
			set x = POSITION_MAX_X
		elseif x < POSITION_MIN_X then
			set x = POSITION_MIN_X
		endif
		return x
	endfunction
	
	function IsSafeX takes real x returns boolean
		return x >= POSITION_MIN_X and x <= POSITION_MAX_X
	endfunction
	
	function GetSafeY takes real y returns real
		if y > POSITION_MAX_Y then
			set y = POSITION_MAX_Y
		elseif y < POSITION_MIN_X then
			set y = POSITION_MIN_Y
		endif
		return y
	endfunction
	
	function IsSafeY takes real y returns boolean
		return y >= POSITION_MIN_Y and y <= POSITION_MAX_Y
	endfunction
    
    function IsSafeZ takes real z returns boolean
        return z >= POSITION_MIN_Z and z <= POSITION_MAX_Z
    endfunction
    
    function GetSafeZ takes real z returns real
        if z > POSITION_MAX_Z then
			set z = POSITION_MAX_Z
		elseif z < POSITION_MIN_Z then
			set z = POSITION_MIN_Z
		endif
		return z
    endfunction
    
    function IsSafeXYAngle takes real a returns boolean
        return a <= POSITION_TWO_PI and a >= POSITION_NEG_TWO_PI
    endfunction
	
	function GetSafeXYAngle takes real a returns real
		loop
			exitwhen a >= POSITION_NEG_TWO_PI and a <= POSITION_TWO_PI
			if a <= POSITION_NEG_TWO_PI then
				set a = a + POSITION_TWO_PI
			else
				set a = a - POSITION_TWO_PI
			endif
		endloop
		return a
	endfunction
    
    module IsPosition
        private real X = 0.
        private real Y = 0.
        private real Z = 0.
        private real XYAngle = 0.
        private real ZAngle = 0.
        
        method operator x= takes real x returns nothing
            set .X = GetSafeX(x)
        endmethod
        
        method operator x takes nothing returns real
            return .X
        endmethod
        
        method operator y= takes real y returns nothing
            set .Y = GetSafeY(y)
        endmethod
        
        method operator y takes nothing returns real
            return .Y
        endmethod
        
        method operator z= takes real z returns nothing
            set .Z = GetSafeZ(z)
        endmethod
        
        method operator z takes nothing returns real
            return .Z
        endmethod
        
        method operator xyAngle= takes real xyAngle returns nothing
            set .XYAngle = GetSafeXYAngle(x)
        endmethod
        
        method operator xyAngle takes nothing returns real
            return .XYAngle
        endmethod
        
        method operator zAngle= takes real zAngle returns nothing
            set .ZAngle = zAngle
        endmethod
        
        method operator zAngle takes nothing returns real
            return .ZAngle
        endmethod
        
        method move takes real dist returns nothing
            set .x = .X + dist * Cos(.XYAngle)
            set .y = .Y + dist * Sin(.XYAngle)
        endmethod
        
        method moveFaced takes real dist, real angle returns nothing
            set .x = .X + dist * Cos(angle)
            set .y = .Y + dist * Sin(angle)
        endmethod
        
        method applyUnit takes unit theUnit returns nothing
            set .x = GetUnitX(theUnit)
            set .y = GetUnitY(theUnit)
            set .z = GetLocZ(.X, .Y) + GetUnitFlyHeight(theUnit)
            set .xyAngle = GetUnitFacing(theUnit) * bj_DEGTORAD
            set .zAngle = 90. * bj_DEGTORAD
        endmethod
        
        static method fromUnit takes unit theUnit returns thistype
            local thistype this = thistype.allocate()
            call .applyUnit(theUnit)
            return this
        endmethod
        
        method applyItem takes item theItem returns nothing
            set .x = GetItemX(theItem)
            set .y = GetItemY(theItem)
            set .z = GetLocZ(.X, .Y)
            set .xyAngle = 270. * bj_DEGTORAD
            set .zAngle = 90. * bj_DEGTORAD
        endmethod
        
        static method fromItem takes item theItem returns thistype
            local thistype this = thistype.allocate()
            call .applyItem(theItem)            
            return this
        endmethod
        
        method applyDest takes destructable theDest returns nothing
            set .x = GetDestructableX(theDest)
            set .y = GetDestructableY(theDest)
            set .z = GetLocZ(.X, .Y)
            set .xyAngle = 270. * bj_DEGTORAD
            set .zAngle = 90. * bj_DEGTORAD
        endmethod
        
        static method fromDest takes destructable theDest returns thistype
            local thistype this = thistype.allocate()
            call .applyDest(theDest)
            return this
        endmethod
        
        method applyXY takes real x, real y returns nothing
            set .x = x
            set .y = y
            set .z = GetLocZ(.X, .Y)
            set .xyAngle = 270. * bj_DEGTORAD
            set .zAngle = 90. * bj_DEGTORAD
        endmethod
        
        static method fromXY takes real x, real y returns thistype
            local thistype this = thistype.allocate()
            call .applyXY(x, y)
            return this
        endmethod
        
        method applyPos takes thistype pos returns nothing
            set .x = pos.x
            set .y = pos.y
            set .z = pos.z
            set .xyAngle = pos.xyAngle
            set .zAngle = pos.zAngle
        endmethod
        
        static method fromPos takes thistype pos returns thistype
            local thistype this = thistype.allocate()
            call .applyPos(pos)
            return this
        endmethod
    endmodule
    
    struct Position
        implement IsPosition
    endstruct

    private function init takes nothing returns nothing
        set POSITION_MIN_X = GetRectMinX(bj_mapInitialPlayableArea)
		set POSITION_MIN_Y = GetRectMinY(bj_mapInitialPlayableArea)
		set POSITION_MAX_X = GetRectMaxX(bj_mapInitialPlayableArea)
		set POSITION_MAX_Y = GetRectMaxY(bj_mapInitialPlayableArea)
		set POSITION_MIN_Z = 0.
		set POSITION_MAX_Z = 25000.
    endfunction
    
endlibrary

Library:
JASS:
library Dummy requires Position

	globals
		constant integer DUMMY_RAWCODE = 'Dumy'
	endglobals

	module IsDummy
        private Position    Pos     = 0
		private unit        Handle	= null
		
		public static method create takes real x, real y returns thistype
			local thistype this = thistype.allocate()
		
			set .Handle = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMY_RAWCODE, 0., 0., 270.)
            call UnitAddAbility(.Handle, 'Arav')
            call UnitAddAbility(.Handle, 'Avul')
            call UnitAddAbility(.Handle, 'Aloc')
            call SetUnitPathing(.Handle, false)
            
			set .x = x
			set .y = y
			set .z = GetLocZ(.x, .y)
            
            set .Pos = Position.fromUnit(.Handle)
			
			return this
		endmethod
        
        method operator subject takes nothing returns unit
            return .Handle
        endmethod
		
		method operator xyAngle= takes real angle returns nothing
            set angle = GetSafeXYAngle(angle)
			call SetUnitFacing(.Handle, angle * bj_RADTODEG)
            set .Pos.xyAngle = angle
		endmethod
		
		method operator xyAngle takes nothing returns real
			return GetUnitFacing(.Handle) * bj_DEGTORAD
		endmethod
		
		method operator zAngle= takes real angle returns nothing
			local integer i = R2I(angle * bj_RADTODEG + 90.5)
            
            if i >= 180 then
               set i = 179
            elseif i < 0 then
               set i = 0
            endif
               
            call SetUnitAnimationByIndex(.Handle, i)
            set .Pos.zAngle = angle
		endmethod
		
		method operator zAngle takes nothing returns real
			return .Pos.zAngle
		endmethod
		
		method operator x= takes real x returns boolean
			local boolean inBounds = IsSafeX(x)
            set x = GetSafeX(x)
			call SetUnitX(.Handle, x)
            set .Pos.x = x
			return inBounds
		endmethod
		
		method operator x takes nothing returns real
			return GetUnitX(.Handle)
		endmethod
	
		method operator y= takes real y returns boolean
			local boolean inBounds = IsSafeY(y)
            set y = GetSafeY(y)
			call SetUnitY(.Handle, y)
            set .Pos.y = y
			return inBounds
		endmethod
		
		method operator y takes nothing returns real
			return GetUnitY(.Handle)
		endmethod
		
		method operator z= takes real z returns boolean
			local real flyHeight = z - GetLocZ(.x, .y)
			local boolean inBounds = IsSafeZ(z)
			
            set z = GetSafeZ(z)
			
			if flyHeight < 0. then
				call ShowUnit(.Handle, false)
			else
				call ShowUnit(.Handle, true)
			endif
			
			call SetUnitFlyHeight(.Handle, flyHeight, 0.)
            set .Pos.z = z
			
			return inBounds
		endmethod
		
		method operator z takes nothing returns real
			return .Pos.z
		endmethod
        
        method operator fly= takes real flyHeight returns nothing
            set .z = GetLocZ(.x, .y) + flyHeight
        endmethod
        
        method operator fly takes nothing returns real
            return GetUnitFlyHeight(.Handle)
        endmethod
		
		method operator mana= takes real val returns nothing
			call SetUnitState(.Handle, UNIT_STATE_MANA, val)
		endmethod
		
		method operator mana takes nothing returns real
			return GetUnitState(.Handle, UNIT_STATE_MANA)
		endmethod
		
		method operator hp= takes real val returns nothing
			call SetUnitState(.Handle, UNIT_STATE_LIFE, val)
		endmethod
		
		method operator hp takes nothing returns real
			return GetUnitState(.Handle, UNIT_STATE_LIFE)
		endmethod
		
		method operator owner= takes player owner returns nothing
			call SetUnitOwner(.Handle, owner, true)
		endmethod
		
		method operator owner takes nothing returns player
			return GetOwningPlayer(.Handle)
		endmethod
        
        method operator pos takes nothing returns Position
            return .Pos
        endmethod
        
        method move takes real dist returns nothing
            set .x = .x + dist * Cos(.xyAngle)
            set .y = .y + dist * Sin(.xyAngle)
        endmethod
        
        method moveFaced takes real dist, real angle returns nothing
            set .x = .x + dist * Cos(angle)
            set .y = .y + dist * Sin(angle)
        endmethod
	endmodule
	
	struct Dummy
		implement IsDummy
	endstruct

endlibrary

Addons:

JASS:
library Caster requires Dummy

	module IsCaster
        private static thistype GroupDelegate = 0
		private delegate Dummy Handler = 0
		private integer spellRaw = 0
		private integer spellOrder = 0
		
		public static method create takes real x, real y, player owner returns thistype
			local thistype this = thistype.allocate()
		
			set .Handler = Dummy.create(x, y)
			set .owner = owner
			
			return this
		endmethod
	
		method operator [] takes integer abilityId returns integer
			return GetUnitAbilityLevel(.subject, abilityId)
		endmethod
		
		method operator []= takes integer abilityId, integer abilityLvl returns nothing
			if abilityLvl > 0 then
				if this[abilityId] <= 0 then
					call UnitAddAbility(.subject, abilityId)
				endif
				call SetUnitAbilityLevel(.subject, abilityId, abilityLvl)
			else
				call UnitRemoveAbility(.subject, abilityId)
			endif
		endmethod
		
		method spell takes integer spellRaw, integer spellOrder returns nothing
			// remove old spell
			if this[.spellRaw] > 0 then
				set this[.spellRaw] = -1
			endif
			// add new spell
			set this[spellRaw] = 1
			set .spellRaw = spellRaw
			set .spellOrder = spellOrder
		endmethod
		
		method castOnSelf takes nothing returns nothing
			call IssueImmediateOrderById(.subject, .spellOrder)
		endmethod
		
		method castOnWidget takes widget theTarget returns nothing
			call IssueTargetOrderById(.subject, .spellOrder, theTarget)
		endmethod
		
		private static method delegateGroupCast takes nothing returns nothing
			call thistype.GroupDelegate.castOnWidget(GetEnumUnit())
		endmethod
		
		method castOnGroup takes group theGroup returns nothing
            set thistype.GroupDelegate = this
			call ForGroup(theGroup, function thistype.delegateGroupCast)
		endmethod
		
		method castOnLoc takes real x, real y returns nothing
			call IssuePointOrderById(.subject, .spellOrder, x, y)
		endmethod
	endmodule
    
    struct Caster
        implement IsCaster
    endstruct

endlibrary

JASS:
library Effect requires Dummy

	module IsEffect
		private delegate Dummy Handler = 0
		
		private integer	Red		= 255
		private integer	Green	= 255
		private	integer	Blue	= 255
		private	integer	Alpha	= 0
        
        private real    Scale   = 1.
		
		private effect	Sfx		= null
		private string	SfxPath	= null
		
		public static method create takes real x, real y returns thistype
			local thistype this = thistype.allocate()
		
			set .Handler = Dummy.create(x, y)
			
			return this
		endmethod
		
		method operator sfx= takes string eff returns nothing
			if .Sfx != null then
				call DestroyEffect(.Sfx)
			endif
			set .SfxPath = eff
			set .Sfx = AddSpecialEffectTarget(eff, .subject, "origin")
		endmethod
		
		method operator sfx takes nothing returns string
			return .SfxPath
		endmethod
		
		method operator red= takes integer val returns nothing
			set .Red = val
			call SetUnitVertexColor(.subject, .Red, .Green, .Blue, .Alpha)
		endmethod
		
		method operator red takes nothing returns integer
			return .Red
		endmethod
		
		method operator green= takes integer val returns nothing
			set .Green = val
			call SetUnitVertexColor(.subject, .Red, .Green, .Blue, .Alpha)
		endmethod
		
		method operator green takes nothing returns integer
			return .Green
		endmethod
		
		method operator blue= takes integer val returns nothing
			set .Blue = val
			call SetUnitVertexColor(.subject, .Red, .Green, .Blue, .Alpha)
		endmethod
		
		method operator blue takes nothing returns integer
			return .Blue
		endmethod
		
		method operator alpha= takes integer val returns nothing
			set .Alpha = val
			call SetUnitVertexColor(.subject, .Red, .Green, .Blue, .Alpha)
		endmethod
		
		method operator alpha takes nothing returns integer
			return .Alpha
		endmethod
		
		method argb takes integer red, integer green, integer blue, integer alpha returns nothing
			set .Red = red
			set .Green = green
			set .Blue = blue
			set .Alpha = alpha
			call SetUnitVertexColor(.subject, .Red, .Green, .Blue, .Alpha)
		endmethod
        
        method operator scale= takes real scale returns nothing
            set .Scale = scale
            call SetUnitScalePercent(.subject, .Scale, .Scale, .Scale)
        endmethod
        
        method operator scale takes nothing returns real
            return .Scale
        endmethod
	endmodule
	
	struct Effect
		implement IsEffect
	endstruct

endlibrary


JASS:
library ShapeEffect requires Effect, Position

	globals
		private Position TMP_POS = 0
	endglobals

	module IsShapeEffect
        private static      Position    TMP_POS = 0
    
		private delegate	Effect		SFX		= 0
		private				Position	Origin	= 0
		private				real		Dist	= 0.
		private				real		Angle	= 0.
		private				real		Height	= 0.
		private				real		XYAngle	= 0.
		private				real		ZAngle	= 0.
        
        public method update takes boolean withPos returns nothing
			if withPos then
				call thistype.TMP_POS.applyPos(.Origin)
				call thistype.TMP_POS.moveFaced(.Dist, .Angle)
				set .SFX.x = thistype.TMP_POS.x
				set .SFX.y = thistype.TMP_POS.y
			else
				call thistype.TMP_POS.applyPos(.pos)
			endif
			set .SFX.z = thistype.TMP_POS.z + .Height
			set .SFX.xyAngle = .XYAngle
			set .SFX.zAngle = .ZAngle
		endmethod
        
        public static method create takes Position pos, real dist, real angle, string sfxPath returns thistype
            local thistype this = thistype.allocate()
            
            set .Dist = dist
            set .Angle = angle
            set .Origin = pos
            
            call .update(true)
            
            set .SFX = Effect.create(.SFX.x, .SFX.y)
            set .SFX.sfx = sfxPath
            
            return this
        endmethod
		
		// no longer allow manipulation of x
		method operator x= takes real value returns nothing
		endmethod
		
		// no longer allow manipulation of y
		method operator y= takes real value returns nothing
		endmethod
		
		// no longer allow manipulation of z
		method operator z= takes real value returns nothing
		endmethod
		
		method operator height= takes real value returns nothing
			set .Height = value
			set .SFX.z = .Origin.z + .Height
		endmethod
		
		method operator xyAngle= takes real value returns nothing
			set .XYAngle = value
			set .SFX.xyAngle = .XYAngle
		endmethod
		
		method operator zAngle= takes real value returns nothing
			set .ZAngle = value
			set .SFX.zAngle = .ZAngle
		endmethod
		
		method operator dist= takes real value returns nothing
			set .Dist = value
			call .update(true)
		endmethod
		
		method operator angle= takes real value returns nothing
			set .Angle = value
			call .update(true)
		endmethod
        
        private static method onInit takes nothing returns nothing
            set thistype.TMP_POS = Position.create()
        endmethod
	endmodule
    
    struct ShapeEffect
        implement IsShapeEffect
    endstruct

endlibrary
JASS:
library Shape requires Stack, ShapeEffect

	module IsShape
		private	delegate	Stack		Effects	= 0
		private				Position	Self	= 0
		
		//! textmacro ShapeOperator takes NAME, POS
		method operator $NAME$= takes real value returns nothing
			set .Self.$NAME$ = value
			
			call .Effects.reset()
			loop
				exitwhen not .Effects.hasNext()
				call ShapeEffect(.Effects.getNext()).update($POS$)
			endloop
		endmethod
        
        method operator $NAME$ takes nothing returns real
            return .Self.$NAME$
        endmethod
		//! endtextmacro
		
		//! runtextmacro ShapeOperator("x", "true")
		//! runtextmacro ShapeOperator("y", "true")
		//! runtextmacro ShapeOperator("z", "false")
		//! runtextmacro ShapeOperator("xyAngle", "false")
		//! runtextmacro ShapeOperator("zAngle", "false")
        
        method operator pos takes nothing returns Position
            return .Self
        endmethod
	endmodule
	
	struct Shape
		implement IsShape
	endstruct

endlibrary
JASS:
library ShapeLib initializer test requires Shape, ShapeEffect

	function Circle takes real x, real y, real angle, real radius, real effDist, string sfx returns Shape
		local Shape crcl = Shape.create()
		local integer effects = 10
		local real radPerEff = (360. / effects) * bj_DEGTORAD
		
		loop
			exitwhen effects <= 0
			call crcl.add(ShapeEffect.create(crcl.pos, radius, radPerEff * effects, sfx))
			set effects = effects -1
		endloop
		
		return crcl
	endfunction
	
	function Square takes real x, real y, real angle, real height, real width, real effDist, string sfx returns Shape
		local Shape sqr = Shape.create()
		local real minX = x - (width / 2)
		local real maxX = x + (width / 2)
		local real minY = y - (height / 2)
		local real maxY = y + (height / 2)
		local integer horCnt = R2I((maxX - minX) / effDist)
		local integer verCnt = R2I((maxY - minY) / effDist)
		local Position cur = Position.create()
		local integer i = 0
		
		// Create top effects
		set cur.x = x - (horCnt * effDist) / 2
		set cur.y = y + (verCnt * effDist) / 2
		set i = 0
		loop
			exitwhen i > horCnt
			call sqr.add(ShapeEffect.create(sqr.pos, 0., 0., sfx))
			call cur.moveFaced(effDist, 0. * bj_DEGTORAD)
			set i = i +1
		endloop
		
		// Create bottom effects
		set cur.x = x - (horCnt * effDist) / 2
		set cur.y = y - (verCnt * effDist) / 2
		set i = 0
		loop
			exitwhen i > horCnt
			call sqr.add(ShapeEffect.create(sqr.pos, 0., 0., sfx))
			call cur.moveFaced(effDist, 0. * bj_DEGTORAD)
			set i = i +1
		endloop
		
		// Create left effects
		set cur.x = x - (horCnt * effDist) / 2
		set cur.y = y - (verCnt * effDist) / 2
		set i = 0
		loop
			exitwhen i > verCnt
			call sqr.add(ShapeEffect.create(sqr.pos, 0., 0., sfx))
			call cur.moveFaced(effDist, 90. * bj_DEGTORAD)
			set i = i +1
		endloop
		
		// Create left effects
		set cur.x = x + (horCnt * effDist) / 2
		set cur.y = y - (verCnt * effDist) / 2
		set i = 0
		loop
			exitwhen i > verCnt
			call sqr.add(ShapeEffect.create(sqr.pos, 0., 0., sfx))
			call cur.moveFaced(effDist, 90. * bj_DEGTORAD)
			set i = i +1
		endloop
		
		return sqr
	endfunction
	
	function Star takes real x, real y, real angle, real spikeDist, integer spikeCount, real effDist, string sfx returns Shape
		return spikeCount
	endfunction
	
	globals
		private Shape TestCircle = 0
		private Shape TestSquare = 0
		private Shape TestStar = 0
	endglobals
	
	private function spinCircle takes nothing returns nothing
		set TestCircle.xyAngle = TestCircle.xyAngle + 9. * bj_DEGTORAD
	endfunction
	
	private function test takes nothing returns nothing
		//							x,	y,	angle,	radius,	dist,	sfx
		set TestCircle = Circle(	0.,	0.,	0., 	250.,	64.,	"Units\\Human\\HeroBloodElf\\BloodElfBall.mdl"	) 
		
		//							x,	y,	angle,	height	width,	dist,	sfx
		//set TestSquare = Square(	0., 0., 0.,		250.,	250.,	64.,	""	)
		
		//						x,	y,	angle,	spikeDist,	spikeCount,	dist,	sfx
		//set TestStar = Star(	0.,	0.,	0., 	250.,		5,			64.,	""	)
		
		//call TimerStart(CreateTimer(), 0.1, true, function spinCircle)
	endfunction

endlibrary
 
Top