Executor
I see you
- Reaction score
- 57
Shape Creator 2.1
by Executor alias Lord_Executor
Description:
This library allows you to work easily with various shapes. You simply choose the shape you want, define the number of points you need and define the callback function, which will be called for every single point of the shape. Of course there are more parameters than only number of points and callback function, but this shall help understand how my system works.
Screenshot:
Circle + IntersectedStarPolygon with 5 corners + NonIntersectedStarPolygon with 5 corners:
More Screenshots:
Circle + IntersectedStarPolygon with 7 corners + NonIntersectedStarPolygon with 7 corners:
Line + Circle, Line periodically adjusts sx,sy,sz of the circle => a Spiral
Circle summoning Water Elementals
Line + Circle, Line periodically adjusts sx,sy,sz of the circle => a Spiral
Circle summoning Water Elementals
Interface:
JASS:
// Shaper Interface
//
// Shape.createLine(real sx, real sy, real sz,
// real xyAngle, real zAngle,
// real distance, integer count,
// real interval,
// usrfunc periodic, usrfunc final)
//
// Shape.createEllipsis(real mx, real my, real mz,
// real sAngle, real xyAngle, real zAngle,
// real r1, real r2, integer count,
// integer dir, real interval,
// usrfunc periodic, usrfunc final)
//
// Shape.createSquare(real mx, real my, real mz,
// real angleToStartCorner, real zAngle,
// real edgeLength, integer countPerEdge,
// integer dir, real interval,
// usrfunc periodic, usrfunc final)
//
//
// Shape.createIntersectedStarPolygon(real mx, real my, real mz,
// real angleToStartCorner, real zAngle,
// real r, integer corners, integer countPerEdge,
// integer dir, real interval,
// usrfunc periodic, usrfunc final)
//
// Shape.createNonIntersectedStarPolygon(real mx, real my, real mz,
// real angleToStartCorner, real zAngle,
// real r, integer corners, integer countPerEdge,
// integer dir, real interval,
// usrfunc periodic, usrfunc final)
//
// set Instance.limit = integer
// set integer = Instance.limit
// limit equals the total points being calculated. Setting limit to limit*2 (after you called the create func of course)
// will result in the shape to be drawn two times one after the other...
//
// call Instance.stop()
// stops the shape-creation and erases the instance.
Code:
JASS:
// ===============================================================
// ======================== Shape Creator ========================
// ===============================================================
// Desc:
// This library allows you to easily loop through shapes
// You can for example damage in a line, create effect pentagramms,
// create unit circles, etc.
//
// How to:
//
// sx : source x sy : source y sz : source z mx : mid x my : mid y mz : mid z
//
// interval: time between each step
// periodic: this code will be fired each step
// final: this code will on the last step, if final == 0 then periodic will be fired
//
//
// Line:
//
// Shape.createLine(real sx, real sy, real sz, real xyAngle, real zAngle, real distance,
// integer count, real interval, usrfunc periodic, usrfunc final)
//
// xyAngle: in which direction the line shall be created
// zAngle: angle between xy-plane and the line
// distance: the length of the line
// count: how many steps till end of the line
//
// Circle:
//
// Shape.createEllipsis takes real mx, real my, real mz, real r1, real r2, real sAngle, real xyAngle,
// real zAngle, integer dir,integer count, real interval, usrfunc periodic, usrfunc final)
//
// r1: first radius
// r2: second radius
//
// sAngle: angle to the first point of the circle, 90° will be the most northern point
// zAngle: angle between xy-plane and the ellipsis-plane
// xyAngle: where the point with the lowest z-value shall point at, relative to the mid
// direction: clockwise or not clockwise? 1 or -1
// count: how many steps till the circle is finished
//
// StarPolygons:
//
// <a href="http://upload.wikimedia.org/wikipedia/commons/9/96/Regular_Star_Polygons.jpg" target="_blank" class="link link--external" rel="nofollow ugc noopener">http://upload.wikimedia.org/wikipedia/commons/9/96/Regular_Star_Polygons.jpg</a>
// You can create the far left and the far right diagonal chain
//
// Far left chain/ IntersectedStarPolygons:
//
// Shape.createIntersectedStarPolygon takes real mx, real my, real mz, real angleToStartCorner, integer corners,
// real r, real zAngle, integer dir, integer countPerEdge, real interval, usrfunc periodic, usrfunc final)
//
// Far right diagonal chain/ NonIntersectedStarPolygons:
//
// Shape.createNonIntersectedStarPolygon takes real mx, real my, real mz, real angleToStartCorner, integer corners,
// real r, real zAngle, integer dir, integer countPerEdge, real interval, usrfunc periodic, usrfunc final)
//
// angleToStartCorner: angle to the first corner
// corners: how many corners?
// r: radius of the circumcircle
// zAngle: angle between the xy-plane and the plane of the shape
// dir: direction of the shape creation, +1 or -1
// countPerEdge: steps each edge
// interval: time between each step
// code: this code will be fired each step
//
// usrfunc issues:
//
// The code has to take nothing and returns nothing
// When in the usrfunc you may use Shape.getData() to return the "triggering" Shape instance
// Aswell as .x and .y as parameters for the current step + .customValue (integer) for attaching
//
// Have Fun!
// Credits to Lord_Executor
library ShapeCreator requires optional TimerUtils
private function interface usrfunc takes Shape sp returns nothing
private function interface flusher takes integer this returns nothing
private struct LineData
real vx
real vy
real vz
//! runtextmacro ShapeCreator_Flush()
endstruct
private struct EllipsisData
real modAngle
real currAngle
real cosB
real sinB
real cosA
real sinA
real r1
real r2
//! runtextmacro ShapeCreator_Flush()
endstruct
private struct StarPolygonData
integer remPointsOnStage
integer pointsPerStage
real modAngle
real currAngle
real vx
real vy
real vz
real tx
real ty
real tz
real cosB
real sinB
real cosA
real sinA
real offset
//! runtextmacro ShapeCreator_Flush()
endstruct
struct Shape
real x
real y
real z
integer customValue
real sx
real sy
real sz
private integer remPoints
private integer shapeData
private flusher flushData
private usrfunc periodic
private usrfunc final
private timer intervalTimer
private static constant real PI2 = 2*bj_PI
private static constant real PIDiv2 = bj_PI/2
static if not LIBRARY_TimerUtils then
private static hashtable link
private static method onInit takes nothing returns nothing
set .link = InitHashtable()
endmethod
endif
method stop takes nothing returns nothing
call .flushData.evaluate(.shapeData)
call .destroy()
endmethod
method operator limit takes nothing returns integer
return .remPoints
endmethod
method operator limit= takes integer i returns nothing
set .remPoints = i
endmethod
private static method onPause takes nothing returns nothing
//! runtextmacro ShapeCreator_GetInstance()
call .flushData.evaluate(.shapeData)
call .destroy()
endmethod
private static method onCreateLineTimer takes nothing returns nothing
//! runtextmacro ShapeCreator_GetInstance()
local LineData d = .shapeData
set .x = .x + d.vx
set .y = .y + d.vy
set .z = .z + d.vz
//! runtextmacro ShapeCreator_ReleaseInstance()
endmethod
static method createLine takes real sx, real sy, real sz, real xyAngle, real zAngle, real distance, integer count, real interval, usrfunc periodic, usrfunc final returns thistype
local thistype this = thistype.allocate()
local real offset = distance/(count-1)
local real cosB = Cos(xyAngle-.PIDiv2)
local real sinB = Sin(xyAngle-.PIDiv2)
local real cosA = Cos(zAngle)
local real sinA = Sin(zAngle)
local real fac = cosA * offset
//! runtextmacro ShapeCreator_VarSetup("Line")
set .remPoints = count
set .sx = sx
set .sy = sy
set .sz = sz
set d.vx = -sinB * fac
set d.vy = cosB * fac
set d.vz = sinA * offset
set .x = sx - d.vx
set .y = sy - d.vy
set .z = sz - d.vz
//! runtextmacro ShapeCreator_TimerSetup("Line","periodic","final")
return this
endmethod
private static method onCreateEllipsisTimer takes nothing returns nothing
//! runtextmacro ShapeCreator_GetInstance()
local EllipsisData d = .shapeData
local real vx = d.r1 * Cos(d.currAngle)
local real vy = d.r2 * Sin(d.currAngle)
local real fac = d.cosA * vy
set .x = .sx + d.cosB * vx - d.sinB * fac
set .y = .sy + d.sinB * vx + d.cosB * fac
set .z = .sz + d.sinA * vy
set d.currAngle = d.currAngle + d.modAngle
//! runtextmacro ShapeCreator_ReleaseInstance()
endmethod
static method createEllipsis takes real mx, real my, real mz, real sAngle, real xyAngle, real zAngle,/*
*/real r1, real r2,integer count, integer dir, real interval, usrfunc periodic, usrfunc final returns thistype
local thistype this = thistype.allocate()
//! runtextmacro ShapeCreator_VarSetup("Ellipsis")
set .remPoints = count
set .sx = mx
set .sy = my
set .sz = mz
set xyAngle = xyAngle - .PIDiv2
set d.currAngle = sAngle
set d.cosB = Cos(xyAngle)
set d.sinB = Sin(xyAngle)
set d.cosA = Cos(zAngle)
set d.sinA = Sin(zAngle)
set d.r1 = r1
set d.r2 = r2
set d.modAngle = .PI2/(count) * dir
//! runtextmacro ShapeCreator_TimerSetup("Ellipsis","periodic","final")
endmethod
private static method onCreateStarPolygonTimer takes nothing returns nothing
//! runtextmacro ShapeCreator_GetInstance()
local StarPolygonData d = .shapeData
local real fac = 0
local real ux = 0
local real uy = 0
if d.pointsPerStage == 0 then
set d.remPointsOnStage = d.remPointsOnStage
set d.pointsPerStage = d.remPointsOnStage - 1
return
endif
set .x = .x + d.vx
set .y = .y + d.vy
set .z = .z + d.vz
set d.remPointsOnStage = d.remPointsOnStage - 1
if d.remPointsOnStage < 1 then
set d.currAngle = d.currAngle+d.modAngle
set ux = Cos(d.currAngle) * d.offset
set uy = Sin(d.currAngle) * d.offset
set fac = d.cosA * uy
set d.vx = d.cosB * ux - d.sinB * fac
set d.vy = d.sinB * ux + d.cosB * fac
set d.vz = d.sinA * uy
set d.remPointsOnStage = d.pointsPerStage
endif
//! runtextmacro ShapeCreator_ReleaseInstance()
endmethod
static method createIntersectedStarPolygon takes real mx, real my, real mz, real angleToStartCorner, real zAngle, real r,/*
*/integer corners, integer countPerEdge, integer dir, real interval, usrfunc periodic, usrfunc final returns thistype
local thistype this = thistype.allocate()
local real edgeLength = 0
local real fac = 0
local real ux = 0
local real uy = 0
//! runtextmacro ShapeCreator_VarSetup("StarPolygon")
set .remPoints = countPerEdge * corners - corners
set d.remPointsOnStage = countPerEdge
set .sx = mx
set .sy = my
set .sz = mz
set angleToStartCorner = angleToStartCorner - .PIDiv2
set d.cosB = Cos(angleToStartCorner)
set d.sinB = Sin(angleToStartCorner)
set d.cosA = Cos(zAngle)
set d.sinA = Sin(zAngle)
set d.pointsPerStage = 0
set d.modAngle = bj_PI-bj_PI/corners
set edgeLength = SquareRoot(2*r*r*(1-Cos(d.modAngle)))
set d.modAngle = d.modAngle * dir
set d.currAngle = bj_PI+(d.modAngle/2)
set d.offset = edgeLength/(countPerEdge-1) * dir
set uy = r
set fac = d.cosA * uy
set .x = mx - d.sinB * fac
set .y = my + d.cosB * fac
set .z = mz + d.sinA * uy
set ux = Cos(d.currAngle) * d.offset
set uy = Sin(d.currAngle) * d.offset
set fac = d.cosA * uy
set d.vx = d.cosB * ux - d.sinB * fac
set d.vy = d.sinB * ux + d.cosB * fac
set d.vz = d.sinA * uy
set .x = .x - d.vx
set .y = .y - d.vy
set .z = .z - d.vz
//! runtextmacro ShapeCreator_TimerSetup("StarPolygon","periodic","final")
endmethod
static method createNonIntersectedStarPolygon takes real mx, real my, real mz, real angleToStartCorner, real zAngle, real r,/*
*/integer corners, integer countPerEdge, integer dir, real interval, usrfunc periodic, usrfunc final returns thistype
local thistype this = thistype.allocate()
local real edgeLength = 0
local real fac = 0
local real ux = 0
local real uy = 0
//! runtextmacro ShapeCreator_VarSetup("StarPolygon")
set .remPoints = countPerEdge * corners - corners
set d.remPointsOnStage = countPerEdge
set .sx = mx
set .sy = my
set .sz = mz
set angleToStartCorner = angleToStartCorner - .PIDiv2
set d.cosB = Cos(angleToStartCorner)
set d.sinB = Sin(angleToStartCorner)
set d.cosA = Cos(zAngle)
set d.sinA = Sin(zAngle)
set d.pointsPerStage = 0
set d.modAngle = .PI2/corners
set edgeLength = 2*r * Sin(d.modAngle/2)
set d.modAngle = d.modAngle * dir
set d.currAngle = bj_PI+(d.modAngle/2)
set d.offset = edgeLength/(countPerEdge-1) * dir
set uy = Sin(.PIDiv2) * r
set fac = d.cosA * uy
set .x = mx - d.sinB * fac
set .y = my + d.cosB * fac
set .z = mz + d.sinA * uy
set ux = Cos(d.currAngle) * d.offset
set uy = Sin(d.currAngle) * d.offset
set fac = d.cosA * uy
set d.vx = d.cosB * ux - d.sinB * fac
set d.vy = d.sinB * ux + d.cosB * fac
set d.vz = d.sinA * uy
set .x = .x - d.vx
set .y = .y - d.vy
set .z = .z - d.vz
//! runtextmacro ShapeCreator_TimerSetup("StarPolygon","periodic","final")
endmethod
static method createSquare takes real mx, real my, real mz, real angleToStartCorner, real zAngle, real edgeLength,/*
*/integer countPerEdge, integer dir, real interval, usrfunc periodic, usrfunc final returns thistype
local real e2 = edgeLength*edgeLength
return .createNonIntersectedStarPolygon(mx,my,mz,angleToStartCorner,zAngle,0.5*SquareRoot(2*e2),4,countPerEdge,dir,interval,periodic,final)
endmethod
//! textmacro ShapeCreator_GetInstance
static if LIBRARY_TimerUtils then
local thistype this = GetTimerData(GetExpiredTimer())
else
local thistype this = LoadInteger(.link,GetHandleId(GetExpiredTimer()),0)
endif
//! endtextmacro
//! textmacro ShapeCreator_ReleaseInstance
set .remPoints = .remPoints- 1
if .remPoints< 1 then
call PauseTimer(.intervalTimer)
call TimerStart(.intervalTimer,0.,false,function thistype.onPause)
if .final != 0 then
call .final.evaluate(this)
return
endif
endif
call .periodic.evaluate(this)
//! endtextmacro
//! textmacro ShapeCreator_Flush
static method flush takes integer i returns nothing
call thistype(i).destroy()
endmethod
//! endtextmacro
//! textmacro ShapeCreator_VarSetup takes FUNCNAME
local $FUNCNAME$Data d = $FUNCNAME$Data.create()
set .shapeData = d
set .flushData = $FUNCNAME$Data.flush
//! endtextmacro
//! textmacro ShapeCreator_TimerSetup takes FUNCNAME, PERIODIC, FINAL
static if LIBRARY_TimerUtils then
if .intervalTimer == null then
set .intervalTimer = NewTimer()
endif
call SetTimerData(.intervalTimer,this)
else
if .intervalTimer == null then
set .intervalTimer = CreateTimer()
endif
call SaveInteger(.link,GetHandleId(.intervalTimer),0,this)
endif
set .periodic = $PERIODIC$
set .final = $FINAL$
call TimerStart(.intervalTimer,interval,true,function thistype.onCreate$FUNCNAME$Timer)
return this
//! endtextmacro
endstruct
endlibrary
Example Usage:
JASS:
scope WaterElemental initializer Init
private function Amount takes integer lvl returns integer
return lvl * 2
endfunction
private function Radius takes integer lvl returns real
return 150.+lvl*40.
endfunction
private function LifeTime takes integer lvl returns real
return 10.
endfunction
private function CreationTimePerElemental takes integer lvl returns real
return 0.1
endfunction
globals
private constant integer SPELLID = 039;A000039;
private constant integer SPAWNID = 039;hwat039;
private constant string SPAWN_SFX = "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl"
endglobals
// End Config
private function createElemental takes Shape sp returns nothing
call DestroyEffect(AddSpecialEffect(SPAWN_SFX,sp.x,sp.y))
call UnitApplyTimedLife(CreateUnit(Player(0),SPAWNID,sp.x,sp.y,bj_RADTODEG * Atan2(sp.y-sp.sy,sp.x-sp.sx)),039;0000039;,LifeTime(sp.customValue))
endfunction
private function onCast takes nothing returns boolean
local unit u = null
local integer lvl = 0
if GetSpellAbilityId() != SPELLID then
return false
endif
set u = GetTriggerUnit()
set lvl = GetUnitAbilityLevel(u,SPELLID)
set Shape.createEllipsis(GetUnitX(u),GetUnitY(u),0.,Radius(lvl),Radius(lvl),0.,0.,0.,1,Amount(lvl),CreationTimePerElemental(lvl),createElemental,0).customValue = lvl
return false
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterUnitEvent(t,HERO,EVENT_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function onCast))
endfunction
endscope
Changelog:
v2.2: Renamed from "Shaper" to "Shape Creator"; Updated some descriptions; Added Square-wrapper
v2.1: Cleaned up the code; Added Instance.stop(); Reorganized function parameters
v2.0: 3D-Upgrade
v1.1: Added optional TimerUtils usage
v1.0: Release
v2.1: Cleaned up the code; Added Instance.stop(); Reorganized function parameters
v2.0: 3D-Upgrade
v1.1: Added optional TimerUtils usage
v1.0: Release
Note:
I'm still working on it, but I'd like to receive constructive criticism to improve.
Greetings