Getting a map script into Civ 6

cephalo

Deity
Joined
Jul 26, 2007
Messages
2,058
Location
Missouri, USA
So I am contemplating updating my PerfectWorld mapscript for civ 6, and apparantly I don't have the chops to make it happen. I looked at some existing examples in other map scripts of the various xml files, and tried to emulate what I saw, but my map won't appear in the list at game start. In fact the only one that seemed to work is Seven05's Detailed Worlds, but why mine doesn't or the others don't is a mystery.

I checked all the log files I could find, and didn't see any errors.

I have attached what I have so far, if someone could take a glance and see what I'm not seeing that would be great. This is a very early version of the mapscript that probably won't work, but I need to get it in game so I can fix it and expand it.
 

Attachments

  • PerfectWorld6.zip
    20.8 KB · Views: 295
Hey Cephalo! I am EXTREMELY excited to see this post because PerfectWorld is my favorite Civ map script ever. I know you are a busy guy, but I really hope you find the time to finish this. Perfect World for Civ 6 would be a dream come true!

I attached the fixed version to this post. I assume you have Rise and Fall active, which is why it wasn't showing up. Your Maps table needs another column called Domain to work with Rise and Fall, which I've added. It seems like you were using an early, pre-Rise and Fall version of Detailed Worlds as your config template.

I also added the Parameters table, allowing the 'advanced' map creation options to be toggled by the player. (World Age, Temperature, Rainfall, Sea Level, Resources, and Start Position).

Beyond that, I've noticed that in your modinfo, you seem to have some extraneous parameters. The following can probably all be deleted safely.
Code:
    <HideSetupGame>0</HideSetupGame>
    <SupportsSinglePlayer>1</SupportsSinglePlayer>
    <SupportsMultiplayer>0</SupportsMultiplayer>
    <SupportsMac>1</SupportsMac>
    <ReloadLandmarkSystem>0</ReloadLandmarkSystem>
    <ReloadStrategicViewSystem>0</ReloadStrategicViewSystem>
    <ReloadUnitSystem>0</ReloadUnitSystem>

For your purposes, you probably only need Name, Teaser, Description, Authors, SpecialThanks, and AffectsSavedGames.

Anyway, I can select your map now, but I get kicked back to the main menu due to an error. Here's the relevant Lua log:

Code:
Syntax Error: C:\Users\p0kiehl\Documents\My Games\Sid Meier's Civilization VI\Mods\PerfectWorld6\Maps\PerfectWorld6.lua:2612: unexpected symbol near ')'
 - Error loading C:\Users\p0kiehl\Documents\My Games\Sid Meier's Civilization VI\Mods\PerfectWorld6\Maps\PerfectWorld6.lua.
GenerateRandomMap: Map Seed = -1179937363
Runtime Error: Cannot find map script entry point GenerateMap()
stack traceback:
    [C]: in function '(anonymous)'
LoadScreen: OnLoadGameViewStateDone
Mods: Failed to create mods browser search context!
Test: Test.LUA loaded!
JoiningRoom: OnFinishedGameplayContentConfigure() g_waitingForContentConfigure=true
JoiningRoom: OnFinishedGameplayContentConfigure() g_waitingForContentConfigure=true
JoiningRoom: OnFinishedGameplayContentConfigure() g_waitingForContentConfigure=true

Let me know whatever else help you need man!
 

Attachments

  • MapScripts.xml
    1.9 KB · Views: 289
Last edited:
Thanks pokiehl! You are a genius!

My first goal is to get this working. Then I want to reintroduce the Civ4 option that PW had of a lost continent or 'Terra' type start. I had one by chance in a Civ6 game recently, and I think it works great. Every civ game needs that option in my opinion. In PW2 it worked well because it wasn't an east/west divide, it could be north/south, or any angle, sandwiched between two 'old worlds' or even multiple 'new worlds'.

I'm likely going to need to replace the starting plot system, which means I"m going to have to quantify the quality of a given start. This will be a work in progress since I'm not super familiar with Civ6 still, and probably don't really know what's balanced.

EDIT: Is there a way to reveal the map without your civ 'knowing' it's been revealed? I don't want to click through the natural wonders and meet everyone just to see the map.
 
Last edited:
No problem at all - I am more than happy to help you. Knowing you're working on this makes my day! I have long dreamed of loading up a PerfectWorld6 :D. As far as Terra, that would be super cool too. Gedemon has made a Terra script for YNAMP, so you may find it beneficial to take a look at his code for that once you get to that stage.

