Requesting following features

oooo I didn't know about that.... I usally use world builder to keep an eye on things! thanks!

why would the CyGame.getActivePlayer() be needed why not

if getHuman(eRome):
etc
 
Aha, you already have a getHuman() function in your mod? Well, look "under the hood" and you will be able to answer your own question. ;)
 
actualy it is isHuman(name)
Code:
def isHuman(name): # takes the Civ name (string) as the argument 
    pPlayer = pointer(name, CyPlayer) # assines the CyPlayer instance of the CivPlayer corresponding to name to the value pPlayer 
    return pPlayer,isHuman() # return the return value of CyPlayer.isHuman()

why couldn't I use that?

edit: is it because of cyplayer?
 
Aha. Well, it depends on how you go about this. But using CyPlayer.isHuman() - which is all that the above isHuman() function does - would probably involve looping through all PlayerTypes and stopping once you get the current human player. My point is that there already is a method for this in the API - CyGlobalContext.getActivePlayer(). Why re-invent the wheel? (Especially since the API methods are written in C++ and are probably 100 times faster.)

Also note that the function is invalid because of the comma on the last line!

This is what a getHuman() function could look like:
Code:
def getHuman():
	return gc.getActivePlayer()
So now you have one. :D
 
the comma is corrected in helpers anyway but I am not at home so I had to use this, which, I had posted ages ago (incorrectly)

I will add in the getHuman then!
 
btw I made this little program in my spare time (this is only part of it :D)
Spoiler :

Code:
def translate(X, Y, P , Q, bPrint = True):
    if bPrint:
        print "New Coords: ", (X + P, Y + Q)
    else:
        return (X + P, Y + Q)

def enlarge(tCoords, tCoords1, SF):
    X, Y = tCoords
    X1, Y1 = tCoords1
    n1 = X1 - X
    n2 = Y1 - Y
    if SF == 2:
        print "New Coords: ", translate(X1, Y1, n1, n2, False)
    elif SF == 0.5:
        n3 = n1 / 2
        n4 = n2 / 2
        print "New Coords: ", translate(X1, Y1, -n3, -n4, False)
    else:
        if SF > 2:
            while SF > 2:
                X1, Y1 = translate(X1, Y1, n1, n2, False)
                SF = SF - 1
                if SF == 2:
                    print "New Coords: ", translate(X1, Y1, n1, n2, False)
        elif SF == -1:
            print "New Coords: ", translate(X, Y, -n1, -n2, False)
        elif SF < -1:
            while SF < -1:
                X, Y = translate(X, Y, -n1, -n2, False)
                SF = SF + 1
                if SF == -1:
                    print "New Coords: ", translate(X,Y,-n1, -n2, False)
        else:
            print "Unavailable Scale Factor!"
            


loop = 1
while loop == 1:
    X = input("X: ")
    Y = input("Y: ")
    X1 = input("X1: ")
    Y1 = input("Y1: ")
    SF = input("sf: ")
    tCoords = (X, Y)
    tCoords1 = (X1, Y1)
    enlarge(tCoords, tCoords1, SF)

def rotate(tCoords, tCoords1, angle):
    X, Y = tCoords
    X1, Y1 = tCoords1
    if angle == 180:
        n1 = X1 - X
        n2 = Y1 - Y
        print "New Coords: ", translate(X, Y, -n1, -n2, False)
    elif angle == 90:
        n1 = X1 - X
        n2 = Y1 - Y
        translate(X, Y,  n2, -n1)#The reversal of the Ns allows the prgram to switch direction!
    elif angle == -90:
        n1 = X1 - X
        n2 = Y1 - Y
        translate(X, Y, -n2, n1)


I made it to test out a few things (such as defaulting function options and tuples.)

Thought it would help improve my python understanding of certain things!
 
Yeah, keep up the learning! It'll serve you well when it comes to modding. :king:
 
I will be back home in about an hour so I can start testing then :D
 
