Bad People Mod -- adds prostitutes, druglords, and mafia.

Hi RogerBacon,
I've just played all the way through a game with BadPeople and I think it is an absolutely vital mod because it adds a whole new dimension to the game.

But I want to add more risk to it, specifically, the level of risk associated with when a spy is caught taking action and is detained. First, I want to get a handle on setting a condition based on whether the player has Scotland Yard (so they can detect said actions, even involving foreign bads in foreign cities). And I want an elegant message that says "A Mongolian bad person is causing trouble in the Egyptian city of Alexandria."

So far, I have this message except the adjective (Egyptian) of the owner of the victim city (Alexandria). I can't figure out how to pull this adjective and post it to CyInterface (herein declared as victimCivAdjective).

Here's what I have (with most of this code being yours!), with inconsequential code snipped:

Code:
	def runBadPeopleList(self, iPlayer):
		...

		for i in range (len(self.BadPeopleWatch)):
			# Check the list for BadPeoples belonging to this player
			if (iPlayer == self.BadPeopleWatch[i][0]):
				pUnit = self.BadPeopleWatch[i][2]
				iCounter = self.BadPeopleWatch[i][3]
				pUnitInfo = PyInfo.UnitInfo(pUnit.getUnitType())

				if ((pUnit.plot().isCity() == True) and (pUnit.getOwner() != pUnit.plot().getPlotCity().getOwner())):
					# BadPeople is ready to make his move..
					if (iCounter < 1):
						pPlayer = gc.getPlayer(pUnit.getOwner())
#						adjKey = pPlayer.getCivilizationAdjectiveKey()                         ... not used anywhere in this class
						civAdjective = gc.getCivilizationInfo(pPlayer.getCivilizationType()).getAdjective(0)
						victimCivAdjective = gc.getCivilizationInfo(pUnit.plot().getPlotCity().getOwner().getCivilizationType()).getAdjective(0)

						# eventually, display this message only on conditions related to Scotland Yard, etc....
						humanHasScotlandYard = 1
						if (humanHasScotlandYard == 1):
							scotlandyardBrief = "A %s bad person is causing trouble in the %s city of %s" %(civAdjective,victimCivAdjective,(pUnit.plot().getPlotCity().getName()))
							CyInterface().addImmediateMessage(scotlandyardBrief, "")

My Python skills are at the "informed cut-and-paste" level, so this may be a no-brainer for you :blush:

Thanks for your help!!
Spocko
 
Now it needs a new Civ: Columbia, and a new unit: Chavs

Oooh or maybe a new UU for England: Soccer Hooligans, can attack cities and wreck buildings even in peace time.
 
Spocko said:
Hi RogerBacon,
I've just played all the way through a game with BadPeople and I think it is an absolutely vital mod because it adds a whole new dimension to the game.

Thanks. :)

So far, I have this message except the adjective (Egyptian) of the owner of the victim city (Alexandria). I can't figure out how to pull this adjective and post it to CyInterface (herein declared as victimCivAdjective).

Here's what I have (with most of this code being yours!), with inconsequential code snipped:

Code:
victimCivAdjective = gc.getCivilizationInfo(pUnit.plot().getPlotCity().getOwner().getCivilizationType()).getAdjective(0)

My Python skills are at the "informed cut-and-paste" level, so this may be a no-brainer for you :blush:

Thanks for your help!!
Spocko

It looks like it should work. What is it printing out exactly?

Roger Bacon
 
Thanks RogerBacon,

The line

victimCivAdjective = gc.getCivilizationInfo(pUnit.plot().getPlotCity().getOwner().getCivilizationType()).getAdjective(0)

generates the Python Exception of:
'int' object has no attribute 'getCivilizationType'

Also... I saved a game one turn away from the foreign agent taking action, and as you documented (arghhh!), the bad person did not take action on the next turn. I suppose this happened because the AI does not know to move the unit one step out of the city and back into the city to start the activation cycle. While testing, I knew that the agent took action on year 2052, so I saved the game at 2051 - oops.

I wonder if we could modify this so that on game load, the AI automatically moves all bad peoples and Assassins one step away from their current location and then back to where they were at game load. I guess we would have to check for an adjacent legal square, and we would lose agents that were sitting in one-tile-island cities. What do you think? Would we have to check for legal tiles, or could we somehow simulate the unit re-entering the city?

