Jump to content

How to Create Lootable Maps for Build 41.6+


RingoD123

Recommended Posts

First, create the following file structure (if you are adding the lootable map to your own map mod then create all folders within the media folder below in your map mods media folder instead):

 

Spoiler

MyLootableMapsMod
>media

   >>lua
      >>>server
         >>>>Items

     >>>client

         >>>>ISUI

              >>>>>Maps

>scripts
>textures
    >>worldMap

 

Next up create a .txt file in the scripts folder called something like "mylootablemap" (except make it more unique to avoid any possible compatability issues with other mods that might use the same names), it should include this code:

 

Spoiler

module Base
{
    
    item MyLootableMap
    {
    DisplayCategory = Cartography,
        Type                =            Map,
        DisplayName            =            Your map name here,
        Icon                =            Map,
        Weight                =            0.1,
        Map                 =           MyLootableMap,
    WorldStaticModel = Map,
    }

}

 

The above code is adding a new item with the internal name "MyLootableMap" (so again make sure yours is something unique) into the vanilla pool of items, the above settings work for maps.

 

The next file you need you will want to create in the "media\lua\server\Items" folder, call it something like MyLootableMapDistribution.lua but again make it's a unique name to avoid any possible mod imcompatability with other mods. It should contain the following code:

 

Spoiler

local function preDistributionMerge()
    table.insert(ProceduralDistributions.list.MagazineRackMaps.items, "MyLootableMap");
    table.insert(ProceduralDistributions.list.MagazineRackMaps.items, 50);
end
Events.OnPreDistributionMerge.Add(preDistributionMerge);

 

In the above code you can see that we are adding our new Item "MyLootableMap" into the "MagazineRackMaps"  loot table inside of ProceduralDistributions.lua, this will affect any roomDef of any building that pulls from the MagazineRackMaps loot table. We are doing it this way as the definition we want to add to has the "procedural" tag in Distributions.lua and is therefore using the procedural loot tables. The number 50 is the "weight" of the item you are adding, higher number = more chance. To find the current room and container definitions, navigate to your "steamapps\common\ProjectZomboid\media\lua\server\Items" folder and open the Distributions.lua file.

 

If the definition you want to add your item to is not procedural (does not have the "procedural = true" line) then you want to add this code instead of the above code:

 

Spoiler

local myMapdistributionTable = {

    all = {
        shelves = {
            rolls = 5,
            items = {
                "Magazine", 20,
                "Newspaper", 20,
                "Book", 20,
                "SheetPaper2", 20,
                "Notebook", 20,
                "BookTailoring1", 2,
                "BookTailoring2", 1,
                "BookTailoring3", 0.7,
                "BookTailoring4", 0.5,
                "BookTailoring5", 0.3,
                "BookCarpentry1", 2,
                "BookCarpentry2", 1,
                "BookCarpentry3", 0.7,
                "BookCarpentry4", 0.5,
                "BookCarpentry5", 0.3,
                "BookCooking1", 2,
                "BookCooking2", 1,
                "BookCooking3", 0.5,
                "BookCooking4", 0.3,
                "BookForaging1", 2,
                "BookForaging2", 1,
                "BookForaging3", 0.7,
                "BookForaging4", 0.5,
                "BookForaging5", 0.3,
                "BookFarming1", 2,
                "BookFarming2", 1,
                "BookFarming3", 0.7,
                "BookFarming4", 0.5,
                "BookFarming5", 0.3,
                "BookFishing1", 2,
                "BookFishing2", 1,
                "BookFishing3", 0.7,
                "BookFishing4", 0.5,
                "BookFishing5", 0.3,
                "BookTrapping1", 2,
                "BookTrapping2", 1,
                "BookTrapping3", 0.7,
                "BookTrapping4", 0.5,
                "BookTrapping5", 0.3,
                "BookFirstAid1", 2,
                "BookFirstAid2", 1,
                "BookFirstAid3", 0.7,
                "BookFirstAid4", 0.5,
                "BookFirstAid5", 0.3,
                "BookMetalWelding1", 2,
                "BookMetalWelding2", 1,
                "BookMetalWelding3", 0.7,
                "BookMetalWelding4", 0.5,
                "BookMetalWelding5", 0.3,
                "BookElectrician1", 2,
                "BookElectrician2", 1,
                "BookElectrician3", 0.7,
                "BookElectrician4", 0.5,
                "BookElectrician5", 0.3,
                "BookMechanic1", 2,
                "BookMechanic2", 1,
                "BookMechanic3", 0.7,
                "BookMechanic4", 0.5,
                "BookMechanic5", 0.3,
                "FishingMag1", 1,
                "FishingMag2", 1,
                "HuntingMag1", 1,
                "HuntingMag2", 1,
                "HuntingMag3", 1,
                "HerbalistMag", 1,
                "FarmingMag1", 1,
                "CookingMag1", 1,
                "CookingMag2", 1,
                "ElectronicsMag1", 1,
                "ElectronicsMag2", 1,
                "ElectronicsMag3", 1,
                "ElectronicsMag4", 1,
                "ElectronicsMag5", 1,
                "MechanicMag1", 1,
                "MechanicMag2", 1,
                "MechanicMag3", 1,
                "EngineerMagazine1", 1,
                "EngineerMagazine2", 1,
                "MetalworkMag1", 1,
                "MetalworkMag2", 1,
                "MetalworkMag3", 1,
                "MetalworkMag4", 1,
                "Journal", 2,
                "Radio.RadioBlack",2,
                "Radio.RadioRed",1,
                "MyLootableMap", 50,
                }
            },
    }
}

