Exfyre
hmm...
- Reaction score
- 60
MySimple Projectile System
I found out that there was already a projectile system called Simple Projectile System, which I had originally intended on naming this. Therefore, to avoid conflicts, I renamed this to MySPS.
Requires:
-JASS NewGen Pack
-Key Timers 2
JASS:
//
// My
// .-. . .--. . . .-. .
//( ) o | | ) o _|_ o | ( ) _|_
// `-. . .--.--. .,-. | .-. |--'.--..-. . .-. .-.| . | .-. `-. . ..--.| .-. .--.--.
//( ) | | | | | )|(.-' | | ( )|(.-'( | | |(.-' ( )| |`--.| (.-' | | |
// `-'-' `-' ' `-|`-' `-`--' ' ' `-' | `--'`-'`-'-' `-`-`--' `-' `--|`--'`-'`--'' ' `-
// | ; ; By Exfyre - v1.1
// ' `-' `-'
// What is SPS?
// ¯¯¯¯¯¯¯¯¯¯¯¯
// -SPS allows you to add simple projectiles, with trajectory, quite easily.
//
// How to implement?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// -Create a new trigger object called SPS, go to "Edit -> Convert to Custom Text," and paste
// this code into the trigger.
// -Copy the Model file in the import section (F12) to your map
// -Copy the dummy unit "Dummy Caster" from this map to yours
//
// Functions:
// ¯¯¯¯¯¯¯¯¯¯
// SPS_Add(real x, real y, integer projectiles, real scaling, real power,
// real angle, real rotation, string model, string post, real spreadXY, real spreadZ,
// boolean follow, code func)
// -x, y: This is the starting location of the projectile
// -projectiles: # of projectiles to be created
// -scaling: scaling size of the model to be attached
// -power: the inital velocity of the projectile (as a percentage of 100, see globals to change power constant)
// -angle: the angle of the shot in Z direction, from ground level (90 being straight up)
// -rotation: firing angle in the XY plane (90 being North)
// -model: model of the projectile while in air
// -post: effect to play when the projectile hits the ground
// -spreadXY: spread of the shot (when int projectiles > 1) in the XY direction (random)
// -spreadZ: spread of the shot (when int projectiles > 1) in the Z direction (odered)
// -follow: when set to true, the camera will follow the projectile through the air
// -func: The function you want to run after the projectile hits
// Wrappers:
// ¯¯¯¯¯¯¯¯¯
// SPS_GetEndX() returns real
// SPS_GetEndY() returns real
// SPS_GetHurter() returns unit
// SPS_GetAbilId() returns integer
library SPS uses T32
//configurables
globals
private constant integer DUMMYUNIT=039;h001039;
private constant real GRAVITY = 1000 //How fast the missles fall
private constant real POWERC = 40 //multiple for power
endglobals
//endconfigurables
globals
private location L = Location(0,0)
unit Hurter
real EndX
real EndY
integer AbilId
endglobals
private struct InstanceData
unit hurter
unit dummy
effect dummyeffect
real time = 0
real x
real y
real z
real power
real angle
real rotation
boolean follow
string post
integer abilId
trigger t = CreateTrigger()
private method FindD takes real power, real angle, real time returns real
return power*Cos(angle)*time
endmethod
private method FindX takes real x, real rotation, real power, real angle, real time returns real
return x + FindD(power, angle, time) * Cos(rotation)
endmethod
private method FindY takes real y, real rotation, real power, real angle, real time returns real
return y + FindD(power, angle, time) * Sin(rotation)
endmethod
private method FindZ takes real power, real angle, real time returns real
return (power*Sin(angle)) * time - ((GRAVITY) * (time*time) / 2.) //D=(Vi)t+(1/2)(a)(t^2)
endmethod
private method IsFalling takes real power, real angle, real time returns boolean
return 2./time*(FindD(power, angle, time)/time-power)<0
endmethod
private method periodic takes nothing returns nothing
local real time = this.time
local real xx = FindX(this.x, this.rotation, this.power, this.angle, time)
local real yy = FindY(this.y, this.rotation, this.power, this.angle, time)
local real zz = FindZ(this.power, this.angle, this.time)
set this.time = this.time + T32_PERIOD
call SetUnitPosition(this.dummy, xx, yy)
call SetUnitFlyHeight(this.dummy, zz, 0.0)
if (this.follow==true) then
call PanCameraToWithZ(xx, yy, zz)
endif
if zz <= 1 and IsFalling(this.power, this.angle, time) then
call DestroyEffect(this.dummyeffect)
call DestroyEffect(AddSpecialEffect(this.post, xx, yy))
call RemoveUnit(this.dummy)
set Hurter = this.hurter
set EndX = xx
set EndY = yy
set AbilId = this.abilId
call TriggerExecute(this.t)
call DestroyTrigger(this.t)
call this.stopPeriodic()
call this.destroy()
endif
endmethod
implement T32x
static method create takes integer abilId, unit hurter, real x, real y, real scaling, real power, real angle, real rotation, string model, string post, boolean follow, trigger t returns thistype
local thistype this = thistype.allocate()
set this.hurter = hurter
set this.x = x
set this.y = y
set this.power = power*POWERC
set this.angle = angle
set this.rotation = rotation
set this.post = post
set this.follow = follow
set this.abilId = abilId
set this.t = t
set this.dummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMYUNIT, x, y, 0)
set this.dummyeffect = AddSpecialEffectTarget(model, this.dummy, "origin")
call SetUnitScale(this.dummy, scaling, scaling, scaling)
call MoveLocation(L, x, y)
set this.z = GetLocationZ(L)
return this
endmethod
endstruct
public function Add takes integer abilId, unit hurter, real x, real y, integer projectiles, real scaling, real power, real angle, real rotation, string model, string post, real spreadXY, real spreadZ, boolean follow, code func returns nothing
local integer i = 1
local trigger array t
loop
exitwhen i == projectiles+1
set t<i> = CreateTrigger()
call TriggerAddAction(t<i>, func)
call InstanceData.create(abilId, hurter, x + GetRandomReal(0., spreadXY), y + GetRandomReal(0., spreadXY), scaling, power + (projectiles/2 - i) * spreadZ, angle*bj_DEGTORAD, rotation*bj_DEGTORAD, model, post, follow, t<i>).startPeriodic()
set t<i> = null
set i = i + 1
endloop
endfunction
//wrappers
public function GetEndX takes nothing returns real
return EndX
endfunction
public function GetEndY takes nothing returns real
return EndY
endfunction
public function GetHurter takes nothing returns unit
return Hurter
endfunction
public function GetAbilId takes nothing returns integer
return AbilId
endfunction
//endwrappers
endlibrary</i></i></i></i>
v1.0
JASS:
//
// My
// .-. . .--. . . .-. .
//( ) o | | ) o _|_ o | ( ) _|_
// `-. . .--.--. .,-. | .-. |--'.--..-. . .-. .-.| . | .-. `-. . ..--.| .-. .--.--.
//( ) | | | | | )|(.-' | | ( )|(.-'( | | |(.-' ( )| |`--.| (.-' | | |
// `-'-' `-' ' `-|`-' `-`--' ' ' `-' | `--'`-'`-'-' `-`-`--' `-' `--|`--'`-'`--'' ' `-
// | ; ; By Exfyre - v1.0
// ' `-' `-'
// What is MySPS?
// ¯¯¯¯¯¯¯¯¯¯¯¯
// -MySPS allows you to add simple projectiles, with trajectory, quite easily.
//
// How to implement?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// -Create a new trigger object called MySPS, go to "Edit -> Convert to Custom Text," and paste
// this code into the trigger.
//
// Functions:
// ¯¯¯¯¯¯¯¯¯¯
// MySPS_Add(real x, real y, integer projectiles, real scaling, real power,
// real angle, real rotation, string model, string post, real spreadXY, real spreadZ,
// boolean follow)
// -x, y: This is the starting location of the projectile
// -projectiles: # of projectiles to be created
// -scaling: scaling size of the model to be attached
// -power: the inital velocity of the projectile (as a percentage of 100, see globals to change power constant)
// -angle: the angle of the shot in Z direction, from ground level (90 being straight up)
// -rotation: firing angle in the XY plane (90 being North)
// -model: model of the projectile while in air
// -post: effect to play when the projectile hits the ground
// -spreadXY: spread of the shot (when int projectiles > 1) in the XY direction (random)
// -spreadZ: spread of the shot (when int projectiles > 1) in the Z direction (odered)
// -follow: when set to true, the camera will follow the projectile through the air
//
// MySPS_AddSimple(real x, real y, real scaling, real power, real angle,
// real rotation, string model, string post)
// -Has same values as above. Default fires 1 projectile, without following with camera
//
// MySPS_AddTimed(real x, real y, integer projectiles, real scaling, real power,
// real angle, real rotation, string model, string post, real spreadXY, real spreadZ,
// boolean follow, real rate)
// -rate: will fire all projectiles with real rate interval between firings
// -Other values same as SPS_Add
library MySPS uses KT
globals
private constant integer DUMMYUNIT=039;h001039;
private constant real PERIOD = .03125 //Period for the timer
private constant real GRAVITY = 1000 //How fast the missles fall
private constant real POWERC = 40 //multiple for power
endglobals
private struct InstanceData
unit dummy
effect dummyeffect
real time = 0
real x
real y
real power
real angle
real rotation
boolean follow
string post
endstruct
private struct TimedData
real x
real y
integer projectiles
real scaling
real power
real angle
real rotation
string model
string post
real spreadXY
real spreadZ
boolean follow
endstruct
private function FindD takes real power, real angle, real time returns real
return power*Cos(angle* bj_DEGTORAD)*time
endfunction
private function FindX takes real x, real rotation, real power, real angle, real time returns real
return x + FindD(power, angle, time) * Cos(rotation * bj_DEGTORAD)
endfunction
private function FindY takes real y, real rotation, real power, real angle, real time returns real
return y + FindD(power, angle, time) * Sin(rotation * bj_DEGTORAD)
endfunction
private function FindZ takes real power, real angle, real time returns real
return (power*Sin(angle* bj_DEGTORAD)) * time - ((GRAVITY) * (time*time) / 2.) //D=(Vi)t+(1/2)(a)(t^2)
endfunction
private function IsFalling takes real power, real angle, real time returns boolean
return 2./time*(FindD(power, angle, time)/time-power)<0
endfunction
private function Fire takes nothing returns boolean
local InstanceData d = KT_GetData()
local real x = d.x
local real y = d.y
local real time = d.time
local real rotation = d.rotation
local real power = d.power*POWERC
local real angle = d.angle
local real xx = FindX(x, rotation, power, angle, time)
local real yy = FindY(y, rotation, power, angle, time)
local real zz = FindZ(power, angle, time)
set d.time = d.time + PERIOD
call SetUnitPosition(d.dummy, xx, yy)
call SetUnitFlyHeight(d.dummy, zz, 0.0)
if (d.follow==true) then
call PanCameraToWithZ(xx, yy, zz)
endif
if GetUnitFlyHeight(d.dummy) <= 1 and IsFalling(power, angle, time) then
call DestroyEffect(d.dummyeffect)
call DestroyEffect(AddSpecialEffect(d.post, xx, yy))
call RemoveUnit(d.dummy)
return true
endif
return false
endfunction
public function Add takes real x, real y, integer projectiles, real scaling, real power, real angle, real rotation, string model, string post, real spreadXY, real spreadZ, boolean follow returns nothing
local InstanceData array d
local integer i = 1
loop
exitwhen i == projectiles+1
set d<i> = InstanceData.create()
set d<i>.x = x + GetRandomReal(0., spreadXY)
set d<i>.y = y + GetRandomReal(0., spreadXY)
set d<i>.angle = angle
set d<i>.rotation = rotation
set d<i>.power = power + (projectiles/2 - i) * spreadZ
set d<i>.dummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMYUNIT, x, y, 0)
call SetUnitScale(d<i>.dummy, scaling, scaling, scaling)
set d<i>.dummyeffect = AddSpecialEffectTarget(model, d<i>.dummy, "origin")
set d<i>.follow = follow
set d<i>.post = post
call KT_Add(function Fire, d<i>, PERIOD)
set i = i + 1
endloop
endfunction
public function AddSimple takes real x, real y, real scaling, real power, real angle, real rotation, string model, string post returns nothing
call Add(x, y, 1, scaling, power, angle, rotation, model, post, 0, 0, false)
endfunction
private function AddViaStruct takes nothing returns boolean
local TimedData d = KT_GetData()
call Add(d.x, d.y, 1, d.scaling, d.power, d.angle, d.rotation, d.model, d.post, d.spreadXY, d.spreadZ, d.follow)
if d.projectiles == 0 then
return true
endif
set d.projectiles = d.projectiles-1
return false
endfunction
public function AddTimed takes real x, real y, integer projectiles, real scaling, real power, real angle, real rotation, string model, string post, real spreadXY, real spreadZ, boolean follow, real rate returns nothing
local TimedData d = InstanceData.create()
set d.x = x
set d.y = y
set d.angle = angle
set d.rotation = rotation
set d.model = model
set d.power = power
set d.follow = follow
set d.post = post
set d.scaling = scaling
set d.projectiles = projectiles
set d.spreadXY = spreadXY
set d.spreadZ = spreadZ
call KT_Add(function AddViaStruct, d, rate)
endfunction
endlibrary</i></i></i></i></i></i></i></i></i></i></i></i></i>
Changelog:
v1.1 - Switched from KT to T32, added more functionality, other stuff. Map updated
v1.0 - First release
v1.0 - First release
Summary:
This system creates projectiles that originate from a rotated source at an angle with a speed.
The demo map includes 3 different implementations, using a tank with 3 weapons.
-single shot
-buck shot
-carpet bomb
What I WANT to be able to do is to retrieve the X and Y coordinates of the ending location after each projectile lands, and do something with that - but I don't have any idea how to implement that.
Also, I'm sure the code can be optimized, so suggestions are welcome.