my idea for the civ specific dawn of man screen is alot more complicated than first thought...

It appears to be a class and I feel that my input would do nothing useful...

Can you check the BTS/Assets/Python/Screens/CvDawnOfMan.py and see what complications there would be?
 
Nothing really to be scared about - its just that the code has been put into a class. This means that somewhere in the interface code there is a CvDawnOfMan constructor called, but this is nothing to be concerned about.

You probably know about global names and local names - variables and functions that are either available to the whole module - or only within one function definition. Well, all the stuff referenced with self. are names (attributes) of that class - each instance of CvDawnOfMan has these attributes. View them as the attributes of units (strength, movement) or cities (size, food) - each Dawn of Man screen has its own set of these. And the they are all defined under the __init__() definition - the constructor. (Some are derived from other values, so if you start changing them from the top - the edit will transplant itself through the whole thing dynamically.)

What exactly are you looking to do with this? :D
 
what I was thinking was instead of having the reguar screen you would get a screen depending on who you are. for Example:

playing as Carthage:

The Sun rises on the year 4000 BC, The Great Civilization of Carthage yearns to become the greatest sea empire the world has ever seen (or will see for that matter). Of course being spread over two land bases does have it's disadvantages, however the mighty rulers of Carthage care little for this. Why? Because their Naval might is unmatched and their warriors take advantage of this, they have little neighbours but the pathetic Numidians to the west or the Greek Colonists to the east of sicily...They are no hassle... Maybe... Just one day... they can rule the World...

or something similar (I actualy really like that for something I just pulled off of the top of my head :D) and of course these would be different for each civ
 
Ok, I'll get back to you with a complete setup shortly. You'll get to learn about dictionaries this time. :D
 
Byzantium now works perfectly, on to my next task!
 
also I would like the change the name of the message so far it is layed out like this:

Dawn of Man
The Sun rised(...)

if posssible along side the civ specific message I would like the name displayed as the title:
Rome
Greece
Carthage
etc

BTW - on testing the XML TXT tags I came across an undesirable error.... The message displayed when my roman quintrireme captured a pictish tririme was: A Pictia Trireme has been captured!

how can I make it say Pictish (or anyother name for that matter?)? It is defined in CustomFeautres and the tag is this:
<Tag>TXT_KEY_CUSTOMFEATURES_COMMANDERING</Tag>
<English>A %s1 %s2 unit has been captured!</English>
 
Ok, in CvDawnOfMan we need to edit the CvDawnOfMan.interfaceScreen() method. Say hallo to our old friend getActivePlayer() from earlier today, but this one is actually from the CyGame class and thus the CyGlobalContext.getPlayer() method is used to fetch the CyPlayer instance instead:
Code:
	def interfaceScreen(self):
		'Use a popup to display the opening text'
		...
		self.player = gc.getPlayer(gc.getGame().getActivePlayer())
So, we already have the human player - assigned to the attribute player of the CvDawnOfMan object (created elsewhere).

This is the line that defines the main body of text (line 146):
Code:
		bodyString = localText.getText("TXT_KEY_DAWN_OF_MAN_TEXT", (CyGameTextMgr().getTimeStr(gc.getGame().getGameTurn(), false), self.player.getCivilizationAdjectiveKey(), self.player.getNameKey()))
Clearly there is a lot going on here and the important things to note are that the CyTranslator.getText() method is used to get the correct string (with respect to the language settings) corresponding to the XML tag string, and also that there are three string values included in the tuple for the second parameter. Compare with the API! The resulting string (after concatenation and translation) is assigned to the local variable (not attribute of the class instance) bodyString.

What we need to do, then, is to make that XML tag string change depending on which player is the human player. So far, so good.

The most basic solution would be to simply use the CyPlayer.getID() method on the self.player attribute from above and create a if/elif/else tree which makes the string variable point to some string value defined by XML tags. But this is hardly an elegant solution, now is it? ;) Because it would involve copy-pasting that long line of code 8 or so times.