table.insert(Distributions, 2, myMapdistributionTable);

This would add your map to the existing "all>shelves" definitions, which would be every shelves container in the game world not inside a roomdef defined inside Distributions.lua, so for example your map would not spawn on shelves that are placed inside a "bookstore" room def as that room def already exists in Distributions.lua with a rule for shelves.

You can also check this thread:

for a more in-depth guide to working with the loot tables.

 

Lastly, inside of your "media\lua\client\ISUI\Maps" folder create a new file called something like MyLootableMapDefinition.lua (make it unique to your mod instead of a generic name) and include the following code:

 

Spoiler

require "ISMapDefinitions"

 

MapUtils = {}

 

function MapUtils.initDirectoryMapData(mapUI, directory)
    local mapAPI = mapUI.javaObject:getAPIv1()
    local file = directory..'/worldmap-forest.xml'
    if fileExists(file) then
        mapAPI:addData(file)
    end
    file = directory..'/worldmap.xml'
    if fileExists(file) then
        mapAPI:addData(file)
    end

    -- This call indicates the end of XML data files for the directory.
    -- If map features exist for a particular cell in this directory,
    -- then no data added afterwards will be used for that same cell.
    mapAPI:endDirectoryData()

 

    mapAPI:addImages(directory)
end

 

function MapUtils.initDefaultMapData(mapUI)
    local mapAPI = mapUI.javaObject:getAPIv1()
    mapAPI:clearData()
    -- Add data from highest priority (mods) to lowest priority (vanilla)
    local dirs = getLotDirectories()
    for i=1,dirs:size() do
        MapUtils.initDirectoryMapData(mapUI, 'media/maps/'..dirs:get(i-1))
    end
end

 

local MINZ = 0
local MAXZ = 24

 

local WATER_TEXTURE = false

 

function MapUtils.initDefaultStyleV1(mapUI)
    local mapAPI = mapUI.javaObject:getAPIv1()
    local styleAPI = mapAPI:getStyleAPI()

 

    local r,g,b = 219/255, 215/255, 192/255
    mapAPI:setBackgroundRGBA(r, g, b, 1.0)
    mapAPI:setUnvisitedRGBA(r * 0.915, g * 0.915, b * 0.915, 1.0)
    mapAPI:setUnvisitedGridRGBA(r * 0.777, g * 0.777, b * 0.777, 1.0)

 

    styleAPI:clear()

 

    local layer = styleAPI:newPolygonLayer("forest")
    layer:setMinZoom(13.5)
    layer:setFilter("natural", "forest")
    if true then
        layer:addFill(MINZ, 189, 197, 163, 0)
        layer:addFill(13.5, 189, 197, 163, 0)
        layer:addFill(14, 189, 197, 163, 255)
        layer:addFill(MAXZ, 189, 197, 163, 255)
    else
        layer:addFill(MINZ, 255, 255, 255, 255)
        layer:addFill(MAXZ, 255, 255, 255, 255)
        layer:addTexture(MINZ, "media/textures/worldMap/Grass.png")
        layer:addTexture(MAXZ, "media/textures/worldMap/Grass.png")
        layer:addScale(13.5, 4.0)
        layer:addScale(MAXZ, 4.0)
    end
    
    layer = styleAPI:newPolygonLayer("water")
    layer:setMinZoom(MINZ)
    layer:setFilter("water", "river")
    if not WATER_TEXTURE then
        layer:addFill(MINZ, 59, 141, 149, 255)
        layer:addFill(MAXZ, 59, 141, 149, 255)
    else
        layer:addFill(MINZ, 59, 141, 149, 255)
        layer:addFill(14.5, 59, 141, 149, 255)
        layer:addFill(14.5, 255, 255, 255, 255)
        layer:addTexture(MINZ, nil)
        layer:addTexture(14.5, nil)
        layer:addTexture(14.5, "media/textures/worldMap/Water.png")
        layer:addTexture(MAXZ, "media/textures/worldMap/Water.png")
