Requesting following features

ok thanks for the free tech things, what should I do with the changeYeild class provided just look at the code and figure something out?
Yeah, what I was hinting on is the CyCity.changeExtraHappiness() method. You can use it to give a city a unhappiness penalty also.

the civic swap could work on a a return basis, the player gets a popup asking which civic it wants to swap to and that is then returned to the code and encorporated into the changeCivic method :D
So there would be more than one option then? :confused: I was assuming that the Senate proposes some change and that the player can then reject or adapt it.

There isn't a problem as such as I have not hooked up the code at all yet :p just want to make sure what I have done is all correct
I see. There are several ways of setting these things up. But have you thought what you wanna do with the actual Mission class instances? I suggest you create them only once at startup and store in an array of some sort. But since you have different kinds of missions - with different incoming calls - you might as well use separate arrays. Or a dictionary of arrays.

But using constants for pointing to each instance works also. It might be clearer also.

what is the args list exactly I have always wondered about it and never thought to ask...
All the game events happen in the DLL and are directed to the Python interface as callbacks. All the relevant parameters - or arguments - are packed together into a data structure - a tuple - not a list - and passed along. You can access the values either by indexing the data using brackets, or with tuple assignment. You have probably seen examples of both in the code.
 
well I guess it should be proposal based and not player selected,

I will add in the happiness change then (I thikn I know what to do there :p)

Not sure what you mean regarding the instance setup
 
Not sure what you mean regarding the instance setup
The main thing is to create the instances and store the pointers. This is one way:
Code:
eventByzantium = Mission(tByzantium, messageByzantium1, messageByzantium2, eRome, messageByzantium3, messageByzantiumHold, 400, 500)
But then you need to hard-code when and where the instance should be processed.

Another way would to add all the settings into a data structure, index it, use the values as arguments for creating the instances, and add the values into some array. The upside would be that you can simply iterate the data in order to process the instances when the appropriate game events occur.

You probably need to take this in stages; start with only a few missions and get those working before trying make more of them.
 
I really need to get started with this :D Will get on to it soon!
 
in the code
Code:
def FreeTech(pPlayer, header=freeTechMessage):
    if pPlayer.isHuman():
            pPlayer.chooseTech(1, header, False)
    else:
            pPlayer.AI_chooseFreeTech()
what would pPlayer and freeTechMessage be defined as would it be eRome and something along the lines of the Senate has gifted you a free technology!

ok, this is most probably wrong hinting at eRome here but I made a little function drawn from parts of the civil war code and the method povided to give me this:
Code:
def Happy(iHappiness):
    pCities = eRome.getCityList()
    pCities.reverse()
    for pCity in (city.GetCy() for city in pCities):
        pCity.changeExtraHappiness(iHappiness)
what will this do in terms of long term? (are all cities going to be PERMINENTLY happy or just temporary?) Also what should the object of getCityList() be?
will this actually work (ignoring the eRome bit) and I know I shouldn't copy code without knowing but I wanted to have the code there and then understand it so:
why use reverse() what does it do?
what is the for pCity in (city.GetCy() for city in pCities) all about? (I recently got my head about the for loop :D)


observing the civil war function I forgot what I was playing at here and well probably need help refiguring it out :rolleyes:
Code:
def CivilWar():
    condition = False #add standard conditioning
    if condition:
        lCities = 
        CivilWar.initCivilWar(instance("Rome"), lCities)
    else:
        lCities = 
        CivilWar.initCivilWar(instance("Rome"), lCities)
 
in the code
...
what would pPlayer and freeTechMessage be defined as would it be eRome and something along the lines of the Senate has gifted you a free technology!
Normally, any names using the p prefix are pointers to Cy class objects. eRome indicates that its a enumerated PlayerType value - not a CyPlayer object. With CivPlayer in mind, the way to get a CyPlayer object would be:
Code:
instance("Rome").get(CyPlayer)
freeTechMessage is the header of the choose-a-free-tech pop-up. You can define it as anything you like. Even as a empty string ("").

ok, this is most probably wrong hinting at eRome here but I made a little function drawn from parts of the civil war code and the method povided to give me this:
The getCityList() method is part of the PyPlayer class, so you need a PyPlayer instance:
Code:
instance("Rome").get(PyPlayer)
Since the method returns a list array you should probably name it lCities (not pCities).

The CyCity.changeExtraHappiness() method adds permanent happiness to each individual CyCity instance - and only to those cities.

