Codefreak5's Fire Emblem Civilizations

I'm running into a problem handling the second part. There is an event (Events.WarStateChanged) which triggers when war is declared, but it triggers twice for each declaration: once with the attacker as the first argument and the defender as the second, and once with the opposite.
The order in which they trigger is significant ((attacker, defender, true) triggers first, then (defender, attacker, true)), but I'm not quite good enough at lua modding to use that to my advantage. Presumably a custom table would have to be created to keep track of which events have triggered during a turn, which is beyond me. Could someone offer help or insight on this?
 
I'm running into a problem handling the second part. There is an event (Events.WarStateChanged) which triggers when war is declared, but it triggers twice for each declaration: once with the attacker as the first argument and the defender as the second, and once with the opposite.
The order in which they trigger is significant ((attacker, defender, true) triggers first, then (defender, attacker, true)), but I'm not quite good enough at lua modding to use that to my advantage. Presumably a custom table would have to be created to keep track of which events have triggered during a turn, which is beyond me. Could someone offer help or insight on this?

Do Events-based events (as opposed to GameEvents-based) trigger for the AI players as well? I'm assuming that final parameter is a boolean flag for the state of war now? (As in, it's true because war is now happening) With all of that, maybe something like this:

Code:
warTable = {}

function WarDeclared(attacker, defender, declaration)
	if (not declaration) then
		return
	end

	if (warTable[attacker] ~= nil) then
		warTable[attacker] = nil
	else
		warTable[defender] = attacker
		
		-- do all your UA stuff here, 'attacker' is the declaring player's ID
		-- and 'defender' is the defending player's ID at this point
	end
end
Events.WarStateChanged.Add(WarDeclared)

Technically this will only work if you can't save and exit the game between the two events (which I would think should be difficult). Even so, that should only actually be a problem if, after doing that, the game sends the second event after you reload the save file, which seems unlikely. Off the top of my head, I think this logic should be able to handle multiple declarations of war/peace between the same players in the event of multiplayer shenanigans (in the far distant future where mods work in multiplayer).

Disclaimer: totally untested, but hopefully helpful. ;)
 
Sure, I'll give it a shot. The OP doesn't seem to have the link in it though. I see "A current version of the mod can be downloaded below." and then no link.
That's odd. I'm sure I uploaded them - I distinctly remember doing so.

Ah, well. They're back up now. If it happens again, I'll see what I can do about it.
 
Do Events-based events (as opposed to GameEvents-based) trigger for the AI players as well? I'm assuming that final parameter is a boolean flag for the state of war now?
Yes (presumably because a declaration of war always leads to UI stuff) and yes. Thank you for the code, this should be quite helpful. One thing looks odd about it though. Since the ID order is reversed when the event triggers for the second time, shouldn't the value you make not-nil be the value you're NOT testing for? Otherwise you will still find the 'defender' value to be nil the second time because the value you changed is now the 'attacker' value.
 
Yes (presumably because a declaration of war always leads to UI stuff) and yes. Thank you for the code, this should be quite helpful. One thing looks odd about it though. Since the ID order is reversed when the event triggers for the second time, shouldn't the value you make not-nil be the value you're NOT testing for? Otherwise you will still find the 'defender' value to be nil the second time because the value you changed is now the 'attacker' value.

Very true, I've edited my post to use what I think should be correct code.

Do you know if the event still fires when two AIs that the human player hasn't met declare war on each other then? That seems like it might not change any UI, but I'm not sure.
 
I don't know, unfortunately. That would be rather hard to figure out by testing.

Put some print statements in that say who is declaring on who. Then set up an AI game with yourself, Ylisse, Attila, Genghis, etc. (warmongers) and try not to reveal much of the map. ;) That's the first thing that comes to mind for me. (Possibly using AI autoplay from FireTuner, but I don't remember if that reveals the map while it's going.)
 
So far I've found that it at least triggers when an unmet AI declares on a met one, even though the player doesn't get any notification of that. But even with 12 total players on a pangaea map sized for 4, quick speed and no barbarians or city-states and with all victory types other than domination disabled, wars are disappointingly uncommon. They're so uncommon among the AIs I do meet (and I can't help but meet four of them pretty quickly even doing nothing) that I dare not infer there must have been one among the ones I didn't.
 