--        layer:addScale(MINZ, 4.0)
--        layer:addScale(MAX, 4.0)
    end

 

    layer = styleAPI:newPolygonLayer("road-trail")
    layer:setMinZoom(12.0)
    layer:setFilter("highway", "trail")
    layer:addFill(12.25, 185, 122, 87, 0)
    layer:addFill(13, 185, 122, 87, 255)
    layer:addFill(MAXZ, 185, 122, 87, 255)

 

    layer = styleAPI:newPolygonLayer("road-tertiary")
    layer:setMinZoom(11.0)
    layer:setFilter("highway", "tertiary")
    layer:addFill(11.5, 171, 158, 143, 0)
    layer:addFill(13, 171, 158, 143, 255)
    layer:addFill(MAXZ, 171, 158, 143, 255)

 

    layer = styleAPI:newPolygonLayer("road-secondary")
    layer:setMinZoom(11.0)
    layer:setFilter("highway", "secondary")
    layer:addFill(MINZ, 134, 125, 113, 255)
    layer:addFill(MAXZ, 134, 125, 113, 255)

 

    layer = styleAPI:newPolygonLayer("road-primary")
    layer:setMinZoom(11.0)
    layer:setFilter("highway", "primary")
    layer:addFill(MINZ, 134, 125, 113, 255)
    layer:addFill(MAXZ, 134, 125, 113, 255)

 

    layer = styleAPI:newPolygonLayer("railway")
    layer:setMinZoom(14.0)
    layer:setFilter("railway", "*")
    layer:addFill(MINZ, 200, 191, 231, 255)
    layer:addFill(MAXZ, 200, 191, 231, 255)

 

    -- Default, same as building-Residential
    layer = styleAPI:newPolygonLayer("building")
    layer:setMinZoom(13.0)
    layer:setFilter("building", "yes")
    layer:addFill(13.0f, 210, 158, 105, 0)
    layer:addFill(13.5f, 210, 158, 105, 255)
    layer:addFill(MAXZ, 210, 158, 105, 255)

 

    layer = styleAPI:newPolygonLayer("building-Residential")
    layer:setMinZoom(13.0)
    layer:setFilter("building", "Residential")
    layer:addFill(13.0f, 210, 158, 105, 0)
    layer:addFill(13.5f, 210, 158, 105, 255)
    layer:addFill(MAXZ, 210, 158, 105, 255)

 

    layer = styleAPI:newPolygonLayer("building-CommunityServices")
    layer:setMinZoom(13.0)
    layer:setFilter("building", "CommunityServices")
    layer:addFill(13.0f, 139, 117, 235, 0)
    layer:addFill(13.5f, 139, 117, 235, 255)
    layer:addFill(MAXZ, 139, 117, 235, 255)

 

    layer = styleAPI:newPolygonLayer("building-Hospitality")
    layer:setMinZoom(13.0)
    layer:setFilter("building", "Hospitality")
    layer:addFill(13.0f, 127, 206, 225, 0)
    layer:addFill(13.5f, 127, 206, 225, 255)
    layer:addFill(MAXZ, 127, 206, 225, 255)

 

    layer = styleAPI:newPolygonLayer("building-Industrial")
    layer:setMinZoom(13.0)
    layer:setFilter("building", "Industrial")
    layer:addFill(13.0f, 56, 54, 53, 0)
    layer:addFill(13.5f, 56, 54, 53, 255)
    layer:addFill(MAXZ, 56, 54, 53, 255)

 

    layer = styleAPI:newPolygonLayer("building-Medical")
    layer:setMinZoom(13.0)
    layer:setFilter("building", "Medical")
    layer:addFill(13.0f, 229, 128, 151, 0)
    layer:addFill(13.5f, 229, 128, 151, 255)
    layer:addFill(MAXZ, 229, 128, 151, 255)

 

    layer = styleAPI:newPolygonLayer("building-RestaurantsAndEntertainment")
    layer:setMinZoom(13.0)
    layer:setFilter("building", "RestaurantsAndEntertainment")
    layer:addFill(13.0f, 245, 225, 60, 0)
    layer:addFill(13.5f, 245, 225, 60, 255)
    layer:addFill(MAXZ, 245, 225, 60, 255)

 

    layer = styleAPI:newPolygonLayer("building-RetailAndCommercial")
    layer:setMinZoom(13.0)
    layer:setFilter("building", "RetailAndCommercial")
    layer:addFill(13.0f, 184, 205, 84, 0)
    layer:addFill(13.5f, 184, 205, 84, 255)
    layer:addFill(MAXZ, 184, 205, 84, 255)
end

 

function MapUtils.overlayPaper(mapUI)
    local mapAPI = mapUI.javaObject:getAPIv1()
    local styleAPI = mapAPI:getStyleAPI()
    local layer = styleAPI:newTextureLayer("paper")
    layer:setMinZoom(0.00)
    local x1 = mapAPI:getMinXInSquares()
    local y1 = mapAPI:getMinYInSquares()
    local x2 = mapAPI:getMaxXInSquares() + 1
    local y2 = mapAPI:getMaxYInSquares() + 1
    layer:setBoundsInSquares(x1, y1, x2, y2)
    layer:setTile(true)
    layer:setUseWorldBounds(true)
    layer:addFill(14.00, 128, 128, 128, 0)
    layer:addFill(15.00, 128, 128, 128, 32)
    layer:addFill(15.00, 255, 255, 255, 32)
    layer:addTexture(0.00, "media/white.png")
    layer:addTexture(15.00, "media/white.png")
    layer:addTexture(15.00, "media/textures/worldMap/Paper.png")
end

 

