A couple more "quick" inquiries

The method is apparently InstanceManager.ReleaseInstance(table instance). Judging from the code, the table is most likely SVInstances with playerID and cityID passed to it, as it was in CityBannerManager. The question is now... what InstanceManager do we use? :confused:
The code uses g_SVStrikeIM, but that's apparently the ranged strike button:
Code:
local g_SVStrikeIM = InstanceManager:new( "SVRangeStrikeButton", "Anchor", Controls.StrategicViewStrikeButtons );

So then is the relevant method really setting the SVInstances to nil, as they do 1 line later in CityBannerManager?
Code:
SVInstances[playerID][cityID] = nil;

This is a whole new scope of modding for me...

EDIT: Dang! This was post #2000 for me and I didn't even notice when I posted! :cringe:
Well, here's an obligatory dancing banana and party sequence -----> :banana::clap::banana:[party]:trophy2nd:[party]:banana::clap::banana:
EDIT2: And this is also post 42 of the thread! :goodjob: What a serendipitous coincidence, amirite?
 
Yeah.. I'm more or less as stumped as you are.

For me, I needed a way to mod the tech tree display to remove some icons, but invariably, I wound up having to look into these instances as well, and I couldn't really figure them out.

I'll have to try again at some point, since so far it feels like many people are getting confused about why my Civ doesn't gain trade routes from techs because they don't read the description of the Palace UB explaining it, and just assume they will get one because the icon is still there on the technology.

In either case, I believe I was trying to make my way through whoward's UI tutorial on Menus which explains the whole concept of instances, but I didn't have enough time to digest everything prior to release.
 
You might be on the right track, AW.
As DarkScythe says, whoward's Tutorial is a blessing, if you have the patience you will learn eventually, it is very well written and explained, you only need the basics of XML/Lua to get it.
I am usually very frustrated with UI modding, but that's me.


EDIT: I think I'm getting the gist of it. Funny enough, the part I'm most getting stumped is the XML. :p
 
You're going to have to supply a modified version of CityBannerManager.lua with your mod, as all the instance managers you need are hidden inside it from other Lua contexts.

now, you could just do
Code:
Events.SerialEventCityDestroyed(nil, iPlayer, iCity, -1);
to remove the city banner, BUT, any other mod/core system listening on that event would think that the city had been destroyed - probably not what you wanted to achieve!

The replacement CityBannerManager.lua file only needs one extra line

Code:
LuaEvents.RemoveCityBanner.Add(function (iPlayer, iCity) OnCityDestroyed(nil, iPlayer, iCity, -1) end);

and you can then remove city banners within your own lua file with
Code:
LuaEvents.RemoveCityBanner(iPlayer, iCity)

Note that as a saved game is loaded all banners are recreated, so you're code will need to take steps to remove them again

Also note, that in hotseat, you'll have to remove the banner for all players during their turn (thanks to the Game.GetActiveTeam() call in the listener)
 
You're going to have to supply a modified version of CityBannerManager.lua with your mod, as all the instance managers you need are hidden inside it from other Lua contexts.

now, you could just do
Code:
Events.SerialEventCityDestroyed(nil, iPlayer, iCity, -1);
to remove the city banner, BUT, any other mod/core system listening on that event would think that the city had been destroyed - probably not what you wanted to achieve!

The replacement CityBannerManager.lua file only needs one extra line

Code:
LuaEvents.RemoveCityBanner.Add(function (iPlayer, iCity) OnCityDestroyed(nil, iPlayer, iCity, -1) end);

and you can then remove city banners within your own lua file with
Code:
LuaEvents.RemoveCityBanner(iPlayer, iCity)

Note that as a saved game is loaded all banners are recreated, so you're code will need to take steps to remove them again

Also note, that in hotseat, you'll have to remove the banner for all players during their turn (thanks to the Game.GetActiveTeam() call in the listener)
The usual praise be unto the Much-Knowing whoward :D

Does it matter where that line is placed? Such as, must it be within the OnCityDestroyed function, near the bottom I'd guess? Or specifically outside the function? I've only observed other people create new lua events, so I'm guessing the former...?
 
Outside of the function, after the other ".Add" line
 
Outside of the function, after the other ".Add" line
Thank you kindly, sir; I'll give this a try.

Question about the parameters though - is iPlayer the owner of the city or the person that's not supposed to see the city? The latter, I suppose?

And to add a function to re-invoke city visibility, I guess it would be pretty similar except linking to OnCityCreated... so...
Code:
LuaEvents.ReAddCityBanner.Add(function (iPlayer, iCity) OnCityCreated(nil, iPlayer, iCity) end);
 