Yes there is a way! It involves FireTuner.

Open up the Map panel, then click the button that says "Set Observer to OBSERVER." Then it will reveal everything without triggering natural wonders, civ meetings, etc.

If you don't know how to use FireTuner, let me know and I'll post a quick and easy walk-through for you.
 
Last edited:
No problem at all - I am more than happy to help you. Knowing you're working on this makes my day! I have long dreamed of loading up a PerfectWorld6 :D. As far as Terra, that would be super cool too. Gedemon has made a Terra script for YNAMP, so you may find it beneficial to take a look at his code for that once you get to that stage.
Well as I have borrowed a bit of PerfectWorld code (Attenuation factors) in my Terra Script, I doubt that cephalo has anything to learn from me in map scripting, I'm sure it's the other way.
 
Well as I have borrowed a bit of PerfectWorld code (Attenuation factors) in my Terra Script, I doubt that cephalo has anything to learn from me in map scripting, I'm sure it's the other way.

Ooh, how did you prevent continents from getting starts from major civs? That would be a big time saver if I could just copy your method.
 
I assume that x = 0 is the start of the "old world" and define a value based on the map width that represent the NewWorldStartX for the "New World" (ie the new world continents are placed on the east side of the map)

Then I override AssignStartingPlots:__SetStartMinor(plots) and AssignStartingPlots:__SetStartMajor(plots, iMajorIndex) (ie copy and edit them from AssignStartingPlots.lua) in the Terra Map script to prevent a start position to be chosen if positionX is > newWorldStartX, depending of the selected options (ie allowing only CS on new world, every civilizations or nobody)
 
Ok, so if I just copy that function, AssignStartingPlots:__SetStartMajor(plots, iMajorIndex), the map script will use mine instead?
 
yes, you can replace any function of AssignStartingPlot (or from the other files you include at the top of your mapscript) this way
 
One more question, PW makes much of a map unusable and works better with fewer civs for a given size. Is there a way to either increase the map sizes or decrease the default number of civs for a specific map type?
 
It's definitely not possible to do script-specific sizes with database editing, but maybe with Lua. In Gedemon's Terra, he defines his map sizes, but again, I know nothing of map scripts or Lua editing so this may or may not be useful:

Code:
------------------------------------------------------------------------------
-- Defines
------------------------------------------------------------------------------

g_iW        = 0
g_iH        = 0
g_MapSize    = 0

-- The base map is the Largest Earth Map
local g_LargestMapWidth     = 230
local g_LargestMapHeight     = 116
local g_LargestMapOldWorldX    = 155

local g_SizeDual                  =  44*26
local g_SizeTiny                  =  60*36
local g_SizeSmall                 =  74*46
local g_SizeStandard              =  84*54
local g_SizeLarge                 =  96*60
local g_SizeHuge                  = 106*66
local g_SizeEnormous              = 128*80
local g_SizeGiant                 = 180*94
local g_SizeLudicrous             = 230*115
local g_LargestEarthOceanWidth     = 24

Another option is to create custom PerfectWorld map sizes. For example, instead of MAPSIZE_STANDARD, we'd have PW_MAPSIZE_STANDARD and it'd be called "Standard (PerfectWorld)" or whatever you wish.

Then, you can easily make it so that when the PerfectWorld map script is chosen from the dropdown, the player can only choose from your custom sizes. This way you will limit compatibility issues with other mods, and not cause hiccups when players choose a different map script.

You need several files to configure new map sizes. I've attached a mock-up of the 3 kinds you'll need, with the default map info loaded in for your convenience to reference. I commented in each whether it should be loaded FrontEnd or InGame.

To limit the PerfectWorld script to certain mapsizes when it's selected, you'll need to add another Table (MapSupportedValues) to your Mapscripts.xml file. I've gone ahead and added a template version of that too.
 

Attachments

  • PW_Maps_Gameplay.xml
    2.2 KB · Views: 119
  • PW_Map_Text.xml
    1.4 KB · Views: 67
  • PW_Maps_Config.xml
    1.6 KB · Views: 271
  • MapScripts.xml
    2.1 KB · Views: 258
Last edited:
Awesome, thanks pokiehl. In Civ 5, making the huge size bigger than normal caused a lot of problems and glitches. Has anyone seen any functional problems associated with extra large maps?
 
Anytime. Also, as you replied, I edited in some potentially relevant code from Gedemon's Terra lua, just in case that helps.

