What the new patch has wrecked/changed

But you could do that ALREADY. I'd replaced AssignStartingPlots, TopPanel, TechButtonInclude, and so on with my own heavily-modified versions.

If you mean replace database XML files altogether (instead of having to delete each line individually) then I can see the appeal there, but that would seem to conflict with the whole UpdateDatabase system they already have. But regardless, that doesn't apply to the cases we were talking about (new .DDS files, new .lua files), all of which replaced the old files entirely under the old system already, but which now won't do so until you set this flag.

Again, the question isn't "what can you do with it set to True", because we already know that; it was set to True before, so we've already got that as our baseline. The question is "what can you do with it set to False that you couldn't do when it defaulted to True". As in, why would you EVER want to leave it set to False (or more specifically, why you would ever want to leave it to the user to decide whether it's True or False instead of hard-coding it to True for asset files and such). If you can give some explicit examples then it'll make it far easier for us to figure out things like why AssignStartingPlots is crashing.

I did indeed mean replacing XML files.

IIRC, the ability to set it to false was mostly to address issues with multiple xml files with the same name (look below); At this point, though, I really don't know too much more than you guys. I'm waiting for clarification, and when I get it, I will make sure to pass what I can on.

About all I know: "Import into VFS" should be set to FALSE if you do not want files to replace existing files but instead be treated like a separate entity. For gameplay XML files, or new UI addin files, keep this set to false so that the modding framework references it directly. For files that you DO want to replace (like the unit art xml or any existing interface xmls such as InGame.xml) then you want the property to be set to TRUE.

How? I'm not trying to be confrontational here, I mean exactly how? Are you saying that if two mods change AssignStartingPlots.lua, it WON'T still freak out? I can understand if, by sheer coincidence, two mods happened to use the same names for two totally unrelated NEW files (although that's really the modders' fault), but when you're editing old stuff, there's no possible way the code is intelligent enough to merge both sets of modifications seamlessly, and for something like AssignStartingPlots (which runs once and then is done) it couldn't treat them as separate routines and execute them separately.

Multiple XML files with the same names (new files) would cause issues. This happened extremely often if people followed Kael's guide to the letter, which many new modders did.

Lua files, of course, would still have issues. No way around taht.

It's very useful to have a tool like that, but the only problem here is that we don't usually keep around a copy of the old versions of the official files. If I'm changing 50 lines in a file and the patch changed 5, it'd be easier to diff the pre-patch and post-patch versions and move those 5 lines into my own mod. But currently, you can only diff your mod and the post-patch version, which means any difference lines will be either your work OR the patch's, so you just have to hope you remember which of the 55 lines were the ones you changed.
I didn't think about this until after the patch, but I've now made a backup directory of all the Lua and XML files, so that I can do this sort of thing the next time.

I was going to say that you'd have YOUR version of the file, but then I read a bit further.

Honestly, that is why I typically comment things in Lua and interface xmls.
 
About all I know: "Import into VFS" should be set to FALSE if you do not want files to replace existing files but instead be treated like a separate entity. For gameplay XML files, or new UI addin files, keep this set to false so that the modding framework references it directly. For files that you DO want to replace (like the unit art xml or any existing interface xmls such as InGame.xml) then you want the property to be set to TRUE.

Seems reasonable. So my new Terraform.lua (which is linked inside InGame.xml at the moment, although I'm trying to break that dependency) would be False, but InGame.xml and AssignStartingPlots.lua would be True.

Honestly, that is why I typically comment things in Lua and interface xmls.

Commenting can only get you so far. For instance, take AssignStartingPlots.lua.
In my mod, I added three new future-era strategic resources (one land, one sea, one both). That means I had to:
> Add new ID definitions at the top of the file
> Edit the two routines that return spawn amounts (Major and Small), which now set and return three additional values
> Add two new routines for spawning the water-based resources (similar to the existing Oil logic)
> Edit all of the Small spawn randomization tables, both in terms of the maximum random roll and the chance of each resource
> Increase the NUMBER of Small spawns made overall (went from 23 to 35) to keep from reducing the numbers of old resources.
> Edit all of the Major spawn randomization tables, both in terms of the probabilities of each resource and the probability that a given hex has a resource at all
> Add more minimum spawn checks at the end
And then to top it off, I'd also created a few new blocks of code in there to spawn a few extras of each new resource to balance the probabilities correctly.

As you can guess, I am NOT going to redo all of that every time a patch comes out that changes one or two lines in the base version. I did it this one time, because I didn't have a baseline to compare to any more, but never again.
 
Seems reasonable. So my new Terraform.lua (which is linked inside InGame.xml at the moment, although I'm trying to break that dependency) would be False, but InGame.xml and AssignStartingPlots.lua would be True.

Correct. If it's crashing when lua files are set to true, something is wrong and needs to be fixed.

Commenting can only get you so far. For instance, take AssignStartingPlots.lua.
In my mod, I added three new future-era strategic resources (one land, one sea, one both). That means I had to:
> Add new ID definitions at the top of the file
> Edit the two routines that return spawn amounts (Major and Small), which now set and return three additional values
> Add two new routines for spawning the water-based resources (similar to the existing Oil logic)
> Edit all of the Small spawn randomization tables, both in terms of the maximum random roll and the chance of each resource
> Increase the NUMBER of Small spawns made overall (went from 23 to 35) to keep from reducing the numbers of old resources.
> Edit all of the Major spawn randomization tables, both in terms of the probabilities of each resource and the probability that a given hex has a resource at all
> Add more minimum spawn checks at the end
And then to top it off, I'd also created a few new blocks of code in there to spawn a few extras of each new resource to balance the probabilities correctly.

As you can guess, I am NOT going to redo all of that every time a patch comes out that changes one or two lines in the base version. I did it this one time, because I didn't have a baseline to compare to any more, but never again.

Yeah, some files are a pain to work with. Backups are very useful. :goodjob:

I had a situation like that with my own DarkAges mod (which now CAN"T be released, as I used scriptdata... :wallbash: Hopefully that is addressed soon) and the top panel, to display it correctly. Wholesale replacement of functions, rather than adding code into them.
 
(which now CAN"T be released, as I used scriptdata... :wallbash: Hopefully that is addressed soon)

No kidding. I only used scriptdata in a very limited way (parts taken from Whys' Building Resources mod), but that's broken now. It boggles the mind that the devs would remove any working functionality for any reason while leaving in nonfunctional stubs for things like Religion, but it's even more insane when you realize how fundamental of a thing they removed. (Seriously, people figured out a way to save variables in an intelligent way, the one thing that's practically essential for any real modding, and THAT'S what gets removed?)

Obviously I have a vested interest in sorting this whole VFS thing out. My mod has a few entirely new Lua files, several mod-specific changes to existing mods (like the AssignStartingPlots) and several cases where I improved the existing logic. And yes, I mean improve, they're not just tweaks to make things look the way I want, they're things that fix mistakes in the base code.
For instance, Bombardment.lua: it tries to draw the boundary of what a unit can bombard, showing that red ring on the ground. What do you think happens if an Air unit has a range larger than half the size of the world? Hint: it doesn't handle the overlap too well...
Or, TopPanel.lua. If you take a strategic resource and give it some Happiness, it'll show up in the happiness list, but it'll no longer show up as a strategic at the top of the screen (in the part that shows you how many you have left). It SHOULD show up in both, so I fixed the logic.
From the sound of it, it should be False only for the Lua I created myself (which I added in InGame.xml) and the database XMLs, True for everything else. I'll try this when I get home.
 
I didn't use lua for my mod, just straight XML, and it's worked fine...until the patch. I've had the same txt_key and dds problems other people mentioned. Some of this thread is getting a bit involved and over my head. Can these things be fixed in my XML? If so, can anyone post an example of what needs to be changed? Perhaps before and after pics?
 
I didn't use lua for my mod, just straight XML, and it's worked fine...until the patch. I've had the same txt_key and dds problems other people mentioned. Some of this thread is getting a bit involved and over my head. Can these things be fixed in my XML? If so, can anyone post an example of what needs to be changed? Perhaps before and after pics?

I answered your question in my mod thread. But the short verison is that you need to right click a file, including XML and set the VFS property to true.

As far as I can tell, this property does not work as intended, as I have new files - lua and xml - and if the property is not set to true, they are not used.

While I am at this, it is always bad form to make a change that changes the currently working defaults. So if they needed to add this property, the default value should have been set to True.
 
In terms of AssignStartingPlots.lua, I happened to have a copy of the old one saved on a USB drive. Spoiled below is a unified diff of the changes, which are pretty extensive.

Spoiler :
Code:
--- AssignStartingPlots_0621.lua	2010-09-21 21:20:38.000000000 -0400
+++ AssignStartingPlots_1135.lua	2010-12-15 19:28:21.971348600 -0500
@@ -139,6 +139,7 @@
 		CanBeMesa = AssignStartingPlots.CanBeMesa,
 		CanBeReef = AssignStartingPlots.CanBeReef,
 		CanBeKrakatoa = AssignStartingPlots.CanBeKrakatoa,
+		CanBeRareMystical = AssignStartingPlots.CanBeRareMystical,
 		GenerateNaturalWondersCandidatePlotLists = AssignStartingPlots.GenerateNaturalWondersCandidatePlotLists,
 		AttemptToPlaceNaturalWonder = AssignStartingPlots.AttemptToPlaceNaturalWonder,
 
@@ -218,7 +219,7 @@
 		mesa_list = {},
 		reef_list = {},
 		krakatoa_list = {},
-		krakatoa_fallback_list = {},
+		mystical_list = {},
 		placed_natural_wonder = {},
 		
 		-- City States variables
@@ -4760,7 +4761,7 @@
 	for loop = 1, self.iNumCivs do
 		local player_ID = self.player_ID_list[loop];
 		if civ_status[player_ID + 1] == false then -- Using C++ player ID, which starts at zero. Add 1 for Lua indexing.
-			table.insert(playerList, player_ID); -- Using C++ player ID, which starts at zero.
+			table.insert(playerList, player_ID);
 		end
 		if region_status[loop] == false then
 			table.insert(regionList, loop);
@@ -4856,19 +4857,16 @@
 function AssignStartingPlots:CanBeGeyser(x, y)
 	-- Checks a candidate plot for eligibility to be the Geyser.
 	local plot = Map.GetPlot(x, y);
-	-- Checking center plot, which must be at least two plots away from any salt water, and not be in the desert or tundra.
+	-- Checking center plot, which must be at least one plot away from any salt water.
 	if plot:IsWater() then
 		return
 	end
 	local iW, iH = Map.GetGridSize();
 	local plotIndex = y * iW + x + 1;
-	if self.plotDataIsCoastal[plotIndex] == true or self.plotDataIsNextToCoast[plotIndex] == true then
+	if self.plotDataIsCoastal[plotIndex] == true then
 		return
 	end
 	local terrainType = plot:GetTerrainType()
-	if terrainType == TerrainTypes.TERRAIN_DESERT or terrainType == TerrainTypes.TERRAIN_TUNDRA then
-		return
-	end
 	local iNumMountains, iNumHills, iNumDeserts, iNumTundra = 0, 0, 0, 0;
 	local plotType = plot:GetPlotType();
 	if plotType == PlotTypes.PLOT_MOUNTAIN then
@@ -4876,6 +4874,11 @@
 	elseif plotType == PlotTypes.PLOT_HILLS then
 		iNumHills = iNumHills + 1;
 	end
+	if terrainType == TerrainTypes.TERRAIN_TUNDRA then
+		iNumTundra = iNumTundra + 1;
+	elseif terrainType == TerrainTypes.TERRAIN_DESERT then
+		iNumDeserts = iNumDeserts + 1;
+	end
 	-- Now process the surrounding plots. We are checking for lakes, mountains, hills, tundra and deserts.
 	for loop, direction in ipairs(self.direction_types) do
 		local adjPlot = Map.PlotDirection(x, y, direction)
@@ -4896,14 +4899,14 @@
 		end
 	end
 	-- If too many deserts, tundra or mountains, reject this site.
-	if iNumDeserts > 2 or iNumTundra > 2 or iNumMountains > 5 then
+	if iNumDeserts > 3 or iNumTundra > 3 or iNumMountains > 5 then
 		return
 	end
 	-- If not enough hills or mountains, reject this site.
 	if iNumMountains < 1 and iNumHills < 4 then
 		return
 	end
-	-- This site is inland, has hills or mountains, not too many deserts, and not too many mountains, so it's good.
+	-- This site is inland, has hills or mountains, not too many tundra or desert, and not too many mountains, so it's good.
 	table.insert(self.geyser_list, plotIndex);
 end
 ------------------------------------------------------------------------------
@@ -4948,7 +4951,7 @@
 		end
 	end
 	-- If too many hills or mountains, reject this site.
-	if iNumMountains > 1 or iNumHills + iNumMountains > 3 then
+	if iNumMountains > 2 or iNumHills + iNumMountains > 4 then
 		return
 	end
 	-- This site is inland, in desert or tundra with no grass around, and does not have too many hills and mountains, so it's good.
@@ -4981,12 +4984,12 @@
 			iNumLand = iNumLand + 1;
 		end
 	end
-	-- If too much land, reject this site.
+	-- If too much land (or none), reject this site.
 	if iNumLand ~= 1 then
 		return
 	end
 	-- If not enough coast, reject this site.
-	if iNumCoast < 4 then
+	if iNumCoast < 3 then
 		return
 	end
 	-- This site is good.
@@ -5038,10 +5041,10 @@
 		end
 	end
 	-- If too many hills, reject this site.
-	if iNumHills > 1 then
+	if iNumHills > 2 then
 		return
 	end
-	-- This site is on an eligible landmass, in grassland or plains, with no more than one Hills nearby, so it's good.
+	-- This site is on an eligible landmass, in grassland or plains, with no more than two Hills nearby, so it's good.
 	table.insert(self.fuji_list, plotIndex);
 end
 ------------------------------------------------------------------------------
@@ -5058,7 +5061,7 @@
 		return
 	end
 	local terrainType = plot:GetTerrainType()
-	if terrainType == TerrainTypes.TERRAIN_GRASS or terrainType == TerrainTypes.TERRAIN_TUNDRA then -- Rejecting grass or tundra.
+	if terrainType == TerrainTypes.TERRAIN_GRASS then -- Rejecting grass.
 		return
 	end
 	local iNumMountains, iNumHills = 0, 0;
@@ -5075,7 +5078,7 @@
 			return
 		end
 		terrainType = adjPlot:GetTerrainType()
-		if terrainType == TerrainTypes.TERRAIN_GRASS or terrainType == TerrainTypes.TERRAIN_TUNDRA then
+		if terrainType == TerrainTypes.TERRAIN_GRASS then
 			return
 		end
 		plotType = adjPlot:GetPlotType();
@@ -5093,7 +5096,7 @@
 	if iNumHills < 2 then
 		return
 	end
-	-- This site is inland, in desert or plains with no grass or tundra around, and has a moderate amount of hills and mountains.
+	-- This site is inland with no grass around, and has a moderate amount of hills and mountains.
 	table.insert(self.mesa_list, plotIndex);
 end
 ------------------------------------------------------------------------------
@@ -5158,21 +5161,10 @@
 function AssignStartingPlots:CanBeKrakatoa(x, y)
 	-- Checks a candidate plot for eligibility to be Krakatoa the volcano.
 	local plot = Map.GetPlot(x, y);
-	-- Check the center plot. If it's a 1-tile island we've lucked out.
-	local bOneTileIsland = false;
+	-- Check the center plot, which must be ocean surrounded on all sides by more ocean. (Updated Nov 2010)
 	if not plot:IsWater() then
-		local iAreaID = plot:GetArea();
-		local area = Map.GetArea(iAreaID);
-		local iNumAreaTiles = area:GetNumTiles();
-		if iNumAreaTiles == 1 then -- This is a prime candidate for Krakatoa.
-			bOneTileIsland = true;
-		else -- Land area of multiple plots, we're in the wrong place.
-			return
-		end
+		return
 	end
-	local iW, iH = Map.GetGridSize();
-	local plotIndex = y * iW + x + 1;
-	-- Even if the center plot is water, it can be forced, if all surrounding plots are ocean.
 	for loop, direction in ipairs(self.direction_types) do
 		local adjPlot = Map.PlotDirection(x, y, direction)
 		if adjPlot:IsWater() == false then
@@ -5180,11 +5172,25 @@
 		end
 	end
 	-- Surrounding tiles are all ocean water, not lake, and free of Feature Ice, so it's good.
-	if bOneTileIsland then
-		table.insert(self.krakatoa_list, plotIndex);
-	else
-		table.insert(self.krakatoa_fallback_list, plotIndex);
+	local iW, iH = Map.GetGridSize();
+	local plotIndex = y * iW + x + 1;
+	table.insert(self.krakatoa_list, plotIndex);
+end
+------------------------------------------------------------------------------
+function AssignStartingPlots:CanBeRareMystical(x, y)
+	-- Checks a candidate plot for eligibility to be the one of the rare mystical wonders.
+	local plot = Map.GetPlot(x, y);
+	-- Checking center plot, which must be at least one plot away from any salt water.
+	if plot:IsWater() then
+		return
 	end
+	local iW, iH = Map.GetGridSize();
+	local plotIndex = y * iW + x + 1;
+	if self.plotDataIsCoastal[plotIndex] == true then
+		return
+	end
+	-- This site is inland, so it's good.
+	table.insert(self.mystical_list, plotIndex);
 end
 ------------------------------------------------------------------------------
 function AssignStartingPlots:GenerateNaturalWondersCandidatePlotLists()
@@ -5194,7 +5200,10 @@
 	local biggest_landmass = Map.FindBiggestArea(false)
 	self.iBiggestLandmassID = biggest_landmass:GetID()
 	local biggest_ocean = Map.FindBiggestArea(true)
-	local iNumBiggestOceanPlots = biggest_ocean:GetNumTiles()
+	local iNumBiggestOceanPlots = 0;
+	if biggest_ocean ~= nil then
+		iNumBiggestOceanPlots = biggest_ocean:GetNumTiles()
+	end
 	if iNumBiggestOceanPlots > (iW * iH) / 4 then
 		self.bWorldHasOceans = true;
 	else
@@ -5212,6 +5221,7 @@
 				self:CanBeMesa(x, y)
 				self:CanBeReef(x, y)
 				self:CanBeKrakatoa(x, y)
+				self:CanBeRareMystical(x, y)
 			end
 		end
 	end
@@ -5223,13 +5233,13 @@
 	local iCanBeMesa = table.maxn(self.mesa_list);
 	local iCanBeReef = table.maxn(self.reef_list);
 	local iCanBeKrakatoa = table.maxn(self.krakatoa_list);
-	local iKrakFallbacks = table.maxn(self.krakatoa_fallback_list);
+	local iCanBeRareMystical = table.maxn(self.mystical_list);
 
 	-- Sort the wonders with fewest candidates listed first.
-	-- If the Geyser is eligible, always choose it and give it top priority.
-	local NW_eligibility_order, NW_eligibility_unsorted, NW_eligibility_sorted = {}, {}, {}; 
+	local NW_eligibility_order, NW_eligibility_unsorted, NW_eligibility_sorted, NW_remaining_to_sort_by_occurrence = {}, {}, {}, {}; 
 	if iCanBeGeyser > 0 then
-		table.insert(NW_eligibility_order, 1);
+		table.insert(NW_eligibility_unsorted, {1, iCanBeGeyser});
+		table.insert(NW_eligibility_sorted, iCanBeGeyser);
 	end
 	if iCanBeCrater > 0 then
 		table.insert(NW_eligibility_unsorted, {2, iCanBeCrater});
@@ -5254,26 +5264,32 @@
 	if iCanBeKrakatoa > 0 then
 		table.insert(NW_eligibility_unsorted, {7, iCanBeKrakatoa});
 		table.insert(NW_eligibility_sorted, iCanBeKrakatoa);
-	elseif iKrakFallbacks > 0 then
-		table.insert(NW_eligibility_unsorted, {8, iKrakFallbacks});
-		table.insert(NW_eligibility_sorted, iKrakFallbacks);
+	end
+	if iCanBeRareMystical > 0 then
+		table.insert(NW_eligibility_unsorted, {8, iCanBeRareMystical});
+		table.insert(NW_eligibility_sorted, iCanBeRareMystical);
+		table.insert(NW_eligibility_unsorted, {9, iCanBeRareMystical});
+		table.insert(NW_eligibility_sorted, iCanBeRareMystical);
+		table.insert(NW_eligibility_unsorted, {10, iCanBeRareMystical});
+		table.insert(NW_eligibility_sorted, iCanBeRareMystical);
 	end
 	table.sort(NW_eligibility_sorted);
 	
 	-- Match each sorted eligibility count to the matching unsorted NW number and record in sequence.
-	for NW_order = 1, 7 do
+	for NW_order = 1, 10 do
 		for loop, data_pair in ipairs(NW_eligibility_unsorted) do
 			local unsorted_count = data_pair[2];
 			if NW_eligibility_sorted[NW_order] == unsorted_count then
 				local unsorted_NW_num = data_pair[1];
 				table.insert(NW_eligibility_order, unsorted_NW_num);
+				table.insert(NW_remaining_to_sort_by_occurrence, unsorted_NW_num);
 				table.remove(NW_eligibility_unsorted, loop);
 				break
 			end
 		end
 	end
 	
-	--[[ Debug printout of natural wonder candidate plot lists
+	-- Debug printout of natural wonder candidate plot lists
 	print("-"); print("-"); print("--- Number of Candidate Plots on the map for Natural Wonders ---"); print("-");
 	print("- Geyser:", iCanBeGeyser);
 	print("- Crater:", iCanBeCrater);
@@ -5282,18 +5298,89 @@
 	print("- Mesa:", iCanBeMesa);
 	print("- Reef:", iCanBeReef);
 	print("- Krakatoa:", iCanBeKrakatoa);
-	print("- Krakatoa fallback:", iKrakFallbacks);
+	print("- Rare Mystical:", iCanBeRareMystical);
 	print("-"); print("--- End of candidates readout for Natural Wonders ---"); print("-");	
-	]]--
+	--
 
-	return NW_eligibility_order;
+	-- Read in from the XML for each eligible wonder, obtaining OccurrenceFrequency data.
+	--
+	-- Set up NW IDs.
+	local wonder_list = table.fill(-1, 10);
+	for thisFeature in GameInfo.Features() do
+		if thisFeature.Type == "FEATURE_GEYSER" then
+			wonder_list[1] = thisFeature.ID;
+		elseif thisFeature.Type == "FEATURE_CRATER" then
+			wonder_list[2] = thisFeature.ID;
+		elseif thisFeature.Type == "FEATURE_GIBRALTAR" then
+			wonder_list[3] = thisFeature.ID;
+		elseif thisFeature.Type == "FEATURE_FUJI" then
+			wonder_list[4] = thisFeature.ID;
+		elseif thisFeature.Type == "FEATURE_MESA" then
+			wonder_list[5] = thisFeature.ID;
+		elseif thisFeature.Type == "FEATURE_REEF" then
+			wonder_list[6] = thisFeature.ID;
+		elseif thisFeature.Type == "FEATURE_VOLCANO" then
+			wonder_list[7] = thisFeature.ID;
+		elseif thisFeature.Type == "FEATURE_FOUNTAIN_YOUTH" then
+			wonder_list[8] = thisFeature.ID;
+		elseif thisFeature.Type == "FEATURE_POTOSI" then
+			wonder_list[9] = thisFeature.ID;
+		elseif thisFeature.Type == "FEATURE_EL_DORADO" then
+			wonder_list[10] = thisFeature.ID;
+		end
+	end
+	-- Set up pool of entries and enter an entry for each level of OccurrenceFrequency for each eligible NW.
+	local NW_candidate_pool_entries, NW_final_selections = {}, {};
+	for loop, iNaturalWonderNumber in ipairs(NW_eligibility_order) do
+		local NW_ID = wonder_list[iNaturalWonderNumber];
+		local iFrequency = GameInfo.Features[NW_ID].OccurrenceFrequency;
+		--
+		print("-"); print("NW#", iNaturalWonderNumber, "of ID#", NW_ID, "has OccurrenceFrequency of:", iFrequency);
+		--
+		for entry = 1, iFrequency do
+			table.insert(NW_candidate_pool_entries, iNaturalWonderNumber);
+		end
+	end
+	PrintContentsOfTable(NW_candidate_pool_entries)
+	local iNumNWtoProcess = table.maxn(NW_remaining_to_sort_by_occurrence)
+	if iNumNWtoProcess > 0 then
+		-- Choose at random from the entry pool to select the final order of operations for NW placement.
+		local entry_count = table.maxn(NW_candidate_pool_entries)
+		for loop = 1, iNumNWtoProcess do
+			local current_NW_selected = false;
+			local current_attempt_to_select = 0;
+			while current_NW_selected == false do
+				if current_attempt_to_select > 1000 then
+					break
+				end
+				current_attempt_to_select = current_attempt_to_select + 1;
+				print("Selection for #", loop, "NW to be assigned -- ATTEMPT #", current_attempt_to_select);
+				local diceroll = 1 + Map.Rand(entry_count, "Checking a random pool entry for NW assignment - Lua");
+				local possible_selection = NW_candidate_pool_entries[diceroll];
+				local bFoundValue, iNumTimesFoundValue, table_of_indices = IdentifyTableIndex(NW_remaining_to_sort_by_occurrence, possible_selection)
+				if bFoundValue then
+					table.insert(NW_final_selections, possible_selection)
+					table.remove(NW_remaining_to_sort_by_occurrence, table_of_indices[1])
+					print("NW#", possible_selection, "chosen.");
+					current_NW_selected = true;
+				end
+			end
+		end
+	end
+	
+	if NW_final_selections ~= nil then
+		return NW_final_selections;
+	else
+		print("ERROR: Failed to produce final selection list of NWs!");
+	end
 end
 ------------------------------------------------------------------------------
 function AssignStartingPlots:AttemptToPlaceNaturalWonder(iNaturalWonderNumber)
 	-- Attempt to place a specific Natural Wonder.
-	-- 1 Everest - 2 Crater - 3 Titicaca - 4 Fuji - 5 Mesa - 6 Reef - 7 Krakatoa (unforced) - 8 Krakatoa (forced)
+	-- 1 Everest - 2 Crater - 3 Titicaca - 4 Fuji - 5 Mesa - 6 Reef - 7 Krakatoa
+	-- 8 Fountain of Youth - 9 Potosi - 10 El Dorado
 	local iW, iH = Map.GetGridSize();
-	local wonder_list = table.fill(-1, 8);
+	local wonder_list = table.fill(-1, 10);
 	for thisFeature in GameInfo.Features() do
 		if thisFeature.Type == "FEATURE_GEYSER" then
 			wonder_list[1] = thisFeature.ID;
@@ -5309,7 +5396,12 @@
 			wonder_list[6] = thisFeature.ID;
 		elseif thisFeature.Type == "FEATURE_VOLCANO" then
 			wonder_list[7] = thisFeature.ID;
+		elseif thisFeature.Type == "FEATURE_FOUNTAIN_YOUTH" then
 			wonder_list[8] = thisFeature.ID;
+		elseif thisFeature.Type == "FEATURE_POTOSI" then
+			wonder_list[9] = thisFeature.ID;
+		elseif thisFeature.Type == "FEATURE_EL_DORADO" then
+			wonder_list[10] = thisFeature.ID;
 		end
 	end
 
@@ -5336,7 +5428,7 @@
 				local plotIndex = y * iW + x + 1;
 				self.playerCollisionData[plotIndex] = true;				-- Record exact plot of wonder in the collision list.
 				--
-				--print("- Placed Geyser in Plot", x, y);
+				print("- Placed Geyser in Plot", x, y);
 				--
 				return true
 			end
@@ -5355,9 +5447,9 @@
 				if not plot:IsMountain() then
 					plot:SetPlotType(PlotTypes.PLOT_MOUNTAIN, false, false);
 				end
-				if plot:GetTerrainType() ~= TerrainTypes.TERRAIN_DESERT then
-					plot:SetTerrainType(TerrainTypes.TERRAIN_DESERT, false, false)
-				end
+				--if plot:GetTerrainType() ~= TerrainTypes.TERRAIN_DESERT then
+					--plot:SetTerrainType(TerrainTypes.TERRAIN_DESERT, false, false)
+				--end
 				-- Now place Crater and record the placement.
 				plot:SetFeatureType(wonder_list[2])
 				table.insert(self.placed_natural_wonder, 2);
@@ -5370,7 +5462,7 @@
 				local plotIndex = y * iW + x + 1;
 				self.playerCollisionData[plotIndex] = true;				-- Record exact plot of wonder in the collision list.
 				--
-				--print("- Placed Crater in Plot", x, y);
+				print("- Placed Crater in Plot", x, y);
 				--
 				return true
 			end
@@ -5395,8 +5487,8 @@
 							adjPlot:SetTerrainType(TerrainTypes.TERRAIN_COAST, false, false)
 						end
 					else
-						if adjPlot:GetPlotType() ~= PlotTypes.PLOT_LAND then
-							adjPlot:SetPlotType(PlotTypes.PLOT_LAND, false, false);
+						if adjPlot:GetPlotType() ~= PlotTypes.PLOT_MOUNTAIN then
+							adjPlot:SetPlotType(PlotTypes.PLOT_MOUNTAIN, false, false);
 						end
 					end
 				end
@@ -5412,7 +5504,7 @@
 				local plotIndex = y * iW + x + 1;
 				self.playerCollisionData[plotIndex] = true;				-- Record exact plot of wonder in the collision list.
 				--
-				--print("- Placed Gibraltar in Plot", x, y);
+				print("- Placed Gibraltar in Plot", x, y);
 				--
 				return true
 			end
@@ -5446,7 +5538,7 @@
 				local plotIndex = y * iW + x + 1;
 				self.playerCollisionData[plotIndex] = true;				-- Record exact plot of wonder in the collision list.
 				--
-				--print("- Placed Fuji in Plot", x, y);
+				print("- Placed Fuji in Plot", x, y);
 				--
 				return true
 			end
@@ -5465,9 +5557,9 @@
 				if not plot:IsMountain() then
 					plot:SetPlotType(PlotTypes.PLOT_MOUNTAIN, false, false);
 				end
-				if plot:GetTerrainType() ~= TerrainTypes.TERRAIN_DESERT then
-					plot:SetTerrainType(TerrainTypes.TERRAIN_DESERT, false, false)
-				end
+				--if plot:GetTerrainType() ~= TerrainTypes.TERRAIN_DESERT then
+					--plot:SetTerrainType(TerrainTypes.TERRAIN_DESERT, false, false)
+				--end
 				-- Now place Mesa and record the placement.
 				plot:SetFeatureType(wonder_list[5])
 				table.insert(self.placed_natural_wonder, 5);
@@ -5480,7 +5572,7 @@
 				local plotIndex = y * iW + x + 1;
 				self.playerCollisionData[plotIndex] = true;				-- Record exact plot of wonder in the collision list.
 				--
-				--print("- Placed Mesa in Plot", x, y);
+				print("- Placed Mesa in Plot", x, y);
 				--
 				return true
 			end
@@ -5561,7 +5653,7 @@
 				local plotIndex = y * iW + x + 1;
 				self.playerCollisionData[plotIndex] = true;				-- Record exact plot of wonder in the collision list.
 				--
-				--print("- Placed Reef in Plot", x, y);
+				print("- Placed Reef in Plot", x, y);
 				--
 				return true
 			end
@@ -5602,92 +5694,54 @@
 				local plotIndex = y * iW + x + 1;
 				self.playerCollisionData[plotIndex] = true;				-- Record exact plot of wonder in the collision list.
 				--
-				--print("- Placed Krakatoa in Plot", x, y);
+				print("- Placed Krakatoa in Plot", x, y);
 				--
 				return true
 			end
 		end
 		-- If reached here, Krakatoa was unable to be placed because all candidates are too close to an already-placed NW.
-		-- Use fallbacks and try again.
-		local candidate_plot_list = GetShuffledCopyOfTable(self.krakatoa_fallback_list)
-		for loop, plotIndex in ipairs(candidate_plot_list) do
-			if self.naturalWondersData[plotIndex] == 0 then -- No collision with civ start or other NW, so place Krakatoa here!
-				local x = (plotIndex - 1) % iW;
-				local y = (plotIndex - x - 1) / iW;
-				local plot = Map.GetPlot(x, y);
-				-- Where it does not already, force the local terrain to conform to what the NW needs.
-				if not plot:IsMountain() then
-					plot:SetPlotType(PlotTypes.PLOT_MOUNTAIN, false, false);
-				end
-				if plot:GetTerrainType() ~= TerrainTypes.TERRAIN_GRASS then
-					plot:SetTerrainType(TerrainTypes.TERRAIN_GRASS, false, false)
-				end
-				for loop, direction in ipairs(self.direction_types) do
-					local adjPlot = Map.PlotDirection(x, y, direction)
-					if adjPlot:GetTerrainType() ~= TerrainTypes.TERRAIN_COAST then
-						adjPlot:SetTerrainType(TerrainTypes.TERRAIN_COAST, false, false)
-					end
-				end
-				-- Now place Krakatoa and record the placement.
-				plot:SetFeatureType(wonder_list[7])
-				table.insert(self.placed_natural_wonder, 7);
-				self:PlaceResourceImpact(x, y, 6, math.floor(iH / 5))	-- Natural Wonders layer
-				self:PlaceResourceImpact(x, y, 1, 1)					-- Strategic layer
-				self:PlaceResourceImpact(x, y, 2, 1)					-- Luxury layer
-				self:PlaceResourceImpact(x, y, 3, 1)					-- Bonus layer
-				self:PlaceResourceImpact(x, y, 4, 1)					-- Fish layer
-				self:PlaceResourceImpact(x, y, 5, 1)					-- City State layer
-				self:PlaceResourceImpact(x, y, 7, 1)					-- Marble layer
-				local plotIndex = y * iW + x + 1;
-				self.playerCollisionData[plotIndex] = true;				-- Record exact plot of wonder in the collision list.
-				--
-				--print("- Placed Krakatoa in Plot", x, y);
-				--
-				return true
-			end
-		end
-		-- If reached here, even the fallbacks for Krakatoa have failed. Must be a very dry map with only a few small oceans.
 		return false
 
-	elseif iNaturalWonderNumber == 8 then -- Krakatoa, forced in a random ocean plot.
-		local candidate_plot_list = GetShuffledCopyOfTable(self.krakatoa_fallback_list)
+	elseif iNaturalWonderNumber == 8 or iNaturalWonderNumber == 9 or iNaturalWonderNumber == 10 then -- Rare Mystical
+		local candidate_plot_list = GetShuffledCopyOfTable(self.mystical_list)
 		for loop, plotIndex in ipairs(candidate_plot_list) do
-			if self.naturalWondersData[plotIndex] == 0 then -- No collision with civ start or other NW, so place Krakatoa here!
+			if self.naturalWondersData[plotIndex] == 0 then -- No collision with civ start or other NW, so place wonder here!
 				local x = (plotIndex - 1) % iW;
 				local y = (plotIndex - x - 1) / iW;
 				local plot = Map.GetPlot(x, y);
-				-- Where it does not already, force the local terrain to conform to what the NW needs.
-				if not plot:IsMountain() then
-					plot:SetPlotType(PlotTypes.PLOT_MOUNTAIN, false, false);
-				end
-				if plot:GetTerrainType() ~= TerrainTypes.TERRAIN_GRASS then
+				-- Now place the Rare Mystical wonder and record the placement.
+				if iNaturalWonderNumber == 8 then
+					plot:SetPlotType(PlotTypes.PLOT_LAND, false, false);
 					plot:SetTerrainType(TerrainTypes.TERRAIN_GRASS, false, false)
+					plot:SetFeatureType(wonder_list[8])
+					table.insert(self.placed_natural_wonder, 8);
+					print("- Placed Fountain of Youth in Plot", x, y);
+				elseif iNaturalWonderNumber == 9 then
+					if not plot:IsMountain() then
+						plot:SetPlotType(PlotTypes.PLOT_MOUNTAIN, false, false);
+					end
+					plot:SetFeatureType(wonder_list[9])
+					table.insert(self.placed_natural_wonder, 9);
+					print("- Placed Potosi in Plot", x, y);
+				elseif iNaturalWonderNumber == 10 then
+					plot:SetPlotType(PlotTypes.PLOT_LAND, false, false);
+					plot:SetTerrainType(TerrainTypes.TERRAIN_PLAINS, false, false)
+					plot:SetFeatureType(wonder_list[10])
+					table.insert(self.placed_natural_wonder, 10);
+					print("- Placed El Dorado in Plot", x, y);
 				end
-				for loop, direction in ipairs(self.direction_types) do
-					local adjPlot = Map.PlotDirection(x, y, direction)
-					if adjPlot:GetTerrainType() ~= TerrainTypes.TERRAIN_COAST then
-						adjPlot:SetTerrainType(TerrainTypes.TERRAIN_COAST, false, false)
-					end
-				end
-				-- Now place Krakatoa and record the placement.
-				plot:SetFeatureType(wonder_list[8])
-				table.insert(self.placed_natural_wonder, 8);
 				self:PlaceResourceImpact(x, y, 6, math.floor(iH / 5))	-- Natural Wonders layer
 				self:PlaceResourceImpact(x, y, 1, 1)					-- Strategic layer
 				self:PlaceResourceImpact(x, y, 2, 1)					-- Luxury layer
 				self:PlaceResourceImpact(x, y, 3, 1)					-- Bonus layer
-				self:PlaceResourceImpact(x, y, 4, 1)					-- Fish layer
 				self:PlaceResourceImpact(x, y, 5, 1)					-- City State layer
 				self:PlaceResourceImpact(x, y, 7, 1)					-- Marble layer
 				local plotIndex = y * iW + x + 1;
 				self.playerCollisionData[plotIndex] = true;				-- Record exact plot of wonder in the collision list.
-				--
-				--print("- Placed Krakatoa in Plot", x, y);
-				--
 				return true
 			end
 		end
-		-- If reached here, Krakatoa was unable to be placed because all candidates are too close to an already-placed NW.
+		-- If reached here, a Rare Mystical was unable to be placed because all candidates are too close to an already-placed NW.
 		return false
 
 	end
@@ -5699,17 +5753,16 @@
 	local NW_eligibility_order = self:GenerateNaturalWondersCandidatePlotLists()
 	local iNumNWCandidates = table.maxn(NW_eligibility_order);
 	if iNumNWCandidates == 0 then
-		--print("No Natural Wonders placed, no eligible sites found for any of them.");
+		print("No Natural Wonders placed, no eligible sites found for any of them.");
 		return
 	end
 	
-	--[[ Debug printout
+	-- Debug printout
 	print("-"); print("--- Readout of NW Assignment Priority ---");
 	for print_loop, order in ipairs(NW_eligibility_order) do
 		print("NW Assignment Priority#", print_loop, "goes to NW#", order);
 	end
 	print("-"); print("-");
-	]]--
 	
 	-- Determine how many NWs to attempt to place. Target is regulated per map size.
 	-- The final number cannot exceed the number the map has locations to support.
@@ -5726,43 +5779,27 @@
 	local target_number = worldsizes[Map.GetWorldSize()];
 	local iNumNWtoPlace = math.min(target_number, iNumNWCandidates);
 	local selected_NWs, fallback_NWs = {}, {};
-	local iNumSelectedSoFar = 0;
-	-- If Geyser is eligible, always choose it. (This is because its eligibility requirements are so much steeper.)
-	if NW_eligibility_order[1] == 1 then
-		table.insert(selected_NWs, NW_eligibility_order[1]);
-		--[[ This was a section to give a second NW the "always choose" priority, but that wonder got changed.
-		if NW_eligibility_order[2] == 3 then
-			table.insert(selected_NWs, 3);
-			table.remove(NW_eligibility_order, 2);
-			iNumSelectedSoFar = iNumSelectedSoFar + 1;
-		end
-		]]--
-		table.remove(NW_eligibility_order, 1);
-		iNumSelectedSoFar = iNumSelectedSoFar + 1;
-	end
-	-- Choose a random selection from the others, to reach the quota to place. If any left over, set as fallbacks.
-	local NW_shuffled_order = GetShuffledCopyOfTable(NW_eligibility_order);
 	for loop, NW in ipairs(NW_eligibility_order) do
-		for test_loop, shuffled_NW in ipairs(NW_shuffled_order) do
-			if shuffled_NW == NW then
-				if test_loop <= iNumNWtoPlace - iNumSelectedSoFar then
-					table.insert(selected_NWs, NW);
-				else
-					table.insert(fallback_NWs, NW);
-				end
-			end
+		if loop <= iNumNWtoPlace then
+			table.insert(selected_NWs, NW);
+		else
+			table.insert(fallback_NWs, NW);
 		end
 	end
 	
-	--[[
+	--
 	print("-");
 	for loop, NW in ipairs(selected_NWs) do
 		print("Natural Wonder #", NW, "has been selected for placement.");
 	end
 	print("-");
+	for loop, NW in ipairs(fallback_NWs) do
+		print("Natural Wonder #", NW, "has been selected as fallback.");
+	end
+	print("-");
 	--
 	print("--- Placing Natural Wonders! ---");
-	]]--
+	--
 	
 	-- Place the NWs
 	local iNumPlaced = 0;
@@ -5784,13 +5821,13 @@
 		end
 	end
 	
-	--[[
+	--
 	if iNumPlaced >= iNumNWtoPlace then
 		print("-- Placed all Natural Wonders --"); print("-"); print("-");
 	else
 		print("-- Not all Natural Wonders targeted got placed --"); print("-"); print("-");
 	end
-	]]--
+	--
 		
 end
 ------------------------------------------------------------------------------
 
In terms of AssignStartingPlots.lua, I happened to have a copy of the old one saved on a USB drive. Spoiled below is a unified diff of the changes, which are pretty extensive.

Very handy, thanks. I don't see anything there not related to natural wonders, so I don't know why it would cause any crashes if you changed the rest of the file to match previous mods, as long as you left the natural wonder part alone.

I'll try a few things when I get home tonight. Here's hoping...
 
I answered your question in my mod thread. But the short verison is that you need to right click a file, including XML and set the VFS property to true.

As far as I can tell, this property does not work as intended, as I have new files - lua and xml - and if the property is not set to true, they are not used.

While I am at this, it is always bad form to make a change that changes the currently working defaults. So if they needed to add this property, the default value should have been set to True.

Saw it and responded. Thanks!
 
I answered your question in my mod thread. But the short verison is that you need to right click a file, including XML and set the VFS property to true.

As far as I can tell, this property does not work as intended, as I have new files - lua and xml - and if the property is not set to true, they are not used.

While I am at this, it is always bad form to make a change that changes the currently working defaults. So if they needed to add this property, the default value should have been set to True.

I've had the same experience. I couldn't get any of my files to load unless I added them to the VFS. I took the "will replace any file of the same name" comment as clarification with "in addition to all your other files" as understood. So, basically, I've had to set every file in my mod to true to get the main engine to recognize that they exist.
 
Okay, I've got the AssignStartingPlots crash thing working. It was my fault, sort of; SOMEHOW, what had been underscores in one of my variable names (and that worked previously) were spontaneously replaced by spaces. And no, I have no idea why.

As to the Text Key issue, it must be a cache issue. For whatever reason, ONE of my language files (GameTextInfos2.xml) isn't being loaded... except that it is. The three variables that have been in that file for months ARE being used correctly, but anything added after a couple months ago isn't. And the XML itself is fine; when I cut and pasted those particular values into a different XML file they worked just fine.

So it looks like somehow, an old version is being used instead of the new one. Is there some way to clean out the file cache that I'm missing?
 
Valk I'm not sure you are right.

You are probably right when it comes to XML. All my XML files are either* listed in actions (i.e. OnModActivated UpdateDatabase) or* are replacing existing files and have 'Import into VFS' enabled.

But VFS is not just used to replace existing files, it also seems to be used to make art (.dds) files usable in XML.

If I don't enable the 'Import into VFS' property on my .dds files then the game will complain it can't find those files. I'm talking about unique .dds files with icons I use in my mod that are not replacing any existing game files.


* For files that replace existing core XML files I just enable VFS and I don't have to list them as OnModActivated UpdateDatabase entries in the Actions. They seems to work fine this way.
 
Valk I'm not sure you are right.

You are probably right when it comes to XML. All my XML files are either* listed in actions (i.e. OnModActivated UpdateDatabase) or* are replacing existing files and have 'Import into VFS' enabled.

But VFS is not just used to replace existing files, it also seems to be used to make art (.dds) files usable in XML.

If I don't enable the 'Import into VFS' property on my .dds files then the game will complain it can't find those files. I'm talking about unique .dds files with icons I use in my mod that are not replacing any existing game files.


* For files that replace existing core XML files I just enable VFS and I don't have to list them as OnModActivated UpdateDatabase entries in the Actions. They seems to work fine this way.

That's kind of obvious, isn't it? If the file isn't put into the virtual file system and it's not loaded in some other way, it's invisible to the game. So texture files and the like also have to have VFS enabled

Edit: I expect that this includes any lua files loaded as InGameUIAddin or similar
 
@alpaca: yes it is obvious, but it wasn't how it worked before the patch.

@skodkim: I replied in your thread
 
Valk I'm not sure you are right.

You are probably right when it comes to XML. All my XML files are either* listed in actions (i.e. OnModActivated UpdateDatabase) or* are replacing existing files and have 'Import into VFS' enabled.

But VFS is not just used to replace existing files, it also seems to be used to make art (.dds) files usable in XML.

If I don't enable the 'Import into VFS' property on my .dds files then the game will complain it can't find those files. I'm talking about unique .dds files with icons I use in my mod that are not replacing any existing game files.


* For files that replace existing core XML files I just enable VFS and I don't have to list them as OnModActivated UpdateDatabase entries in the Actions. They seems to work fine this way.

As Alpaca said, that is entirely because there is no load command for art. Pre-patch, the VFS checkbox defaulted to true. Post-patch, it defaults to false, but you have the ability to toggle it.
 
As Alpaca said, that is entirely because there is no load command for art. Pre-patch, the VFS checkbox defaulted to true. Post-patch, it defaults to false, but you have the ability to toggle it.

In addition to files without load commands, any file hooked up via the Content mechanisms has to be added to the VFS, too, so any lua scripts or UI files need this (even if they're referenced by other UI files).
 
In addition to files without load commands, any file hooked up via the Content mechanisms has to be added to the VFS, too, so any lua scripts or UI files need this.

No, my homemade Lua worked just fine with only the Content tab and no VFS. Only the Lua that was edited versions of existing script needed VFS.
 
Back
Top Bottom