iPlayer is the owner of the city (iCity)

Because this is UI related it will affect the active player's view of the game ... hence the comment about needing to call the LuaEvent multiple times if you need to allow for HotSeat games
 
Ah. So then there's no need to identify who the city should be invisible to?
...Which may pose a problem, since I'd like the city to be invisible to everyone except the city owner, and invisible to everyone else who don't have a unit adjacent to the city.

Per my original query:
8) Using methods such as [Pazyryk's method of subscribing to SerialEvents], is it possible to make City X, a city of Player X, appear invisible to Player Y if Player Y does not have a unit adjacent to City X?
We determined this is possible to remove just the city from view, and then launched into the whole "banner not disappearing" problem.

I'll assume the SerialEvents' iPlayer parameter also refers to city owner and not the active player... Is this not possible then? :( Or am I just severely misunderstanding?
 
I guess the whole invisible city thing is pretty much impossible without completely redoing the UI. :/

Since this thread is still technically on the front page, I guess it's still safe to necro...
Might as well rename it to "AW's Help Thread of Confusion and Lack of Knowingness. :p If any mod is reading this, question: Would you consider it better to compile all inquiries into one thread like this, or keep creating new threads as the occasion requires? Or does no one, as Douglas Adams put it, "give a wet slap" about it?

Here's my newest issue:
9) Finding a completely random plot on the map and the plots surrounding it.
This is probably possible with PlotIterators. Except for as hard as I've tried to understand what in the world is going on in that file, I can't.

The former I seem to be having more trouble than is probably necessary with. The function will be called with an event hook with passes no x/y/z parameters, so I can't simply do "local pPlot = Map.GetPlot(iX, iY)", which probably wouldn't even work anyway.

But once pPlot is found, would finding adjacent plots work with a "for" loop?
Code:
for pRingPlot in Map.GetPlot((pPlot:GetX() + math.ceil(math.random(-1,1))), (pPlot:GetY() + math.ceil(math.random(-1,1)))) do
Again, there's probably a much easier way to do this with PlotIterators, which I don't know how. Looking again at that segment of JFD's coding which uses PlotIterators:
Code:
...
iRadius = 3

function Sukritact_PlaceResource(pCity)
    local pPlot = pCity:Plot()
    local tPlots = {}
    local iNumtoPlace = 1
    for pLoopPlot in PlotAreaSweepIterator(pPlot, iRadius, SECTOR_NORTH, DIRECTION_CLOCKWISE, DIRECTION_OUTWARDS, CENTRE_EXCLUDE) do
        table.insert(tPlots, pLoopPlot)
    end
...
I'm sure I can reuse most of this, simply adjusting the radius to be 1 and pPlot to be that plot randomly found earlier. Right?

9.5) If that randomly plot happens to be in a completely unsatisfactory location - such as, in the middle of the ocean, tundra, or desert - essentially, wherever neither pPlot nor any of its surrounding plots meet a terrain requirement, how can I make so that the game keeps randomy picking plots until one of them works?

Simple as discarding that variable/table and trying again? Probably a "while" loop in there?
 
Trying to find a plot without having the X/Y is going to be tough, unless you literally attempt to plug in random x/y values (which you could technically do.) Alternatively, you could try to find a plot via random Plot ID's.

What exactly are you trying to do? Why do you need plots around a target plot?

If you're going to have loops going to randomly pick X and Y coordinates, you can bind them to the map size with Map.GetGridSize(). A table to hold plots can also be used, but I don't know how you would actually use it.
 
Well...

I'm trying to add a new function which will fire on Events.SequenceGameInitComplete, which passes no parameters. The function will, as its ultimate goal, place 10 new resource types on the map, but each one only in a small clump confined to one region in the world. This way, I don't have to deal with AssignStartingPlots (please excuse my language) and/or MapGenerator, and it will add a new level of unique gameplay immersion.

The clump need not be more than a single center plot with all the plots adjacent to it, and the resource isn't going to be placed on every single one of the 7 plots in that clump anyway. I was intending to have the algorithm place the resource in one of those plots randomly - providing that it meets the terrain and feature restrictions - and then all the rest of the tiles in the clump have, say, a 66% chance of also getting the resource.

But the resources do each have their own stringent requirements on what terrain and feature types they can validly placed on, and I don't want the algorithm to just give up because the first random clump it finds doesn't have a single plot that meets the requirements.

I can explain it more detailed in a PM or email or something. Since we all know how carefully I guard many of my secret plans... :shifty:
 
Haha, fair enough; I know the feeling, as I was similarly secretive during development of my Holo Civ.

