• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece!🔗 Click here to enter!

Terrain Deformations through abilities and triggers

Status
Not open for further replies.
Level 39
Joined
Feb 27, 2007
Messages
5,031
I'm trying to make a quick, deep terrain deformation from 1 location to another, but I don't really understand what some of the arguments do in the natives, and the BJ terrain deformation functions don't make it any clearer. They are below:
JASS:
//Natives
//===========================================================================
native TerrainDeformCrater          takes real x, real y, real radius, real depth, integer duration, boolean permanent returns terraindeformation
native TerrainDeformRipple          takes real x, real y, real radius, real depth, integer duration, integer count, real spaceWaves, real timeWaves, real radiusStartPct, boolean limitNeg returns terraindeformation
native TerrainDeformWave            takes real x, real y, real dirX, real dirY, real distance, real speed, real radius, real depth, integer trailTime, integer count returns terraindeformation
native TerrainDeformRandom          takes real x, real y, real radius, real minDelta, real maxDelta, integer duration, integer updateInterval returns terraindeformation
native TerrainDeformStop            takes terraindeformation deformation, integer duration returns nothing
native TerrainDeformStopAll         takes nothing returns nothing


//BJs
//===========================================================================
function TerrainDeformationCraterBJ takes real duration, boolean permanent, location where, real radius, real depth returns terraindeformation
    set bj_lastCreatedTerrainDeformation = TerrainDeformCrater(GetLocationX(where), GetLocationY(where), radius, depth, R2I(duration * 1000), permanent)
    return bj_lastCreatedTerrainDeformation
endfunction

//===========================================================================
function TerrainDeformationRippleBJ takes real duration, boolean limitNeg, location where, real startRadius, real endRadius, real depth, real wavePeriod, real waveWidth returns terraindeformation
    local real spaceWave
    local real timeWave
    local real radiusRatio

    if (endRadius <= 0 or waveWidth <= 0 or wavePeriod <= 0) then
        return null
    endif

    set timeWave = 2.0 * duration / wavePeriod
    set spaceWave = 2.0 * endRadius / waveWidth
    set radiusRatio = startRadius / endRadius

    set bj_lastCreatedTerrainDeformation = TerrainDeformRipple(GetLocationX(where), GetLocationY(where), endRadius, depth, R2I(duration * 1000), 1, spaceWave, timeWave, radiusRatio, limitNeg)
    return bj_lastCreatedTerrainDeformation
endfunction

//===========================================================================
function TerrainDeformationWaveBJ takes real duration, location source, location target, real radius, real depth, real trailDelay returns terraindeformation
    local real distance
    local real dirX
    local real dirY
    local real speed

    set distance = DistanceBetweenPoints(source, target)
    if (distance == 0 or duration <= 0) then
        return null
    endif

    set dirX = (GetLocationX(target) - GetLocationX(source)) / distance
    set dirY = (GetLocationY(target) - GetLocationY(source)) / distance
    set speed = distance / duration

    set bj_lastCreatedTerrainDeformation = TerrainDeformWave(GetLocationX(source), GetLocationY(source), dirX, dirY, distance, speed, radius, depth, R2I(trailDelay * 1000), 1)
    return bj_lastCreatedTerrainDeformation
endfunction

//===========================================================================
function TerrainDeformationRandomBJ takes real duration, location where, real radius, real minDelta, real maxDelta, real updateInterval returns terraindeformation
    set bj_lastCreatedTerrainDeformation = TerrainDeformRandom(GetLocationX(where), GetLocationY(where), radius, minDelta, maxDelta, R2I(duration * 1000), R2I(updateInterval * 1000))
    return bj_lastCreatedTerrainDeformation
endfunction

//===========================================================================
function TerrainDeformationStopBJ takes terraindeformation deformation, real duration returns nothing
    call TerrainDeformStop(deformation, R2I(duration * 1000))
endfunction

//===========================================================================
function GetLastCreatedTerrainDeformation takes nothing returns terraindeformation
    return bj_lastCreatedTerrainDeformation
endfunction
So first off, if you've used these before and could explain, for example:
  • Why the fuck are durations in integers? I realize its in MS but... why?
  • spaceWaves/timeWaves?
  • What exactly are dirx and diry for? When TerrainDeformationWaveBJ uses them they're effectively Cos() and Sin() of the angle between start/end points, but I tried putting that in to my own call and it went all wonky.
  • What does integer count do in TerrainDeformWave?