Since the playable players are simply indexed 0-7 it would be convenient to use a list (or tuple) array with the XML tag strings and index it with the PlayerType (Player ID). But then the mod would break if someone wants to play one of the minor civs and enables it in the WBS. :p

A somewhat more sophisticated solution is to use a dictionary to index these players. Firstly the data structure itself:
Code:
dawnOfManBodyDict = {
    "eRome": "TXT_KEY_DAWN_OF_MAN_TEXT_ROME",
    "eCarthage": "TXT_KEY_DAWN_OF_MAN_TEXT_CARTHAGE",
    }
The braces indicate that the enclosed data is part of a dictionary and each data consists of a pair of values. The first one is the integer PlayerType value you assigned to the constants in the eNums module, and the other one is the (new) XML tag. You should of course complete the data structure, but be mindful of the syntax!

What we do is we encapsulate the expression on line 146 (above) into a new method that incorporates both the enumerated constants from your mod - and the data structure from above:
PHP:
	def getBodyString(self):
		from eNums import *
		dawnOfManBodyDict = {
		    "eRome": "TXT_KEY_DAWN_OF_MAN_TEXT_ROME",
		    "eCarthage": "TXT_KEY_DAWN_OF_MAN_TEXT_CARTHAGE",
		    }
		defaultBodyTag = "TXT_KEY_DAWN_OF_MAN_TEXT"
		ePlayer = self.player.getID()
		bodyTag = dawnOfManBodyDict.get(ePlayer, defaultBody)
		timeString = CyGameTextMgr().getTimeStr(gc.getGame().getGameTurn(), false)
		civilizationAdjective = self.player.getCivilizationAdjectiveKey()
		playerNameKey = self.player.getNameKey()
		tStrings = (timeString, civilizationAdjective, playerNameKey)
		bodyString = localText.getText(bodyTag, tStrings)
		return bodyString
If we start from the end, then I've broken down the line from earlier on multiple lines and returning the resulting bodyString value. The interesting bit is however that we're indexing the dawnOfManBodyDict with the get() dictionary method. This is actually a clever devil, as it takes a secondary parameter, namely a default escape value in case the dictionary is missing a key corresponding to the first parameter. So while we index the dictionary with the value of ePlayer - we get the value of defaultBody as the return value if it happens to be a invalid key. The return value is what we assign to the bodyTag local variable.

In other words, if someone makes the Iberians playable, they won't brake the mod just because there is no Dawn of Man XML tag defined for that Civ. Instead the default XML tag will be used.

The ePlayer value is of course fetched from the CyPlayer instance living in the self.player attribute. And the defaultTag value is of course the original XML tag from the original code. The method takes no parameters - except self - which it inherits from the method invocation:
Code:
		bodyString = [B]self.[/B]getBodyString()
Note that we didn't have to pass on the self.player attribute as a parameter, because its an attribute of self - which in turn is a reference to the class instance itself. So it - and all other attributes - are always available within the class.

So you add the getBodyString() method to the module and change line 146 as described above. All you have to do is get those XML tags defined and you're good to go! :D
 
also I would like the change the name of the message so far it is layed out like this:

Dawn of Man
The Sun rised(...)

if posssible along side the civ specific message I would like the name displayed as the title:
Rome
Greece
Carthage
etc
Do you want to monkey with the pop-up title also - not just the body of the text? (I'm afraid I don't quite understand what you need.)

BTW - on testing the XML TXT tags I came across an undesirable error.... The message displayed when my roman quintrireme captured a pictish tririme was: A Pictia Trireme has been captured!

how can I make it say Pictish (or anyother name for that matter?)? It is defined in CustomFeautres and the tag is this:
<Tag>TXT_KEY_CUSTOMFEATURES_COMMANDERING</Tag>
<English>A %s1 %s2 unit has been captured!</English>
This is where its defined in CustomFeatures:
Code:
def commandeering(pWinner, pLoser, winnerInfo, loserInfo):
	...
                [COLOR="Red"]tStrings[/COLOR] = [B]pLoserCiv.getName()[/B], loserInfo.getDescription()
		...
                addMessage(captureMessage, [COLOR="Red"]tStrings[/COLOR], eColor, getCoords(pWinner))
