• Check out the results of the Techtree Contest #19!
  • 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!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • Create a void inspired texture for Warcraft 3 and enter Hive's 34th Texturing Contest: Void! Click here to enter!
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!

Dynamic terrain change

Level 2
Joined
Dec 9, 2025
Messages
2
I was playing a round-based map (a lot) and started feeling like seeing the same terrain over and over was getting kinda stale. So I thought, "Wouldn't it be cool if we got a different terrain every run? Or even better - every round?"

I took it personally and decided to figure out a way to change the terrain during runtime. I ended up developing a couple of tools (in Python) that let me build multiple terrains for the same map.

I was really happy with the result. The whole process was much smoother than I expected. I can create several terrains (one in each map) and then use the tool to “combine” them into a single map. The terrains can then be swapped via triggers. Currently it supports terrain tiles, height and doodads.

Obviously, I'm pushing the game to its limits (and maybe even a bit beyond hehe). Understandably, there are some hurdles. I was wondering if anyone knows a better way to handle this.

1. Heightmap

I am using the following native to change the terrain:
JASS:
call TerrainDeformCrater(x, y, 1, delta, 1, true)
I call this once for every vertex in the terrain on the map.
Visually, it looks great. It is completely indistinguishable from regular "terraining". However, there are two issues with this approach.

First: Camera Z-offset

Updating the terrain using the native above does not update the camera's Z-offset. If the deformation creates tall hills, the camera can even end up moving under the terrain!

This can be fixed via triggers. I found an old thread that already worked out all the math, and I used the interpolation method from that thread to manually update the camera's Z-offset. Essentially, I do this:

JASS:
private function UpdateCamera takes nothing returns nothing
    local real x = GetCameraTargetPositionX()
    local real y = GetCameraTargetPositionY()
 
    call SetCameraField(CAMERA_FIELD_ZOFFSET, GetCorrectHeight(x, y), 0.03)
endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterTimerEvent(t, 0.03, true)
    call TriggerAddAction(t, function UpdateCamera)
endfunction

Basically, I manually compute the correct Z-offset every 0.03 seconds. The calculation itself seems near-perfect. The only real issue is the 0.03-second periodic trigger. Suddenly moving the camera via the minimap can cause a very brief (just a few frames) and slightly janky camera update. Other than that, it works perfectly.


Second: Performance in classic

Reforged seems to have improved terrain handling a lot. Especially the way terrain deformations interact with doodads. On classic (1.26), however, it's very slow and causes a noticeable lag spike. Depending on the number of doodads on the map, even a single call can take quite a while. Thankfully, this isn't an issue in Reforged, and the transition is completely smooth.


2. Water​

The only native that seems to interact with water during runtime is SetWaterDeforms native, but I haven't found any practical way to use it. Since we can't directly manipulate water, we run into a few problems:

  1. Water level must remain constant - in every terrain, the water level stays the same. This is an acceptable limitation most of the time.
  2. Water transparency - Water transparency doesn't seem to respond to terrain deformations. As a result, all water appears as deep water and becomes completely opaque.
  3. Waves - Shore waves seem to be calculated at the start of the game (or in the editor). Terrain deformations don’t affect them. This isn't a huge issue, since it can be worked around.


Are there better approaches to this? Having dynamic terrain changes would add a really nice touch to the map.

EDIT: I'm aware that terrain deformations can generally cause desyncs. However, since I'm manually setting every vertex to a specific height, this shouldn't be an issue.
 
Last edited:

2. Water​

The only native that seems to interact with water during runtime is SetWaterDeforms native, but I haven't found any practical way to use it. Since we can't directly manipulate water, we run into a few problems:

  1. Water level must remain constant - in every terrain, the water level stays the same. This is an acceptable limitation most of the time.
  2. Water transparency - Water transparency doesn't seem to respond to terrain deformations. As a result, all water appears as deep water and becomes completely opaque.
  3. Waves - Shore waves seem to be calculated at the start of the game (or in the editor). Terrain deformations don’t affect them. This isn't a huge issue, since it can be worked around.

Using the assets could help Animated Fluid Planes HD
 
Back
Top