function MapUtils.revealKnownArea(mapUI)
    local mapAPI = mapUI.javaObject:getAPIv1()
    local x1 = mapAPI:getMinXInSquares()
    local y1 = mapAPI:getMinYInSquares()
    local x2 = mapAPI:getMaxXInSquares()
    local y2 = mapAPI:getMaxYInSquares()
    WorldMapVisited.getInstance():setKnownInSquares(x1, y1, x2, y2)
end

-----

 

local function replaceWaterStyle(mapUI)
    if not WATER_TEXTURE then return end
    local mapAPI = mapUI.javaObject:getAPIv1()
    local styleAPI = mapAPI:getStyleAPI()
    local layer = styleAPI:getLayerByName("water")
    if not layer then return end
    layer:setMinZoom(MINZ)
    layer:setFilter("water", "river")
    layer:removeAllFill()
    layer:removeAllTexture()
    layer:addFill(MINZ, 59, 141, 149, 255)
    layer:addFill(MAXZ, 59, 141, 149, 255)
end

 

local function overlayPNG(mapUI, x, y, scale, layerName, tex, alpha)
    local texture = getTexture(tex)
    if not texture then return end
    local mapAPI = mapUI.javaObject:getAPIv1()
    local styleAPI = mapAPI:getStyleAPI()
    local layer = styleAPI:newTextureLayer(layerName)
    layer:setMinZoom(MINZ)
    layer:addFill(MINZ, 255, 255, 255, (alpha or 1.0) * 255)
    layer:addTexture(MINZ, tex)
    layer:setBoundsInSquares(x, y, x + texture:getWidth() * scale, y + texture:getHeight() * scale)
end

 

local function overlayPNG2(mapUI, x, y, scaleX, scaleY, tex)
    local mapAPI = mapUI.javaObject:getAPIv1()
    local styleAPI = mapAPI:getStyleAPI()
    local layer = styleAPI:newTextureLayer("lootMapPNG")
    layer:setMinZoom(MINZ)
    local texture = getTexture(tex)
    layer:addFill(MINZ, 255, 255, 255, 128)
    layer:addTexture(MINZ, tex)
    layer:setBoundsInSquares(x, y, x + texture:getWidth() * scaleX, y + texture:getHeight() * scaleY)
end

-- -- -- -- --

 

Now, after the last set of dashed lines you can add your lootable map definitions with the following code:

Spoiler

LootMaps.Init.MyLootableMap = function(mapUI)
    local mapAPI = mapUI.javaObject:getAPIv1()
    MapUtils.initDirectoryMapData(mapUI, 'media/maps/MyMapMod')
    -- 'media/maps/MyMapMod' - this should be where your maps worldmap.xml file is

 

    MapUtils.initDefaultStyleV1(mapUI)
    -- Specify the appearance of the map.

 

    replaceWaterStyle(mapUI)
    -- Use solid color for water instead of a texture.

 

    mapAPI:setBoundsInSquares(12900, 9900, 14399, 11399)
    -- (starting x, starting y, ending x, ending y) of the area you want to display and uncover, in World Co-ordinates.

 

    overlayPNG(mapUI, 14299, 9900, 0.666, "badge", "media/textures/worldMap/MyLootableMapBadge.png")
    -- Add your lootable maps banner PNG.

 

    overlayPNG(mapUI, 13000, 10000, 0.666, "legend", "media/textures/worldMap/Legend.png")
    -- Add the legend PNG.

 

    MapUtils.overlayPaper(mapUI)
    -- Draw a paper-like texture overtop the map.


end

 

Make sure that your "LootMaps.Init.MyLootableMap" on line 1 matches the name you specified on the "Maps = " line in your map item script you made earlier in this tutorial. The rest of the code is commented to describe what they do.

The "textures\worldMap" folder that you created at the start should be used to store your maps name banner png if you have one and is referenced in the above code to make your lootable map look more official.

As you can see, no external PNG's need to be created as the map is drawn from the data stored in the maps worldmap.xml file, which is what the "mapAPI:setBoundsInSquares" is using to draw a certain section of the overall world map.

 

And that's it, copy your entire folder structure into your "C:\Users\YourUserNameHere\Zomboid\Mods" folder, load up the game, enable the mod (Your map mod if you made your lootable maps as part of a map mod) and start a new game, you now have your lootable map in game and waiting for you to find, and when you do it will uncover that area automatically on the main in game map.

 

If you need a working example you can always subscribe to Bedford Falls on Steam and check it's workshop folder "steamapps\workshop\content\108600\522891356" . It's handy to verify your folder/file structure etc if you're having problems.

Link to comment
Share on other sites

  • 2 years later...
  • RingoD123 changed the title to How to Create Lootable Maps for Build 41.51+
  • 4 weeks later...

Good morning, excellent tutorial.

A query .... assuming my map has text in English ... but I want an alternative version with text in another language.

How could I make the attribute:

"Map = media / ui / LootableMaps / MyLootableMap.png,"

Change that image for another according to the language the game is running?

It's possible?

Link to comment
Share on other sites

  • RingoD123 changed the title to How to Create Lootable Maps for Build 41.6+
  • 2 weeks later...

I'm finding this all a bit confusing but I'm wondering if this method can be used to create a lootable world map similar to the toggleable world map in game? I'm stuck at the "media/maps/MyMapMod" and "worldmap.xml" parts.