If you want, you can send a PM my way, though I think I have an idea of what you're trying to achieve now.

Keep in mind that I think SequenceGameInitComplete fires each time the game is loaded, so unless you have some way of keeping track via persisted data it will go looking for and place resources again each time you save and load the game.

Regardless, you can get the map size with X,Y = Map.GetGridSize(). Then you can randomly pick combinations of those to test for plots and from there expand into the plot iteration loops. I'll try to write up some actual code now, but that's a starting point. Will probably be a few minutes for some (untested) sample code.

Edit:
Okay, here's some very rough, untested code that should do what you need, as I currently understand it.
Lots of placeholders, and comments indicate areas where you can add additional if conditions and checks.

Spoiler :
Code:
local function RandomResourceSeed()
	local iMaxX, iMaxY = Map.GetGridSize()
	local bValidPlotFound
	while not bValidPlotFound do
		local iX = math.random(iMaxX)
		local iY = math.random(iMaxY)
		local pPlot = Map.GetPlot(iX, iY)
		if pPlot then
			-- Plot exists; stuff additional terrain/feature checks here as necessary
			local tempPlotTable = {pPlot}
			-- Fill in the table with adjacent tiles
			for i = 0, DirectionTypes.NUM_DIRECTION_TYPES - 1 do
				local pAdjacentPlot = Map.PlotDirection(iX, iY, i)
				if pAdjacentPlot then
					--Plot Exists
					-- Stuff more terrain/feature checks here if you need all surrounding plots to abide by the same rules as well
					if pAdjacentPlot:GetTerrainType() == TerrainTypes.TERRAIN_TUNDRA then
						table.insert(tempPlotTable, pAdjacentPlot)
					end
				end
			end
			if #tempPlotTable > 3 then
				-- This would only run if the table has more than 3 entries in it (Worst case, a corner tile would only be able to find 2 other adjacent tiles.)
				-- You can increase the number to however many tiles you need at minimum.
				local iResourceCount = 3 -- However many copies you need to place
				-- This is where you can place JFD's table randomization code
				for i = 1, iResourceCount do
					local bResourcePlaced
					while not bResourcePlaced and #tempPlotTable > 0 do
						local iRandomIndex = math.random(#tempPlotTable)
						local pTargetPlot = tempPlotTable[iRandomIndex]
						-- Additional checks here if you want, if you didn't already filter them in the previous loop
						pTargetPlot:SetResourceType(GameInfoTypes.RESOURCE_SECRET, 1)
						bResourcePlaced = true
						table.remove(tempPlotTable, iRandomIndex)
					end
				end
				local bValidPlotFound = true
			end
		end
	end
end
 
Here, sent you a PM with the concept in much more detail, so you can judge how well the code would work for it. For now, all I can do is assume this is right.
 
Supernecro 2.0 ++!

I just thought I'd ask and see if anyone has any idea if this is possible, let alone worth trying to code...
#???) A building which, if it exists in City X when City X is burned to the ground, allows City X's owner, Player X, to build a new city, City X 2.0, on the plot that formerly held City X, and have City X 2.0 automatically gain all the buildings that existed in City X the turn before it burned to the ground.

Hopefully that made sense...
 
Basically, yeah. I imagine you'd have a run a check each turn to find every city with Building X and feed its coordinates and player into a table, (and remove any city without building X, in case some one decided to sell it) along with all the buildings in the city... and when a city is founded whose owner is the same and on a plot that has the same coordinates, give the city all the buildings. But that sounds... a bit complicated and would very possibly create massive overhead lag...
 
I have need for a way to detect when a City has been razed as well, but I wasn't able to find any reliable method of doing so in terms of Game Events, so you'll likely have to make do with storing all that data in a table and checking it every turn. It's currently the only workaround I have available for Holo. (For whatever reason, the SerialEvents for CityDestroyed never did anything in my testing. At least they never fired the print statements I provided.)

On the other hand, you do have a reliable method for catching when a City is first founded -- GameEvents.PlayerCityFounded() which, luckily for you, is available for G&K.

You can probably store the plot ID of the City's plot whenever it's been founded, and check it each turn in order to populate a table of buildings in that City. Each turn, if the City still exists, it'll just update the table, but if the city is no longer there, then you can found a city on that plot and go through the stored building table, providing a copy of everything the City had on the turn prior. Edit: Keep in mind you will need some way of persisting this data, be it through SaveUtils, or TableSaverLoader, or some other method.

However, this won't catch when a player sells off buildings each turn while the City is razing. You'll spawn a new City with the buildings that it had just before it finally finished burning.
 
Top Bottom