"city.GetCy() for city in lCities" is a generator expression. Its somewhat advanced and you could express the same logic more simply like this:
Code:
for city in lCities:
    pCity = city.GetCy()

The reverse() method is a list method and reverses the order of the items part of the list. I used it in order to start with the latest city and work backwards to the first city (most likely the capital - makes sense, not?).

observing the civil war function I forgot what I was playing at here and well probably need help refiguring it out :rolleyes:
If you can define the cities affected (in English) we can then figure out how to get those into lCities (in Python).
 
so this:
Code:
def Unhappy(iHappiness):
    pCities = instance("Rome").get(PyPlayer).getCityList()
    pCities.reverse()
    for pCity in (city.GetCy() for city in pCities):
        pCity.changeExtraHappiness(-iHappiness)
?

but I still dont understand what pPlayer would be in the free tech thing just "rome"?
 
I'd suggest this:
Code:
def Unhappy(iHappiness):
    [B]l[/B]Cities = instance("Rome").get(PyPlayer).getCityList()
    for pCity in (city.GetCy() for city in [B]l[/B]Cities):
        pCity.changeExtraHappiness(-iHappiness)
You don't need to reverse the list since its not looped in any particular priority. In this particular context. (I used it in another context, where the loop wasn't supposed to always include all of the cities.)

but I still dont understand what pPlayer would be in the free tech thing just "rome"?
Your mean in the actual function call? You'd use it like this:
Code:
pPlayer = instance("Rome").get(CyPlayer)
FreeTech(pPlayer)
Makes sense?
 
ahhh ok so I could make the function this:
Code:
def FreeTech(player, header=freeTechMessage):
    pPlayer = instance(player).get(CyPlayer)
    if pPlayer.isHuman():
            pPlayer.chooseTech(1, header, False)
    else:
            pPlayer.AI_chooseFreeTech()
where player is inputed as "Rome"


currently all the functions are:
Code:
# rewards

def Gold(iChange, ePlayer):
    giveGold(iChange, ePlayer)
def Unit(eUnitType, tCoords, iNum):
    spawnUnits(eRome, eUnitType, tCoords, iNum)
def GoldenAge(iTurns):
    giveGoldenAge(eRome, iTurns)
def Happy(iHappiness):
    lCities = instance("Rome").get(PyPlayer).getCityList()
    for pCity in (city.GetCy() for city in lCities):
        pCity.changeExtraHappiness(iHappiness)
def UpgradeBuild():
    pass
def Build():
    pass
def FreeCivic():
    pass
def FreeTech(player, header=freeTechMessage):
    pPlayer = instance(player).get(CyPlayer)
    if pPlayer.isHuman():
            pPlayer.chooseTech(1, header, False)
    else:
            pPlayer.AI_chooseFreeTech()
def CitySelect():
    pass

# penalties
def GoldDeduct(iChange, ePlayer):
    giveGold(-iChange, ePlayer)
def RebelUnit(eUnitType, tCoords, iNum):
    spawnUnits(eItalianRebels, eUnitType, tCoords, iNum)
def Unhappy(iHappiness):
    lCities = instance("Rome").get(PyPlayer).getCityList())
    for pCity in (city.GetCy() for city in lCities):
        pCity.changeExtraHappiness(-iHappiness)
def BuildingDest():
    pass
def Anarchy():
    pass
def CivilWar():
    condition = False #add standard conditioning
    if condition:
        lCities = 
        CivilWar.initCivilWar(instance("Rome"), lCities)
    else:
        lCities = 
        CivilWar.initCivilWar(instance("Rome"), lCities)

can you complete some of these?

for the lCities in the civil war should I just do a slice of the cities first on the founded list reverse and just ingore the whole unhappy thing for example pretty much how you did it for the actual class itself just without the happiness checks?

what on earth was I going on about with that whole standard conditioning nonsense :crazyeye:

can you explain the %s1 things again I am not sure I understand as much as I need to :p
 
ahhh ok so I could make the function this:
...
where player is inputed as "Rome"
Sure.

can you complete some of these?
Sure, I'll try tonight. But could you give a more detailed explanation as to what you need from each function?

for the lCities in the civil war should I just do a slice of the cities first on the founded list reverse and just ingore the whole unhappy thing for example pretty much how you did it for the actual class itself just without the happiness checks?
I don't know. What are the parameters affecting which cities will defect? Should it always be the cities founded/acquired last? Half of the cities?