I'm also using the Assassin mod and the Training Barracks mod (with the linear promotion model, not the constant).

Hmmm. Also, on this same game, I pummeled a neighbor city with Prostitutes and Druglords - the victim city reduced to a population size of negative 2 and negative production. I wonder if we need to put a check on the floor level at which we can impact a city? Maybe include something like the linear promotion model of Training Barracks, such that the more Prostitutes there are there already, the less impact yet another Prostitute would have on the city - to the point of being ineffective after a certain level of infilitration.

Great stuff. These three mods are worth the time to enhance and I'll be happy to share my code once I've reached a few milestones with this.

Cheers,
Spocko
 
Spocko said:
Thanks RogerBacon,

The line

victimCivAdjective = gc.getCivilizationInfo(pUnit.plot().getPlotCity().getOwner().getCivilizationType()).getAdjective(0)

generates the Python Exception of:
'int' object has no attribute 'getCivilizationType'

OK, I thinik I know that is going on. getOwner() is returning 0 instead of a player object. You need something like:

iPlayer = gc.getCivilizationInfo(pUnit.plot().getPlotCity().getOwner()
pPlayer = gc.getPlayer(iPlayer)
victimCivAdjective = pPlayer .getCivilizationType()).getAdjective(0)

Try that and see if it work. I didn't test it but I've had that error before so I know the cause of it.
Of course, you can put it all in one line but that gets kind of hard for others to read and looks complicated. There's not much of a performance hit by assigning a couple of temporary variables here so I'd break it up to make it look cleaner.

Roger Bacon
 
Hi Roger Bacon,

Could you check the syntax in the code?

RogerBacon said:
iPlayer = gc.getCivilizationInfo(pUnit.plot().getPlotCity().getOwner()
pPlayer = gc.getPlayer(iPlayer)
victimCivAdjective = pPlayer .getCivilizationType()).getAdjective(0)

I got a syntax error for the iPlayer line due to the missing parenthesis - I changed it to:
Code:
iPlayer = gc.getCivilizationInfo(pUnit.plot().getPlotCity().getOwner())
After correcting(?) the first of these three lines, I get a Python Exception for the second line, pPlayer = gc.getPlayer(iPlayer)
The Python Exception message is:

Code:
Assignment Error: Python argument types in
   CyGlobalContext.getPlayer (CyGlobalContext, CvCivilizationInfo)
did not match C++ Signature
   getPlayer(class CyGlobalContext {|value}, int)

In addition, I can't figure out how to fix the third line, to account for the double parenthesis after .getCivilizationType))...

As I re-read this, I sound ungrateful - believe me, I'm quite grateful for the help!

Anyway, if you could help sort out the syntax, I'd then be able to study how you made this work. Thank you!

Spocko
ps: when I cut and pasted the code directly (with correct indentation), as written, Python failed to load complaining of a syntax error (the white error screen at loadup, not the Python Exception blue screen that we see during gameplay)
 
OK, the syntax was messed up. I cut and pasted from you code above and when I broke it up I forgot to account for the extra parenthesis.

iPlayer = gc.getCivilizationInfo(pUnit.plot().getPlotCity(). getOwner())
pPlayer = gc.getPlayer(iPlayer)
victimCivAdjective = pPlayer .getCivilizationType().getAdjective(0)

I'm not sure why pPlayer = gc.getPlayer(iPlayer) is not working. Try printing out the value of iPlayer and make sure it is 0 (for the human player). Add this code in the line right before pPlayer = gc.getPlayer(iPlayer).

message = "iPlayer = %s" %iPlayer
CyInterface().addImmediateMessage(message,"")
CvUtil.pyPrint(message)

Roger Bacon
 
RogerBacon said:
OK, the syntax was messed up. I cut and pasted from you code above and when I broke it up I forgot to account for the extra parenthesis.

No hard feelings :p

iPlayer = gc.getCivilizationInfo(pUnit.plot().getPlotCity(). getOwner())
pPlayer = gc.getPlayer(iPlayer)
victimCivAdjective = pPlayer .getCivilizationType().getAdjective(0)
I eventually ended up with this permutation of code - thanks! :D
I'm not sure why pPlayer = gc.getPlayer(iPlayer) is not working. Try printing out the value of iPlayer and make sure it is 0 (for the human player). Add this code in the line right before pPlayer = gc.getPlayer(iPlayer).
Interesting. iPlayer = ... blank!