Right. While the issue of whether the trigger will work between unseen AIs is not 100% cleared up, I did finish fixing up the necessary lua code.
Code:
print("------------------------------------------")
print("--- Ylisse support script initializing ---")
print("------------------------------------------")

iBonusPerTurn = 2		--To be tweaked by playtesting. Put here for easy changing.
warTable = {}

function raiseCityStateInfluence( player )
local pPlayer = Players[player]
if pPlayer:IsEverAlive() and pPlayer:IsAlive() then
print("Turn started for ",pPlayer:GetCivilizationShortDescription())
if pPlayer:GetCivilizationType() == GameInfoTypes["CIVILIZATION_YLISSE"] then
	iTeam=pPlayer:GetTeam()
	pTeam=Teams[iTeam]
	atPeace=true
	for iOtherTeam, pOtherTeam in pairs(Teams) do
		if pTeam:IsAtWar(iOtherTeam) and iOtherTeam~=63 then atPeace=false end	--Exclude 63 because that is Barbarians!
	end
	if (not atPeace) then print("--Ylisse is at war. Influence will not be raised.") end
	if atPeace then
		print("--raising influence with protected city-states")
		for iLoop = GameDefines.MAX_MAJOR_CIVS, GameDefines.MAX_CIV_PLAYERS-1, 1 do
			pMinorCiv=Players[iLoop]
			if pMinorCiv:IsEverAlive() and pMinorCiv:IsAlive() then
				if pPlayer:IsProtectingMinor(iLoop) then
					print("--",pMinorCiv:GetCivilizationShortDescription())
					pMinorCiv:ChangeMinorCivFriendshipWithMajor(player,iBonusPerTurn)
				end
			end
		end
	end
end end
end



function WarDeclared(attacker, defender, declaration)
	if (not declaration) then
		return
	end

	if (warTable[attacker] ~= nil) then
		warTable[attacker] = nil
	else
		warTable[defender] = attacker

		for iAttackPlayer = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do			--need to move from Teams to Players
		for iDefendPlayer = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do
		pAttackPlayer=Players[iAttackPlayer]
		pDefendPlayer=Players[iDefendPlayer]
		if pAttackPlayer:IsEverAlive() and pAttackPlayer:IsAlive()			--basic Is Alive checkups
			and pDefendPlayer:IsEverAlive() and pDefendPlayer:IsAlive() then

		if pAttackPlayer:GetTeam()==attacker and pDefendPlayer:GetTeam()==defender then	--now we can finally get somewhere
			print(pAttackPlayer:GetCivilizationShortDescription(),"declared war on",pDefendPlayer:GetCivilizationShortDescription())
			if pDefendPlayer:GetCivilizationType() == GameInfoTypes["CIVILIZATION_YLISSE"] then
				print("--Reducing city-state influence accordingly")
				for iLoop = GameDefines.MAX_MAJOR_CIVS, GameDefines.MAX_CIV_PLAYERS-1, 1 do	--go through minor civs
					pMinorCiv = Players[iLoop]
					if pMinorCiv:IsEverAlive() and pMinorCiv:IsAlive() then
						iYlisseInfluence=pMinorCiv:GetMinorCivFriendshipWithMajor(iDefendPlayer)
						pMinorCiv:ChangeMinorCivFriendshipWithMajor(iAttackPlayer, (0-iYlisseInfluence))
					end
				end
			end
		end	
		end end end
	end
end

Events.WarStateChanged.Add(WarDeclared)
GameEvents.PlayerDoTurn.Add(raiseCityStateInfluence)
 
I finished creating the Civilopedia entries for Emmeryn and Ylisse. The updated version of the mod can be found in the OP, as usual.

Right. While the issue of whether the trigger will work between unseen AIs is not 100% cleared up, I did finish fixing up the necessary lua code.
Code:
print("------------------------------------------")
print("--- Ylisse support script initializing ---")
print("------------------------------------------")