can you explain the %s1 things again I am not sure I understand as much as I need to :p
The %s part means what you're inserting a string value into the string. The number indicates that this is the first string. %s2 is of course the second string. Example:
Code:
string = "This text includes %s1 inserted %s2 values"
value1 = "two"
value2 = "string"
print string % (value1, value2)
This would print the following sentence:
This text includes two inserted string values
Note however that I already included a helper function for handling all this stuff:
Spoiler :
Code:
def addMessage(tag, tValues, eColor, tCoords=(-1, -1)):
        """
        Adds the tag (string) message to the game in eColor. (The preset pointers to valid
        ColorTypes are eRed, eGreen and eWhite. A None value will disable the message.) If
        the tag argument requires other values to be included in the message, then these
        can be supplied with the tValues (tuple) argument. The optional tCoords (tuple)
        argument is set to a pair of default -1 values that indicate that no arrow should
        accompany the text message. (Valid map tile coordinates will enable the arrow.)
        """
        if eColor == None: return
        message = Translator.getText(tag, tValues)
        bArrow = tCoords != (-1, -1)
        Interface.addMessage(pHumanCiv.get(playerID), True, 20, message, "", eMinorEvent, "", eColor, tCoords[0], tCoords[1], bArrow, bArrow)
Example of usage:
Code:
string = "This text includes %s1 inserted %s2 values"
tValues = "two", "string"
addMessage(string, tValues, eWhite)
 
makes much more sense now :D!

right looking at the code the functions incomplete are:
rewards
upgradebuild - this upgrades a specified building's yeilds for all cities which could be food, beaker boost, hammer boost or defence increase(walls) which would be inputed in a parameter. (simmilar to some random events where one of the options is to make public transportation +1 commerce or whatever)

build - makes a building defined into either a defined city or a random city (the random part decided by a list array which returns all cities without that building and picks the one most recently founded)

freecivic - self expanatory

cityselect - builds a city based on the players input, I have forgotten how we were going to do this but we should be able to work it out.

penaltiesbuildingdest - when this function is called a random nonwonder building is removed from the capital or other defined city or possibly if a building parameter is given you can pick what building!

anarchy - pretty self explanatory, x turns of anarchy is given to the whole civ (like during civic swaps)

also in the happiness function which gives permenant happiness, what will the message be? It could be made into custom messages such as "you completed the senate's mission!". you think it's possible?
 
right looking at the code the functions incomplete are:
I never got around to it tonight, but I'll get back to you on another day.

freecivic - self expanatory
Really? Please explain anyway.

cityselect - builds a city based on the players input, I have forgotten how we were going to do this but we should be able to work it out.
I think we were discussion historical locations and founding dates of colonies, right? If you compile the data we could base the reward around this.

also in the happiness function which gives permenant happiness, what will the message be? It could be made into custom messages such as "you completed the senate's mission!". you think it's possible?
I'm not aware of any message, but you're free to add anything you like/need.
 
ok Tommorrow morning I will explain the civic and work on the list of cities!
 
You could simplify it also and just have a dictionary of city sites and names. The founding dates would cause the logic to become somewhat complicated and there would probably be a lot of special cases.
 
ok, sites and names it is then
anyway regarding the civics, The python will randomly assign a civic type and then civic to the senate mission via Rand function and then the code checks the players civics and if they already have that one selected it runs the function again untill it has picked an appropriate civic then asks the player if they want to swap to it which will result in either 1 turn of anarchy or a free civic swap! of course It is still possible to enter a civic in the civic = None parameter as to overide the Rand function :D that sound at all possible?
 
I dunno how many civics are actually appropriate as candidates within a historical context. The Senate basically doesn't want Hereditary Rule and probably thinks that Rome needs Slavery. Whether or not Organized Religion should apply or not might not even be any concern of the Senate, and there might not be any legal or economic civics available to even contemplate?

So, the senate Mission would be to adapt a non-monarchic government and to keep the slaves. Thats it?
 
Before I start working on this, I might point out that there seems to be no way to have a building increase the city's defensive bonus (with Python). You might find something in this vein in Asaf's custom DLL however - I suggest you have a look.

Further regarding the upgraded building yields - you realize that this only affects cities currently held and not cities yet to be built/acquired? It would be much more complicated to store custom values for these bonuses that are then added to each new city once they are acquired. But its quite doable, if you got the time to get it working...

Also note that these bonuses aren't player/civilization specific, but rather city specific. So they apply even if the city changes owners. This could however also be nerfed with another custom feature that resets all cities once lost from the Romans. More work...

