- Joined
- Jan 9, 2005
- Messages
- 2,126
I've never used modules before. I'm trying to make a system that can be used like Missile or Buff System, that is to say, you can do something like
The above example isn't working, and I can't say I know why because I don't really get any of this. I've been trying to read the code behind Missile or Buff System, and the only thing I've been able to identify is
I guess my question is... how do you make this work? I'm not even sure I'm explaining my problem correctly. I'm making a lightning-effect handler that behaves slightly differently that the others. I'll just post my code below:
call Thing.dothething(instance)
and then it will run the various methods inside of the struct Thing. So, for example:
JASS:
struct MovingPoint
static method onPeriod takes Beam b returns nothing
local real a = GetBeamAngle(b) // returns angle in radians
local real dist = GetBeamLength(b)
local real x = GetPointX(b.impact) + Cos(a) * dist + 10.
local real y = GetPointY(b.impact) + Sin(a) * dist + 10.
call Point.update(b.impact, x, y, 0.)
call BJDebugMsg("test")
endmethod
implement BeamControl
endstruct
static if thistype.onPeriod.exists then
inside the module that is then implemented into your custom struct that has Implement MyModule.I guess my question is... how do you make this work? I'm not even sure I'm explaining my problem correctly. I'm making a lightning-effect handler that behaves slightly differently that the others. I'll just post my code below:
JASS:
library Beam
globals
private constant real TIMEOUT = .03125
private constant location LOC = Location(0., 0.)
private timer IntervalTimer = null
private integer BeamCount = 0
private Beam array ActiveBeams
endglobals
function GetLocalUnitZ takes unit u returns real
call MoveLocation(LOC, GetUnitX(u), GetUnitY(u))
return GetUnitFlyHeight(u) + GetLocationZ(LOC)
endfunction
// Point getters
function GetPointX takes Point point returns real
return point.x
endfunction
function GetPointY takes Point point returns real
return point.y
endfunction
function GetPointZ takes Point point returns real
return point.z
endfunction
// Beam getters
function GetBeamAngle takes Beam b returns real
return Atan2(b.impact.y - b.launch.y, b.impact.x - b.launch.x)
endfunction
function GetBeamLength takes Beam b returns real
return SquareRoot( (b.impact.x - b.launch.x)*(b.impact.x - b.launch.x) + (b.impact.y - b.launch.y)*(b.impact.y - b.launch.y) )
endfunction
module BeamControl
private static method remove takes integer starterInt returns nothing
local integer i = starterInt
loop
set ActiveBeams[i] = ActiveBeams[i + 1]
set i = i + 1
exitwhen i > BeamCount
endloop
set BeamCount = BeamCount - 1
call ActiveBeams[starterInt].destroy()
endmethod
private static method interval takes nothing returns nothing
local integer i = 1
local Beam b
local boolean moveBeam = false
local real x
local real y
local real z
local real a
loop
set i = i + 1
set b = ActiveBeams[i]
exitwhen i > BeamCount
// runs every TIMEOUT seconds
static if thistype.onPeriod.exists then
call thistype.onPeriod(b)
endif
// runs if the
static if thistype.onEnd.exists then
endif
if b.source != null then
if b.sourceFacing then
set a = b.sourceAngle + GetUnitFacing(b.source) * bj_DEGTORAD
else
set a = b.sourceAngle
endif
set x = GetUnitX(b.source) + Cos(a) * b.sourceDistance
set y = GetUnitY(b.source) + Sin(a) * b.sourceDistance
set z = GetLocalUnitZ(b.source) + b.sourceZOffset
call Point.update(b.launch, x, y, z)
endif
if b.target != null then
if b.targetFacing then
set a = b.targetAngle + GetUnitFacing(b.target) * bj_DEGTORAD
else
set a = b.targetAngle
endif
set x = GetUnitX(b.target) + Cos(a) * b.targetDistance
set y = GetUnitY(b.target) + Sin(a) * b.targetDistance
set z = GetLocalUnitZ(b.target) + b.targetZOffset
call Point.update(b.launch, x, y, z)
endif
if Point.hasMoved(b.launch) or Point.hasMoved(b.impact) then
call MoveLightningEx(b.beam, true, b.launch.x, b.launch.y, b.launch.z, b.impact.x, b.impact.y, b.impact.z)
endif
// if not in the fade phase
if not b.isFading then
set b.beamTime = b.beamTime - TIMEOUT
if b.beamTime <= 0. then
set b.isFading = true
endif
// if in the fade phase
else
set b.fadeTime = b.fadeTime - TIMEOUT
if b.fadeTime <= 0. then
call thistype.remove(i)
endif
endif
endloop
if BeamCount <= 0 then
call PauseTimer(IntervalTimer)
endif
endmethod
static method cast takes Beam b returns nothing
local real xSource
local real ySource
local real xTarget
local real yTarget
local real x
local real y
local real z
if not b.isCast then
set b.isCast = true
if b.source != null then
// if you have a source, calculate the angle and distance between the launch coordinates and the source.
// these values will then recalculate every interval to determine if the Point has moved or not.
set xSource = GetUnitX(b.source)
set ySource = GetUnitY(b.source)
set b.sourceAngle = Atan2(b.yLaunch - ySource, b.xLaunch - xSource)
set b.sourceDistance = SquareRoot( (b.xLaunch - xSource)*(b.xLaunch - xSource) + (b.yLaunch - ySource)*(b.yLaunch - ySource) )
set b.sourceZOffset = b.zLaunch - GetLocalUnitZ(b.source)
endif
set b.launch = Point.create(b.xLaunch, b.yLaunch, b.zLaunch)
if b.target != null then
// same as the above, but for targets
set xTarget = GetUnitX(b.target)
set yTarget = GetUnitY(b.target)
set b.targetAngle = Atan2(b.yImpact - yTarget, b.xImpact - xTarget)
set b.targetDistance = SquareRoot( (b.xImpact - xTarget)*(b.xImpact - xTarget) + (b.yImpact - yTarget)*(b.yImpact - yTarget) )
set b.targetZOffset = b.zImpact - GetLocalUnitZ(b.target)
endif
set b.impact = Point.create(b.xImpact, b.yImpact, b.zImpact)
set b.beam = AddLightningEx(b.beamFX, true, b.launch.x, b.launch.y, b.launch.z, b.impact.x, b.impact.y, b.impact.z)
if b.beamTime < 0. then
set b.isFading = true
else
set b.isFading = false
endif
set BeamCount = BeamCount + 1
if BeamCount == 1 then //if BeamCount is equal to 1 then that means it was previously zero, which means the timer was inactive.
call TimerStart(IntervalTimer, TIMEOUT, true, function thistype.interval)
endif
// do I need to create these triggers?
/*static if thistype.onPeriod.exists then
endif
static if thistype.onFade.exists then
endif*/
endif
endmethod
endmodule
struct Point
readonly real x
readonly real y
readonly real z
private real xOld
private real yOld
private real zOld
static method remove takes thistype point returns nothing
set point.x = 0.
set point.y = 0.
set point.z = 0.
set point.xOld = 0.
set point.yOld = 0.
set point.zOld = 0.
call point.deallocate()
endmethod
static method hasMoved takes thistype point returns boolean
if point.x != point.xOld or point.y != point.yOld or point.z != point.zOld then
return true
else
return false
endif
endmethod
static method update takes thistype point, real X, real Y, real Z returns nothing
set point.xOld = point.x
set point.yOld = point.y
set point.zOld = point.z
set point.x = X
set point.y = Y
set point.z = Z
endmethod
static method create takes real X, real Y, real Z returns thistype
local thistype point = allocate()
set point.x = X
set point.y = Y
set point.z = Z
set point.xOld = X
set point.yOld = Y
set point.zOld = Z
return point
endmethod
endstruct
struct Beam
unit source
unit target
// these reals will be used to recalculate the new coordiates of Points should the source or target move
real sourceAngle
real sourceDistance
real sourceZOffset
real targetAngle
real targetDistance
real targetZOffset
// these booleans will move the point around the source/target with relation to their facing angle
boolean sourceFacing
boolean targetFacing
// these values will either be the launch and impact coordinates, or offset the source and
// target location by these values. Refer to the demo for a exmaple of how to use those as offsets.
real xLaunch
real yLaunch
real zLaunch
real xImpact
real yImpact
real zImpact
real beamTime
real fadeTime
// these variables store the launch and impact Points of the beam instance.
Point impact
Point launch
lightning beam
string beamFX
real red
real blue
real green
real alpha
boolean isFading
boolean isCast
method destroy takes nothing returns nothing
if this.beam != null then
call DestroyLightning(this.beam)
set this.beam = null
endif
set this.source = null
set this.target = null
set this.isCast = false
call this.deallocate()
endmethod
static method create takes nothing returns thistype
local thistype b = allocate()
//initialise all variables to their default value
set b.source = null
set b.target = null
set b.sourceAngle = 0.
set b.sourceDistance = 0.
set b.sourceZOffset = 0.
set b.targetAngle = 0.
set b.targetDistance = 0.
set b.targetZOffset = 0.
set b.sourceFacing = false
set b.targetFacing = false
set b.xLaunch = 0.
set b.yLaunch = 0.
set b.zLaunch = 0.
set b.xImpact = 0.
set b.yImpact = 0.
set b.zImpact = 0.
set b.beamTime = 0.
set b.fadeTime = 0.
set b.impact = 0
set b.launch = 0
set b.beam = null
set b.beamFX = null
set b.red = 1.
set b.blue = 1.
set b.green = 1.
set b.alpha = 1.
set b.isFading = false
set b.isCast = false
return b
endmethod
endstruct
endlibrary
JASS:
scope MovingPointDemo initializer init
struct MovingPoint
// this method is never called :(
// how do I make it work?
static method onPeriod takes Beam b returns nothing
local real a = GetBeamAngle(b) // returns angle in radians
local real dist = GetBeamLength(b)
local real x = GetPointX(b.impact) + Cos(a) * dist + 10.
local real y = GetPointY(b.impact) + Sin(a) * dist + 10.
call Point.update(b.impact, x, y, 0.)
call BJDebugMsg("test")
endmethod
implement BeamControl
endstruct
private function Actions takes nothing returns nothing
local unit Source = GetTriggerUnit()
local real xSource = GetUnitX(Source)
local real ySource = GetUnitY(Source)
local real xTarget = GetSpellTargetX()
local real yTarget = GetSpellTargetY()
local real a = Atan2(yTarget - ySource, xTarget - xSource)
local real dist = 80.//GetUnitCollision(Source)
local Beam b = Beam.create()
set b.source = Source
set b.beamFX = "BLNL"
set b.xLaunch = xSource + Cos(a) * dist
set b.yLaunch = ySource + Sin(a) * dist
set b.zLaunch = GetUnitFlyHeight(Source) + 80.
set b.xImpact = xTarget
set b.yImpact = yTarget
set b.zImpact = 0.
set b.beamTime = 2.
call MovingPoint.cast(b)
set Source = null
endfunction
private function init takes nothing returns nothing
call RegisterSpellEffectEvent('A000', function Actions)
endfunction
endscope