With larger map sizes, the only functional problem is of course the expected increased turn time. Custom, large map sizes are all that I play with and it's very stable (I've made my own larger map sizes in this mod on Steam: https://steamcommunity.com/sharedfiles/filedetails/?id=894934462). I've never once had the game crash on me during normal gameplay with these.

Maybe the improved stability is a function of Civ 6 being 64-bit vs Civ 5 being 32-bit.
 
One more question, PW makes much of a map unusable and works better with fewer civs for a given size. Is there a way to either increase the map sizes or decrease the default number of civs for a specific map type?
There are two functions (AFAIK) that allow to pass/override the setup screen or base game options from the map script to the game engine

GetMapScriptInfo (example from WorldBuilderMap.lua)
Code:
------------------------------------------------------------------------------
-- The application side will call GetMapScriptInfo directly to request
-- information about the map script.
------------------------------------------------------------------------------
function GetMapScriptInfo()
    local world_age, temperature, rainfall, sea_level, resources = GetCoreMapOptions()
    return {
        Name = "TXT_KEY_MAP_WORLDBUILDER",
        Description = "TXT_KEY_MAP_WORLDBUILDER_HELP",
        IsAdvancedMap = 0,
        IconIndex = 0,
        SortIndex = 2,
        CustomOptions = {world_age, temperature, rainfall, sea_level, resources},
    };
end

and GetMapInitData, this one I use to set custom size for a YnAMP option that allow to select only a portion of a TSL Earth map to play on
(example from InlandSea.lua)
Code:
-- Input a Hash; Export width, height, and wrapX
function GetMapInitData(MapSize)
    local MapSizeTypes = {};
    local Width = 0;
    local Height = 0;

    for row in GameInfo.Maps() do
        if(MapSize == row.Hash) then
            Width = row.GridWidth;
            Height = row.GridHeight;
        end
    end

    local WrapX = false;

    return {Width = Width, Height = Height, WrapX = WrapX,}
end
The Width, Height you set in that function will be returned by Map.GetGridSize() in the other parts of the map generation scripts
 
The GetMapInitData example confuses me. The MapSizeTypes object goes unused. The MapSize hash is what exactly? The loop appears to look for the particular row in the size table, and then sets the Width and Height to exactly what it already was... Perhaps the purpose of it's use is to only change the x wrap?

EDIT: Never mind I figured it out. It works great, I just multiplied the sizes by 1.10 and made sure the results were even numbers.
 
Last edited:
I apologize about that Cephalo - I hope my suggestion for new map sizes didn't cause you to waste any time. It just didn't occur to me that there would be a Lua solution to that at first.
 
I confirm: I use GetMapInitData to set custom size for a YnAMP option that allow to select only a portion of a TSL Earth map to play on, see the Giant Earth Map config and script for example

But example from civ5 are maybe clearer and simpler than the civ6 example Firaxis left us or my own use:
sid meier's civilization v\Assets\DLC\DLC_SP_Maps_3\Maps\Script_Random_China.lua
Code:
function GetMapInitData(worldSize)
    -- China has fully custom grid sizes to match the slice of Earth being represented.
    local worldsizes = {
        [GameInfo.Worlds.WORLDSIZE_DUEL.ID] = {26, 20},
        [GameInfo.Worlds.WORLDSIZE_TINY.ID] = {36, 26},
        [GameInfo.Worlds.WORLDSIZE_SMALL.ID] = {44, 32},
        [GameInfo.Worlds.WORLDSIZE_STANDARD.ID] = {52, 36},
        [GameInfo.Worlds.WORLDSIZE_LARGE.ID] = {60, 42},
        [GameInfo.Worlds.WORLDSIZE_HUGE.ID] = {72, 50}
        }
    local grid_size = worldsizes[worldSize];
    --
    local world = GameInfo.Worlds[worldSize];
    if(world ~= nil) then
    return {
        Width = grid_size[1],
        Height = grid_size[2],
        WrapX = false,
    };     
     end
end

or even simplier
sid meier's civilization v\Assets\DLC\DLC_07\Scenarios\Conquest of the New World Deluxe\NewWorld_Scenario_MapScript.lua
Code:
function GetMapInitData(worldSize)
    return {
        Width = 75,
        Height = 100,
        WrapX = false,
    };     
end
 
I'm on it! I'm struggling a bit getting back into lua. I'm trying to transfer pseudocode of an algorithm that does index math, into a language that uses 1 based indexing! Yuck! However, the map looks great and I will power through the remaining issues soon.
 
Top Bottom