iBonusPerTurn = 2		--To be tweaked by playtesting. Put here for easy changing.
warTable = {}

function raiseCityStateInfluence( player )
local pPlayer = Players[player]
if pPlayer:IsEverAlive() and pPlayer:IsAlive() then
print("Turn started for ",pPlayer:GetCivilizationShortDescription())
if pPlayer:GetCivilizationType() == GameInfoTypes["CIVILIZATION_YLISSE"] then
	iTeam=pPlayer:GetTeam()
	pTeam=Teams[iTeam]
	atPeace=true
	for iOtherTeam, pOtherTeam in pairs(Teams) do
		if pTeam:IsAtWar(iOtherTeam) and iOtherTeam~=63 then atPeace=false end	--Exclude 63 because that is Barbarians!
	end
	if (not atPeace) then print("--Ylisse is at war. Influence will not be raised.") end
	if atPeace then
		print("--raising influence with protected city-states")
		for iLoop = GameDefines.MAX_MAJOR_CIVS, GameDefines.MAX_CIV_PLAYERS-1, 1 do
			pMinorCiv=Players[iLoop]
			if pMinorCiv:IsEverAlive() and pMinorCiv:IsAlive() then
				if pPlayer:IsProtectingMinor(iLoop) then
					print("--",pMinorCiv:GetCivilizationShortDescription())
					pMinorCiv:ChangeMinorCivFriendshipWithMajor(player,iBonusPerTurn)
				end
			end
		end
	end
end end
end



function WarDeclared(attacker, defender, declaration)
	if (not declaration) then
		return
	end

	if (warTable[attacker] ~= nil) then
		warTable[attacker] = nil
	else
		warTable[defender] = attacker

		for iAttackPlayer = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do			--need to move from Teams to Players
		for iDefendPlayer = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do
		pAttackPlayer=Players[iAttackPlayer]
		pDefendPlayer=Players[iDefendPlayer]
		if pAttackPlayer:IsEverAlive() and pAttackPlayer:IsAlive()			--basic Is Alive checkups
			and pDefendPlayer:IsEverAlive() and pDefendPlayer:IsAlive() then

		if pAttackPlayer:GetTeam()==attacker and pDefendPlayer:GetTeam()==defender then	--now we can finally get somewhere
			print(pAttackPlayer:GetCivilizationShortDescription(),"declared war on",pDefendPlayer:GetCivilizationShortDescription())
			if pDefendPlayer:GetCivilizationType() == GameInfoTypes["CIVILIZATION_YLISSE"] then
				print("--Reducing city-state influence accordingly")
				for iLoop = GameDefines.MAX_MAJOR_CIVS, GameDefines.MAX_CIV_PLAYERS-1, 1 do	--go through minor civs
					pMinorCiv = Players[iLoop]
					if pMinorCiv:IsEverAlive() and pMinorCiv:IsAlive() then
						iYlisseInfluence=pMinorCiv:GetMinorCivFriendshipWithMajor(iDefendPlayer)
						pMinorCiv:ChangeMinorCivFriendshipWithMajor(iAttackPlayer, (0-iYlisseInfluence))
					end
				end
			end
		end	
		end end end
	end
end

Events.WarStateChanged.Add(WarDeclared)
GameEvents.PlayerDoTurn.Add(raiseCityStateInfluence)

Is this the final code, or do you still need to test it? I can put it into a Lua file in the mod directory right away if it is.
 
I've tested, adjusted, retested and readjusted that code until it worked. It's good to go.
Also, I've just done a special test making me confident that war declarations will be picked up between invisible AIs. I just used the Team:DeclareWar function in the LiveTuner console to force the issue, and indeed the event triggered.
 
I've tested, adjusted, retested and readjusted that code until it worked. It's good to go.
Also, I've just done a special test making me confident that war declarations will be picked up between invisible AIs. I just used the Team:DeclareWar function in the LiveTuner console to force the issue, and indeed the event triggered.

Excellent. I also put together an icon for the Shrine of Naga. (Okay - I took a picture of Naga and put a circle around one part of it. It works.)

