• 🏆 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!

[JASS] [Snippet] TerrainSkin

Level 9
Joined
Jun 21, 2012
Messages
432
JASS:
library TerrainSkin/*
****************************************************************************************************************
*
*   ************************************************************************************************************
*
*   */ uses /*
*       */ DimensionalArray /* hiveworkshop.com/forums/submissions-414/snippet-dimensional-array-265011/
*       */ WorldBounds      /* github.com/nestharus/JASS/blob/master/jass/Systems/WorldBounds/script.j
*
*   ************************************************************************************************************
*
*   TerrainSkin
*   ___________
*   v1.0.1.1
*   by Trigger.edge
*   
*   Change the terrain texture without lost the original set.
*
*   API:
*   ____
*   struct TerrainSkin extends array
*       - static method create takes real x, real y, integer terrainType, boolean permanent returns TerrainSkin
*           - creates a TerrainSkin.
*       - method destroy takes nothing returns nothing
*           - destroy it.
*       - static method getDefault takes real x, real y returns integer
*           - get default terrain set.
*
*   Credits:
*   ________
*       - Nestharus: WorldBounds
*
***************************************************************************************************************/
    struct TerrainSkin extends array
        private static Array data=0
        
        private static method getTile takes real xy, real mincord, real maxcord returns integer
            local integer tile
            if(xy<0)then
                set tile=R2I(mincord)
                loop
                    exitwhen(tile>=0 or tile>=xy-64)
                    set tile=tile+128
                endloop
            else
                set tile=R2I(maxcord)
                loop
                    exitwhen(tile<=0 or tile<=xy+64)
                    set tile=tile-128
                endloop
            endif
            return tile
        endmethod
        
        static method getDefault takes real x, real y returns integer
            local integer ix=getTile(x,WorldBounds.minX,WorldBounds.maxX)
            local integer iy=getTile(y,WorldBounds.minY,WorldBounds.maxY)
            local integer i=data[ix][iy].integer
            if(0==i)then
                set data[ix][iy].integer=GetTerrainType(ix,iy)
                return data[ix][iy].integer
            endif
            return i
        endmethod
        
        private method changeSkin takes real x, real y, integer terrainType returns nothing
            local integer ix=getTile(x,WorldBounds.minX,WorldBounds.maxX)
            local integer iy=getTile(y,WorldBounds.minY,WorldBounds.maxY)
            if(not data[ix][iy].has.integer)then
                set data[ix][iy].integer=GetTerrainType(ix,iy)
            endif
            call SetTerrainType(ix,iy,terrainType,-1,1,0)
        endmethod
        
        static method create takes real x, real y, integer terrainType, boolean permanent returns TerrainSkin
            local thistype this=data[0].integer
			if(0==data[this].integer)then
				set data[0].integer=this+1
			else
				set data[0].integer=data[this].integer
                call data[this].remove.integer()
			endif
            set data[0][this].real=x
            set data[1][this].real=y
            set data[-1][this].integer=terrainType
            call .changeSkin(x,y,terrainType)
            return this
        endmethod
        
        method destroy takes nothing returns nothing
            call .changeSkin(data[0][this].real,data[1][this].real,data[-1][this].integer)
            call data[0][this].remove.real()
            call data[1][this].remove.real()
            call data[-1][this].remove.integer()
            set data[this].integer=data[0].integer
			set data[0].integer=this
        endmethod
        
        private static method onInit takes nothing returns nothing
            set data=Array.create()
            set data[0].integer=1
        endmethod
    endstruct
endlibrary
 
Last edited:

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
Could be useful but need to be much more advanced. Like saving the original terrain type and the lastly changed and the current type. And like regionally change terrain with specific iteration delay: within rect, circle, etc. And doing nothing in the constructor method seems weird. I don't recommend the use of struct in this case, hashtable would be better. You also can utilize TileDefinition by IcemanBo for better accuracy, it's not approved yet alright but I guarantee it's ready to go resource.

I want to make something like this as well actually, but seems like somebody else has managed to submit one :(
 
Level 9
Joined
Jun 21, 2012
Messages
432
- Could be useful but need to be much more advanced. Like saving the original terrain type

- You also can utilize TileDefinition by IcemanBo for better accuracy, it's not approved yet alright but I guarantee it's ready to go resource.

- I want to make something like this as well actually, but seems like somebody else has managed to submit one :(

- In the script description i put: // Change the terrain texture without lost the original set. ^^

- Ok i'll see how func this.

- :( xd
 
Level 33
Joined
Apr 24, 2012
Messages
5,113
DimensionalArray isn't approved so why not use Table instead and then use TableArray or HashTable to have a chance of getting approved?

could have been much better if it uses TileDefinition, because of this:
JASS:
            local integer tile
            if(xy<0)then
                set tile=R2I(mincord)
                loop
                    exitwhen(tile>=0 or tile>=xy-64)
                    set tile=tile+128
                endloop
            else
                set tile=R2I(maxcord)
                loop
                    exitwhen(tile<=0 or tile<=xy+64)
                    set tile=tile-128
                endloop
            endif
            return tile
TileDefinition's GetTileId does it much better

*I should start writing the TileMap now :V
 
It should use TileDefinition and Table.

TileDefinition to get the index of a tile, and then only a single array is needed, so no multidemensional array. But as default array size is limited one single Table can be used to solve this.

I believe it would be handy if user could set an option to auto detect all default terrain tiles onInit.
Or maybe at a given rect which is given as parameter. It would be quite a bit effort for the user to write an algortihm to get default terrain first of all terrain tiles he needs, because eventualy even one needs to care of OP limit. So automated function would help.
 
Last edited:
Getting the origin terrain type is probably handy sometimes. Though it is also pretty specific in terms of usage -- the elemental thought is to cache an integer (terrain type) based on keys x/y (coordinates) and to call it later with respective keys.

The changes we talked about above would bring some more comfort, and would be definitly still good to see, but honestly I don't see it as useful enough for JASS submissions.
Though it still might have some use in case or someone might be interested in concept... I would move this to The Lab.
 
Top