or just link me to a tutorial (googled but I couldn't find one) about all these different functions I would be greatly appreciative.


Now, I'm presuming I don't actually want to use these because I've read about their ability to cause desyncs with GetLocationZ(), but if I'm not gonna trigger them then what other options do I have? This thread (click link and search for "deform") seems to imply that I could do it by casting a dummy Shockwave/Thunderclap/War Stomp ability, but it looks like I can only modify two data fields and neither of those will change the radius of the deformation.
Code:
Data - Terrain Deformation Amplitude
Data - Terrain Deformation Duration (ms)


Anyone have experience with deformations? I want to create a thin, deep deformation from point 1 to point 2 that travels relatively quickly. And I want to avoid casting a dummy War Stomp ability 100+ times if I can avoid it.
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
In actual programming languages, they often use int milliseconds, for resolution and precision probably.
dirX/Y are the components of the direction vector, so only the ratio and signs matter. I do not know why they did not take an angle there, maybe to increase precision as well, so they could pinpoint a source and target location like they did in the BJ.
count is the amount of waves appearing in succession.

The problem of GetLocationZ in relation to terrain deformations is that the movements are only visible to players with view of the source point. Also, I guess the exact transition could alter since it's only for showing -> subject to rendering process. It's the same with the ability-based terrain deformations. The permanent end result of TerrainDeformCrater in contrast is visible to everyone and safe. It's a question of what and how you use it. How do you want GetLocationZ to behave when there is a terrain deformation? Maybe you could only use insta-permanent craters or cache GetLocationZ values of the unaltered terrain. The performance drops you experience with terrain deformations are mostly due to terrain-clipped doodads being pitched and rolled.
 
Level 39
Joined
Feb 27, 2007
Messages
5,031
Guess I should have clarified that this is a temporary deformation for part of an ability-- the thin, deep deformation will be removed almost instantly. So I don't anticipate any desync problems. But to make sure I understand: if I took a blank map and made a non-permanent-crater deformation somewhere that was in FoW for Player 1 but visible to Player 2 and compared GetLocationZ(deformcenter) to a value I'd calculated on map init... for Player 1 the difference would be 0 but for Player 2 it would be nonzero? Or does it have to do with actually having the deform point in the current camera FoV?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
Why the fuck are durations in integers? I realize its in MS but... why?
Why not? A lot of timing in computers is done in integers. Everything is done with integers in StarCraft II, although in the form of fixed point fractions.

spaceWaves/timeWaves?
They are the time and space (some measurement of distance) for the waves.

What exactly are dirx and diry for? When
TerrainDeformationWaveBJ
uses them they're effectively Cos() and Sin() of the angle between start/end points, but I tried putting that in to my own call and it went all wonky.
They are a unit vector for the wave to travel at from the start location. I am guessing your mathematics must have an error, or that deformation waves are subject to rounding error of sort.

What does
integer count
do in
TerrainDeformWave
?
Either it is the number of times the wave will repeat, or it is an unused field. Try experimenting with it.

Now, I'm presuming I don't actually want to use these because I've read about their ability to cause desyncs with GetLocationZ(), but if I'm not gonna trigger them then what other options do I have? This thread (click link and search for "deform") seems to imply that I could do it by casting a dummy Shockwave/Thunderclap/War Stomp ability, but it looks like I can only modify two data fields and neither of those will change the radius of the deformation.
The problem is that GetLocationZ returns a local value. Walkable destructables not in sight will not be factored into the values returned by GetLocationZ. Different values will be returned depending on the graphic settings used by Warcraft III. Terrain deformation results depend on the setting of physics quality. Values of GetLocationZ are different between Windows and Mac clients.

It is not that terrain deformations are unsafe and break GetLocationZ, it is that GetLocationZ is unsafe and just cannot be used in a context that will alter game results. GetLocationZ can only be used for eye candy, eg for correct lightning Z or possibly the fly height of a dummy missile.

For physics systems it might be a good idea to write ones own GetLocationZ which looks up/interpolates values from some kind of hard-coded map or data structure. This way the results of everything will be synchronous across all clients.
 
Name me any other WC3 function that uses int ms instead of real s. I asked because it seems highly abnormal.

Some sound ones use them: SetSoundPlayPosition, SetSoundDuration, etc. :p

But that aside, when I had to use terrain deformations in the past, it was pretty helpful to look at the GUI triggers. Choose one of the terrain deformation actions--they usually have helpful descriptions. Then you can just convert it to custom text and look at how the BJ uses the native, e.g.
JASS:
function TerrainDeformationRippleBJ takes real duration, boolean limitNeg, location where, real startRadius, real endRadius, real depth, real wavePeriod, real waveWidth returns terraindeformation
    local real spaceWave
    local real timeWave
    local real radiusRatio

    if (endRadius <= 0 or waveWidth <= 0 or wavePeriod <= 0) then
        return null
    endif

    set timeWave = 2.0 * duration / wavePeriod
    set spaceWave = 2.0 * endRadius / waveWidth
    set radiusRatio = startRadius / endRadius

    set bj_lastCreatedTerrainDeformation = TerrainDeformRipple(GetLocationX(where), GetLocationY(where), endRadius, depth, R2I(duration * 1000), 1, spaceWave, timeWave, radiusRatio, limitNeg)
    return bj_lastCreatedTerrainDeformation
endfunction

I'd do it myself but I'm on my mac. :( I don't know of any guides on it, so best of luck!
 
Status
Not open for further replies.
Top