Cyphose's Compendium of Questions

there is no simpler solution
Well...

whoward here has some mod somewhere (note my immense awareness of his mods :p) which adds a number of extra Lua event hooks, one of which is basically the improvements equivalent of GameEvents.CityCanConstruct, which is used to disable a certain city from being able to build a certain building, using whatever conditions you want which can be computed in Lua.
So, you could give your mod a dependency to whoward's mod, and the addition of the new event hook might make your job simpler.

...keep in mind, though, that whoward makes DLL mods - i.e., he mods the C++ game core which will explode if anything is half an atom out of place. That property of game cores isn't exactly the problem here, but rather, the fact that the modded DLL has to actually override the DLL already used by the game means that only one DLL mod may be used at any time. This is true of any two mods that override the same file: the game will use the last version of the file loaded and ignore the others (IIRC), which can - technically speaking - screw things up something bad. :p

So I don't use whowards DLL, for 3 reasons:
1) Compatibility reduction
2) It would require people to enable a mod just to enable a mod, which has always been a concept I've found fairly irritating
3) whoward's current DLL isn't compatibility with my version number ;_;

But if it works for you, more power to you.
 
Funny you mention DLL mods, because I've long since accepted my fate and added a dependency on the CP DLL. For a mod like mine with such sweeping changes, the amount of quality of life additions for getting these changes done in an efficient manner is astounding. The compatibility issue is, of course, a problem, but luckily the CP DLL is the most popular DLL mod and therefore presents less of a compatibility issue than, say, a custom DLL mod you made specifically for your own mod (Mac users are obviously left in the dust in either case, unfortunately).

It's funny, reflecting back on my beginning Civ5 modding days (only a mere month or so ago), with bright-eyed, bushy-tailed Cyphose being astounded at how modular Civ5 was! Oh, the possibilities! And look at how simple XML is, yet how much it does!

...I was very quickly put in my proper place, of course.

Civ5 is the first game I've ever tried to mod, though I suspect it's quite similar elsewhere. I feel like the motto of the modding community in general should be something to the effect of "we didn't start out insane, but we're being driven there."
 
CP has all the code (and hence events) from my DLL, so the events you're interested in are

Code:
// Events sent by plots (v30)
//   GameEvents.PlayerCanBuild.Add(function(iPlayer, iUnit, iX, iY, iBuild) return true end)
//   GameEvents.PlotCanImprove.Add(function(iX, iY, iImprovement) return true end)
//   GameEvents.PlayerBuilding.Add(function(iPlayer, iUnit, iX, iY, iBuild, bStarting) end) (v46)
//   GameEvents.PlayerBuilt.Add(function(iPlayer, iUnit, iX, iY, iBuild) end) (v46)
#define MOD_EVENTS_PLOT                             gCustomMods.isEVENTS_PLOT()
specifically PlotCanImprove(iX, iY, iImprovement)

if iImprovement is your specific improvement, loop the plots around (iX, iY) and only return true if one of them has a (non-pillaged) pasture
 
Wow, that was actually something I had completely forgotten about the CP DLL. I mostly began using it for the Unified Yields aspect, which makes traits, policies, beliefs, buildings, etc. so much easier to work with. I totally let it slip my mind that it added new Lua hooks as well! There's obviously a lot of investigation I need to do to find out exactly what new limits the CP DLL allows me to get to. Thanks, that neatly solves my problem!

I've got another question, simply while I'm thinking of it. I actually solved the basic question on my own, but I'm asking it in the pursuit of an answer to a related issue that it creates:

Say I want a building that, for every 4 you own, City-State Influence decays slower. Easy enough: use Lua to track the amount you have, grant dummy Policies that lower CS Influence decay whenever you reach certain thresholds. The issue this creates, however, is related to the fact that you can also dip down below thresholds after reaching them (say you have 5 of this building and lose two of them; now you have 3 and technically this means you shouldn't get the bonus policy anymore). Because of this, it means the Policies need to be granted and taken away depending on the thresholds, and the problem comes in with the taking away part.

I know that taking away a Policy without putting one in its place completely breaks the Social Policy cost calculation, so I just remove the CS Influence policy and give the player a placeholder policy until they reach that threshold again, whereupon I remove the placeholder and give them the proper policy again. Again, it seems like it would work in theory, but I remember hearing that if you fiddle around with Policies too much, especially with the SetNumFreePolicies(1)/SetNumFreePolicies(0) trick, it causes problems with Policies as well.

I seem to remember hearing that doing it too many times can cause some problems, and obviously, in this circumstance, adding and taking away Policies as necessary might have unforeseen consequences in and of itself.

So, my question is this: what exactly are the repercussions with granting too many "dummy" free Policies through Lua (through the SetNumFreePolicies trick described above)? Are there any, or am I completely mistaken about the risks of doing so? Can I do it as many times I want safely, or do I need to keep a close eye on how many I'm giving? Is this entire issue not actually an issue, and I've just been misinformed?
It's not a pressing question related to how to solve something, and far more related to what my limits are (since that's a useful thing to know)! I just thought I would inquire while I had the chance, since I'd prefer to find out sooner rather than later if my solution might cause some gamebreaking Policy-related crash of all that is good in the world once I granted one too many free dummy Policies.
 
I mostly began using it for the Unified Yields aspect, which makes traits, ...

Believe me, I know!

WRT new events, look in the CustomModOptions.xml file
WRT new Lua API methods, they were documented here - but I suspect that's now out-of-date

As for policies, you'll need someone more versed in their usage and pitfalls to answer
 
There are two issues with giving free social policies to a player:
  1. Breaking the next social policy cost system
  2. Breaking the player notification system that they have a social policy they can choose
  • WRT #1 and giving dummy policies, so long as you swap a placeholder policy for a 'real' dummy policy whenever you need to take away the 'real' dummy policy, you are fine. You are also fine when you swap the 'real' dummy policy back in for the placeholder policy. You are also fine if you swap one 'real' dummy policy for a different 'real' dummy policy. The basic rule here is that the total number of policies a player has should never change as a result of removing a given policy from a player (hence the need for swapping placeholders).
  • WRT #2, this happens if too many of these policy-swaps, free policy giveaways, etc., have occured. As I recall from my testing once a total of 23 swaps or new free policies have been given, the player notification pop-up ceases to function. This also can be solved by forcing the notification if the player's accumulated culture is >= to the next social policy cost.
Give a new free 'real' dummy policy:
Code:
pPlayer:SetNumFreePolicies(1)
pPlayer:SetNumFreePolicies(0)
pPlayer:SetHasPolicy(iTruePolicyToGive, true)
Swap a Placeholder for the previously-given policy1:
Code:
pPlayer:SetHasPolicy(iTruePolicyToGive, false)
pPlayer:SetHasPolicy(iPlaceholder1, true)
Swap a different 'real' dummy policy for the 1st placeholder1:
Code:
pPlayer:SetHasPolicy(iPlaceholder1, false)
pPlayer:SetHasPolicy(iTruePolicyToGive2, true)
Directly swap one 'real' dummy policy for another 'real' dummy policy1:
Code:
pPlayer:SetHasPolicy(iTruePolicyToGive, false)
pPlayer:SetHasPolicy(iTruePolicyToGive2, true)
None of the foregoing has any of the logic that needs to be handled before these lines are executed, however. So in the very first example we really ought to 'wrap' those lines with a conditional that checks to see if the player already has the policy2:
Code:
if not pPlayer:HasPolicy(iTruePolicyToGive) then
	if pPlayer:HasPolicy(iPlaceholder1) then
		pPlayer:SetHasPolicy(iPlaceholder1, false)
		pPlayer:SetHasPolicy(iTruePolicyToGive, true)
	elseif pPlayer:HasPolicy(iTruePolicyToGive2) then
		pPlayer:SetHasPolicy(iTruePolicyToGive2, false)
		pPlayer:SetHasPolicy(iTruePolicyToGive, true)
	else
		pPlayer:SetNumFreePolicies(1)
		pPlayer:SetNumFreePolicies(0)
		pPlayer:SetHasPolicy(iTruePolicyToGive, true)
	end
end

----------------------------------------------------------------------------------------------------------------------------

This is the code I use in the Dynamic Social Policy Effects system to cure the broken 'select social policy' notifications.
  • Since the Dynamic Social Policy Effects system goes ahead and purposefully breaks the pop-up notification system from the very beginning of the game, I did not have to consider issues with both this code and the game's usual systems wanting to 'double-pop' essentially the same player notification.
Code:
--Fixes the issue with the social policy pop-up notification not wanting to display