And equally interesting, I'm not expecting this to be 0, as I am playing Germany, and my ScotlandYard will know that the Mongolian Bad Person is causing trouble in Alexandria, Egypt. So I expect iPlayer to be something other than 0. And, this message works fine without the victim's civAdjective, for as Germany, I get "A Mongolian agent is causing trouble in Alexandria" - my challenge is knowing what civ owns Alexandria. So this is why I am trying to grab the CivAdjective that pertains to the cityplot in which the Mongolian unit is standing.

(Actually, I've included the Alt City Names mod [successfully], so when I learn of Mongolian activitiy in Inet-Tun, I don't know offhand what civ that city would belong too [here, it is Egypt]... I'm using Alexandria to make it easier to illustrate what I'm doing here).

I know I could just drop the quest for a city adjective, but this message would greatly enhance the power of the messages coming out of my spy center. I plan to add a die roll so that there is a random factor in determining whether my spy center "learns" about the foreign agent acting in the foreign city.

Hope you can help me - thanks for your continued attention!
Spocko
 
What about a plague carrier unit? Requires a city with the slum building (-3 to health) but is a stealth unit that can kill a third of an enemy cities population. Or a pop or two for a few turns?

:yuck: :yuck: :cry: :yuck: :cry: :yuck:
 
:cool:

... and I've added State Police (White Rabbit's Riot Police) as National Units that can help remove the three vices.

Somehow, I bet the AI doesn't know how to use this unit, or doesn't know the benefits of say, a POLICE STATE, for controlling the spawning of these vices.

How does the AI learn about new units? Does it scour through all of the Python code identifying conditions for managing different activities (like, if Police State, less vice)? :p Or do I have to figure out how to code it into the dll using the SDK and C++? :(

Spocko
 
there should be certain civics where it has a negative effect on your empire somehow and if your badpeople spread to neighboring empire then it will have like -1 on diplomacy...or something...
havent really thought it out at all but just throwing it out there:D
 
Spocko said:
How does the AI learn about new units? Does it scour through all of the Python code identifying conditions for managing different activities (like, if Police State, less vice)? :p Or do I have to figure out how to code it into the dll using the SDK and C++?
The AI is very A and not that I when you wander into uncharted territory. I think you will need to code a new mission type since what you're describing (a seek-and-destroy mission) isn't something that matches any existing AI thought patterns.

For example, I think the AI builds counter-Bad People buildings because buildings are coded with flavors. If the Bad People are wreaking havoc on population via unhappiness, the AI might prioritize the corresponding flavor (Growth, I think) and therefore deal with the Bad People. The AI definitely does NOT do any "investigation" of unit values, skills, behaviors, etc.

The closest AI behavior I can think of to leverage would be the Great Artist's culture bomb -- but the AI would only think to use that when culture is a problem (or opportunity?). Another alternative would be to have a fake building like the gallows that the Police "builds", which you code as having the appropriate counter-flavor, and that building triggers Python code to get rid of a vice. (Or maybe it builds a real building).
 
You could start with gallows, upgrade to firing squad, then THE CHAIR!!! Funny stuff. Great work. You could always make a suicide bomber unit as the "Anti-culture bomb."
 
RogerBacon, have you been able to figure out why the druglord sound bite doesn't work?

Strange that it doesn't work - I wonder if it is because there is too much sound in the file - the background hiss of the clip might cause the sound file to have too much data and so Civ4 craps out trying to play it. THe hiss may increase dramatically the range of sound the Civ sound player needs to interpret.

Who Knows?

The sound clip works fine as is using Windows Media Player...

Right now I've mapped the druglord sound to be the kiss of the prostitute - I like to hear that sound every chance I get :D

Thanks!
 
Spocko said:
RogerBacon, have you been able to figure out why the druglord sound bite doesn't work?

No I haven't. Actually I had forgotten about that one. I had planned to look in to it but I got off onto other projects. I'll try to get back to it next weekend.

Roger Bacon
 
False prophets? What an excellent idea. But er... your going to cop it for this idea. :lol:
 
Back
Top Bottom