Link to comment
Share on other sites

  • 3 weeks later...

Is it possible to include multiple mod areas into a single lootable map? You can easily include the area that contains both of the mod areas, and they will show up fine on the 'M' map, but the lootable map item will only show a single mod area.

Edited by Phyne
Link to comment
Share on other sites

  • 2 months later...

There seems to be some additional revision needed.

 

When discussing the folder structure...

 

>textures
    >>worldMap

 

These folders are no longer used from what I'm reading of the How-To as it currently is. Am I missing something?

Link to comment
Share on other sites

13 hours ago, AlexSledge said:

There seems to be some additional revision needed.

 

When discussing the folder structure...

 

>textures
    >>worldMap

 

These folders are no longer used from what I'm reading of the How-To as it currently is. Am I missing something?

As you can see from the tutorial, the worldMap folder holds some PNG's such as the Legend and map badge.

Link to comment
Share on other sites

Thanks RingoD123. My apologies for the oversight.

 

As yet untested, but I spent a good bit of the day incorporating in-game maps for 71 maps I making a personal pack for. Somewhere around half & half as regards procedural generation vs provided static png image due to lack of xml files.

 

Thanks again for this How-To, it certainly made my day more productive.

Edited by AlexSledge
Link to comment
Share on other sites

Hey, this is a great guide, I had a few issues but figured them out, however, I now have my map working, when I loot it the area unlocked is correct but when the visual of the map comes up there is no banner or legend. I cannot for love nor money figure this out but I would love to solve it.
I have also made a png for my map and would like that to displaybut I also couldn't figure that out either. I copied the bedford falls file and made changes including the filename of my png but it just doesn't seem to work, is there any chance you could explain the IUSI>Maps lua file?

The lines I seem to be struggling with are:

 

overlayPNG(mapUI, 14299, 9900, 0.666, "badge", "media/textures/worldMap/BedfordBadge.png")
	overlayPNG(mapUI, 13000, 10000, 0.666, "legend", "media/textures/worldMap/Legend.png")
	MapUtils.overlayPaper(mapUI)
--	overlayPNG(mapUI, 36*300, 21*300+190, 0.666, "lootMapPNG", "media/ui/LootableMaps/bedfordfallsmap.png", 0.5)

 

I cannot get the legend to display, I made a badge and couldn't get that to display either and ideally I'd like to use a map overlay to display the map I designed.

Link to comment
Share on other sites

1 hour ago, BigZombieMonkey said:

Hey, this is a great guide, I had a few issues but figured them out, however, I now have my map working, when I loot it the area unlocked is correct but when the visual of the map comes up there is no banner or legend. I cannot for love nor money figure this out but I would love to solve it.
I have also made a png for my map and would like that to displaybut I also couldn't figure that out either. I copied the bedford falls file and made changes including the filename of my png but it just doesn't seem to work, is there any chance you could explain the IUSI>Maps lua file?

The lines I seem to be struggling with are:

 

overlayPNG(mapUI, 14299, 9900, 0.666, "badge", "media/textures/worldMap/BedfordBadge.png")
	overlayPNG(mapUI, 13000, 10000, 0.666, "legend", "media/textures/worldMap/Legend.png")
	MapUtils.overlayPaper(mapUI)
--	overlayPNG(mapUI, 36*300, 21*300+190, 0.666, "lootMapPNG", "media/ui/LootableMaps/bedfordfallsmap.png", 0.5)

 

I cannot get the legend to display, I made a badge and couldn't get that to display either and ideally I'd like to use a map overlay to display the map I designed.

The co-ordinates you give for your PNG's (the first 2 numbers) should be within the co-ordinates you specified in the setBoundsInSquares line, with the co-ordinate supplied being where the top-left pixel of your image will be placed. The third number is to scale your image to be bigger or smaller.

 

So in my example below the mapBadge png is being placed 100 pixels in from the right hand border(ending x) and in line with the top border (starting y) of the map area specified in the first line.

The legend is being placed 100 pixels in from the left border (starting x) and 100 pixels down from the top border (starting y).

Both have been scaled to be 66% of their original size.

    mapAPI:setBoundsInSquares(12900, 9900, 14399, 11399)
    -- (starting x, starting y, ending x, ending y) of the area you want to display and uncover, in World Co-ordinates.

 

    overlayPNG(mapUI, 14299, 9900, 0.666, "badge", "media/textures/worldMap/MyLootableMapBadge.png")
    -- Add your lootable maps banner PNG.

 

    overlayPNG(mapUI, 13000, 10000, 0.666, "legend", "media/textures/worldMap/Legend.png")
    -- Add the legend PNG.

Link to comment
Share on other sites

11 hours ago, RingoD123 said:

The co-ordinates you give for your PNG's (the first 2 numbers) should be within the co-ordinates you specified in the setBoundsInSquares line, with the co-ordinate supplied being where the top-left pixel of your image will be placed. The third number is to scale your image to be bigger or smaller.

 

So in my example below the mapBadge png is being placed 100 pixels in from the right hand border(ending x) and in line with the top border (starting y) of the map area specified in the first line.

