------------------------------------------------------------------------------
-- FILE: LWFA-Redux_EXPERIMENTAL.lua
-- BUILD: X1
-- AUTHOR: Jamie 'Skweetis' M. (jm)
-- ABOUT: Total overhaul of my 'LargeWorldFitsAll' script, allowing for more
-- user choice as to how the world is generated. Blah blah blah...
-- (refer to design journal p.73, make it readable!)
--
------------------------------------------------------------------------------
-- TODO:
-- < > Keep documenting! I know you hate it, but you know it's indespensible!
-- < > come up with map name, based on addon module theme...
-- < > Consider keeping override sea_level option, for greater end-user
-- customisablility, somebody may want to override. Need to make sure
-- we add selection for Use Game Start Map Size.
-- < > Restore world_age, but rename to mountain height or something, the
-- idea of age does not fit with add-on mod theme.
-- < > Set all option defaults to Random, the main idea is unpredictability.
------------------------------------------------------------------------------
-- CHANGES:
--
------------------------------------------------------------------------------
------------------------------------------------------------------------------
-- Lua scripts to include so we can call the functions in them, without having
-- to rewrite them
-- UPDATES:
include("MapGenerator");
include("FractalWorld");
include("FeatureGenerator");
include("TerrainGenerator");
------------------------------------------------------------------------------
-- Create our own Custom Options, make sure to add to GetMapScriptInfo()
-- UPDATES:
player_start_option = {
Name = "Player Starts",
Values = {
"Old World",
"Continental",
"Anywhere",
"Random",
},
DefaultValue = 4,
SortPriority = 0,
};
-- FOR DEBUG IN MAP BUILDER ONLY
override_map_size = {
Name = "Override Map Size",
Values = {
"Huge: 12 on 128x80",
"Large: 10 on 104x64",
"Standard: 8 on 80x52",
"Small: 6 on 66x42",
"Tiny: 4 on 56x36",
"Duel: 2 on 40x24",
"Random Map Size",
},
DefaultValue = 3, -- make default "Standard: 8 on 80x52"
SortPriority = 1,
};
-- FOR DEBUG IN MAP BUILDER ONLY
------------------------------------------------------------------------------
-- Gets the options available at Game Setup
-- UPDATES:
function GetMapScriptInfo()
local world_age, temperature, rainfall, sea_level, resources = GetCoreMapOptions()
return {
Name = "Eternal Arena - X1",
Description = "An unpredictable but natural looking 94x58 tile world that uses Map Size to determine Total Land Plots.",
IsAdvancedMap = false,
SupportsMultiplayer = false,
IconIndex = 1,
CustomOptions = {
--[[ world_age ]]-- Add back in after Total Land Area calibration work completed.
temperature, -- 1
rainfall, -- 2
sea_level, -- 3
resources, -- 4
player_start_option, -- 5
override_map_size, -- 6 this is for WorldBuilder Debug, ***DEPRECATE AT RELEASE***
},
};
end
------------------------------------------------------------------------------
-- Resets map grid sizes and/or world wrap
-- UPDATES: X1,
function GetMapInitData(worldSize)
--[[
NOTES:
I borrowed this function from Firaxis' Terra.lua. Useful for overriding
default map grid sizes without having to actually mod any files.
CHANGES:
X1: Return Fixed size between Standard and Large (92x58).
]]--
local worldsizes = {
[GameInfo.Worlds.WORLDSIZE_DUEL.ID] = {92, 58}, --{40, 24},
[GameInfo.Worlds.WORLDSIZE_TINY.ID] = {92, 58}, --{56, 36},
[GameInfo.Worlds.WORLDSIZE_SMALL.ID] = {92, 58}, --{66, 42},
[GameInfo.Worlds.WORLDSIZE_STANDARD.ID] = {92, 58}, --{80, 52},
[GameInfo.Worlds.WORLDSIZE_LARGE.ID] = {92, 58}, --{104, 64},
[GameInfo.Worlds.WORLDSIZE_HUGE.ID] = {92, 58}, --{128, 80}
}
local grid_size = worldsizes[worldSize];
local world = GameInfo.Worlds[worldSize];
--------------------------------------------------------------------------
-- BLOCK START
-- TEST: override GameInfo.Worlds.<WorldSize>.<DefaultPlayers>/<DefaultMinorCivs>? See CIV5Worlds.xml
--
-- BLOCK END
--------------------------------------------------------------------------
if(world ~= nil) then
return {
Width = grid_size[1],
Height = grid_size[2],
WrapX = true,
};
end
end
------------------------------------------------------------------------------
-- This is based on Bob Thomas' (Sirian of Firaxis) custom Fractal Method
-- from Continents.lua. ***Play around later with renaming***
-- UPDATES: X1,
ContinentsFractalWorld = {}; -- this sets the name of custom function? - jm
function ContinentsFractalWorld.Create(fracXExp, fracYExp)
--[[
NOTES:
I believe this creates the Map grid, filling it with ocean plots, and returns
it for use with the Generate PlotTypes custom method. I likely could alter
map grid size in here, no?
CHANGES:
nil
]]--
local gridWidth, gridHeight = Map.GetGridSize();
local data = {
InitFractal = FractalWorld.InitFractal,
ShiftPlotTypes = FractalWorld.ShiftPlotTypes,
ShiftPlotTypesBy = FractalWorld.ShiftPlotTypesBy,
DetermineXShift = FractalWorld.DetermineXShift,
DetermineYShift = FractalWorld.DetermineYShift,
GenerateCenterRift = FractalWorld.GenerateCenterRift,
GeneratePlotTypes = ContinentsFractalWorld.GeneratePlotTypes, -- Custom method
iFlags = Map.GetFractalFlags(),
fracXExp = fracXExp,
fracYExp = fracYExp,
iNumPlotsX = gridWidth,
iNumPlotsY = gridHeight,
plotTypes = table.fill(PlotTypes.PLOT_OCEAN, gridWidth * gridHeight)
};
return data;
end
------------------------------------------------------------------------------
-- This must be where the custom fractal plot method gets applied, after the
-- map dimensions are laid with ocean plots in ContinentsFractalWorld.Create()
-- UPDATES: X1
function ContinentsFractalWorld:GeneratePlotTypes(args)
--[[
NOTES:
Still going to use the Fixed Map method, and adjust Sea_Level to match +/-
for number of civilizations. The difference from LargeWorldFitsAll_v3 will
be that the variation is much tighter to maintain optimum balance, so we need
to:
1...find out the AVERAGE number of land tiles generated by default MAP GRID
SIZE. We will then use this to make sure land area is consistent with
NORMAL sea level for the DEFAULT MAP GRID SIZES. We will then +/- that
percentage to randomise low/arid||normal||high/lush for that number
of Civs.
CHANGES:
X1: 'sea_level_<1...6>' percentages equal to 'landmass_<DUEL2...HUGE12>'
]]--
if(args == nil) then args = {}; end
-- sea_level defaults in Continents.lua were low=67, normal= 72, high=76
-- now is 1 to 6 or lowest percent to highest.Percentages below are
-- calibrated to Total Number Land Plots generated for equivalent MapSize
-- from Firaxis' Pangaea.lua.
-- EternalArena.lua is half way between Default Standard and Large Size Maps
-- at 94X54 generating a total of 5076 Total Plots.
-- so the ratio of sea to land will be different (ie, not always Pangaea at
-- Larger Size.) Calibration values range from +/- 30 to 100 tiles from
-- Duel to Huge respectively. These assume Normal Sea Levels in all cases.
local sea_level_HUGE12 = 41; --X1: Calibration HUGE12 = 3000 Total Land Tiles
local sea_level_LARGE10 = 61; --X1: Calibration LARGE10 = 2000 Total Land Tiles
local sea_level_STANDARD8 = 75; --X1: Calibration STANDARD8 = 1250 Total Land Tiles
local sea_level_SMALL6 = 83; --X1: Calibration SMALL6 = 850 Total Land Tiles
local sea_level_TINY4 = 88; --X1: Calibration TINY4 = 600 Total Land Tiles
local sea_level_DUEL2 = 94; --X1: Calibration DUEL2 = 300 Total Land Tiles
local sea_level_low = -2;
local sea_level_normal = 0;
local sea_level_high = 2;
local world_age_adjustment = 5;
local extra_mountains = 0; --what does this do?
local grain_amount = 3; --need to learn more about grains
local adjust_plates = 1.5; --set to default value for New in Continents.lua
local shift_plot_types = true;
local tectonic_islands = false; --whatdoes this do?
local hills_ridge_flags = self.iFlags; --what is this for?
local peaks_ridge_flags = self.iFlags; --what is this for?
local has_center_rift = false; --looks better if it happens naturally.
--------------------------------------------------------------------------
-- BLOCK START
--
--
-- BLOCK END
--------------------------------------------------------------------------
--------------------------------------------------------------------------
-- BLOCK START
-- This block of code sets up sea level based on option selected at
-- GameSetup, uses that sea level to +/- the sea_level based
-- on the number of Civs for the map size option that was selected
-- Get GameOption sea_level, we will use later to vary the percentage a little
local sea_level_option = Map.GetCustomOption(3)
print("Sea Level option: ", sea_level_option); --DEBUG
if sea_level_option == 4 then --sea level selected is Random
sea_level_option = 1 + Map.Rand(3, "Random Sea Level - Lua");
end
--Get map size chosen at GameSetup
local WorldSizeTypes = {}; --create the container
for row in GameInfo.Worlds() do
WorldSizeTypes[row.Type] = row.ID;
end
local sizekey = Map.GetWorldSize();
-- Sea Level by Map Size Num Civs
local sizevalues = {
[WorldSizeTypes.WORLDSIZE_DUEL] = 6,
[WorldSizeTypes.WORLDSIZE_TINY] = 5,
[WorldSizeTypes.WORLDSIZE_SMALL] = 4,
[WorldSizeTypes.WORLDSIZE_STANDARD] = 3,
[WorldSizeTypes.WORLDSIZE_LARGE] = 2,
[WorldSizeTypes.WORLDSIZE_HUGE] = 1,
};
local pregame_size = sizevalues[sizekey] or 3;
--DEBUG MAPSIZE OVERRIDE FOR WORLDBUILDER
local override_mapsize_option = Map.GetCustomOption(6) --override is debug for worldbuilder
print("- override_mapsize_option is: ", override_mapsize_option); --DEBUG
if override_mapsize_option == 7 then
override_mapsize_option = 1 + Map.Rand(6, "Random WorldSize Sea Level Override - Lua");
end
print("- PreGame world size was: ", pregame_size);
pregame_size = override_mapsize_option;
print("- PreGame world size is now: ", pregame_size);
--DEBUG MAPSIZE
local water_percent = sea_level_STANDARD8; -- init to Standard size, just in case
--set map generation values, depending on Map Size (From Pregame)
if pregame_size == 6 then
water_percent = sea_level_DUEL2;
elseif pregame_size == 5 then
water_percent = sea_level_TINY4;
elseif pregame_size == 4 then
water_percent = sea_level_SMALL6;
elseif pregame_size == 3 then
water_percent = sea_level_STANDARD8;
elseif pregame_size == 2 then
water_percent = sea_level_LARGE10;
else --only option left is 1, so it must be...
water_percent = sea_level_HUGE12;
end
-- now apply sea_level_option (+/-) from user selection to water_percent:
if sea_level_option == 1 then --------- Low Sea Level, %--
water_percent = water_percent + sea_level_low;
elseif sea_level_option == 3 then ----- High Sea Level, %++
water_percent = water_percent + sea_level_high;
else ------------------------------- Normal Sea Level, %+-
water_percent = water_percent + sea_level_normal;
end
-- BLOCK END
--------------------------------------------------------------------------
--------------------------------------------------------------------------
-- FROM Continents.lua --
-- borrowed these because I really like the way sirian's new (3Bill)
-- mountain ranges look. No need to reinvent the wheel. Original Code has
-- been modified or deleted to suit my purposes.
-- -- --
-- Comments below this are not by Skweets unless marked '-jm' --
world_age = 1;
-- Apply adjustment to hills and peaks settings.
local hillsBottom1 = 28 - world_age_adjustment;
local hillsTop1 = 28 + world_age_adjustment;
local hillsBottom2 = 72 - world_age_adjustment;
local hillsTop2 = 72 + world_age_adjustment;
local hillsClumps = 1 + world_age_adjustment;
local hillsNearMountains = 91 - (world_age_adjustment * 2) - extra_mountains;
local mountains = 97 - world_age_adjustment - extra_mountains;
local grain = 4;
local numPlates = 18;
-- Add in any plate count modifications passed in from the map script.
-- Think about possibly randomising the number of plates between 18 24 for variety? --jm
numPlates = numPlates * adjust_plates; --with current settings will result in 24 total plates -jm
-- Generate continental fractal layer and examine the largest landmass.
local iWaterThreshold,
biggest_area,
iNumTotalLandTiles,
iNumBiggestAreaTiles,
iBiggestID;
local grain_dice = Map.Rand(7, "Continental Grain roll - LUA Continents");
if grain_dice < 4 then
grain_dice = 2;
else
grain_dice = 1;
end
self:InitFractal{continent_grain = grain_dice};
iWaterThreshold = self.continentsFrac:GetHeight(water_percent);
-- START BLOCK INFO: this gets the total number of land tiles on the map. useful... -jm
iNumTotalLandTiles = 0;
for x = 0, self.iNumPlotsX - 1 do
for y = 0, self.iNumPlotsY - 1 do
local i = y * self.iNumPlotsX + x;
local val = self.continentsFrac:GetHeight(x, y);
if(val <= iWaterThreshold) then
self.plotTypes[i] = PlotTypes.PLOT_OCEAN;
else
self.plotTypes[i] = PlotTypes.PLOT_LAND;
iNumTotalLandTiles = iNumTotalLandTiles + 1;
end
end
end
-- END BLOCK INFO -jm
self:ShiftPlotTypes();
SetPlotTypes(self.plotTypes);
Map.RecalculateAreas();
biggest_area = Map.FindBiggestArea(false);
iNumBiggestAreaTiles = biggest_area:GetNumTiles();
iBiggestID = biggest_area:GetID();
--[[BEGIN Printout for DEBUG use only ]]--
print("-"); print("--- Continents landmass generation, Attempt#", iAttempts, "---");
print("- This attempt successful: ", done);
print("- Total Land Plots in world:", iNumTotalLandTiles);
print("- Land Plots belonging to biggest landmass:", iNumBiggestAreaTiles);
print("- Continent Grain for this attempt: ", grain_dice);
print("- Rift Grain for this attempt: ", rift_dice);
print("- Water Percent for this attempt: ", water_percent);
print("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
print(".");
--[[ END Printout for DEBUG use only ]]--
-- Generate fractals to govern hills and mountains
self.hillsFrac = Fractal.Create(self.iNumPlotsX, self.iNumPlotsY, grain, self.iFlags, self.fracXExp, self.fracYExp);
self.mountainsFrac = Fractal.Create(self.iNumPlotsX, self.iNumPlotsY, grain, self.iFlags, self.fracXExp, self.fracYExp);
self.hillsFrac:BuildRidges(numPlates, hills_ridge_flags, 1, 2);
self.mountainsFrac:BuildRidges((numPlates * 2) / 3, peaks_ridge_flags, 6, 1);
-- Get height values
local iHillsBottom1 = self.hillsFrac:GetHeight(hillsBottom1);
local iHillsTop1 = self.hillsFrac:GetHeight(hillsTop1);
local iHillsBottom2 = self.hillsFrac:GetHeight(hillsBottom2);
local iHillsTop2 = self.hillsFrac:GetHeight(hillsTop2);
local iHillsClumps = self.mountainsFrac:GetHeight(hillsClumps);
local iHillsNearMountains = self.mountainsFrac:GetHeight(hillsNearMountains);
local iMountainThreshold = self.mountainsFrac:GetHeight(mountains);
local iPassThreshold = self.hillsFrac:GetHeight(hillsNearMountains);
-- Set Hills and Mountains
for x = 0, self.iNumPlotsX - 1 do
for y = 0, self.iNumPlotsY - 1 do
local plot = Map.GetPlot(x, y);
local mountainVal = self.mountainsFrac:GetHeight(x, y);
local hillVal = self.hillsFrac:GetHeight(x, y);
if plot:GetPlotType() ~= PlotTypes.PLOT_OCEAN then
if (mountainVal >= iMountainThreshold) then
if (hillVal >= iPassThreshold) then -- Mountain Pass though the ridgeline
plot:SetPlotType(PlotTypes.PLOT_HILLS, false, false);
else -- Mountain
plot:SetPlotType(PlotTypes.PLOT_MOUNTAIN, false, false);
end
elseif (mountainVal >= iHillsNearMountains) then
plot:SetPlotType(PlotTypes.PLOT_HILLS, false, false);
elseif ((hillVal >= iHillsBottom1 and hillVal <= iHillsTop1) or (hillVal >= iHillsBottom2 and hillVal <= iHillsTop2)) then
plot:SetPlotType(PlotTypes.PLOT_HILLS, false, false);
end
end
end
end
end
------------------------------------------------------------------------------
------------------------------------------------------------------------------
function GeneratePlotTypes()
-- Customized plot generation to ensure avoiding "near Pangaea" conditions.
print("Generating Plot Types (Lua Continents) ...");
local fractal_world = ContinentsFractalWorld.Create();
fractal_world:GeneratePlotTypes();
GenerateCoasts();
end
------------------------------------------------------------------------------
function GenerateTerrain()
print("Generating Terrain (Lua Continents) ...");
-- Get Temperature setting input by user.
local temp_option = Map.GetCustomOption(1)
if temp_option == 4 then
temp_option = 1 + Map.Rand(3, "Random Temperature - Lua");
end
--------------------------------------------------------------------------
-- START BLOCK:
-- overriding Defaults in TerrainGenerator.lua by sending as ARGS.
-- I'm sure there is a better way to do this, but I don't have time to
-- muck around with it.
-- **** THIS NEEDS TO BE LOOKED AT A LITTLE MORE ****
local DesertPercent = 32;
local PlainsPercent = 50;
local SnowLatitude = 0.75;
local TundraLatitude = 0.6;
local GrassLatitude = 0.1;
local DesertBottomLatitude = 0.2;
local DesertTopLatitude = 0.5;
if temp_option == 1 then -- COLD
DesertPercent = DesertPercent + 12;
PlainsPercent = PlainsPercent + 10;
SnowLatitude = SnowLatitude - 0.2;
TundraLatitude = TundraLatitude - 0.2;
GrassLatitude = GrassLatitude - 0.05;
DesertBottomLatitude = DesertBottomLatitude - 0.05;
DesertTopLatitude = DesertTopLatitude - 0.2;
elseif temp_option == 3 then -- HOT
DesertPercent = DesertPercent + 12;
GrassLatitude = GrassLatitude + 0.05;
DesertBottomLatitude = DesertBottomLatitude + 0.1;
else --must be 2 then...
SnowLatitude = SnowLatitude - 0.1;
TundraLatitude = TundraLatitude - 0.1;
DesertTopLatitude = DesertTopLatitude - 0.1;
end
local args = {
temperature = temp_option,
iDesertPercent = DesertPercent,
iPlainsPercent = PlainsPercent,
fSnowLatitude = SnowLatitude,
fTundraLatitude = TundraLatitude,
fGrassLatitude = GrassLatitude,
fDesertBottomLatitude = DesertBottomLatitude,
fDesertTopLatitude = DesertTopLatitude
};
-- END BLOCK
--------------------------------------------------------------------------
local terraingen = TerrainGenerator.Create(args);
terrainTypes = terraingen:GenerateTerrain();
SetTerrainTypes(terrainTypes);
end
------------------------------------------------------------------------------
function AddFeatures()
print("Adding Features (Lua Continents) ...");
local rain = Map.GetCustomOption(2)
if rain == 4 then
rain = 1 + Map.Rand(3, "Random Rainfall - Lua");
end
local args = {rainfall = rain, clump_grain = 4}; --X1: passed clump_grain value to override default in
local featuregen = FeatureGenerator.Create(args);
featuregen:AddFeatures();
end
------------------------------------------------------------------------------
------------------------------------------------------------------------------
function StartPlotSystem()
-- Get Resources setting input by user.
local res = Map.GetCustomOption(4)
if res == 6 then
res = 1 + Map.Rand(3, "Random Resources Option - Lua");
end
print("Creating start plot database.");
local start_plot_database = AssignStartingPlots.Create()
print("Dividing the map in to Regions.");
-- Regional Division Method = how the start positions are distributed
local starts = Map.GetCustomOption(5)
if starts == 4 then --Player start selection was Random
starts = 1 + Map.Rand(3, "Roll Random Division Method - JC Lua");
end
local args = {
method = starts,
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
------------------------------------------------------------------------------