function PlayerSocialPolicyPopUpNotification(iPlayer)
	local pPlayer = Players[iPlayer]
	if pPlayer:IsHuman() then
		if pPlayer:GetJONSCulture() >= pPlayer:GetNextPolicyCost() then
			pPlayer:AddNotification(NotificationTypes.NOTIFICATION_POLICY, "SocialPolicy" ,"May Adopt Policy", -1, -1)
		end
	end
end
GameEvents.PlayerDoTurn.Add(PlayerSocialPolicyPopUpNotification)

Spoiler notations :

1note that in this case we don't use pPlayer:SetNumFreePolicies
2this would be the basic structure for giving the player iTruePolicyToGive when there are two 'real' dummy policies and one placeholder policy, and the player can only ever have one of the three. But it quickly can become very complicated in terms of the required code when there are multiple 'real' dummy policies and multiple 'placeholder' policies to account for.
 
Believe me, I know!
Oh, I know you know :p Take it as a compliment that I'd mention to you how useful the work you (and others) have done is!

Also, thanks for all the clarification, LeeS. Policies are really effective way to get stuff done, but I was worried that over-using them would lead to problems like the ones you describe. It's very helpful to know that when adding/taking away placeholder policies that the "SetNumFreePolicies" isn't used; I had that in my solution and, while it wouldn't necessarily cause problems, it's definitely an unnecessary and risky addition.

With regards to the "notification" fix so that overusing swaps/free Policies doesn't cause the popup to stop appearing: would it be safe to assume that I should use it in any circumstance when I'm granting free "dummy" Policies? Even if I'm not necessarily swapping and changing them around constantly, I would suppose that including the notification force is just a nice failsafe to ensure that no matter what I do, the Policy notification will work regardless.
 
It depends entirely on your usage for giving and taking away policies. If you only ever give one or two policies to the same player, and then never take those policies away, or never do swaps back and forth between them, there will be no reason to add the code to force the notification.

Quite a few civ-mods give a free dummy policy to create the desired UA effect, for example. In this case the policy is given at game-start, and never taken away again, so there would be no need for the notification 'forcing' method.
 
Okay, so this is undoubtedly the weirdest, most inconsequential question I have yet to ask, but since I'm a real stickler for tooltip consistency, it's been driving me up a wall because I swear it's only happening to me.

