Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
Introduction
First of all, Credits and thanks to BPower, Dirac, and Vexorian for their missile systems at which I based this system upon, and to AGD for the help with effect orientation methods.
This is a Missile system that I put together initially to fulfill my resources needs. Very often while I was creating system, spells and maps I found myself in need of a such systems, but all the available options usually have a little flaw that forced me to used something else.
For example, let's say I wanted a missile that can arc and homing to a target, well there goes BPower's system. It can arc/curve but can't do homing with arc/curve natively. So the options left are Vexorian xemissile which can arc and do homing but cant curve, and Dirac's Missile system. Then again more problems with those, because Vexorian system do not have a lot of the useful events like Dirac's and BPower's systems. Dirac's system can arc/curve and do homing but it's T32 timer is never stopped and it do not have some useful events that the BPower system has. So I decided to get all three system together and build my own system with the stuff I think is useful and with the syntax I think is the most friendly, because I'm not a genius of vJASS myself.
What's different in this system?
Ok, so why it's called "Relativistic Missiles"? Well because mid development I realize that the way missiles were being processed could be optimized and the Einstein postulates about Time Dilation by Gravity gave the idea behind the implementation. Yeah, I know, WTH?
When it comes to Missile systems, performance is everything, and all missiles systems do basically the same thing when processing missiles instances, they loop every set period, which is usually 1/32, through all instances and do their calculations and event calls. The problem with it, is that the more instances existing at a given moment the greater will be the tanking of the game frame rate because the game will lower its fps so all that's need to be done before the next frame gets drawn have time to do so, and that's where the Einstein postulates gave me an idea.
See, when we study Relativity, we learn that gravity dilates time, the greater the gravitational potential (more or less mass) the slower time passes relative to an outside point of reference. Gravity in this analogy would be the amount of missiles instances currently existing, so instead of letting the game frame rate drops drastically to move all those instances, I make the missile instances have their time dilated.
Ok, but how?? Simple, first we need to find what I'll be calling the system Sweet Spot, which is the amount of missiles the game can handle without dropping to much performance per given period, which I found out to be between 150 and 200 missiles. Then we limit the amount of missiles processed per period to this sweet spot, and move the next missile in the line to be processed and all other behind it to the front, In terms of data structures, think of a circular list with a head and tail, and we move the head and tail to change the initial and final positions. I did it with arrays because they are a bit faster and because I'm lazy .
But that's not all, because by limiting the amount of missiles processed, we delay their next process call by (total amount)/(sweet spot), so now their speed needs to be corrected and relativity comes full circle now, because time dilation has it's relation with Length Contraction, so we increment the missiles speed by this factor.
Also, something very important is that this system is using only effects as missiles, thanks to the new natives introduced in 1.31, so no dummy units, no CreateUnit() and SetUnitFacing() blasphemy. I've included in the test map a version of this system that do use the dummy method for those that do not have the newer versions of the game. I Also included a version of this system that uses the usual process method, so processing all missiles in a single blow.
Results
I've taken the liberty to test this system against the king of Missile systems for some time, BPower's System. Below, there are 3 videos I make for stress test. The first from the left is BPower's Missile System reworked by AGD. Amazing job btw. You will be able to notice what I was talking about earlier about the sweet spot, when there are more than 150 or so missiles being processed, the fps goes basically to 0 and it freezes until the missiles are finished.
The video in the middle is my system in its normal version (not relativistic). It performs a little better (I've build it a little differently), but in the same way, when the missile count near 250, the fps starts to go down hill real quick.
The video in the right is the relativistic version, notice the missile count and fps compared to the 2 other system. At about 600 missiles fps get really low, but not so much because of the amount of missiles being processed but because of the amount of visual effects in the screen. If the screen was moved to the side where not so many stuff is visible, fps goes up. In my internal tests I was reaching more than 1200 missiles with about 16 fps but with no screen freezes.
And Last but not Least, a video with the examples.
vJASS:
event onPeriod takes nothing returns boolean
-> if declared will run whenever every missile period
event onHit takes unit hit returns boolean
-> if declared and collision is greater than 0
-> will run whenever the missile collides with a unit
event onMissile takes Missiles missile returns boolean
-> if declared and collision is greater than 0
-> will run whenever the missile collides with another missile
event onDestructable takes destructable dest returns boolean
-> if declared and collision is greater than 0
-> will run whenever the missile collides with a destructable
event onItem takes item i returns boolean
-> if declared and collision is greater than 0
-> will run whenever the missile collides with an item
event onCliff takes nothing returns boolean
-> if declared, will run whenever the missile collides with a cliff wall
-> with height greater than the current missile height
event onTerrain takes nothing returns boolean
-> if declared, will run whenever the missile collides with terrain
event onTileset takes nothing returns boolean
-> if declared, will run whenever the missile changes tileset types
event onFinish takes nothing returns boolean
-> if declared, will run when the missiles reaches its destination
event onBoundaries takes nothing returns boolean
-> if declared, will run whenever the missile tries to go out
-> of the map boundaries.
event onPause takes nothing returns boolean
-> if declared, will run when the missile is paused
event onResume takes nothing returns boolean
-> if declared, will run when the missile is unpaused
event onRemove takes nothing returns nothing
-> if declared, will run when the missile is removed
vJASS:
x -> The current x coordinate of the missile (readonly)
y -> The current y coordinate of the missile (readonly)
z -> The current z coordinate of the missile (readonly)
prevX -> The previous x coordinate of the missile (readonly)
prevY -> The previous y coordinate of the missile (readonly)
prevZ -> The previous z coordinate of the missile (readonly)
nextX -> The next x coordinate of the missile (readonly)
nextY -> The next y coordinate of the missile (readonly)
nextZ -> The next z coordinate of the missile (readonly)
travel -> The current traveled distance of the missile (readonly)
source -> The source unit for the missile (read and write)
target -> The target unit for the missile. If set the missile will be roaming (read and write)
owner -> The owning player of the missile (read and write)
vision -> The sight range of the missile (read and write)
collideZ -> If true, the missile will take into consideration the unit collision size, destructable oclusion height and item size when running the onHit, onDestructable, onItem events (read and write)
collision -> The collision size of the missile. If not set, the events onHit, onDestructable, onItem and onMissile will no run (read and write)
damage -> Stores the amount of damage to be used inside an event (read and write)
acceleration -> The missile acceleration (read and write)
data -> Stores information to be used inside any event (read and write)
model -> The model of the missile (read and write)
curve -> The curve of the missile (read and write)
arc -> The Arc of the missile (read and write)
scale -> The scale of the missile (read and write)
speed -> The speed of the missile (read and write)
duration -> Set the speed of the missile to match a duration (read and write)
roll -> If true, the missile will roll as well (1.31+ only) (read and write)
type -> Integer that can be used to diferentiate missiles (read and write)
paused -> True when the missile is paused, false otherwise (read and write)
tileset -> The current terrain type under the missile (readonly)
timeScale -> The time scale of the effect model (read and write) (1.31+ non dummmy version only)
alpha -> The effect model alpha value (read and write) (1.31+ non dummmy version only)
playerColor -> The effect model player color (read and write) (1.31+ non dummmy version only)
animation -> The effect model animation type (read and write) (1.31+ non dummmy version only)
impact -> The object representing the impact coordinates (x, y, z, angle, distance, square, slope, alpha) (read and write)
origin -> The object representing the origin coordinates (x, y, z, angle, distance, square, slope, alpha) (read and write)
effect -> The object representing the missile (size, yaw, pitch, roll, path, effect, attachments), and attachments has (x, y, z, size, yaw, pitch, roll, path, effect)
vJASS:
x -> The current x coordinate of the missile (readonly)
y -> The current y coordinate of the missile (readonly)
z -> The current z coordinate of the missile (readonly)
prevX -> The previous x coordinate of the missile (readonly)
prevY -> The previous y coordinate of the missile (readonly)
prevZ -> The previous z coordinate of the missile (readonly)
nextX -> The next x coordinate of the missile (readonly)
nextY -> The next y coordinate of the missile (readonly)
nextZ -> The next z coordinate of the missile (readonly)
travel -> The current traveled distance of the missile (readonly)
source -> The source unit for the missile (read and write)
target -> The target unit for the missile. If set the missile will be roaming (read and write)
owner -> The owning player of the missile (read and write)
collideZ -> If true, the missile will take into consideration the unit collision size, destructable oclusion height and item size when running the onHit, onDestructable, onItem events (read and write)
collision -> The collision size of the missile. If not set, the events onHit, onDestructable, onItem and onMissile will no run (read and write)
damage -> Stores the amount of damage to be used inside an event (read and write)
acceleration -> The missile acceleration (read and write)
data -> Stores information to be used inside any event (read and write)
model -> The model of the missile (to set use yourMissile:model(string), to get use yourMissile.Model)
curve -> The curve of the missile (to set use yourMissile:curve(real), to get use yourMissile.Curve)
arc -> The Arc of the missile (to set use yourMissile:arc(real), to get use yourMissile.Arc)
scale -> The scale of the missile (to set use yourMissile:scale(real), to get use yourMissile.Scale)
speed -> The speed of the missile (to set use yourMissile:speed(real), to get use yourMissile.Speed)
duration -> Set the speed of the missile to match a duration (to set use yourMissile:duration(real), to get use yourMissile.Duration)
vision -> The sight range of the missile (to set use yourMissile:vision(real), to get use yourMissile.Vision)
roll -> If true, the missile will roll as well (1.31+ only) (read and write)
type -> Integer that can be used to diferentiate missiles (read and write)
paused -> True when the missile is paused, false otherwise (read and write)
timeScale -> The time scale of the effect model (to set use yourMissile:timeScale(real), to get use yourMissile.TimeScale)
alpha -> The effect model alpha value (to set use yourMissile:alpha(integer), to get use yourMissile.Alpha)
playerColor -> The effect model player color (to set use yourMissile:playerColor(integer), to get use yourMissile.playercolor)
animation -> The effect model animation type (to set use yourMissile:animation(integer), to get use yourMissile.Animation)
tileset -> The current terrain type under the missile (readonly)
impact -> The object representing the impact coordinates (x, y, z, angle, distance, square, slope, alpha) (read and write)
origin -> The object representing the origin coordinates (x, y, z, angle, distance, square, slope, alpha) (read and write)
effect -> The object representing the missile (size, yaw, pitch, roll, path, effect, attachments), and attachments has (x, y, z, size, yaw, pitch, roll, path, effect)
vJASS:
Missile -> The missile
MissileDestroy -> Set this variable to true inside a missile event trigger to destroy the missile
MissileStart -> The starting point of the missile. Set this variable before running the MissileCreate trigger
MissileStartZ -> The starting Z of the missile. Set this variable before running the MissileCreate trigger
MissileFinish -> The end point of the missile. Set this variable before running the MissileCreate trigger
MissileFinishZ -> The end Z of the missile. Set this variable before running the MissileCreate trigger
MissileModel -> The missile model. Set this variable before running the MissileCreate trigger. You can set this varible to change the model at any point inside a missile event trigger
MissileScale -> The missile model scale. Set this variable before running the MissileCreate trigger. You can set this varible to change the scale at any point inside a missile event trigger
MissileSpeed -> The missile speed. Set this variable before running the MissileCreate trigger. You can set this varible to change the speed at any point inside a missile event trigger
MissileDuration -> The missile duration. Set this variable before running the MissileCreate trigger. You can set this varible to change the duration at any point inside a missile event trigger
MissileArc -> The missile arc. Set this variable before running the MissileCreate trigger. You can set this varible to change the arc at any point inside a missile event trigger
MissileCurve -> The missile curve. Set this variable before running the MissileCreate trigger. You can set this varible to change the curve at any point inside a missile event trigger
MissileVision -> The missile sight range. Set this variable before running the MissileCreate trigger. You can set this varible to change the sight range at any point inside a missile event trigger
MissileDamage -> Stores the damage. Set this variable before running the MissileCreate trigger. You can set this varible to change the damage at any point inside a missile event trigger
MissileCollision -> The missile collision size. Set this variable before running the MissileCreate trigger. You can set this varible to change the collision at any point inside a missile event trigger
MissileAcceleration -> The missile acceleration. Set this variable before running the MissileCreate trigger. You can set this varible to change the acceleration at any point inside a missile event trigger
MissileCollideZ -> If true, the missile will check Z height when colliding. Set this variable before running the MissileCreate trigger. You can set this varible to change the model at any point inside a missile event trigger
MissileSource -> The missile source unit. Set this variable before running the MissileCreate trigger. You can set this varible to change the source at any point inside a missile event trigger
MissileTarget -> The missile target unit. If set the missile will roam to the target. Set this variable before running the MissileCreate trigger. You can set this varible to change the target at any point inside a missile event trigger
MissileOwner -> The owner of the missile. Set this variable before running the MissileCreate trigger. You can set this varible to change the owner at any point inside a missile event trigger
MissilePaused -> True if the missile is paused, false otherwise
MissileRoll -> If true the missile will use roll (1.31+)
MissileType -> Set if you want to categorize the missile. Set this variable before running the MissileCreate trigger. You can set this varible to change the type at any point inside a missile event trigger
MissilePosition -> The current missile position
MissileZ -> The current missile Z
MissileLastPosition -> The last missile position
MissilePrevZ -> The last missile Z
MissileNextPosition -> The next missile position
MissileNextZ -> The next missile Z
MissileVelocity -> The missile velocity. Velocity is the speed over the system period.
MissileTravelled -> The missile travelled distance. It is reseted if you deflect or bounce the missile.
MissileRemoveLocations -> Set to true before running MissileCreate trigger to remove the MissileStart and MissileFinish points automatically.
MissileHitUnit -> The hitted unit inside an onHit event trigger
MissileHitDestructable -> The hitted destructable inside an onDestructable event trigger
MissileHitItem -> The hitted item inside an onItem event trigger
MissileHitMissile -> The hitted missile inside an onMissile event trigger
MissileTileset -> The terrain type under the missile
MissileData -> The missile data variable can be used to hold information (integer)
MissileTimeScale -> The missile effect time scale. Set this variable before running the MissileCreate trigger. You can set this varible to change the time scale at any point inside a missile event trigger (1.31+ non dummmy version only)
MissileAlpha -> The missile effect alpha value. Set this variable before running the MissileCreate trigger. You can set this varible to change the alpha value at any point inside a missile event trigger (1.31+ non dummmy version only)
MissilePlayerColor -> The missile effect player color. Set this variable before running the MissileCreate trigger. You can set this varible to change the player color of the effect at any point inside a missile event trigger (1.31+ non dummmy version only)
MissileAnimation -> The missile effect animation type. Set this variable before running the MissileCreate trigger. You can set this varible to change the animation type of the effect at any point inside a missile event trigger (1.31+ non dummmy version only)
MissileDeflectTarget -> Set this variable before running the MissileDeflectTarget trigger to deflect the missile to the unit assigned to this variable
MissileRed -> Set this variable (and green and blue) after the missile is created and then run the MissileColor trigger to change the missile effect color values (1.31+ non dummmy version only)
MissileGreen -> Set this variable (and red and blue) after the missile is created and then run the MissileColor trigger to change the missile effect color values (1.31+ non dummmy version only)
MissileBlue -> Set this variable (and red and green) after the missile is created and then run the MissileColor trigger to change the missile effect color values (1.31+ non dummmy version only)
Missile_onPeriod -> Set this variable to a trigger that you want to run on every missile period
Missile_onHit -> Set this variable to a trigger that you want to run when the missile hits an unit. Use the MissileHitUnit variable to access the hitted unit
Missile_onDestructable -> Set this variable to a trigger that you want to run when the missile hits a destructable. Use the MissileHitDestructable variable to access the hitted destructable
Missile_onItem -> Set this variable to a trigger that you want to run when the missile hits an item. Use the MissileHitItem variable to access the hitted item
Missile_onMissile -> Set this variable to a trigger that you want to run when the missile hits another Missile. Use the MissileHitMissile variable to access the hitted Missile
Missile_onCliff -> Set this variable to a trigger that you want to run when the missile collides with a cliff wall with height greater than the current missile height
Missile_onTerrain -> Set this variable to a trigger that you want to run when the missile collides with terrain
Missile_onTileset -> Set this variable to a trigger that you want to run when the missile changes tileset types
Missile_onFinish -> Set this variable to a trigger that you want to run when the missile reaches its destination
Missile_onBoundaries -> Set this variable to a trigger that you want to run when the missile tries to leave the map
Missile_onPause -> Set this variable to a trigger that you want to run when the missile is paused
Missile_onResume -> Set this variable to a trigger that you want to run when the missile is unpaused
Missile_onRemove -> Set this variable to a trigger that you want to run when the missile is removed
MissileEvent -> This variable represents which event is being executed. Compere it to one of the following variables inside a trigger to decide what to do in each event
MissileOnPeriod -> MissileEvent is set to the value of this variable when Missile_onPeriod is set to a trigger
MissileOnHit -> MissileEvent is set to the value of this variable when Missile_onHit is set to a trigger
MissileOnDestructable -> MissileEvent is set to the value of this variable when Missile_onDestructable is set to a trigger
MissileOnItem -> MissileEvent is set to the value of this variable when Missile_onItem is set to a trigger
MissileOnMissile -> MissileEvent is set to the value of this variable when Missile_onMissile is set to a trigger
MissileOnCliff -> MissileEvent is set to the value of this variable when Missile_onCliff is set to a trigger
MissileOnTerrain -> MissileEvent is set to the value of this variable when Missile_onTerrain is set to a trigger
MissileOnTileset -> MissileEvent is set to the value of this variable when Missile_onTileset is set to a trigger
MissileOnFinish -> MissileEvent is set to the value of this variable when Missile_onFinish is set to a trigger
MissileOnBoundaries -> MissileEvent is set to the value of this variable when Missile_onBoundaries is set to a trigger
MissileOnPause -> MissileEvent is set to the value of this variable when Missile_onPause is set to a trigger
MissileOnResume -> MissileEvent is set to the value of this variable when Missile_onResume is set to a trigger
MissileOnRemove -> MissileEvent is set to the value of this variable when Missile_onRemove is set to a trigger
vJASS:
method bounce takes nothing returns nothing
-> Bounces the missile, reseting angles
method deflect takes real x, real y, real z returns nothing
-> Deflects the missile to the x, y and z coordinates
method deflectTarget takes unit u returns nothing
-> Deflects the missile to a unit
method flushAll takes nothing returns nothing
-> Flushes the hit group for the missile
method flush takes widget w returns nothing
-> Remove a unit, destructable, item or missile from the hit group
method hitted takes widget w returns boolean
-> Returns true if the unit, destructable or item was hit by the missile
method attach takes string model, real dx, real dy, real dz, real scale returns effect
-> Attach an effect to the missile and return the effect attached
-> dx, dy, and dz are offsets from the main missile coordinates
method detach takes effect attachment returns nothing
-> Detach an effect attached to the missile
method pause takes boolean flag returns nothing
-> If true will pause the misisle, else will unpause it
method color takes integer red, integer green, integer blue returns nothing
-> Changes the missile effect model color (1.31+ non dummy version only)
vJASS:
MissileDeflectPosition
MissileDeflectZ
MissileDeflectTarget
Set the above variables then run the MissileDeflect or MissileDeflectTarget triggers to deflect the missile
MissileFlushUnit
Set the above variable then run the MissileFlush to make the set unit be able to be hitted again by the missile
MissileHittedUnit
MissileHitted
Set the MissileHittedUnit to a unit then run the MissileHitted trigger. After that you can use the MissileHitted varible to check if the unit was already hitted by the missile
MissileAttachModel
MissileAttachX
MissileAttachY
MissileAttachZ
MissileAttachScale
MissileDetachEffect
Set the above varibles then run the MissileAttach trigger to attach an effect to the missile with MissileAttach(Model, X, Y, Z, Scale)
MissileDetachEffect
Set the above variable to the effect that was previously attached to the missile then run the MissileDetach trigger
Run the MissileBounce trigger to bounce the missile and reset its travalled distance
Run the MissileFlushAll trigger flush all units hitted by the missile
Run the MissilePause trigger pause the missile
Run the MissileResume trigger unpause the missile
Run the MissileBounce trigger to bounce the missile and reset its travalled distance
MissileRed
MissileGreen
MissileBlue
Set the above variables and then run the MissileColor trigger to change the missile effect model color (1.31+ non dummy version only)
vJASS:
function CreateMissileGroup takes nothing returns MissileGroup
-> Creates a missile group and return it
function DestroyMissileGroup takes MissileGroup missiles returns nothing
-> Destroys the misisle group
function MissileGroupGetSize takes MissileGroup missiles returns integer
-> Returns the size of the missile group
function GroupMissileAt takes MissileGroup missiles, integer position returns Missiles
-> Returns the missile at the given index.
function ClearMissileGroup takes MissileGroup missiles returns nothing
-> Clear the missile group
function IsMissileInGroup takes Missiles missile, MissileGroup missiles returns boolean
-> True if the missile is inside the missile group
function GroupRemoveMissile takes MissileGroup missiles, Missiles missile returns nothing
-> Removes the missile from the missile group
function GroupAddMissile takes MissileGroup missiles, Missiles missile returns nothing
-> Add the missile to the missile group
function GroupPickRandomMissile takes MissileGroup missiles returns Missiles
-> Returns a random missile from the misisle group. 0 if empty
function FirstOfMissileGroup takes MissileGroup missiles returns Missiles
-> Returns the first missile inside the missile group. 0 if empty
function GroupAddMissileGroup takes MissileGroup source, MissileGroup destiny returns nothing
-> Add the missiles that are in the source group into the destiny group
function GroupRemoveMissileGroup takes MissileGroup source, MissileGroup destiny returns nothing
-> Remove the missiles that are in the source group from the destiny group
function GroupEnumMissilesOfType takes MissileGroup missiles, integer whichType returns nothing
-> Enumerates the missiles of matching type
function GroupEnumMissilesOfTypeCounted takes MissileGroup missiles, integer whichType, integer amount returns nothing
-> Enumerates up to amount of missiles of matching type
function GroupEnumMissilesOfPlayer takes MissileGroup missiles, player p returns nothing
-> Enumerates the missiles that belongs to a player
function GroupEnumMissilesOfPlayerCounted takes MissileGroup missiles, player p, integer amount returns nothing
-> Enumerates up to amount of missiles that belongs to a player
function GroupEnumMissilesInRect takes MissileGroup missiles, rect r returns nothing
-> Enumerates the missiles inside a region
function GroupEnumMissilesInRectCounted takes MissileGroup missiles, rect r, integer amount returns nothing
-> Enumerates up to amount of missiles inside a region
function GroupEnumMissilesInRangeOfLoc takes MissileGroup missiles, location loc, real radius returns nothing
-> Enumerates the missiles within range of a location
function GroupEnumMissilesInRangeOfLocCounted takes MissileGroup missiles, location loc, real radius, integer amount returns nothing
-> Enumerates up to amount of missiles within range of a location
function GroupEnumMissilesInRange takes MissileGroup missiles, real x, real y, real radius returns nothing
-> Enumerates the missiles within range of x, y
function GroupEnumMissilesInRangeCounted takes MissileGroup missiles, real x, real y, real radius, integer amount returns nothing
-> Enumerates up to amount of missiles within range of x, y
BPower
Dirac
Vexorian
AGD
emjlr3
AceHart
Nestharus
Maghteridon96
Bribe
Flux
Forsakn
(v1.0)
Release
(v1.1)
Merged Normal and Relativistic code for both Legacy and Current versions.
You can use the SWEET_SPOT constant to determine the system behavior
SWEET_SPOT <= 0 -> normal method
SWEET_SPOT > 0 -> relativistic method
Included support for DummyRecycler by Flux for the Legacy version. This should improve its performance even further.
(v1.2)
Fixed a bug for homing missiles height
New configuration member boolean collideZ -> set to true to make the new missile consider z collisions
New Global Configuration constant boolean ROLL -> If true missile will consider roll in orientation. Roll can look really fishy for some users and was never possible until patch 1.31, so if you want it set it to true in the globlas block (1.31+ version only).
You can now attach effects to the main missile effect with an offset through 2 new methods (1.31+ version only)
// dx, dy, and dz are offsets from the main missile coordinates
method attach takes string model, real dx, real dy, real dz, real scale returns effect
WorldBounds now is required (Centralized requirements and outsourced)
New optional event (See Available Events for more info)
method onBoundaries takes nothing returns boolean
Fixed a spelling mistake on the detach functionality.
(v1.6)
MissileEffect library updated to use the BlzSetSpecialEffectOrientation native. (v1.31+ only)
(v1.7)
Standardized getting and setting of the members speed, arc and curve. They now read and write in degrees.
(v1.8)
Made a system function (GetLocZ) private to avoid conflict with other resources.
(v1.9)
System ported to LUA (Credits to Forsakn for the first port).
Added instant facing when creating missiles instances.
Included a version of Missiles that uses the dummy method and a Dummy Pool utilizing the new natives. This version by default will not let missiles clip through terrain.
Code formatting and cleaning.
(v2.0)
System ported to GUI!
Implemented ways to enumerate missiles (Missile Groups)
New method: pause. When called pauses or unpauses the missile
2 new events: onPause and onResume
3 new members: roll, type and paused
Added the attach and detach methods to the LUA version
Fixed a bug on the collideZ
Fixed a bug when deflecting missiles
Refactored code to be more readable and easy to maintain
(v2.1)
Removed the usage of a post 1.30 native being used in the 1.30 version of the system. Now the 1.30- version should work for patches below that
Fixed a bug in the LUA GUI version for the onPause and the onRemove events
Added an alternative method of setting up events for the GUI version. It's more compact, you can set up all events you want inside only 1 trigger (See the Trigger Preview for examples on how to do it)
(v2.2)
Adjusted the initial position of the missile in the versions that use the dummy method.
(v2.3)
2 new events:
onCliff -> Run whenever the missiles collides with a cliff wall and it's height is greater than the current missile height
onTileset -> Run whenever the missile changes terrain types
4 new members
nextX -> The next missile x value
nextY -> The next missile y value
nextZ -> The next missile z value
tileset -> the current terrain type under the missile
Fixed the missile movement on higher ground levels
Fixed the movement of missiles when going over terrain/cliffs for the dummy versions
Separated the GUI version into vJASS and LUA implementations. For those who want to choose between them.
(v2.4)
Missiles can now grant vision using the new member "vision"
vJASS:
// To set (The missile must have a source or a owner)
yourMissile.vision = value
// To get
var = yourMissile.vision
Lua:
-- To set (The missile must have a source or a owner)
yourMissile:vision(value)
-- To get
var = yoruMissile.Vision
Example
Actions
-- Set the MissileVision variable before running the MissileCreate trigger ou at any event trigger (The missile must have a source or a owner) --
Set VariableSet MissileSource = (Triggering unit)
Set VariableSet MissileVision = 800.00
Creates the missile
Trigger - Run MissileCreate <gen> (ignoring conditions)
New required library: Alloc
Fixed a few bugs in the GUI version
(v2.5)
Missiles can now be paused within the onFinish event.
Removed the deflectZ method, now the deflect method expects x, y and z parameters
New method deflectTarget deflects the missile to a unit
New GUI variable MissileData can be used to store information as needed (integer type)
version 1.31+ non dummy only changes:
4 new method operator (operators in vJASS, functions in Lua)
yourMissile.timeScale => changes the time scale of the effect model (animation speed)
yourMissile.alpha => changes the alpha value of the effect model (transparency)
yourMissile.playerColor => changes the player color of the effect model
yourMissile.animation => changes the animation type used by the effect model
1 new method
yourMissile.color(integer, integer, integer) => changes the effect model color (vJASS)
yourMissile:color(integer, integer, integer) => changes the effect model color (Lua)
vJASS:
// To set
yourMissile.timeScale = 3.
yourMissile.alpha = 128
yourMissile.playerColor = GetPlayerId(GetOwningPlayer(unit))
yourMisisle.animation = 3 // ConvertAnimType(3) under the hood
// To get
variable = yourMissile.timeScale
variable = yourMissile.alpha
variable = yourMissile.playerColor
variable = yourMisisle.animation
Lua:
-- To set
yourMissile:timeScale(3.)
yourMissile:alpha(128)
yourMissile:playerColor(GetPlayerId(GetOwningPlayer(unit)))
yourMisisle:animation(3) -- ConvertAnimType(3) under the hood
-- To get
variable = yourMissile.TimeScale
variable = yourMissile.Alpha
variable = yourMissile.playerColor
variable = yourMisisle.Animation
GUIExamle
Actions
Set VariableSet MissileAnimation = 5
Set VariableSet MissileTimeScale = 3.00
Set VariableSet MissilePlayerColor = 3
Set VariableSet MissileAlpha = 128
Trigger - Run MissileCreate <gen> (ignoring conditions)
-------- CHANGING THE COLOR. MUST BE DONE AFTER THE MISSILE IS CREATED (1.31+ NON DUMMY VERSION ONLY) --------
Set VariableSet MissileRed = 123
Set VariableSet MissileGreen = 67
Set VariableSet MissileBlue = 32
Trigger - Run MissileColor <gen> (ignoring conditions)
(v2.6)
Fixed a bug when pausing missiles inside an onFinish event.
(v2.7)
Minor improvements.
(v2.8)
Fixed a bug in the deflect method when the onTerrain event is declared.
Fixed a bug in the flushAll method in the LUA version.
Just a heads up, I used the Missiles library for 1.31+ and it doesn't compile right away on 1.31.1 World Editor, JassHelper complains: View attachment 394509
I took a look at both Reforged and 1.31.1 common.j and JassHelper is right, 1.31.1 lacks BlzSetUnitFacingEx().
It compiles cleanly after changing it to SetUnitFacing() btw.
Weird. I could swear that this function is present in the game since 1.29, but who knows. Are you using the Missiles or Missiles Dummy from the 1.31 folder?
Weird. I could swear that this function is present in the game since 1.29, but who knows. Are you using the Missiles or Missiles Dummy from the 1.31 folder?
I took Missiles, these are the libraries I moved over from your test map to mine, BlzSetUnitFacingEx()has been the only issue so far, the common.j files I checked are from my two copies of 1.31 and Reforged and those are the ones used by JassHelper while compiling I think, anyway:
These are the builds of the 2 world editors I'm using atm, sad part is they don't communicate at all so everything has to be moved over by hand.
What's the deal with BlzSetUnitFacingEx() anyway? What's the difference between that and SetUnitFacing()?
I took Missiles, these are the libraries I moved over from your test map to mine, BlzSetUnitFacingEx()has been the only issue so far, the common.j files I checked are from my two copies of 1.31 and Reforged and those are the ones used by JassHelper while compiling I think, anyway:
Oh, no no, you copied everything. You only need MissileEffect, MissileUtils and only one of the Missiles from the 1.30- or 1.31+ folders. Since you are using 1.31+ you will only need The Missiles, so the other ones with the red X you can delete.
That screenshot is from your own testmap in Reforged World Editor, there's a red mark right of the ones I moved over, I moved over exactly the ones you said + dependencies I didn't have (we use the exact same TimerUtils btw). I can read vJass totally fine don't worry I've done nothing wrong on that part.
...I'm bad with marking stuff I guess
These are all the systems in my map right now, excluding libraries that have functionality unique to my stuff, in 1.31 World Editor, the only actual notable change other than BlzSetUnitFacingEx() is I changed the rawcode of your dummy in Missiles because I had to re-do your dummy object data due to the 2 world editors not communicating etc.
Ok, I finally gave this system a go after looking at a bunch of examples from your testmap and I can say you're right, it's pretty easy to set missiles up and configure them, but there's a couple of things that leave me a bit confused:
During missile creation you need the source x,y and z and then the destination x,y and z, the first 3 are obviously necessary but at first glance I don't see much point to the destination coordinates if, for instance, one makes a missile with a target, which would home in on that. Are those needed to actually fire the missiles, like, when they are created they start heading toward the destination and then the system adjusts the trajectory so the missile starts following the target? If that's not the case wouldn't it be better to let the user create the missile with just the origin coordinates and then provide toX, toY and toZ as members that can be optionally declared like arc, scale etc.?
While I was looking at your code I noticed you used a certain system I can't recall atm (don't wanna open Reforged WE again just for that ngl) to declare the events that spawn the missiles etc. Now, while I do understand you're comfortable writing spells like that and it looks neat and all, consider that it is a testmap meant to show people how your system works, personally I think that not going for a more standard syntax (stuff like TriggerRegisterAnyUnitEventBJ() etc.) hurts readability and could be a source of confusion. (SmitingDevil's post below cleared this up for me)
Also, while looking at the documentation on this thread I noticed that you write this about the target member: target -> The target unit for the missile. If set the missile will be roaming (read and write)
I assume that by "roaming" you actually mean "homing", right?
These are overall small gripes, system's good, 5/5 would copy-paste from Reforged WE to Notepad++ to 1.31.1 WE again.
EDIT: I haven't actually checked if you already addressed some of these things in this thread, if you already did my bad.
Would like to ask is it alright to replace the damage instance used here with bribe's damage engine? I don't get any errors when saving the map, so there's that. And cant have em together cause of redeclared damage events when I tried saving the map.
It's cause the damage instance doesn't seem to support GUI while the damage engine does.
Well, Michael, that method of registering events has been around for so long that you could practically say it is the norm. Besides, if we were to compare
JASS:
static method onCast takes nothing returns nothing
// No need to check for id
endmethod
call RegisterSpellEffectEvent('A002', function thistype.onCast)
with
JASS:
function OnCast takes nothing returns nothing
if GetSpellAbilityId() == 'A002' then
// Do Action
endif
endfunction
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction(t, function OnCast)
I find the former more readable. However, that might be because I am used to it. Then again, the one liner has all the things that is essential, the ability and its function. I don't need to know about triggers or player unit registration.
I guess it makes sense, I've been out of the loop for so much time people have made new systems that get used to simplify stuff etc.
Sure, it's readable and all but it's the first time I've ever saw that tbh. As I said, it's no biggie.
I'm currently way more bothered by the fact opening the Reforged WE this time bricked my 1.31.1 install and no amount of deleting system register keys is bringing it back.
EDIT: in case anybody was wondering, it works again now, fortunately.
During missile creation you need the source x,y and z and then the destination x,y and z, the first 3 are obviously necessary but at first glance I don't see much point to the destination coordinates if, for instance, one makes a missile with a target, which would home in on that. Are those needed to actually fire the missiles, like, when they are created they start heading toward the destination and then the system adjusts the trajectory so the missile starts following the target? If that's not the case wouldn't it be better to let the user create the missile with just the origin coordinates and then provide toX, toY and toZ as members that can be optionally declared like arc, scale etc.?
Destination x, y and z are important for a number of things that are not obvious. First these coordinates are used when a missile is created to create a Coordinate structure that will hold important information like slope, alpha angle, distance between the 2 points, etc.. and those information are used by the system to do other stuff, like correctly orienting the missile right after its creation. Another point is inheritance. The way i created the system (extending the Missiles struct) there can only be one create() method so to keep things simple i decided that taking initial and final coordinates was the best way to go. When the target member is set then the system will automatically update the coordinate struture i mentioned before, making the missile home to its target, but the final coord still necessary internaly.
Also, while looking at the documentation on this thread I noticed that you write this about the target member: target -> The target unit for the missile. If set the missile will be roaming (read and write)
I assume that by "roaming" you actually mean "homing", right?
Would like to ask is it alright to replace the damage instance used here with bribe's damage engine? I don't get any errors when saving the map, so there's that. And cant have em together cause of redeclared damage events when I tried saving the map.
It's cause the damage instance doesn't seem to support GUI while the damage engine does.
I am struggling to make a spell, and I wondered whether someone can help me. I have a spell, in which the caster throws a bomb, and then it exploded in two seconds. To do this, I pause the missile in onFinish and start a timer that terminates the missile in two seconds. Now, I want to make another spell (missile) that can drag the bomb with it (move it in the same direction). The problem is that the bomb does not move, since it is paused. Unpausing the bomb will make it explode. How can I do it?
I am struggling to make a spell, and I wondered whether someone can help me. I have a spell, in which the caster throws a bomb, and then it exploded in two seconds. To do this, I pause the missile in onFinish and start a timer that terminates the missile in two seconds. Now, I want to make another spell (missile) that can drag the bomb with it (move it in the same direction). The problem is that the bomb does not move, since it is paused. Unpausing the bomb will make it explode. How can I do it?
Before unpausing u need to deflect the missile using the deflect(x, y, z) or deflectTarget(unit). This 2 methods will unflag the missile internally as finished allowing the missile to do it's thing again.
You can see an example of me doing something similar in my Jaina Hero Concept. The Living Tide ability is a missile that keeps following the player cursor and when the missile reach the cursor it is constantly pausing and unpausing.
Before unpausing u need to deflect the missile using the deflect(x, y, z) or deflectTarget(unit). This 2 methods will unflag the missile internally as finished allowing the missile to do it's thing again.
You can see an example of me doing something similar in my Jaina Hero Concept. The Living Tide ability is a missile that keeps following the player cursor and when the missile reach the cursor it is constantly pausing and unpausing.
Not finishing in onFinish makes the missile never leave the process queue, so yeah it will break things if you dont know exactly what you are doing. There are reasons for it to be like this (deflection, pausing, resuming, etc...)
Not finishing in onFinish makes the missile never leave the process queue, so yeah it will break things if you dont know exactly what you are doing. There are reasons for it to be like this (deflection, pausing, resuming, etc...)
It would be cool if you added:
1) Rect group selection
2) Functionality to teleport the missle. For example, to create a portal, which teleports the missile from one location to another
Edit: @chopinski, I made this bomb spell with arc, and it is supposed to land at Z 0, but it doesn't. I think it might be a problem with the system?
JASS:
library Bomb /*
[I]/ uses /[/I]
[I]/ SpellFramework /[/I]
*/ BaseFunctions
private module SpellConfiguration
static constant integer SPELL_ABILITY_ID = 'A027'
static constant integer SPELL_EVENT_TYPE = EVENT_SPELL_EFFECT
static constant real SPELL_PERIOD = 1.0
//Models and Effects
static constant string BOMB_MODEL_ID = "Abilities\\Spells\\Other\\StrongDrink\\BrewmasterMissile.mdl"
static constant string EXPLOSION_EFFECT_ID = "Abilities\\Spells\\Human\\ReviveHuman\\ReviveHuman.mdl"
static constant string AOE_CIRCLE = "AoE_1.mdl"
//Params
static constant real BASE_Z = 130
static constant real ANGLE_ADJUSTMENT = -50
static constant real CAST_DIST = 26
static constant real RANGE = 1000
static constant real AOE = 200
static constant real SPEED = 1100
static constant real DETONATION_TIME = 3.0
//Damage Type
static constant attacktype ATTACK_TYPE = ATTACK_TYPE_MAGIC
static constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_MAGIC
static constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS
static method Dmg takes unit caster returns real
return 100.0 + 0.1 * GetHeroStr(caster, true)
endmethod
static method Targets takes unit caster, unit target returns boolean
return BaseBool(target) and/*
*/ IsUnitEnemy(target, GetOwningPlayer(caster))
endmethod
endmodule
globals
private group enemies = CreateGroup()
endglobals
struct Bomb extends Missiles
implement SpellConfiguration
private timer timer
private unit u
private effect aoeCircle
private boolean landed
method onPeriod takes nothing returns boolean
local real effectX
local real effectY
debug call BJDebugMsg("Bomb: Z " + R2S(z))
if landed then
set effectX = GetEffectX(aoeCircle)
set effectY = GetEffectY(aoeCircle)
if effectX != nextX or effectY != nextY then
call SetEffectX(aoeCircle, nextX)
call SetEffectY(aoeCircle, nextY)
endif
endif
return false
endmethod
method onFinish takes nothing returns boolean
if not this.landed then
set timer = NewTimerEx(this)
call TimerStart(this.timer, DETONATION_TIME, false, function thistype.onExpire)
call pause(true)
set this.aoeCircle = AddSpecialEffect(AOE_CIRCLE, x, y)
set this.landed = true
call SetEffectColourEx(this.aoeCircle, 255, 50, 50, 0)
debug call BJDebugMsg("Bomb: onFinish")
return false
endif
call pause(true)
return false
endmethod
private static method onExpire takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
call DestroyEffect(AddSpecialEffect(EXPLOSION_EFFECT_ID, x, y))
call GroupEnumUnitsInRange(enemies, x, y, AOE, null)
loop
set u = FirstOfGroup(enemies)
exitwhen u == null
if Targets(source, u) then
call UnitDamageTarget(source, u, Dmg(source), false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, null)
debug call BJDebugMsg("Bomb: DMG to " + GetUnitName(u))
endif
call GroupRemoveUnit(enemies, u)
endloop
call pause(false)
call DestroyEffect(this.aoeCircle)
call ShowEffect(this.aoeCircle, false)
set this.aoeCircle = null
call terminate()
debug call BJDebugMsg("Bomb: Boom")
call ReleaseTimer(this.timer)
set this.timer = null
endmethod
implement SpellConfiguration
private static method onSpellStart takes nothing returns thistype
local thistype node = GetUnitId(Spell.triggerUnit)
local real cX = GetUnitX(Spell.triggerUnit)
local real cY = GetUnitY(Spell.triggerUnit)
local real angle = GetAngle(cX, Spell.targetX, cY, Spell.targetY)
local real createAngle = angle + ANGLE_ADJUSTMENT
local real bombX = GetXWithOffset(cX, CAST_DIST, angle)
local real bombY = GetYWithOffset(cY, CAST_DIST, angle)
local real bombZ = GetUnitFlyHeight(Spell.triggerUnit) + BASE_Z
local thistype this = thistype.create(bombX, bombY , bombZ , Spell.targetX, Spell.targetY, 0)
set speed = SPEED
set model = BOMB_MODEL_ID
set source = Spell.triggerUnit
set collideZ = false
set collision = AOE
set damage = Dmg(Spell.triggerUnit)
set owner = Spell.triggerPlayer
set arc = 60
set landed = false
set type = 50
call launch()
return node
endmethod
implement SpellEventEx
endstruct
endlibrary
[code]
vjass version should change
private interface MissileEvents
to
interface MissileEvents
so that we can do something like:
JASS:
private struct B extends Missiles
method onFinish takes nothing returns boolean
call BJDebugMsg(" thistype ")
return false
endmethod
endstruct
private struct A extends Missiles
method onHit takes unit hit returns boolean
call BJDebugMsg(" thistype ")
//set si__Missiles__MissileEvents_type[this] = B.typeid // if interface have private keyword, this has 50% chance cause save fail
set si__MissileEvents_type[this] = B.typeid // remove private keyword map can always be save
return false
endmethod
endstruct
local A mis = A.create( cx, cy, cz, tx, ty, tz)
.....
call mis.launch()
I have a feature request / how to: Make missiles fly "erratically" while still seeking a target unit/point intstead just in a straight line or simple curve.
This is sort of a 2d example of what I mean:
I have a feature request / how to: Make missiles fly "erratically" while still seeking a target unit/point intstead just in a straight line or simple curve.
This is sort of a 2d example of what I mean:
I feel like the "onDestructable" function is wierd. The collision size is just the projectile collision size, meaning that a tree, that is around 128 x 128 units big, is very hard to hit with a projectile with a fairly normal collision size (for example, 28), because the projectile only check the rect +/- its own collision size for destructibles.
Even hitting a barrel is harder than it should be. They are 64x64, so with a 28 projectile with speed around 1500, you'll have a semi-hard time hitting that barrel! (well... Harder than expected imo).
I noticed that the Warcraft 3 API for destructibles is really bad, so we cannot detect sizes etc. but I can work around it somewhat by setting I.E. hp to its collision size or something, but I'll still need to check a size bigger than the collision size then. Or if we can increase collision size for destructibles or something.
I'm currently trying to make a map that heavily relies on this system, but I can shoot through walls right now...
Image to show what I mean by that.
Edit: Adding +32 to collision detection to destructables (I.E. enough to make "barrel" hittable by the edge of projectile) made a huge difference!
Weird, are you using the GUI version of the system? If yes you could be hitting the OP Limit for a trigger, since the crash seems to happens when there are a shit ton of missiles at a given moment. Have you tried using the Jass ou Lua version to see if the problem persists?
Post your code so i can take a look when i have some free time in the future.
Weird, are you using the GUI version of the system? If yes you could be hitting the OP Limit for a trigger, since the crash seems to happens when there are a shit ton of missiles at a given moment. Have you tried using the Jass ou Lua version to see if the problem persists?
Post your code so i can take a look when i have some free time in the future.
Code used is what's already there, yup the gui version...
edit: Testing out the sweet spot and checked around 10, is it normal for projectiles to lose pretty much all accuracy? When handling under that neat time method you discovered, the rocks end while mid-air and phoenixes don't return to the blood mage/caster but instead end way off course.
Hello, I just saw this interesting resource, but I wanted to ask how I can import it? I am using the reforged and I am interested with the JASS GUI
Thank you
Hello, I just saw this interesting resource, but I wanted to ask how I can import it? I am using the reforged and I am interested with the JASS GUI
Thank you
1. download the map
2. open the version you want (Missiles[GUI][vJASS].w3x)
3. Ensure that you have "File -> Preferences -> General (tab) -> "Automatically create unknown variables while pasting trigger data"-checkbox checked
4. Copy "Missile" and "Library" folder. (there are several items in library that you don't really need, so it is possible to delete some of them)
5. Open your map
6. paste
If you want the "samples" you'll need to copy them too.
Edit: I think you can only copy one folder at the time, so might need to Window -> Missiles[GUI][vJASS].w3x, and Window -> YOUR MAP for each folder
1. download the map
2. open the version you want (Missiles[GUI][vJASS].w3x)
3. Ensure that you have "File -> Preferences -> General (tab) -> "Automatically create unknown variables while pasting trigger data"-checkbox checked
4. Copy "Missile" and "Library" folder. (there are several items in library that you don't really need, so it is possible to delete some of them)
5. Open your map
6. paste
If you want the "samples" you'll need to copy them too.
Edit: I think you can only copy one folder at the time, so might need to Window -> Missiles[GUI][vJASS].w3x, and Window -> YOUR MAP for each folder
1. download the map
2. open the version you want (Missiles[GUI][vJASS].w3x)
3. Ensure that you have "File -> Preferences -> General (tab) -> "Automatically create unknown variables while pasting trigger data"-checkbox checked
4. Copy "Missile" and "Library" folder. (there are several items in library that you don't really need, so it is possible to delete some of them)
5. Open your map
6. paste
If you want the "samples" you'll need to copy them too.
Edit: I think you can only copy one folder at the time, so might need to Window -> Missiles[GUI][vJASS].w3x, and Window -> YOUR MAP for each folder
Hi, I did what you said, but I got an error regarding the Damage library (I use damage engine) so I deleted it, then I got this new error and I don't know what to do. Gyazo
Hi, I did what you said, but I got an error regarding the Damage library (I use damage engine) so I deleted it, then I got this new error and I don't know what to do. Gyazo
I have an idea so you would want to try it: @chopinski
Imagine those missiles are replaced by bird-like missiles with many colors (Green - Keeper of the grove, Yellow - Sorceress, Cyan - Priest, Turqouise - Mur'gul Blood-Gill, Violet - Satyr Shadowdancer / Black Keeper).
I have an idea so you would want to try it: @chopinski
Imagine those missiles are replaced by bird-like missiles with many colors (Green - Keeper of the grove, Yellow - Sorceress, Cyan - Priest, Turqouise - Mur'gul Blood-Gill, Violet - Satyr Shadowdancer / Black Keeper).
This is a missile system designed to give the user a great deal of control over what the missiles can do, so it's not like you can't do what you suggested. As far as I can tell this system allows the user to adjust basically every property of a missile -> model, scale, color, etc.
In other words, you can try to do this yourself and it shouldn't be too difficult. The missile's model uses Strings so you could have an Array of Strings that represent the different missile model paths (ie -> Set Variable MyMissileArt[1] = units/human/sorceress/missile) and as you create your missiles and choose their model you simply reference one of these Strings at random or go in some kind of order and choose the next one in line. The end result should be something like you described.
Now that there is a gui interface and finding that it is mostly user error up to a point, this blows everything else out of the abyss... Thanks for that, have been really enjoying this. Never thought we'd have a system like this but have always wanted to see something like this, I could never find the motivation to work up to learning the math required for processing instances up to a limit then speeding other instances up to make up for loss processing, after some more testing I found that the lost accuracy isn't too far off to begin with so far.
Only other system of notice I consider since this is the new king, would be Master Projectile System V1.02b which ironically everyone either forgot about or doesn't know of. Otherwise only this is worth using over everything else, been working on converting this system over to legacy format since the demo maps are reforged only. I noticed if one knows what they are doing, they can skip the trigger runs and grab the function calling... Are there other options of improved efficiently besides lua?
I'm afraid, I am too stupid for this system. I tried testing it a little to see what it's capable of, but all I manage to do is creating a special effect that doesn't move, no matter what I seem to do. I'm certain everything is imported correctly since the effect is created, but it just doesn't want to move, am I doing something wrong? All the values below are variables I have declared further above.
I'm afraid, I am too stupid for this system. I tried testing it a little to see what it's capable of, but all I manage to do is creating a special effect that doesn't move, no matter what I seem to do. I'm certain everything is imported correctly since the effect is created, but it just doesn't want to move, am I doing something wrong? All the values below are variables I have declared further above.
What do you mean, thats literally everything. I just tried to use your system the first time with something small (fireball). "target" is = GetSpellTargetUnit() and "uCast" is the caster of the spell (GetTriggerUnit()). I've been creating spells for the past year or so, but I'm unable to get your system to work for some reason. Also have MissileEffect and even MissileUtils imported, so no idea what is wrong. I'm using a VScode setup however and I have the files required in this order: MisileEffect, Missiles, MissilesUtil. Because my setup parses everything into one file on map start in the specified order. My map is a little to big to force you to go trough everything in order to find the problem. I have quite a few files and a unique setup.
It doesn't work because you're doing this on lua root, from what I can tell based on what you showed us.
It should be something like this:
Lua:
do
local function MyActions()
ball = Missiles:create(GetUnitX(uCast) + VecX(75, GetUnitFacing(uCast)), GetUnitY(uCast) + VecY(75, GetUnitFacing(uCast)), 50, GetUnitX(target), GetUnitY(target), 50)
ball.target = target
ball:model("NCOW_SFX_Housenka.mdx")
ball:scale(2)
ball:speed(500)
ball:arc(45)
ball:curve(GetRandomReal(-10, 10))
ball:launch()
end
local oldBliz = InitBlizzard
function InitBlizzard()
oldBliz()
local t = CreateTrigger()
TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
TriggerAddAction(t, MyActions)
end
end
local oldBliz = InitBlizzard is a hook to make the set up on initlization. Chopinski uses his own init script, you can find Bribe's here [Lua] - Total Initialization
Also, you have no events, so GetSpellTargetUnit() will be nil. Nor I believe you when you say this is everything regarding the scope of this script.
No, as I tried to explain before, all the events, variables etc are set up properly, I just didn't go trough the hassle to post everything here you can believe me that there is infact a unit variable that holds the caster and a target variable that holds the target, as well as an event that fires off on cast. As I said I have a little over a year of experience with coding. I'm using a VsCode extension warcraft-vscode, that lets me set up a working environment in VSCode and which does the init stuff for me if I call the init function in main.lua. Also every do end is automatically executed on map start, which I already saw happen many times with other parts of my own code.
EDIT: I've got it to works now. Can't really say what was it tho.
Well, technically most things are "run" on Lua root, for a lack of a better word. However, there are a list of functions that happen always in a specific order, like "config" function being executed when you enter a game in lobby. "main" on loading screen, etc. In a nutshell, Bribe's Initialization relies on hooking these functions with user functions.
Usually people use InitBlizzard or MarkGameStarted like I did if they just want a very simple initialization, which isn't really an API nor recommended.
Just replace the Missiles, MissileUtils and MissileEffect libraries and make sure you match the raw code of the dummy unit inside the Missiles library.
I have to changed it recently to a manually acquired "travel" distance. However, in my test, it showed 0 difference between the missile current location and the location it had a second ago or rather it was so small that there was no discernible difference. Visually, it is clearly moving.
EDIT: did a counter. and it stayed at 1, it appears either the periodic event is resetting all variables. Or am I utilizing the variables incorrectly?
Does deflecting the missile create a new missile instance?
JASS:
library WRSMissiles requires WithinDistance
struct WRSMissile extends Missiles
public unit tar
private unit hit
public integer func
public real dist
public real test
public integer test2
public method onPeriod takes nothing returns boolean
local MissData d = Miss['p000']
local real x = GetUnitX(.tar)
local real y = GetUnitY(.tar)
//distance
local real x3 = (.x - .origin.x) * (.x - .origin.x)
local real y3 = (.y - .origin.y) * (.y - .origin.y)
set y3 = y3 + x3
if .speed != BlzGetUnitWeaponRealField(.source,UNIT_WEAPON_RF_ATTACK_PROJECTILE_SPEED,0) then
set .speed = BlzGetUnitWeaponRealField(.source,UNIT_WEAPON_RF_ATTACK_PROJECTILE_SPEED,0)
endif
set .test2 = .test2 + 1
if .test2 == 32 then
call DisplayTextToPlayer(Player(0),0,0,"Difference:" + R2S(y3 - .test))
call DisplayTextToPlayer(Player(0),0,0,"Distance:" + R2S(y3))
set .test2 = 0
endif
set .test = y3
if y3 >= 2500 and .alpha == 0 then
set .alpha = 255
set .model = d.model
endif
if y3 > .dist then
set .tar = null
set .hit = null
return true
endif
if WithinDistance(.x,.y,x,y,75) == false then
call .deflect(x,y,0)
else
set .hit = .tar
call GetMissileFunction()
call UnitDamageTarget(.source,.tar,.damage,true,false,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
set .tar = null
return true
endif
return false
endmethod
public method onHit takes unit hit returns boolean
local real x = GetUnitX(hit)
local real y = GetUnitY(hit)
if hit != .source and GetUnitTypeId(hit) != 'H03I' and GetUnitTypeId(hit) != 'h046' and GetUnitTypeId(hit) != 'h046' and UnitAlive(hit) and /*
*/ GetUnitAbilityLevel(hit,'A078') <= 0 and WithinDistance(.x,.y,x,y,10) then
set .hit = hit
call UnitDamageTarget(.source,hit,.damage,true,false,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
call GetMissileFunction()
else
call .flush(hit)
endif
return false
endmethod
public method onTerrain takes nothing returns boolean
return false
endmethod
public static method ReAddAbility takes nothing returns nothing
local timer ti = GetExpiredTimer()
local integer t = GetUnitTypeId(PsyI.unit[0])
local MissData d = Miss[t]
call UnitAddAbility(PsyI.unit[0],d.abil2)
call ReleaseTimer(ti)
set ti = null
endmethod
endstruct
endlibrary
//The code that starts the missile
[CODE=JASS]
public function MissileStart takes nothing returns nothing
local real d = EDamage
local unit tar = target
local unit sor = source
local real x = GetUnitX(sor)
local real y = GetUnitY(sor)
local real x2 = GetUnitX(tar)
local real y2 = GetUnitY(tar)
local real x3 = IncAngleDistance(x,y,x2,y2,10000,true)
local real y3 = IncAngleDistance(x,y,x2,y2,10000,false)
local integer t = GetUnitTypeId(sor)
local MissData mi = Miss[t]
local WRSMissile m = WRSMissile.create(x,y,100,x3,y3,100)
set m.source = sor
set m.tar = tar
set m.damage = d
set m.speed = BlzGetUnitWeaponRealField(sor,UNIT_WEAPON_RF_ATTACK_PROJECTILE_SPEED,0)
set m.scale = mi.size
set m.duration = mi.dur
set m.model = null
set m.alpha = 0
set m.func = PsyI[-25]
set m.dist = (BlzGetUnitWeaponRealField(sor,UNIT_WEAPON_RF_ATTACK_RANGE ,0) + 700) * (BlzGetUnitWeaponRealField(sor,UNIT_WEAPON_RF_ATTACK_RANGE ,0) + 700)
// set m.arc = BlzGetUnitWeaponRealField(udg_DamageEventSource,UNIT_WEAPON_RF_ATTACK_PROJECTILE_ARC,0)
set m.data = t
set m.collideZ = false
set m.collision = 200
call m.launch()
set tar = null
set sor = null
endfunction
Loved this work, but is there a 1.31 version that can be easily imported on? I really don't wanna go back and forth with Reforged and 1.31 editors if I can avert it.
Loved this work, but is there a 1.31 version that can be easily imported on? I really don't wanna go back and forth with Reforged and 1.31 editors if I can avert it.
This system is so cool i really like it and want to use it for my map
but i want to create a ability like shotgun ( something like that ) that you click a point ( not a target ) and 6 or 8 (amount dosent matter ) bullet randomly shot and dont have any target just move untill colide with something or get to its point but i cant seem to create it ( i try to create it with gui ) i tried offset but it gets bug when you cast it near your hero ( the bullet with launch behind your hero ) is there anyway to create this without this bugs?
EDIT : nvm manage to create something good after 5 hours nice system btw
Lua version requires users to copy the onInit script, found in Libraries -> Utilities. Missile script uses it, so when a user doesn't have it, he will be kicked to the main menu when testing through the editor.
You should also warn that users can have their own initialization method and possibly replace the onInit line in the code. [Lua] - Total Initialization became quite standard these days.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.