So, we're pretty much done here. Once S3rgeus finishes the Pegasus Knight placeholder and I or someone else comes up with an acceptable Dawn of Man text (and a name for the Trait), there's really not much else to do, except wait for an actual Pegasus Knight model.

Thanks for the help, Harald and S3rgeus. Couldn't have done this without you.
 
Having recently recieved Brave New World in the recent Steam Sale, I have been able to get a first-hand experience with the World Congress and its features, leading me to wonder if the trait for Ylisse should be tweaked to provide a better bonus, or if it should remain unchanged, as the bonus influence it gains from protecting City-States can allow it to gain additional delegates with less effort from the Industrial Era onward.

I also think the UB could hold a Great Work of Art, though Great Artists don't begin generating until the Artist's Guild is built in the Medieval Era, meaning the slot won't be filled for a good while.

Conversely, I would also like to make this available to those playing the Vanilla version of the game, which requires a different UB altogether. A Monument replacement should be sufficiently similar; it exists in the same Era as the Shrine, and it will have an increased Culture output instead of Faith, along with the Happiness bonus. The only difference is a lack of a pre-required tech.

Please tell me what you think about these ideas.
 
The Congress may change Diplomatic Victory a bit, but it's still all about getting a lot of city-state votes. I've been playing Brave New World for quite a while now, so this was certainly on my mind when I proposed the trait.

About the Shrine and Vanilla, it's worth mentioning that there's a trick so that you don't have to choose. Define and assign the Monument replacement in one XML file, then make a second XML file you load last in which you unassign the Monument replacement and define and assign the Shrine replacement. When the mod is loaded into a Vanilla game, the error causes the entire second XML file to be dropped, leaving the Monument replacement in place.
 
The Congress may change Diplomatic Victory a bit, but it's still all about getting a lot of city-state votes. I've been playing Brave New World for quite a while now, so this was certainly on my mind when I proposed the trait.

About the Shrine and Vanilla, it's worth mentioning that there's a trick so that you don't have to choose. Define and assign the Monument replacement in one XML file, then make a second XML file you load last in which you unassign the Monument replacement and define and assign the Shrine replacement. When the mod is loaded into a Vanilla game, the error causes the entire second XML file to be dropped, leaving the Monument replacement in place.

Yeah, I noticed you did that in your mods. I'll have to see how you did it and try it myself.

Thanks for the feedback, Harald.
 
Minor update!
DLC-specific XML files have been added, containing AI behaviour added in G&K and BNW respectively. The G&K file also contains the Shrine, and the default UB has changed to a Monument replacement, the Statue of Naga. The G&K file will replace it with the Shrine.

There is now description text for the trait in the Dawn of Man screen. It still needs a name, and I need to come up with a full DOM speech/text/intro thing. Any help with these would be very much welcome.

Updates and current downloads are available in the OP.
 
Woops sorry for losing track of this

I like your idea for the UA. I kind of wanted to find one of the many "bonds" quotes in Awakening for the name but internet browsing isn't helping much. "Shepherds" might be a good name for it but once again that's more Chrom than Emmeryn.
 
Woops sorry for losing track of this

I like your idea for the UA. I kind of wanted to find one of the many "bonds" quotes in Awakening for the name but internet browsing isn't helping much. "Shepherds" might be a good name for it but once again that's more Chrom than Emmeryn.

The UA was Harald's idea; thank him, not me.

For a name, I'm thinking of something along the lines of peace and diplomacy, while also taking something from the game to appeal to the fans. I'll look around the Fire Emblem Wiki some more to try and find something. You can help too, if you want.

As for losing track of this, it's fine. People get busy and forget things. I do it a lot. So, don't worry about it.

On a completely unrelated note to everything I said in this post, I want to find a way to change the name of the thread. It's no longer "Heavily WIP", it's almost done. I believe I've seen thread names change before. Does anyone know how to do it or where to find this out?
 
Probably only moderators can change thread names. You can hope one of them notices, maybe send a pm if it bothers you that much.
 
Top Bottom