The legend is being placed 100 pixels in from the left border (starting x) and 100 pixels down from the top border (starting y).

Both have been scaled to be 66% of their original size.

    mapAPI:setBoundsInSquares(12900, 9900, 14399, 11399)
    -- (starting x, starting y, ending x, ending y) of the area you want to display and uncover, in World Co-ordinates.

 

    overlayPNG(mapUI, 14299, 9900, 0.666, "badge", "media/textures/worldMap/MyLootableMapBadge.png")
    -- Add your lootable maps banner PNG.

 

    overlayPNG(mapUI, 13000, 10000, 0.666, "legend", "media/textures/worldMap/Legend.png")
    -- Add the legend PNG.

Thank you for the help. I haven't managed to get the legend to work but in all honesty I'd rather use a custom image of a map of my area that I have made and was wondering if you could explain the part of the code in your bedford falls map that allows you to use a custom image?

This code:

 

--	overlayPNG(mapUI, 36*300, 21*300+190, 0.666, "lootMapPNG", "media/ui/LootableMaps/bedfordfallsmap.png", 0.5)

 

I have created a square map matching the size of your bedford falls map image but I just don't seem able to make this code work for my image.

I am guessing the 0.666 again is the scale of the image but I do not understand the  36*300, 21*300+190 or the 0.5 and what they do. Knowing this would allow me to add my own map overlay which I'd much prefer to use.

Edited by BigZombieMonkey
Link to comment
Share on other sites

2 hours ago, BigZombieMonkey said:

Thank you for the help. I haven't managed to get the legend to work but in all honesty I'd rather use a custom image of a map of my area that I have made and was wondering if you could explain the part of the code in your bedford falls map that allows you to use a custom image?

This code:

 

--	overlayPNG(mapUI, 36*300, 21*300+190, 0.666, "lootMapPNG", "media/ui/LootableMaps/bedfordfallsmap.png", 0.5)

 

I have created a square map matching the size of your bedford falls map image but I just don't seem able to make this code work for my image.

I am guessing the 0.666 again is the scale of the image but I do not understand the  36*300, 21*300+190 or the 0.5 and what they do. Knowing this would allow me to add my own map overlay which I'd much prefer to use.

That line is not used, it is commented out, hence the "--" at the start, but it is doing the same thing as the other two lines, stamping down a PNG at the provided co-ordinates, works the same way, the last number is for transparency.

Link to comment
Share on other sites

So I lost what was working on due to a hard drive failure, and I can't for the life of me seem to get it working.

 

Short story, I'm trying to use an existing static image as a map. I was using Eerie Country part A because that map has some nice static png images for maps. So does Lake Ivy, but I digress.

 

I have no issues getting the map items into the world, and spawn lists, etc. The ONLY issue is getting the dang image to show up when reading the map.

 

Here is what I think *should* be working as a MapDefinition file, and yet, no go...

 

LootMaps.Init.EerieALootMap = function(mapUI)
    local mapAPI = mapUI.javaObject:getAPIv1()
    MapUtils.initDirectoryMapData(mapUI, 'media/maps/EerieA')
    MapUtils.initDefaultStyleV1(mapUI)
    replaceWaterStyle(mapUI)
    -- mapAPI:setBoundsInSquares(25*300, 45*300, 32*300, 52*300)
    overlayPNG(mapUI, 25*300, 45*300, 0.666, "lootMapPNG", "media/ui/LootableMaps/Eerie A.png")
    MapUtils.overlayPaper(mapUI)
end

 

Tried with/without setBoundsInSquares commented out.
Tried with/without overlayPNG in both combinations with seBoundsInSquares.

 

    item EerieALootMap
    {
    DisplayCategory = Cartography,
        Type                =            Normal,
        DisplayName            =            Eerie Part A,
        Icon                =            Map,
        Weight                =            0.1,
        Map                 =           media/ui/LootableMaps/Eerie A.png,
    WorldStaticModel = Map,
    }

Lootmap item also points to the png.

 

Any assistance, tips, pointers, and other input appreciated. What am I missing?

Link to comment
Share on other sites

58 minutes ago, AlexSledge said:

So I lost what was working on due to a hard drive failure, and I can't for the life of me seem to get it working.

 

Short story, I'm trying to use an existing static image as a map. I was using Eerie Country part A because that map has some nice static png images for maps. So does Lake Ivy, but I digress.

 

I have no issues getting the map items into the world, and spawn lists, etc. The ONLY issue is getting the dang image to show up when reading the map.

 

Here is what I think *should* be working as a MapDefinition file, and yet, no go...

 

LootMaps.Init.EerieALootMap = function(mapUI)
    local mapAPI = mapUI.javaObject:getAPIv1()
    MapUtils.initDirectoryMapData(mapUI, 'media/maps/EerieA')
    MapUtils.initDefaultStyleV1(mapUI)
    replaceWaterStyle(mapUI)
    -- mapAPI:setBoundsInSquares(25*300, 45*300, 32*300, 52*300)
    overlayPNG(mapUI, 25*300, 45*300, 0.666, "lootMapPNG", "media/ui/LootableMaps/Eerie A.png")
    MapUtils.overlayPaper(mapUI)
