Help writing a new UA in Lua: need to track other civs who have declared war

RSJ87

Chieftain
Joined
Jun 25, 2014
Messages
5
Hi all

First post on Civ Fanatics. I'm new to modding and have released a few Warhammer Fantasy-themed civs, which you may have seen over the last few days. I know my way around XML and all but have definitely realised it only goes so far.

I want to amend the UA of one of my released civs and need a hand using Lua to do it. Basically, the UA I want is:

"All units gain +XX% combat strength when fighting Civilisations that have declared war on you at any time during the game."

I've managed to (sort of) get a Lua test script hooked in to my mod, but don't really know where to start with writing code to achieve the above. If anyone could point me in the right direction I'd be very grateful. If anyone actually wants to write me this code, I'd be even more grateful, and would of course give you credits in the mod.

Thanks in advance for any help. Looking forward to joining the community. :)

- RSJ
 
You may need a DLL mod for that.

To get civs that have declared war on you, you could make a persistent lua table to store that info.

The problem is there are no good combat events. I don't know of any pre-combat events, the Events having to do with combat don't fire (in my tests) when you'd expect (e.g. a unit attacks another) and even WHoward's DLL which has CombatEnded and CombatResult GameEvents just return 0 for me.

You could make some PlayerDoTurn event loops and check units surrounding each of your combat units and if in range to attack could give promotion (and remove if not). However, if a unit is surrounded by units of multiple players, a unit might get the bonus when attacking a player who did not declare war on them.
 
The Events below works. However, what I don't remember is whether iTeam1 and iTeam2 correspond to the DoWer and DoWee, respectively (and reliably) or if order is arbitrary. Or if it fires twice reciprocally. So you would have to test that.

Code:
local function OnWarStateChanged(iTeam1, iTeam2, bWar)		--works even if active player hasn't met either teem
	print("OnWarStateChanged", iTeam1, iTeam2, bWar)

end
Events.WarStateChanged.Add(OnWarStateChanged)

There are many cautions around here about using "Events". The issue is that Events are generated in the exe (code that we don't have access to, which includes graphics engine) whereas "GameEvents" are generated in the dll (C++ code that modders can see so we know exactly how they work). And very many Events are really related to graphic/UI function (SerialEventsCityCreated, etc...) and have nothing to do with game logic. But I'm pretty sure the one above is used for stuff other than graphics so is safe to use.

And my signature below has a solution to the problem of persisting Lua information through game save/load.
 
And very many Events are really related to graphic/UI function (SerialEventsCityCreated, etc...) [...]
Are you sure SerialEventsCityCreated doesn't have game logic? I could swear it works even if the Human isn't looking, like SerialEventCityPopulationChanged.
Not really related to the topic, I know, but I have a Civ in the works that uses SerialEventsCityCreated to identify the 5th city founded by another civ.
 
It's definitely a hook to graphic engine. But that doesn't answer your question, which I don't know the answer to. Some of the graphics hooks fire only when player can see it, but others fire always. I think in this case the "graphics object" gets set up whether or not the player can see it at the time.

Even the ones that fire always do so "at the leisure of" the graphics engine. For example, RunCombatSim and EndCombatSim "work" in the sense that they always fire. But they both fire a long time (in processor time) after the actual combat. It makes sense if you think about the graphics engine queuing up graphics tasks. There's no reason for that to respect game data changes elsewhere.
 
Pretty sure both those events fire regardless, as the CityBannerManager has to build/update the AI city labels for the invisible cities just in case a player scout stumbles across them
 
I think the bigger problem is whether the OTHER civ has DECLARED war. If you attack another civ then the combat events trigger but that doesn't mean that they declared war on you. Do you just want to know if you EVER WENT TO WAR?

I also thought about just checking whether IsEnemyUnit or IsEnemyCity is true during some specific point in the turn. But again, this only tells you that you are in a combat state and not that THEY declared war on you. Unless anyone sees something wrong with this?

If you want to actually check for WAR DECLARATION you may want to hook into the DIPLOMACY messaging where they declare war. I am sure that is not 100% foolproof.

Finally, you could intercept YOUR OWN declaration of war (via UI) and flag something in your own data (against who, etc). Then when you detect combat state (IsEnemyUnit) you will know if it was you that declared war and not them, or vice versa. Just a thought.
 
That information may or may not be obtainable by Events.WarStateChanged. I just don't know. But if someone wants to know the answer, just set up my "listener" posted above.

Perhaps iTeam1 on the first call is always the team that DoWs? But we just won't know unless someone tries. Or unless someone looks in dll and tells us the answer. [strike that. Events aren't in dll]

It's a total guess, but maybe what you will see if team 1 DoWs on team 2 is:

OnWarStateChanged 1 2 true
OnWarStateChanged 2 1 true

If it's consistent like that then you have your solution.
 
Same answer I had above. I don't know. So why not try listener and find out?

I have a vague memory that it will fire twice reciprocally for each DoW, including allied CS DoWs, or I suppose any Full Civs with defensive alliance (which should DoW on attacker when they DoW on the ally). But it only takes a few minutes to test all of this in Fire Tuner so no reason to depend on my vague memory.
 
Back
Top Bottom