Ok, so the %s1 and %s2 correspond to the two string values in the tStrings tuple. The first one is the civilization adjective of the player losing the captured unit. This because of pLoserCiv is a CivPlayer instance and the CivPlayer.getName() method by default fetches the adjective form of the name:
Spoiler :
PHP:
        def getName(self, bLong=None):
                """
                Returns the Civilization name (string) in its adjective form by default. By setting
                the optional bLong parameter to True the method will instead return the full
                civilization name, and a False value will in turn return the short form.
                """
                if bLong == None:
                        name = self.get(CyPlayer).getCivilizationAdjective(0)
                elif bLong:
                        name = self.get(CyPlayer).getCivilizationDescription(0)
                else:
                        name = self.get(CyPlayer).getCivilizationShortDescription(0)
                return str(name)
By adding a True/False parameter you will be able to fetch the long/short form of the name instead. But I'm not sure you wanna do this - shouldn't you change the Pictic adjective form instead?
 
Title is not nessicary just a thought, however Dawn of Man doesn't make sense as a title currently (given every civ has 2 cties :rolleyes:) maybe I can just change it in the XML to Dawn of an Empire or something

it isn't fetching the adjective form... the adjective form is pictish, as defined by the XML. Pictia is the short description (as defined in the XML)

BTW: when I said ERE was perfect, I was wrong. What didn't occur to me was what if rome didn't control any cities... So while playing as carthage I got this error:

File "CvEventManager", line 23, in onEvent
file"CvEventManager", line 187, in handleEvent
File "CvEventManager", line 389, in onBeginGameTurn
File "ModEvents", line 109 in eventERE
File "rebellion", line 532, in initCivilWar

AttributeError: 'NoneType' obect has no attribute 'setRebelHQ'

this fired on the turn the ERE was meant to be...

any ideas?
 
in the previous explanation you said this:
bodyTag = dawnOfManBodyDict.get(ePlayer, defaultBody)
shouldn't it be this:
bodyTag = dawnOfManBodyDict.get(ePlayer, defaultBodyTag)
Just a thought....
 
Title is not nessicary just a thought, however Dawn of Man doesn't make sense as a title currently (given every civ has 2 cties :rolleyes:) maybe I can just change it in the XML to Dawn of an Empire or something
Well, anything is possible. You could try to implement the change yourself. Rather than asking for the whole thing (not that you did with the body text) you could prompt me once you encounter something you can't figure out, or get stuck.

it isn't fetching the adjective form... the adjective form is pictish, as defined by the XML. Pictia is the short description (as defined in the XML)
I'll test the name forms in the console shortly, and post the results here.

BTW: when I said ERE was perfect, I was wrong. What didn't occur to me was what if rome didn't control any cities... So while playing as carthage I got this error:

(...)

AttributeError: 'NoneType' obect has no attribute 'setRebelHQ'

(...)

any ideas?
Yeah, this is classical. :rolleyes: Of course one should always anticipate an empty array if it is being populated from nothing. I'll get back to you with a quick-fix - or can you manage it yourself before I get around to it? ;)

in the previous explanation you said this:
bodyTag = dawnOfManBodyDict.get(ePlayer, defaultBody)
shouldn't it be this:
bodyTag = dawnOfManBodyDict.get(ePlayer, defaultBodyTag)
Just a thought....
Yeah, this is bound to happen when you never test anything you write/post. :p
 
Here's an idea:

Your mod will have another starting date than 4000 BC - I hope! :eek2: Why not change the "Dawn of Man" title to "560 BC" or whatever ("The year 560 BC..."?).
 
Back
Top Bottom