end

 

Tried with/without setBoundsInSquares commented out.
Tried with/without overlayPNG in both combinations with seBoundsInSquares.

 

    item EerieALootMap
    {
    DisplayCategory = Cartography,
        Type                =            Normal,
        DisplayName            =            Eerie Part A,
        Icon                =            Map,
        Weight                =            0.1,
        Map                 =           media/ui/LootableMaps/Eerie A.png,
    WorldStaticModel = Map,
    }

Lootmap item also points to the png.

 

Any assistance, tips, pointers, and other input appreciated. What am I missing?

Quite possibly because you have commented out your mapAPI:setBoundsInSquares line, the overlay PNG needs to be stamped within the bounds set there.

Link to comment
Share on other sites

Tried all the combinations...

 

    mapAPI:setBoundsInSquares(25*300, 45*300, 32*300, 52*300)
    overlayPNG(mapUI, 25*300, 45*300, 0.666, "lootMapPNG", "media/ui/LootableMaps/Eerie A.png")

 

    -- mapAPI:setBoundsInSquares(25*300, 45*300, 32*300, 52*300)
    overlayPNG(mapUI, 25*300, 45*300, 0.666, "lootMapPNG", "media/ui/LootableMaps/Eerie A.png")

 

    mapAPI:setBoundsInSquares(25*300, 45*300, 32*300, 52*300)
    -- overlayPNG(mapUI, 25*300, 45*300, 0.666, "lootMapPNG", "media/ui/LootableMaps/Eerie A.png")

 

The PNG lives at: \media\ui\LootableMaps\Eerie A.png

 

The distribution & item files are working fine, can spawn & find the map objects in game - just nothing on them when I read them. Not even the outline from when it's attempting to generate a map from the xml files (which I don't think it should be doing anyway?).

Link to comment
Share on other sites

39 minutes ago, AlexSledge said:

Tried all the combinations...

 

    mapAPI:setBoundsInSquares(25*300, 45*300, 32*300, 52*300)
    overlayPNG(mapUI, 25*300, 45*300, 0.666, "lootMapPNG", "media/ui/LootableMaps/Eerie A.png")

 

    -- mapAPI:setBoundsInSquares(25*300, 45*300, 32*300, 52*300)
    overlayPNG(mapUI, 25*300, 45*300, 0.666, "lootMapPNG", "media/ui/LootableMaps/Eerie A.png")

 

    mapAPI:setBoundsInSquares(25*300, 45*300, 32*300, 52*300)
    -- overlayPNG(mapUI, 25*300, 45*300, 0.666, "lootMapPNG", "media/ui/LootableMaps/Eerie A.png")

 

The PNG lives at: \media\ui\LootableMaps\Eerie A.png

 

The distribution & item files are working fine, can spawn & find the map objects in game - just nothing on them when I read them. Not even the outline from when it's attempting to generate a map from the xml files (which I don't think it should be doing anyway?).

The roads etc won't show up on the map if the author hasn't added that feature to his mod yet, it's possible that if the game isnt finding any data to generate the map for the area specified in the setBoundsInSquares line that it cannot stamp down a PNG.

You could also try a PNG without any spaces in the name as well as playing with the scale value.

Link to comment
Share on other sites

So I jumped and did a test (many tests) with Lake Ivy Township, which has a static map png and the xml files to generate the in-gamp map. Went through all that various configurations again using Lake Ivy. While it would generate the in game map from the xml info, it did not display the png in any configuration.

 

Am I going out on a limb to say maybe something broke static png's with the latest mapping system update?

Link to comment
Share on other sites

32 minutes ago, AlexSledge said:

So I jumped and did a test (many tests) with Lake Ivy Township, which has a static map png and the xml files to generate the in-gamp map. Went through all that various configurations again using Lake Ivy. While it would generate the in game map from the xml info, it did not display the png in any configuration.

 

Am I going out on a limb to say maybe something broke static png's with the latest mapping system update?

Just checked with Bedford Falls and the PNG stamping is working fine, might be an idea to download Bedford Falls and check its files.

Link to comment
Share on other sites

I was using Bedford Falls as one of my sanity check tests, but it was beyond me why the Eerie Country stuff wasn't working. Bedford Falls includes a static png image in \ui\LootableMaps, which was throwing me off. Obviously a lot of work was put into creating the custom images, so I believe they worked at one point. Anyway...

 

