Fractal Map Options Playground for Virgin 'Scripters [ALPHAv3]

skweetis

Chieftain
Joined
Mar 14, 2008
Messages
58
Location
Canada
Hey all,

this is a cut & paste of a lua script I have used in learning how to script lua for Civ5 maps. I have it set up for WorldBuilder to explore what various fractal options do.

This post prompted me share it, so I thought it would be appropriate to put up here as well. I threw some quick comments in my code, some of which may be incorrect or need better explanation from someone with more experience as to my understanding of how things work. Once I am confident that this is an informative tool, ill package it up and make available for download in game, and here at Civ fanatics.

Hope it helps someone. Feedback encouraged and appreciated.

Code:
------------------------------------------------------------------------------
--	FILE:	 FractalMapOptionsPlayground.lua
--	AUTHOR:  Jamie McQueen (Skweetis)
--	PURPOSE: Map script for exploring Fractal options and their effects during
--			 Map Generation. By a mapscript virgin for mapscript virgins.  
--			 Some options will hang worldbuilder
--			 in certain cases (I.E low continent_grain value and extra_mountains
--			 value above 6 for example.  Generator log printstatements allow
--			 debugging of values.  Best when used with UNOFFICIAL patched 
--			 WorldBuilder version 4 or better (available at www.civfanatics.com)
--			 which keeps the log window open during map generation among other 
--			 improvements.
--			 I have included what comments I can, and have laid it out in a way
--			 that I find easiest to follow. By no means is this reflective of how
--			 things should be laid out.  I have only hobby
--			 level programming experience and am not a coding expert by any stretch.
--			 It has helped me immensly though, in figuring out what things do,
--			 And learning to create mapscripts. As this was created as a personal
--			 reference tool, it has not been tested in-game, though I see no 
--			 reason why it should not work.  Hopefully other budding mapscripters
--			 will find it useful.   I suggest looking through this while also
--			 refering to FractalWorlds.lua in ../GamePlay/Lua/. which is really
--			 the blood and guts of fractal world building, and includes numerous
--			 helpfull comments left by Bob and Brian (some referenced in here)
--			 Enjoy and good luck exploring! -jm
--			 Special thanks to ColBashar for his input on my map script, his
--			 advice helped align me in the direction I needed to go. Turned
--			 into a public tool because of cassembler's request for a blank
--			 map. 
------------------------------------------------------------------------------
--	Copyright (c) 2010 Firaxis Games, Inc. All rights reserved.
------------------------------------------------------------------------------

--what other lua files have code in them we will call in our map script are listed here.
include("MapGenerator");
include("FractalWorld");
include("FeatureGenerator");
include("TerrainGenerator");

------------------------------------------------------------------------------
function GetMapScriptInfo() --somebody else would be better to describe it, I'm sure my explaination would cause more confusion than knowledge.
	local world_age, temperature, rainfall, sea_level, resources = GetCoreMapOptions() -- 'local' statements are where how declare a variable.
	return { -- somebody else can explain returns better.
		Name = "FractalMapOptionsPlayground",
		Description = "A very customisable fractal based world generator.",
		IsAdvancedMap = false, -- setting to True will make this map only appear when Advanced button is clicked
		IconIndex = 16,
		SortIndex = 1,
		CustomOptions = {
		world_age, temperature, rainfall, sea_level, resources, --CustomOption index +5 (5 core map options, which are defaulted to -99 to -95 so as to always come first)
			{
			Name = "Continent Grain", -- Map.GetCustomOption(6) <<I do this only for reference to help remember what Option Pulldown information I am getting when putting in a variable (see next function)
				Values = { -- play and see!  basically smaller values make larger continents or a pangaea, larger will result in scattered islands.
					"1", -- DefaultValue means this will be the first option displayed.  Index (count) starts at 1 and counts up for each entry.  Text is only used in pull down.  Script takes index only.
					"2", -- index value 2
					"3",
					"4",
					"5",
					"6",
					"TXT_KEY_MAP_OPTION_RANDOM"
				},
				DefaultValue = 1, -- which index position will be displayed by default in pulldown. 
				SortPriority = 1, -- which order this option pulldown will be displayed. 
			},
			{
			Name = "Center Rift?", -- Map.GetCustomOption(7)
				Values = { -- puts an ocean rift on the map to difinitively split continents apart. Essentially creates at least two separate land masses.
					"No", -- Default
					"Yes",					
					"TXT_KEY_MAP_OPTION_RANDOM"
				},
				DefaultValue = 1,
				SortPriority = 2,
			},
			{
			Name = "Rift Grain", -- Map.GetCustomOption(8)
				Values = {-- -1 is Default no rifts. Set grain to between 1 and 3 to add rifts. - Bob(FractalWorld.lua)
					"-1", -- Default
					"1",
					"2",
					"TXT_KEY_MAP_OPTION_RANDOM"-- Default
				},
				DefaultValue = 1,
				SortPriority = 3,
			},
			{
			Name = "Has Tectonic Islands?", -- Map.GetCustomOption(9)
				Values = {-- Build islands in oceans along tectonic ridge lines - Brian(FractalWorlds.lua)
					"No", -- Default
					"Yes",
					"TXT_KEY_MAP_OPTION_RANDOM" 
				},
				DefaultValue = 1,
				SortPriority = 4,
			},
			{
			Name = "Polar?", -- Map.GetCustomOption(10)
				Values = { -- I'm not clear exactly on what this does yet -jm
					"No", -- Default
					"Yes",
					"TXT_KEY_MAP_OPTION_RANDOM" 
				},
				DefaultValue = 1,
				SortPriority = 5,
			},
			{
			Name = "Extra Mountains", -- Map.GetCustomOption(11)
				Values = {
					"0", -- Default
					"1",
					"2",
					"3",
					"4",
					"5",
					"6",
					"7",
					"8",
					"9",
					"10",
					"TXT_KEY_MAP_OPTION_RANDOM" 
				},
				DefaultValue = 1,
				SortPriority = 6,
			},
			{
			Name = "Adjust Plates", -- Map.GetCustomOption(12)
				Values = { 
					"0", -- Default
					"1",
					"1.5",
					"3",
					"TXT_KEY_MAP_OPTION_RANDOM"
				},
				DefaultValue = 1,
				SortPriority = 7,
			},
			{
			Name = "Player Distribution",-- Map.GetCustomOption(13)
				Values = {
					"Old World",
					"Continental",
					"Map Rectangle",
					"TXT_KEY_MAP_OPTION_RANDOM"-- DefaultValue = 4,
				},
				DefaultValue = 4, 
				SortPriority = 8
			},
		};		
	};
end
------------------------------------------------------------------------------

------------------------------------------------------------------------------
function GeneratePlotTypes()
	print("Generating Plot Types (Lua Worlds Unlimited) ..."); -- these statements only printout in the log.  Useful for debugging, gives you a reference point when (and it will) your script blows up in the builder.  Last print you see, gives you an idea where to look in your script.

	-- collect user options and put them in a variable.   I do it this way, there are many other methods, likely better coding practice, but
	-- I found this way easier to follow while learning. The index of the option selected above is what we pass to the variable so we can do
	-- stuff with it.
	local sea_level = Map.GetCustomOption(4) -- my translation: "make me a container called sea_level and put the value the Map Option
	local world_age = Map.GetCustomOption(1)	
	local continent_grain = Map.GetCustomOption(6) --this is the first custom option in the above function.
	local rift_bool = Map.GetCustomOption(7) -- bool is short for boolean (true or false) Im in the habit of getting the numerical value, and turn it in to actual true or false after. 
	local rift_grain = Map.GetCustomOption(8)
	local islands_bool = Map.GetCustomOption(9)
	local polar_bool = Map.GetCustomOption(10)
	local extra_mountains = Map.GetCustomOption(11)
	local adjust_plates = Map.GetCustomOption(12)
	
	--default to false, I find it good practice to always 'initialise' your variables (ie, make sure they = something).  I can't remember why though I'm sure there is a good reason! The pros always seem to do it!
	local has_center_rift = false;
	local tectonic_islands = false;
	local polar = false;

	-- calculate random selections, and modify any values
	if sea_level == 4 then -- user selected random, so we are going to select from one of the other options in the list.  Remember, we use the pulldown option index value, the text in quotes means nothing to the script.
		sea_level = 1 + Map.Rand(3, "Random Sea Level - Lua"); -- this one is a bit longer to explain.  try and take a good look at it and see if you can figure out and understand what is happening here (a good habit and skill to practice, imo) if not, make sure you take a peak at one of the tutorial's for Civ5 Map scripting out there.
	end	
	print("DEBUG - Sea Level: ", sea_level); -- we want to see what was picked, this desplays it in the log.  notice how it is written, recognise anything familiar?

	if world_age == 4 then -- always always always try to remember to make sure you use two == when doing an 'if' evaluation. pain in the ass to find when you have a big script and cant find out why it isn't working!
		world_age = 1 + Map.Rand(3, "Random World Age - Lua");
	end
	print("DEBUG - World Age: ", world_age);

	if continent_grain == 7 then
		continent_grain = 1 + Map.Rand(6, "Random Continent Grain - Lua"); 
	end
	print("DEBUG - Continent Grain: ", continent_grain);

	if rift_bool == 3 then
		rift_bool = 1 + Map.Rand(2, "Random Has Rift - Lua"); -- don't add 1, this is boolean.
	end
	if rift_bool == 2 then
		has_center_rift = true;  -- remember we initialised this to false above? well if it isn't random, and they didn't pick the first option (which would be false, and this variable is already set to false) the only option they have left is 2, which translates to true.
	end
	print("DEBUG - Has Center Rift: ", has_center_rift);

	if rift_grain == 4 then
		rift_grain = Map.Rand(3, "Random Continent Grain - Lua"); -- no need to add 1, because randomising resets the index start count to 0, and the value we need from this option is 0.
	else
		rift_grain = rift_grain - 1-- we still need that value to be 0, so if random was not selected, the index count would be 1 if the user selected the first value, and we need 0 for this option, so lets take one away from that value.
	end
	if rift_grain < 1 then -- only do this if the value is 0 or less
		rift_grain = -1; -- we needed the 0, but it is not a valid option, and the first for this list is -1, so this here turns that 0 we can't use into a zero we can.
	end	
	print("DEBUG - Rift Grain: ", rift_grain);

	if polar == 3 then
		polar = 1 + Map.Rand(2, "Random Polar - Lua");
	end
	if polar_bool == 2 then
		polar = true;
	end
	print("DEBUG - Polar: ", polar);

	if islands_bool == 3 then
		islands_bool = 1 + Map.Rand(2, "Random Tectonic Islands - Lua"); 
	end
	if islands_bool == 2 then
		tectonic_islands = true;
	end
	print("DEBUG - Tectonic Islands: ", tectonic_islands);

	if extra_mountains == 12 then
		extra_mountains = Map.Rand(11, "Random Extra Mountains - Lua"); -- no need to add 1, starts at 0
	else
		extra_mountains = extra_mountains -1;
	end
	print("DEBUG - Extra Mountains: ", extra_mountains);

	if adjust_plates == 5 then
		adjust_plates = 1 + Map.Rand(4, "Random Adjust Plates - Lua");
	end
	if adjust_plates == 1 then
		adjust_plates = 0;
	elseif adjust_plates == 2 then
		adjust_plates = 1;
	elseif adjust_plates == 3 then
		adjust_plates = 1.5;	
	elseif adjust_plates == 4 then
		adjust_plates = 3;
	end
	print("DEBUG - Adjust Plates: ", adjust_plates);


	local fractal_world = FractalWorld.Create(); -- the way I undertand it, this gets the code from the Create() function in the file FractalWorld, the . is the separator, and it gets stored in our variable called fractal_world which we will use below.  It may just be that its easier to type fractal_world than FractalWorld.Create() repeatedly... either way we are calling a function from another file we included at the top of our script.
	fractal_world:InitFractal{ -- passing all the values between the braces, each variable separated by commas. the duplicate names may be redundant, but it makes it quicker to play change the value of any of those variables.
		continent_grain = continent_grain,
		rift_grain = rift_grain, 
		has_center_rift = has_center_rift, 
		polar = polar,
		};

	local args = {
		sea_level = sea_level,
		world_age = world_age,
		sea_level_low = 69,
		sea_level_normal = 75,
		sea_level_high = 80,
		extra_mountains = extra_mountains,
		adjust_plates = adjust_plates,
		has_center_rift = has_center_rift,
		tectonic_islands = tectonic_islands,
		};
	local plotTypes = fractal_world:GeneratePlotTypes(args);
	
	SetPlotTypes(plotTypes);
	GenerateCoasts();
end
------------------------------------------------------------------------------
function GenerateTerrain()
	print("Generating Terrain (Lua Worlds Unlimited) ...");
	
	-- Get Temperature setting input by user.
	local temp = Map.GetCustomOption(2)
	if temp == 4 then
		temp = 1 + Map.Rand(3, "Random Temperature");
	end

	local args = {temperature = temp};
	local terraingen = TerrainGenerator.Create(args);

	terrainTypes = terraingen:GenerateTerrain();
	
	SetTerrainTypes(terrainTypes);
end
------------------------------------------------------------------------------
function AddFeatures()
	print("Adding Features (Lua Worlds Unlimited) ...");

	-- Get Rainfall setting input by user.
	local rain = Map.GetCustomOption(3)
	if rain == 4 then
		rain = 1 + Map.Rand(3, "Random Rainfall - Lua");
	end
	
	local args = {rainfall = rain}
	local featuregen = FeatureGenerator.Create(args);

	-- False parameter removes mountains from coastlines.
	featuregen:AddFeatures();
end
------------------------------------------------------------------------------
function StartPlotSystem()
	-- Get Resources setting input by user.
	local res = Map.GetCustomOption(5)
	local start_method = Map.GetCustomOption(13)

	if res == 6 then
		res = 1 + Map.Rand(3, "Random Resources Option");
	end
		
	if start_method == 4 then
		start_method = 1 + Map.Rand(3, "Random Player Distribution");
	end

	print("Creating start plot database.");
	local start_plot_database = AssignStartingPlots.Create()
	
	print("Dividing the map in to Regions.");
	local args = {
		method = start_method,
		resources = res,
		};
	start_plot_database:GenerateRegions(args)

	print("Choosing start locations for civilizations.");
	start_plot_database:ChooseLocations()
	
	print("Normalizing start locations and assigning them to Players.");
	start_plot_database:BalanceAndAssign()

	print("Placing Natural Wonders.");
	start_plot_database:PlaceNaturalWonders()

	print("Placing Resources and City States.");
	start_plot_database:PlaceResourcesAndCityStates()
end
------------------------------------------------------------------------------

EDIT1: fixed small bug! oops
EDIT2: Caught another one (if anyone cares, this version is the same as edit 3 in the other thread. I should have just made sure that one was right before posting this one. sorry for confusion!
 
Back
Top Bottom