View Full Version : Wages of Sin bug/glitch?
Onionsoilder Sep 05, 2009, 09:25 PM Alright, well I was playing this scenario today. I killed the Calabim, Svartalfar and Sheim... but I didn't win. The counter even said "destroy 0 more civilizations to win!" but nothing happend. I took out the Infernals for good measure. Still no victory. Anyone know what's up?
TC01 Sep 05, 2009, 09:34 PM Strange. I can't see any problem with the code. Possibly these values
if gc.getPlayer(1).isAlive(): #Flauros
iCount += 1
if gc.getPlayer(3).isAlive(): #Faeryl
iCount += 1
if gc.getPlayer(5).isAlive(): #Os-Gabella
iCount += 1
if gc.getPlayer(6).isAlive(): #Hyborem
iCount += 1
are wrong? I.e. that the numbers listed here do not match up to the players in comments next to them?
Onionsoilder Sep 11, 2009, 10:26 AM Well, I still can't get it working. I even tried starting up a new scenario(I quickly used WB to win this time) and it still didn't work. Anyone have a text version of the scenario so I can see what happens? I can just start Against the Grey manually, so I don't really need to clear it.
Elyssaen Sep 11, 2009, 05:58 PM It worked for me. I was running patch 0.41d at the time. Let me know if you're running something different.
if gc.getPlayer(1).isAlive(): #Flauros
iCount += 1
if gc.getPlayer(3).isAlive(): #Faeryl
iCount += 1
if gc.getPlayer(5).isAlive(): #Os-Gabella
iCount += 1
if gc.getPlayer(6).isAlive(): #Hyborem
iCount += 1
TC01, let me throw my dignity on the line by trying to interpret a programming language I don't know.
iCount is a variable which is increased by 1 for each of Flauros, Faeryl, Os-Gabella and Hyborem that are alive. This is the only code I'm looking at, but I assume that the game doesn't run this piece of code every turn without setting iCount = 0 beforehand. It should be looking to see how many of these four are alive every turn, and after this piece of code should be another with an appearance a little like this1:
if iCount = 4
write "Destroy 3 more civilizations to win!"
if iCount = 3
write "Destroy 2 more civilizations to win!"
if iCount = 2
write "Destroy 1 more civilizations to win!"
if iCount < 2
write "Destroy 0 more civilizations to win!"
[[Conquest trigger code]]
Back to the crux of the issue. If the code you pasted here was assigning the numbers I've highlighted in blue to the wrong players, Onionsoilder (incidentally, sp?) wouldn't be able to read "Destroy 0 more civilizations to win!" on the screen. He could get that message by destroying the right combination of Malakim, Elohim, Ljosalfar and Mercurian players (as well) but he would have noticed and mentioned that the wrong players were decreasing the count. I think iCount is working as it should be.
His issue is a confusing one, as I didn't have it when playing Wages of Sin. The code/remark I highlighted in red is where the error should be. I want to come up with an explanation that doesn't involve the code being completely wrong, as this should be noticed more universally in an unmodified copy of the scenario file.
Onionsolider, can you tell me what version of Fall from Heaven (version number and patch) you're using?
I'm going to reboot into Windows to see if I can find the file that TC01 is opening. Beware: not only can I not (yet) code in Python, but I'm also sinfully incompetent at understanding Windows. Whether or not I can find what might be a mistake in the code, I can hopefully find you the victory text and an easy instruction for how to tell the game that you've completed Wages of Sin.
1 I mean only to convey the expected shape of the code. This is Python, I suspect, and my knowledge of programming language includes only moderate competence with Fortran. I'd rather write in a sort of programming 'baby speak' than write it how it would be in Fortran and be less clear.
Elyssaen Sep 11, 2009, 06:41 PM I've found the code, including the line I expected to find which is run at the beginning of every turn:
iCount = 0
I'm confident that iCount is functioning as it should be.
I'm quite enjoying looking through and trying to piece everything together. I've found this code:
if iCount < 2:
gc.getGame().setWinner(pHumanPlayer.getTeam(), 2)
I believe these two lines control the victory condition. iCount = 1 describes a turn in which three of the necessary three factions have been destroyed. iCount = 0 describes a turn in which all four have been destroyed. "< 2" rather than "= 1" has to be used in case you destroy the last one required and then the last one in the same turn.
Ah, a thought occurs. The entire code in this section is:
iCount = 0
if (pHumanPlayer.getCivilizationType() == iElohim or pHumanPlayer.getCivilizationType() == iMalakim):
if gc.getPlayer(1).isAlive(): #Flauros
iCount += 1
if gc.getPlayer(3).isAlive(): #Faeryl
iCount += 1
if gc.getPlayer(5).isAlive(): #Os-Gabella
iCount += 1
if gc.getPlayer(6).isAlive(): #Hyborem
iCount += 1
if (pHumanPlayer.getCivilizationType() == iSheaim or pHumanPlayer.getCivilizationType() == iCalabim):
if gc.getPlayer(0).isAlive(): #Varn
iCount += 1
if gc.getPlayer(2).isAlive(): #Arendel
iCount += 1
if gc.getPlayer(4).isAlive(): #Ethne
iCount += 1
if gc.getPlayer(7).isAlive(): #Basium
iCount += 1
if iCount < 2:
gc.getGame().setWinner(pHumanPlayer.getTeam(), 2)
It seems to be in charge of victory alone. This section does not control the pop-up stories or the "Destroy n more civilizations to win!" message. Below this section are if statements for "iCount == 2" and "iCount == 3". These correspond to when one or two factions have been destroyed. With no "iCount == 4" statement this piece of code can't be controlling the "Destroy n more civilizations to win!" messages either (it must be controlling the story line advancement messages when you destroy another faction).
Ah. This bothers me. I assumed the iCount variable would be simultaneously used to determine victory and also control those messages. It doesn't seem to be. I'm looking for other uses of iCount within this document, which doesn't just describe how Wages of Sin is run.
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_W B_WAGES_OF_SIN):
iCount = 0
for iPlayer in range(gc.getMAX_PLAYERS()):
pPlayer = gc.getPlayer(iPlayer)
if pPlayer.isAlive():
if pPlayer.isHuman():
iCount += 1
pHumanPlayer = pPlayer
if iCount == 1:
if pHumanPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_MALAKIM'):
szText = CyTranslator().getText("TXT_KEY_WB_WAGES_OF_SIN_INTRO_MALAKIM",())
if pHumanPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_ELOHIM'):
szText = CyTranslator().getText("TXT_KEY_WB_WAGES_OF_SIN_INTRO_ELOHIM",())
if pHumanPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_SHEAIM'):
szText = CyTranslator().getText("TXT_KEY_WB_WAGES_OF_SIN_INTRO_SHEAIM",())
if pHumanPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_CALABIM'):
szText = CyTranslator().getText("TXT_KEY_WB_WAGES_OF_SIN_INTRO_CALABIM",())
self.addPopupWB(szText, 'art/interface/popups/Wages of Sin.dds')
Ah. iCount is a lot more general, then. Here it's using iCount as a dummy variable – that must be what it is throughout the code – to throw up introductory text. For anyone interested in my stream of consciousness, yes, I've got a feeling that I know what bad assumption I made earlier.
if gc.getGame().isOption(GameOptionTypes.GAMEOPTION_W B_WAGES_OF_SIN):
iCount = 0
if (pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_ELOHIM') or pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_MALAKIM')):
for iPlayer in range(gc.getMAX_PLAYERS()):
pPlayer = gc.getPlayer(iPlayer)
if pPlayer.isAlive():
if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_SHEAIM'):
iCount += 1
if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_CALABIM'):
iCount += 1
if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_INFERNAL'):
iCount += 1
if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_SVARTALFAR') :
iCount += 1
if (pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_SHEAIM') or pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_CALABIM')):
for iPlayer in range(gc.getMAX_PLAYERS()):
pPlayer = gc.getPlayer(iPlayer)
if pPlayer.isAlive():
if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_ELOHIM'):
iCount += 1
if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_MALAKIM'):
iCount += 1
if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_MERCURIANS') :
iCount += 1
if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_LJOSALFAR'):
iCount += 1
szBuffer = szBuffer + CyTranslator().getColorText("TXT_KEY_WB_WAGES_OF_SIN_GOAL", ((iCount - 1, )), gc.getInfoTypeForString("COLOR_RED"))
szBuffer = szBuffer + "</font>"
return szBuffer
At first glance this code seems to be doing much the same as the first code I quoted, which is a larger selection of TC01's quote. It's setting iCount = 0 and then increasing it by 1 for every enemy faction left in the game. It's doing it separately to the other count, and the last three lines somehow describe what's being done with that information.
I can't decipher that very easily, but I've a vague recollection that the "Destroy n more civilizations to win!" messages were in red. If that's true then "COLOR_RED" indicates that this is the code controlling that.
Ah. Damn. In that case we've got one section of code that's checking how many enemy factions are alive to control the "Destroy n more civilizations to win!" messages, and another section that seems to be in charge of both the victory condition and presumably the story line advancement messages when you destroy another faction.
So, after that little rant I have a question.
Onionsolider – did you get story line advancement messages after destroying an enemy faction? If you didn't then iCount isn't counting right in the piece of code controlling both those and victory, even if it's counting right in the "Destroy n more civilizations to win!" messages.
Elyssaen Sep 11, 2009, 07:06 PM Update. I know why the two sections of code that are both counting how many factions are left are separated. The one which controls the "Destroy n more civilizations to win!" messages has to update in the middle of a turn. The other one must update at the beginning of each turn.
I ran a test game playing as the Malakim on 0.41f, which I now believe is what you're running. I received no story line advancement messages and did not achieve a victory. I'm also looking at "Destroy 0 more civilizations to win!". I have a better idea now what part of the code isn't working. It's the part TC01 mentioned, but he probably knows what he's doing more than I do – or didn't type out a lot of reasoning.
iCount = 0
if (pHumanPlayer.getCivilizationType() == iElohim or pHumanPlayer.getCivilizationType() == iMalakim):
if gc.getPlayer(1).isAlive(): #Flauros
iCount += 1
if gc.getPlayer(3).isAlive(): #Faeryl
iCount += 1
if gc.getPlayer(5).isAlive(): #Os-Gabella
iCount += 1
if gc.getPlayer(6).isAlive(): #Hyborem
iCount += 1
if (pHumanPlayer.getCivilizationType() == iSheaim or pHumanPlayer.getCivilizationType() == iCalabim):
if gc.getPlayer(0).isAlive(): #Varn
iCount += 1
if gc.getPlayer(2).isAlive(): #Arendel
iCount += 1
if gc.getPlayer(4).isAlive(): #Ethne
iCount += 1
if gc.getPlayer(7).isAlive(): #Basium
iCount += 1
if iCount < 2:
gc.getGame().setWinner(pHumanPlayer.getTeam(), 2)
It's the text highlighted in red here. We're not interested in the equivalent piece that follows as you're playing the Malakim. I expect the problem is the same.
I'm going to run a quick test where I have an army of barbarians destroy everyone. I think victory should trigger if the numbers are assigned wrong as TC01 suggested.
Edit
Playing Ethne the White I used WorldBuilder to destroy the Calabim, Sheaim and Svartalfar. No victory. I had barbarians destroy the Ljosalfar. No change, no story line message. Then the Mercurians. That immediately triggered the first story line message and then caused a Conquest victory.
The numbers are mixed as of 0.41f.
Elyssaen Sep 11, 2009, 07:40 PM Note: I misremembered. There are no story line messages except for the final one. My apologies.
At first I modified ScenarioFunctions.py (the file in question) to change all the numbers around. This wasn't going to work, because my test had demonstrated that Calabim + Sheaim + Svartalfar + Ljosalfar + Mercurians included 3 'enemy' factions (but they weren't the first three). That is to say, the numbers are mixed rather than switched.
So, I'm trying to find out which players are 0, 2, 4 and 7, while playing Ethne the White but having switched those four numbers with 1, 3, 5 and 6. Sorry for that being a little strange.
Killed Sheaim. Nothing. Killed Svartalfar. Nothing. Killed Calabim. Nothing. Killed Infernal. Victory.
Killed Sheaim. Nothing. Killed Svartalfar. Nothing. Killed Infernal. Nothing. Killed Calabim. Victory.
==> Both Calabim and Infernal are in {0,2,4,7}.
Killed Sheaim. Nothing. Killed Infernal. Nothing. Killed Calabim. Nothing.
==> Svartalfar, Calabim and Infernal are in {0,2,4,7}.
Will edit in a moment.
Edit
Logic be damned, I ran another game to kill Svartalfar, Calabim and Infernal. It didn't trigger victory. I then killed Sheaim. Still no victory. Eventually I threw in Malakim and then victory. That would imply Malakim is in {0,2,4,7}, but I don't know why killing those three didn't work when I just proved it should. I did have trouble making Hyborem wipe off the map – you have to capture Gela, or else he'll linger. Let me try again but not make that mistake.
If I can't work out which four factions are {0,2,4,7}, I have to conclude that the code isn't just selecting the wrong factions as the ones you have to kill – it's not consistently selecting factions at all.
Edit
Killed Infernal. Nothing. Killed Calabim. Nothing. Killed Svartalfar. Nothing.
Killed Infernal. Nothing. Killed Calabim. Nothing. Killed Malakim. Nothing.
...It's getting late. Have I made a logic mistake somewhere here? Now the data suggests that one of Infernal or Calabim shouldn't have been in {0,2,4,7} in the first place. That makes no sense, as killing them has triggered victory so they must be able to lower iCount by not existing.
Edit
I've now managed to run another game where after killing a bunch of factions, I had to kill the Sheaim to trigger victory. There can't be more than four factions that can possibly be the last you kill which trigger victory if the code is working at all right.
I'm going to bed. I'll go through this process more methodically in the morning, or else try to find out what actually assigns the numbers.
Decius = 0
Flauros = 1
Arendel = 2
Faeryl = 3
Ethne = 4
Os-Gabella = 5
Hyborem = 6
Basium = 7
Good: 0, 2, 4, 7
Bad: 1, 3, 5, 6
I numbered everyone by going into WorldBuilder and looking at the order they appear in the list in Player Mode. I then grouped them into Good and Bad. What did I get? Exactly the pattern of numbers used in the code.
I'm havin' fun here, but here I hit a brick wall. I've just managed to justify the numbers that I thought I'd concluded must be wrong.
Onionsoilder Sep 11, 2009, 08:14 PM I'm running .41g, btw. Anyway, I'll try worldbuilder-killing EVERYONE, including the good guys, and seeing what happens.
Elyssaen Sep 11, 2009, 08:28 PM I clearly need to keep up more. The patches come rather quickly, it seems. Nonetheless this bug must have appeared between d and f and still be present in g.
I'm quite sure you'll be successful if you do that. I've managed that several times now. I was just playing the Malakim and killed off every evil faction first, and then saved the game. Killed Basium and own. Back to save. Killed Ljosalfar and won. Back to save. Killed Elohim and didn't win. I'm back to using the proper numbers, so this should be the same experience you get.
Don't just try killing everyone. If you would, repeat what I did. Kill every evil faction, save, and then tell me which of the three remaining friendly factions win the game for you when you kill them.
TC01 Sep 12, 2009, 12:18 PM Elyssaen: The way I approached this was I looked through the entire Wages of Sin code in ScenarioFunctions and checked the way things were working. I discovered all of what you mentioned, figured out that the function appeared (after a quick glance) to be working, and then said "Okay, so the code that actually makes a player the winner appears to work", "The code that updates the message runs independently from the code that checks who's been killed", and "The only thing that I think could go wrong here is that the numbers defining players have been messed up."
So I posted the relevant code, saying, "I can't see any problem with the code, except possibly these values are incorrect?" Which turned out to be the answer.
So yes, I understood a lot of the reasoning you went through but didn't type it out. Time was rushed when I wrote that post, and I had not done any of the testing you did to confirm my result.
You did a good job of proving this was the problem. :goodjob:
|
|