Things that don't matter:

  • lotpacks/bins/lotheaders existing
  • restarting world (don't need to for testing)
  • whitespace in paths or filenames
  • location of png files
  • legend, lootMapPNG, badge or other designations

                Would be nice to know the layer priority for these though, for layering things over the base map, without me having to do more testing.

 

Key bit to add to mental notes as of 41.68...

 

The two files named worldmap.xml and worldmap-forest.xml must exist in media/maps/MAPNAME.
There doesn't have to be anything in them...  I just created two blank text files and named them appropriately.

 

Now that you have those two blank xml files, make your life a bit easier on image placement without having to spend time resizing/tweaking placement, start at 0, and use your image dimensions:

    -- (0, 0, ([image width in pixels] - 1), ([image height in pixels] - 1))
    mapAPI:setBoundsInSquares(0, 0, 2499, 2499) -- Eerie Country map images are 2500x2500 pixels
    overlayPNG(mapUI, 0, 0, 1, "lootMapPNG", "media/ui/LootableMaps/Eerie A.png")

The "--media/maps/MyMapMod' - this should be where your maps worldmap.xml file is'" comment hinted at the required existence of the xml files, but didn't make clear that they must exist. New behavior? Wondering since the xml files do not exist in the Eerie Country or Lake Ivy Township mods, and their fancy maps do. 

 

Anyway, some information for future generations.

Edited by AlexSledge
Link to comment
Share on other sites

  • 5 months later...
  • 2 months later...

Some map tune scripts I use in my workflow:

 

#!/usr/bin/php
<?php

/********* OPTIONS ***********/
const TILES_PER_CELL = 300;
const BOUND_PADDING  = 10;
/*****************************/

$xmin = null;
$ymin = null;
$xmax = null;
$ymax = null;
$cells = [];
if ( !$argv || !$argv[1] || $argv[1] == '' ) {
  echo 'Missing argument';
  exit(1);
}
if ( !file_exists($argv[1]) ) {
  echo "File {$argv[1]} not found";
  exit(1);
}
$xml = file_get_contents($argv[1]);
$xml = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
foreach ( $xml as $elem ) {
  if ( $elem->getName() == 'cell' ) { $cells[] = $elem; }
}
foreach ( $cells as $cell ) {
  foreach ( $cell->attributes() as $name => $value ) {
    if ( $name == 'x' ) {
      $current = (int)$value * TILES_PER_CELL;
      foreach ( $cell->children() as $feature ) {
        if ( $feature->getName() == 'feature' ) {
          foreach ( $feature->children() as $geometry ) {
            if ( $geometry->getName() == 'geometry' ) {
              foreach ( $geometry->children() as $coordinates ) {
                if ( $coordinates->getName() == 'coordinates' ) {
                  foreach ( $coordinates->children() as $point ) {
                    if ( $point->getName() == 'point' ) {
                      foreach ( $point->attributes() as $key => $val ) {
                        if ( $key == 'x' ) {
                          if ( $xmax == null || $xmax < $current + $val ) { $xmax = $current + $val; }
                          if ( $xmin == null || $xmin > $current + $val ) { $xmin = $current + $val; }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    } elseif ( $name == 'y' ) {
      $current = (int)$value * TILES_PER_CELL;
      foreach ( $cell->children() as $feature ) {
        if ( $feature->getName() == 'feature' ) {
          foreach ( $feature->children() as $geometry ) {
            if ( $geometry->getName() == 'geometry' ) {
              foreach ( $geometry->children() as $coordinates ) {
                if ( $coordinates->getName() == 'coordinates' ) {
                  foreach ( $coordinates->children() as $point ) {
                    if ( $point->getName() == 'point' ) {
                      foreach ( $point->attributes() as $key => $val ) {
                        if ( $key == 'y' ) {
                          if ( $ymax == null || $ymax < $current + $val ) { $ymax = $current + $val; }
                          if ( $ymin == null || $ymin > $current + $val ) { $ymin = $current + $val; }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

$xmin -= BOUND_PADDING;
$ymin -= BOUND_PADDING;
$xmax += BOUND_PADDING;
$ymax += BOUND_PADDING;

echo "\n\nXML cell analysis done!\n";
echo "(xmin, ymin, xmax, ymax) = ${xmin}, ${ymin}, ${xmax}, ${ymax}\n";
exit(0);
?>

You can use it in IDEA from context menu when right click a worldmap.xml file by using a remote tool config like this:

image.png.279fe53cfbe8985e6ebbc764e6e5d0b7.png

 

 

And this lua script can be used to convert spawnpoint entries into the objects.lua format:

spawnpoints = {
  unemployed = {
    { worldX = 26, worldY = 39, posX = 274, posY = 31, posZ = 0 },
    { worldX = 27, worldY = 38, posX = 108, posY = 200, posZ = 0 },
    { worldX = 27, worldY = 38, posX = 146, posY = 270, posZ = 0 },
    { worldX = 27, worldY = 39, posX = 227, posY = 114, posZ = 0 },
    { worldX = 28, worldY = 38, posX = 18, posY = 286, posZ = 0 },
  }
}


for profession, entries in pairs(spawnpoints) do
  local prof = tostring(profession)
  if prof == 'unemployed' then prof = 'all' end
  for _, v in pairs(entries) do
    print("{ name = '', type = 'SpawnPoint', x = "..v.worldX*300+v.posX..", y = "..v.worldY*300+v.posY..", z = "..(v.posZ or "0")..", width = 1, height = 1, properties = { Professions = '"..prof.."' } },")
  end
end

 

 

 

 

 

// Btw: is there any documentation about the lot* binaries? Or can anyone provide me with some informationen about their structure?

I'd like to write a script to generate missing worldmap.xml files from them, because there are some nice maps made with much time and love but without worldmap.xml, which is a pity, because of course it massively reduces the quality of that map.

Edited by stuck1a
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...