You seem to have a handle on how to implement the add/remove building logic yourself. The method you need is CyCity.setNumRealBuilding() - the second parameter should be 1 for add building and 0 for remove building. If you need to check a city for a specific building you can use CyCity.getNumRealBuilding() and get this very value returned.

The anarchy penalty is also easily done with CyPlayer.changeAnarchyTurns(). This you can easily manage yourself.

So I guess I'll have a look at the pop-up and whatelse involved with the refuse/second the Senate civic proposal thing. And also help you with the logic for the free settlements on historical colony sites. So you should get back to me on these topics and with any questions you might have for completing the others yourself. Its time to flex those programming muscles you've been developing, you know.
 
I made you a bunch of helpers:
Spoiler :
Code:
def loopCities(name, bCapital=True, bReverse=True):
        """
        Used for looping. Yields one CyCity instance belonging to name (string) at a time. The bCapital (boolean)
        argument determines whether or not the capital city should also be included, and the bReverse (boolean)
        argument yields the cities in reversed order. Both are set to True by default.
        """
        lCityList = getCityList(name, bReverse)
        for pCity in (city.GetCy() for city in lCityList):
                if not bCapital and pCity.isCapital(): continue
                yield pCity

def getCityList(name, bReverse=False):
        """
        Returns a list array of valid CyCity instances belonging to the name (string) Civilization. Setting the bReverse
        argument to a True value reverses the order of the list.
        """
        lCities = instance(name).get(PyPlayer).getCityList()
        if bReverse:
                lCities.reverse()
        return lCities

def getLastCity(name):
        """
        Returns the last CyCity instance of name (string) civilization.
        """
        lCityList = getCityList(name)
        return lCityList[len(lCityList) - 1]

def getRandCity(name):
        """
        Returns a random CyCity instance belonging to the name (string) civilization. No cities causes exception!
        """
        lCityList = getCityList(name)
        iRandCity = getRandNum(len(lCityList), "getRandCity()")
        return lCityList[iRandCity]

def getRandBuilding(pCity):
        """
        Returns a random BuildingType present in pCity. If none is present the function returns -1 (NO_BUILDING).
        """
        pCivilizationInfo = gc.getCivilizationInfo(pCity.getCivilizationType())
        iNumBuildingClasses = gc.getNumBuildingClassInfos()
        iStartingBuildingClass = getRandNum(iNumBuildingClasses, "getRandBuilding()")
        for i in range(iNumBuildingClasses):
                eBuildingClass = (iStartingBuildingClass + i) % iNumBuildingClasses
                eBuilding = pCivilizationInfo.getCivilizationBuildings(eBuildingClass)
                if isBuilding(pCity, eBuilding):
                        return eBuilding
        return -1

def getBuildingClassType(eBuilding):
        """
        Returns the BuildingClassType (integer) of eBuilding (integer).
        """
        return gc.getBuildingInfo(eBuilding).getBuildingClassType()

def isBuilding(pCity, eBuilding):
        """
        Returns True if eBuilding is present in pCity. Otherwise returns False.
        """
        return pCity.getNumRealBuildings(eBuilding) == 1
        
def isWonder(eBuilding):
        """
        Returns True if eBuilding (integer) is a National Wonder, a World Wonder or a Project. Otherwise returns False.
        """
        pBuildingClassInfo = gc.getBuildingClassInfo(getBuildingClassType(eBuilding))
        return ( pBuildingClassInfo.getMaxGlobalInstances() == 1
                 or pBuildingClassInfo.getMaxPlayerInstances() == 1
                 or pBuildingClassInfo.getMaxTeamInstances() == 1 )

def buildingOutput(pCity, eBuilding, iFood=0, iProduction=0, iCommerce=0):
        """
        Adds or subtracts the integer amount of iFood, iProduction or iCommerce from the associated YieldType of
        eBuildingClass (integer) in pCity.
        """
        eBuildingClass = getBuildingClassType(eBuilding)
        tOutputChange = iFood, iProduction, iCommerce
        for iYield in range(len(tOutputChange)):
                pCity.setBuildingYieldChange(eBuildingClass, iYield, tOutputChange[iYield])
None of this is tested so you'll get to do the debugging! :p

You should consider changing the repeating code in your Senate module for looping cities. Use the loopCities() generator function instead, like this:
Code:
for pCity in loopCities("Rome", True, False):
 
Memememe! :D
 
Back
Top Bottom