It's a very simple issue: why do apostrophes appear as quotes in text?! Any time I use ' (in, say, Satrap's Court), it appears as " (and thus something like Satrap"s Court). I'm too anal to allow these semantics to pass!

Case-in-point, here's the code:



And here's how it appears on the tooltip in-game:



Ignore the mostly incomplete changes (like the fact that it still requires a Market), it's a work in progress.

But notice the Satrap"s Court. And the name itself uses the apostrophe just fine! Why?! I could just be blind (it has happened), but I can't seem to find any reason for this to happen, and I've glanced at other code that uses ' (even game code!) and it works fine. My hypothesis for it is twofold: it's either an EUI bug (which wouldn't really make sense considering all the other apostrophes that seem to work), or it's an XML issue (which, again, wouldn't make much sense to me), and I'd rather not turn to SQL as I have no experience with it.

Is this some isolated incident where it's just something wrong with my Civ? It's driving me insane; this is by far the most pressing question I've yet to ask. Save me from myself. i can't wake up
 
Well, unless I did it wrong:



Sadly, it doesn't work either--the apostrophe still appears as a quotation mark to me. Shame, since that seems like a perfectly reasonable solution and I wouldn't be surprised if XML did quirky things like that... but it doesn't seem to be the case here.

EDIT Well, I answered my own question after obsessing about it for so long. Figures I'd find out the problem soon after posting it. On a hunch, I tried something different and got it to work. Turns out that, for whatever reason, the problem is in the <Update> statement; if you assign a new Help tag, it works fine. In this case, I created a brand new Help tag (named after my mod):



...and it worked.

Why apostrophes seem to be incompatible with <Update> statements is beyond me, but there you go; if you want to use an apostrophe, use a brand new text tag. Thank you for your help, Klisz; your advice gave me the hunch (to avoid using quotes--and defining a new tag was the only other way I could think of to do that) I needed to solve it!

EDIT 2 An even better solution that still works: use the <Replace> tag! I've also come to the sudden realization that I was taking screencaps of my code instead of just copy/pasting it in code tags. No idea why I started doing that, but here's everything as it should be:
Code:
<Replace Tag="TXT_KEY_BUILDING_SATRAPS_COURT_HELP">
	<Text>The [COLOR_POSITIVE_TEXT]Satrap's Court[ENDCOLOR] is a unique [COLOR_YIELD_FOOD]Courthouse[ENDCOLOR] replacement that only Persia may build.[NEWLINE][ICON_BULLET]Removes the [ICON_HAPPINESS_4] Unhappiness penalty of City [ICON_OCCUPIED] Occupation.[NEWLINE][ICON_BULLET]Increases the [ICON_CULTURE] Culture output of the City and increases its [ICON_HAPPINESS_1] Happiness.[NEWLINE][ICON_BULLET]During a [ICON_GOLDEN_AGE] Golden Age, the City gains the yields of the [COLOR_YIELD_FOOD]Palace[ENDCOLOR] in the [ICON_CAPITAL] Capital.[NEWLINE][ICON_BULLET]Can be built in non-Occupied Cities, unlike the Courthouse.</Text>
</Replace>
This also produces the desired result (i.e. uses an actual apostrophe) and comes with the added benefit of not having to fiddle around with building definitions and define new tags altogether. Again, why Replace works over Update (or, more accurately, why Update produces such a strange issue in the first place) remains a mystery to me.
 
EDIT 2 An even better solution that still works: use the <Replace> tag! I've also come to the sudden realization that I was taking screencaps of my code instead of just copy/pasting it in code tags. No idea why I started doing that, but here's everything as it should be:
Code:
<Replace Tag="TXT_KEY_BUILDING_SATRAPS_COURT_HELP">
	<Text>The [COLOR_POSITIVE_TEXT]Satrap's Court[ENDCOLOR] is a unique [COLOR_YIELD_FOOD]Courthouse[ENDCOLOR] replacement that only Persia may build.[NEWLINE][ICON_BULLET]Removes the [ICON_HAPPINESS_4] Unhappiness penalty of City [ICON_OCCUPIED] Occupation.[NEWLINE][ICON_BULLET]Increases the [ICON_CULTURE] Culture output of the City and increases its [ICON_HAPPINESS_1] Happiness.[NEWLINE][ICON_BULLET]During a [ICON_GOLDEN_AGE] Golden Age, the City gains the yields of the [COLOR_YIELD_FOOD]Palace[ENDCOLOR] in the [ICON_CAPITAL] Capital.[NEWLINE][ICON_BULLET]Can be built in non-Occupied Cities, unlike the Courthouse.</Text>
</Replace>
This also produces the desired result (i.e. uses an actual apostrophe) and comes with the added benefit of not having to fiddle around with building definitions and define new tags altogether. Again, why Replace works over Update (or, more accurately, why Update produces such a strange issue in the first place) remains a mystery to me.

Thank you thank you thank you.
 
It's even more fun than you think. This is valid code for stating the contents of a TXT_KEY:
Code:
<Row Tag="TXT_KEY_GREAT_PERSON_BUFORD" Text="John Buford" />
If I change it to:
Code:
<Row Tag="TXT_KEY_GREAT_PERSON_BUFORD" Text="John's Buford" />
I get John"s Buford instead of John's Buford. But as you have discovered, changing the presentation syntax of the new Row to:
Code:
<Row Tag="TXT_KEY_GREAT_PERSON_BUFORD">
	<Text>John's Buford</Text>
</Row>
restores the in-game text to John's Buford. You can also present as this:
Code:
<Row>
	<Tag>TXT_KEY_GREAT_PERSON_BUFORD</Tag>
	<Text>John's Buford</Text>
</Row>
And, I am assuming, as:
Code:
<Update>
	<Where>
		<Tag>TXT_KEY_GREAT_PERSON_BUFORD</Tag>
	</Where>
	<Set>
		<Text>John has Buford's first name</Text>
	</Set>
</Update>
Which I suspect will not show the " issue, but will I think display with only the one ' mark.

Long story short is that xml has to be parsed into SQL-correct format when inserted into the game's database(s)1, and the ' and " characters have special usages in SQL, and so as far as I can tell will get parsed into " within <Text> for the language databases if there is any possibilility of confusion in translating into SQL between " and '. This possible confusion-conflict appears to stem from the use of " in xml-code.



1<Language_en_US> is actually its own database and not a table within the overall SQL game database.
 
Top Bottom