• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[General] How to make water deeper?

Status
Not open for further replies.
Level 25
Joined
Feb 2, 2006
Messages
1,689
Hey,
for a submarine map I was wondering how I could make water even deeper without using custom water texture models which are placed manually and flying units?
The deep water has a default cliff height right? Can it be changed somewhere in some constants of an SLK file for a single map?
An alternative is to make all my unit models much smaller but then maybe the water texture will look weird.

Aren't there already any popular submarine underwater maps?
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
I don't think any of the aquatic maps actually use the built in water level. zoom in under the water level - it does not look like it's underwater. the water texture is only rendered from the top. and if you want the view to just be from the top - than it doesn't matter how deep the water is, just ow much you lower the models.
 

deepstrasz

Map Reviewer
Level 69
Joined
Jun 4, 2009
Messages
18,847
Check these:
There's also an underwater map in this campaign: DREAMLORD Episode II.


Also, just searching underwater will bring useful results.

As @Ender Wiggins pointed out, there's no real underwater capability in this game since the water level cannot be raised. Might be some tricks to add/create water-like textured doodads to fill spaces with but that's about it. In that space you'd have to figure out how to restrict and make the stuff you want there move/behave.
 
Last edited:
I don't understand exactly what you are trying to achieve here? If you simply want an underwater map then just place sand tiles, underwater doodads, bubbles and so on around with a blue fog/filter and some moon rays here and there.

If you want a map with both a surface area and an underwater area then you still have several options.

  • If you want a seamless experience one option is, as you already said, by placing water doodads around and using flying units. When you transition from a surface unit to an underwater unit you just zoom in the camera and add a filter.
  • Another option that isn't fully as seamless is to transition to water like you would do with interiors and so on. Fade out/in filter and when it fades in you're underwater.


I think more information about your map is needed before I can suggest anything viable.
 
Level 23
Joined
Oct 18, 2008
Messages
937
1620303324986.png


height deformation -> water -> plateau deformation
dunno how it looks ingame or if this is what you want but it's something I guess
 
Level 25
Joined
Feb 2, 2006
Messages
1,689
thx this is really useful and is exactly what I was looking for. The other maps I tested either have only under water levels or you switch between them but they are two different levels and both are actually ground. I will try to change the unit's flying height under water, too.

With your approach I can even walk on land from my submarine :)
 
Level 25
Joined
Feb 2, 2006
Messages
1,689
Sorry to ask again but I have tried the approach and everything works fine but is it possible to make the water visible from below now. Maybe in this case a whole custom water texture would be better. I was just thinking it would be cool to see the water at the top from below or even better make the water texture transparent, so one can see a bit through it. I know that Warcraft somehow handles the water textures via SLK files and there are some textures which define the water but I have no idea how far one can customize them. Maybe it is a one sided material which could be made two sided and transparent?


Anyway, the solution is already better for me than what the other maps do.

edit:
And I got another problem now. The submarine unit above water is simpliy floating. Everything works fine. For the submarine under water I use a modified model with a different height (edited with the model editor).

However, I want to go up and down under water. This does not work with flying height since it seems that it cannot be negative? If the submarine unit under water is flying it will always be on top of the water. So my only solution seems to be to add different versions of the model with different heights and to transform the unit type going up and down. I am also not sure which height/distance is used when for example there is an explosion of torpedos. I think Warcraft III does not recognize the Z value (maybe add cliffs`?) So if I go down with the submarine and there is an explosion at the top it will likely damage the submarine except if I use a custom spell and check the current Z value of the submarine.

It would be great if you could change the Z/height/flying height of a unit to move under water.
 
Last edited:
Level 25
Joined
Feb 2, 2006
Messages
1,689
Okay and another problem I discovered is that GetLocationZ always seems to be the same no matter how high the cliffs are under the water. I have tried GetLocationZ on the position of the unit or with X and Y coordinates of the units. The cliff level always seems to be 0 as well. This is a problem when I want to calculate the height under water to determine the camera height since if I set a fixed value like 1200.0 it is affected by the cliff under the water (gets higher if there is a cliff).

How can I determine the Z value of the cliff/plateau/terrain under water?
 
Sorry to ask again but I have tried the approach and everything works fine but is it possible to make the water visible from below now. Maybe in this case a whole custom water texture would be better. I was just thinking it would be cool to see the water at the top from below or even better make the water texture transparent, so one can see a bit through it. I know that Warcraft somehow handles the water textures via SLK files and there are some textures which define the water but I have no idea how far one can customize them. Maybe it is a one sided material which could be made two sided and transparent?
Your best bet is a blue filter or similar.
It would be great if you could change the Z/height/flying height of a unit to move under water.
I would have edited the animations of the submarine. Add morph/morph alternate animations and walk alternate animations. You can add lumber and gold animations for multiple depth levels.
Okay and another problem I discovered is that GetLocationZ always seems to be the same no matter how high the cliffs are under the water. I have tried GetLocationZ on the position of the unit or with X and Y coordinates of the units. The cliff level always seems to be 0 as well. This is a problem when I want to calculate the height under water to determine the camera height since if I set a fixed value like 1200.0 it is affected by the cliff under the water (gets higher if there is a cliff).

How can I determine the Z value of the cliff/plateau/terrain under water?
@kovadarra translated a system found somewhere here on Hive to Lua. If you're able to implement it in your map it should solve your problem.

  • local u=udg_MyUnit TimerStart(CreateTimer(),0.03125000,true,function()if not udg_Indoors then SetCameraField(CAMERA_FIELD_TARGET_DISTANCE,1600+BlzGetLocalUnitZ(u)-GetCamOffset(GetUnitX(u),GetUnitY(u)),0)end end)



Code:
do
    local cameramapLoc
    local mapMinX, mapMinY
    local offsets = {}
    local GetCamOffsetInitGrid
    local function GetCamOffsetAt(x, y)
        local idx = y*yfact+x
        local res = rawget(offsets, idx)
        if res then return res end
        res = GetCamOffsetInitGrid(mapMinX+256+512*x, mapMinY+256+512*y)
        rawset(offsets, idx, res)
        return res
    end
    local function GetGridCamOffset(ix, iy, offx, offy)
        local r
        local ixl = ix-1
        local ixr = ix+1
        local iyd = iy-1
        local iyu = iy+1
        if ixl<0 then
            ixl = 0
        end
        if iyd<0 then
            iyd = 0
        end
        if ixr>256 then
            ixr=256
        end
        if iyu>256 then
            iyu=256
        end
        if offx>0 then
            if offy>0 then
                r =   .089696*GetCamOffsetAt(ixl,iyu)+ .139657*GetCamOffsetAt(ix,iyu)+ .097349*GetCamOffsetAt(ixr,iyu)
                r = r+.130989*GetCamOffsetAt(ixl,iy) + .099380*GetCamOffsetAt(ix,iy) + .139657*GetCamOffsetAt(ixr,iy)
                r = r+.082587*GetCamOffsetAt(ixl,iyd)+ .130989*GetCamOffsetAt(ix,iyd)+ .089696*GetCamOffsetAt(ixr,iyd)
            elseif offy<0 then
                r =   .082587*GetCamOffsetAt(ixl,iyu)+ .130989*GetCamOffsetAt(ix,iyu)+ .089696*GetCamOffsetAt(ixr,iyu)
                r = r+.130989*GetCamOffsetAt(ixl,iy) + .099380*GetCamOffsetAt(ix,iy) + .139657*GetCamOffsetAt(ixr,iy)
                r = r+.089696*GetCamOffsetAt(ixl,iyd)+ .139657*GetCamOffsetAt(ix,iyd)+ .097349*GetCamOffsetAt(ixr,iyd)
            else
                r =   .084604*GetCamOffsetAt(ixl,iyu)+ .134226*GetCamOffsetAt(ix,iyu)+ .091913*GetCamOffsetAt(ixr,iyu)
                r = r+.134017*GetCamOffsetAt(ixl,iy) + .101594*GetCamOffsetAt(ix,iy) + .142877*GetCamOffsetAt(ixr,iy)
                r = r+.084604*GetCamOffsetAt(ixl,iyd)+ .134226*GetCamOffsetAt(ix,iyd)+ .091913*GetCamOffsetAt(ixr,iyd)
            end
        elseif offx<0 then
            if offy>0 then
                r =   .097349*GetCamOffsetAt(ixl,iyu)+ .139657*GetCamOffsetAt(ix,iyu)+ .089696*GetCamOffsetAt(ixr,iyu)
                r = r+.139657*GetCamOffsetAt(ixl,iy) + .099380*GetCamOffsetAt(ix,iy) + .130989*GetCamOffsetAt(ixr,iy)
                r = r+.089696*GetCamOffsetAt(ixl,iyd)+ .130989*GetCamOffsetAt(ix,iyd)+ .082587*GetCamOffsetAt(ixr,iyd)
            elseif offy<0 then
                r =   .089696*GetCamOffsetAt(ixl,iyu)+ .130989*GetCamOffsetAt(ix,iyu)+ .082587*GetCamOffsetAt(ixr,iyu)
                r = r+.139657*GetCamOffsetAt(ixl,iy) + .099380*GetCamOffsetAt(ix,iy) + .130989*GetCamOffsetAt(ixr,iy)
                r = r+.097349*GetCamOffsetAt(ixl,iyd)+ .139657*GetCamOffsetAt(ix,iyd)+ .089696*GetCamOffsetAt(ixr,iyd)
            else
                r =   .091913*GetCamOffsetAt(ixl,iyu)+ .134226*GetCamOffsetAt(ix,iyu)+ .084604*GetCamOffsetAt(ixr,iyu)
                r = r+.142877*GetCamOffsetAt(ixl,iy) + .101594*GetCamOffsetAt(ix,iy) + .134017*GetCamOffsetAt(ixr,iy)
                r = r+.091913*GetCamOffsetAt(ixl,iyd)+ .134226*GetCamOffsetAt(ix,iyd)+ .084604*GetCamOffsetAt(ixr,iyd)
            end
        else
            if offy>0 then
                r =   .091913*GetCamOffsetAt(ixl,iyu)+ .142877*GetCamOffsetAt(ix,iyu)+ .091913*GetCamOffsetAt(ixr,iyu)
                r = r+.134226*GetCamOffsetAt(ixl,iy) + .101594*GetCamOffsetAt(ix,iy) + .134226*GetCamOffsetAt(ixr,iy)
                r = r+.084604*GetCamOffsetAt(ixl,iyd)+ .134017*GetCamOffsetAt(ix,iyd)+ .084604*GetCamOffsetAt(ixr,iyd)
            elseif offy<0 then
                r =   .084604*GetCamOffsetAt(ixl,iyu)+ .134017*GetCamOffsetAt(ix,iyu)+ .084604*GetCamOffsetAt(ixr,iyu)
                r = r+.134226*GetCamOffsetAt(ixl,iy) + .101594*GetCamOffsetAt(ix,iy) + .134226*GetCamOffsetAt(ixr,iy)             
                r = r+.091913*GetCamOffsetAt(ixl,iyd)+ .142877*GetCamOffsetAt(ix,iyd)+ .091913*GetCamOffsetAt(ixr,iyd)
            else
                r =   .086125*GetCamOffsetAt(ixl,iyu)+ .136429*GetCamOffsetAt(ix,iyu)+ .086125*GetCamOffsetAt(ixr,iyu)
                r = r+.136429*GetCamOffsetAt(ixl,iy) + .109784*GetCamOffsetAt(ix,iy) + .136429*GetCamOffsetAt(ixr,iy)
                r = r+.086125*GetCamOffsetAt(ixl,iyd)+ .136429*GetCamOffsetAt(ix,iyd)+ .086125*GetCamOffsetAt(ixr,iyd)
            end
        end
        return r
    end
    function GetCamOffset(x, y)
        local ok,res = pcall(function()
            local iXLo = R2I((x-mapMinX)/512.+.5)
            local iYLo = R2I((y-mapMinY)/512.+.5)
            local iXHi = iXLo+1
            local iYHi = iYLo+1
            local iChkXLo
            local iChkXLoOff
            local iChkXHi
            local iChkXHiOff
            local iChkYLo
            local iChkYLoOff
            local iChkYHi
            local iChkYHiOff
            local XLo
            local YLo
            local XHi
            local YHi
            local rX
            local rY
            local r
            local LoDX = (x-mapMinX)-(iXLo*512.-256.)
            local LoDY = (y-mapMinY)-(iYLo*512.-256.)
            if LoDX<=12 then
                iChkXLo = iXLo
                iChkXLoOff = 0
                iChkXHi = iXLo
                iChkXHiOff = 1
            elseif LoDX<500 then
                iChkXLo = iXLo
                iChkXLoOff = 1
                iChkXHi = iXHi
                iChkXHiOff =-1
            else
                iChkXLo = iXHi
                iChkXLoOff =-1
                iChkXHi = iXHi
                iChkXHiOff = 0
            end
            if LoDY<=12 then
                iChkYLo = iYLo
                iChkYLoOff = 0
                iChkYHi = iYLo
                iChkYHiOff = 1
            elseif LoDY<500 then
                iChkYLo = iYLo
                iChkYLoOff = 1
                iChkYHi = iYHi
                iChkYHiOff =-1
            else
                iChkYLo = iYHi
                iChkYLoOff =-1
                iChkYHi = iYHi
                iChkYHiOff = 0
            end
            XLo = iChkXLo*512.+iChkXLoOff*12.-256.
            XHi = iChkXHi*512.+iChkXHiOff*12.-256.
            YLo = iChkYLo*512.+iChkYLoOff*12.-256.
            YHi = iChkYHi*512.+iChkYHiOff*12.-256.
            rX = ((x-mapMinX)-XLo)/(XHi-XLo)
            rY = ((y-mapMinY)-YLo)/(YHi-YLo)
            r =   GetGridCamOffset(iChkXHi,iChkYHi,iChkXHiOff,iChkYHiOff)*rX*rY
            r = r+GetGridCamOffset(iChkXLo,iChkYHi,iChkXLoOff,iChkYHiOff)*(1-rX)*rY
            r = r+GetGridCamOffset(iChkXHi,iChkYLo,iChkXHiOff,iChkYLoOff)rX(1-rY)
            r = r+GetGridCamOffset(iChkXLo,iChkYLo,iChkXLoOff,iChkYLoOff)(1-rX)(1-rY)
            return r
        end)
        if not ok then print('|cffff0000GetCamOffset: '..res) end
        return res
    end
    function GetCamOffsetInitGrid(x,y)
        local index
        local iX = -6
        local iY
        local z
        local r
        local i = 64 --9*4+12*2+4
        MoveLocation(cameramapLoc,x,y)
        z = GetLocationZ(cameramapLoc)
        r = 0.
        MoveLocation(cameramapLoc,x-128.,y)
        r = r+GetLocationZ(cameramapLoc)*4./i
        MoveLocation(cameramapLoc,x,y)
        r = r+GetLocationZ(cameramapLoc)*4./i
        MoveLocation(cameramapLoc,x+128.,y)
        r = r+GetLocationZ(cameramapLoc)*4./i
        MoveLocation(cameramapLoc,x-128.,y+128.)
        r = r+GetLocationZ(cameramapLoc)*4./i
        MoveLocation(cameramapLoc,x,y+128.)
        r = r+GetLocationZ(cameramapLoc)*4./i
        MoveLocation(cameramapLoc,x+128.,y+128.)
        r = r+GetLocationZ(cameramapLoc)*4./i
        MoveLocation(cameramapLoc,x-128.,y-128.)
        r = r+GetLocationZ(cameramapLoc)*4./i
        MoveLocation(cameramapLoc,x,y-128.)
        r = r+GetLocationZ(cameramapLoc)*4./i
        MoveLocation(cameramapLoc,x+128.,y-128.)
        r = r+GetLocationZ(cameramapLoc)*4./i
        MoveLocation(cameramapLoc,x-256.,y-128.)
        r = r+GetLocationZ(cameramapLoc)*2./i
        MoveLocation(cameramapLoc,x-256.,y)
        r = r+GetLocationZ(cameramapLoc)*2./i
        MoveLocation(cameramapLoc,x-256.,y+128.)
        r = r+GetLocationZ(cameramapLoc)*2./i
        MoveLocation(cameramapLoc,x+256.,y-128.)
        r = r+GetLocationZ(cameramapLoc)*2./i
        MoveLocation(cameramapLoc,x+256.,y)
        r = r+GetLocationZ(cameramapLoc)*2./i
        MoveLocation(cameramapLoc,x+256.,y+128.)
        r = r+GetLocationZ(cameramapLoc)*2./i
        MoveLocation(cameramapLoc,x-128.,y-256.)
        r = r+GetLocationZ(cameramapLoc)*2./i
        MoveLocation(cameramapLoc,x,y-256.)
        r = r+GetLocationZ(cameramapLoc)*2./i
        MoveLocation(cameramapLoc,x+128.,y-256.)
        r = r+GetLocationZ(cameramapLoc)*2./i
        MoveLocation(cameramapLoc,x-128.,y+256.)
        r = r+GetLocationZ(cameramapLoc)*2./i
        MoveLocation(cameramapLoc,x,y+256.)
        r = r+GetLocationZ(cameramapLoc)*2./i
        MoveLocation(cameramapLoc,x+128.,y+256.)
        r = r+GetLocationZ(cameramapLoc)*2./i
        MoveLocation(cameramapLoc,x+256.,y+256.)
        r = r+GetLocationZ(cameramapLoc)*1./i
        MoveLocation(cameramapLoc,x+256.,y-256.)
        r = r+GetLocationZ(cameramapLoc)*1./i
        MoveLocation(cameramapLoc,x-256.,y+256.)
        r = r+GetLocationZ(cameramapLoc)*1./i
        MoveLocation(cameramapLoc,x-256.,y-256.)
        r = r+GetLocationZ(cameramapLoc)*1./i
        return r
    end
    local function GetCamOffsetInit()
        local map = GetWorldBounds()
        mapMinX = GetRectMinX(map)
        mapMinY = GetRectMinY(map)
        local mapMaxX = GetRectMaxX(map)
        local mapW = mapMaxX - mapMinX
        yfact = math.floor(mapW / 512 + 0.5)
        RemoveRect(map)
        cameramapLoc = Location(0,0)
    end
    local OldInitBlizzard = InitBlizzard
    function InitBlizzard()
        if OldInitBlizzard then
            OldInitBlizzard()
        end
        GetCamOffsetInit()
    end
end
 
Last edited:
Level 25
Joined
Feb 2, 2006
Messages
1,689
Hmm thx. I am also thinking about maybe using one custom water plane model instead and flying units with different flying heights. I guess it is easier to change the height of units, have some view through the water from down below. On the other hand the pathing type is really useful to block water units from entering the land, so maybe an additional custom water plane below the water surface + the blue filter.



Here is a list of my current issues with the under water map:
  • Player only fog for the under water effect: Another problem is the underwater effect (Underwater effect for maps) I can add a custom filter or try to set the fog for a player only (it is a multiplayer map)
  • Player only weather effect under water: The weather effect of the rays will be above the water. I guess I need a custom model for the rays then to place it under the water or can weather effects and fogs both be for a player only?
  • Fog of War: Another thing I have noticed is that the fog of war of course is only visible on the water surface, so it looks a bit strange under water when units suddenly become visible. Maybe I would have to disable the fog of war under water. edit: I have disabled it now and it looks better.
  • Height Calculation: I have created multiple versions of my submarine now with different heights but the height is not the same as ingame. When I move the submarine in Mago's model editor like -1400 along the Z axis it is not -1400 in the calculation of the height in Warcraft III. I would need to translate Warcraft III Z coordinates into Z coordinates in the model editor. Is there some way to calculate this?
  • When I translate the model by selecting all vertices in Mago's model editor it won't move the attachment points. Do I have to export it to Blender and back or is there some easier method to move everything up and down.
  • Setting the flying height to a negative value did not work. Hence, with flying units it would only work again with fixed model heights or without Warcraft's water surface and instead with a custom one.
  • I probably need a custom water plane/surface from below, to make it look better. I was thinking about editting an existing model like: Lava and make it two sided and add a water texture and still let it be transparent, so you do not directly see units over sea without any blocking surface.
  • Warcraft does not know any Z value in pathing. Hence, all units under water may not block anything. Otherwise, floating units on the water will get stuck. With flying units this wouldn't be a problem but blocking would only make sense if there was a ground level where you could walk and want some blockers. In this case I would have to make all floating units flying again and when the submarine dives down to the ground level it could become floating.
  • Items cannot be placed in water/under water and there is no way to change their pathing (from what I have seen in the object editor). So no items in the water to collect :( However, I can drop items ingame under water, so if I could disable their pathing in the editor or place them via triggers it should work. They even can be picked up.
  • Hiding a submarine: When my submarine submerges it becomes invisible. This works for units which are on the water, so they cannot see/find it anymore. However under water you should be able to see each other. Hence, all under water units will need to be able to see invisible units. Another solution would be to disable the invisible spell and let all units manually target each other. So when you see hostile submarine through the water somehow, you can try to aim for it. I will disable minimap icons either way to make it harder to find each other.
  • Trees under water: I added some coral trees based on Coral Tree and the object editor tree unit. However, it is not visible under water only when dying. I have tried to play around with its values in the object editor. However, it is still not visible. Is there any value I have to change to make it visible standing under water? edit: They are visible now but I don't know what I changed.
  • I have tried the system by @kovadarra but all it does seems to be to set only the camera distance to the current Z value. It is a bit hard for me to work with it since the Z value is apparently 0 with this system on water although the unit is floating on top on the water, so I have to add a fixed value of the depth of the water to it. Since it works with distance and not height I am not sure what to add to it. I have tried to use its result for the camera height as well or just add a constant to it when setting the distance which won't make sense since it will only increase the distance. I think I will need a system which somehow can handle an additional manually set offset with the height/Z value of the unit.
If you are interested in how I try to solve all the issues, here is my map: Submarine Warfare 0.1
and here is my GitHub project: tdauth/submarine-warfare
 
Last edited:
Status
Not open for further replies.
Top