Requesting following features

There is another way to test API methods, and that is to put the code in your scenario events module and save it while the game is running. You don't put the code into any function definition though, but rather at the __main__ level. Where exactly isn't critical - as long as its not the first thing at the top. So if you put this line at the bottom of the module and save the module during game-play:
Code:
CyGame().setGameTurt(100)
...then you game turn will change to 100. Its equivalent to writing the line in the console.

And to test, lets say CyPlayer.changeExtraHappiness(), then you need a CyPlayer instance to invoke the method on:
Code:
gc.getPlayer(0).changeExtraHappiness(3)
This should add 3 happy points to all cities belonging to the first player - every time the module is loaded. And this happens every time you save some .py file!
 
cool. I will have to try this out tommorrow!
 
Any time a module is imported the code inside is also executed, just like with a function call. But nothing encapsulated into functions is run - the functions themselves are evaluated and stored into memory. So this is basically why you wanna put all your code into neat functions - to have the option when to fire said code. Because otherwise it will just be run on initialization and this is almost never what you want.

But for some tasks - like setting up data structures or importing modules - it can be handy to leave code at the __main__ level. Testing code is another practical reason to do this. :D
 
ok heres my helper:
Code:
def giveGoldenAge(ePlayer, eTurns):
    pPlayer = gc.getPlayer(ePlayer)
    pPlayer.changeGoldenAgeTurns(eTurns)

in the mean time for any passing coders:
what do
#INT getHappyTurns ()
#VOID changeExtraHappiness (INT iChange) cycity
#VOID changeHappinessTimer (INT iChange) cycity
#INT getHappinessTimer ()
do?

(really pointing at the INTs here I can find the rest out myself, I think...)
 
You seem to have aced the function. :king:
 
thanks! I can't help my self, I am going to have to use this function to add the golden reward.

also to all my rewards (and the main class it self) I am adding the self.Penalty so that I can use negative values to deduct money in the events!

EDIT: heres the full class as of now!
Code:
from Utils import *
from CustomFunctions import *
##Senate Feature##
#This feature displays messages to Rome to ask them to do stuff, the events#
#(missions) are defined here!#

##constants##
#none
class Mission:
    def __init__(self, tCoords, iStartYear, iEndYear, Reward, Penalty, popHeader, popMessage1, popMessage2\
                 , ePlayer):
        self.tCoords = tCoords
        self.Start = iStartYear
        self.End = iEndYear
        self.Reward = Reward
        self.Penalty = Penalty
        self.Header = popHeader
        self.Message1 = popMessage1
        self.Message2 = popMessage2
        self.ePlayer = ePlayer
    def GoldMission(self):
        if isHuman("Rome") == True:#until function is fixed
            if isDate(self.Start):
                if isPlotOwner(self.tCoords, self.ePlayer) == False and isPlotCity(self.tCoords) == True:
                    showPopup(self.Header, self.Message1)
                else:
                    showPopup(self.Header, self.Message2)
            elif isDate(self.End):
                if isPlotOwner(self.tCoords, self.ePlayer) == True:
                    showPopup(self.Header, "The Senate notes that you have succeeded in your mission and rewards you with ",self.Reward," gold!")
                    giveGold(self.Reward)
                else:
                    showPopup(self.Header, "The Senate notes that you have failed the mission it set you, you will not be rewarded!")
                    giveGold(self.Penalty)
    def UnitMission(self):
        if isCivHuman("Rome") == True:
            if isDate(self.Start):
                if isPlotOwner(self.tCoords, self.ePlayer) == False and isPlotCity(self.tCoords) == True:
                    showPopup(self.Header, self.Message1)
                else:
                    showPopup(self.Header, self.Message2)
            elif isDate(self.End):
                if isPlotOwner(self.tCoords, self.ePlayer) == True:
                    showPopup(self.Header, "The Senate notes that you have succeeded in your mission and rewards you with ",self.Reward," units of Praetorians!")
                    spawnUnits(eRome, ePraetorian, getCapital(eRome), self.Reward)
                else:
                    showPopup(self.Header, "The Senate notes that you have failed the mission it set you, you will not be rewarded!")
                    giveGold(self.Penalty)
    def GoldenAgeMission(self):
        if isCivHuman("Rome") == True:
            if isDate(self.Start):
                if isPlotOwner(self.tCoords, self.ePlayer) == False and isPlotCity(self.tCoords) == True:
                    showPopup(self.Header, self.Message1)
                else:
                    showPopup(self.Header, Self.message2)
            elif isDate(self.End):
                if isPlotOwner(self.tCoords, self.ePlayer) == True:
                    showPopup(self.Header, "The Senate notes that you have succeeded in your mission and rewards you with", self.Reward," turns of Golden Age!")
                    giveGoldenAge(self.Reward)
                else:
                    showPopup(self.Header, "The Senate notes that you have failed the mission it set you, you will not be rewarded!") 

##Byzantium Prompt##
iByzantiumStartYear = 1050
iByzantiumEndYear = 1350
iByzantiumGold = 1000
iByzantiumPenalty = 0
senateHeader = "Senate"
byzantiumMessage1 = "The glorius Senate of Rome requests that you take the city of Byzantium. If you take it and hold it at the end of 30 turns (turn 195) you will be greatly rewarded"
byzantiumMessage2 = "The glorius Senate of Rome wishes that you make sure that you keep control of Byzantium by the end of 30 turns (turn 195). If you successful, you will be rewarded!"
tByzantium = (46, 23)

Byzantium = Mission(tByzantium, iByzantiumStartYear, iByzantiumEndYear, iByzantiumGold, iByzantiumPenalty, senateHeader, byzantiumMessage1, byzantiumMessage2, eRome)
Byzantium.GoldMission()


Authough I just noticed a problem... I am using my isPlotCity() helper and as the classes functions use else wouldn't it say
Code:
 if isPlotOwner(self.tCoords, self.ePlayer) == False and isPlotCity(self.tCoords) == True:
 else: #isPlotOwner(self.tCoords, self.ePlayer) == True and isPlotCity(self.tCoords) == [B]False:[/B]
so obviously the only way it now works is if the city doesn't exist in the first place :crazyeyes:

also another small confirmation I need is this:
showPopup(self.Header, "The Senate notes that you have succeeded in your mission and rewards you with", self.Reward," turns of Golden Age!")

as you can see it has commas next to self.Reward which would cause 4 parameters no? would it work as
showPopup(self.Header, "The Senate notes that you have succeeded in your mission and rewards you with" + self.Reward + " turns of Golden Age!")

instead?
 
Ok, I still think that you're jumping the gun with the actual coding here. Because right now you're just adding methods that are copies of earlier methods for the various mission types. This is actually where sub-classing would come into play.

Basically, you shouldn't repeat any code - you figure out how to get the same job done with just one set of any piece of code. Resorting to copy-pasting to manufacture a large module with methods that are basically the same is just... not good programming. In fact - copy-pasting is not programming.

So I'd suggest you focus on the design on the missions and put it all into writing. Only then can we start building the achitecture from the ground up. And make desicions like: We should have a new class for every type of mission? Or not.

Right now you're producing code you might not even need in the end. Its starting to become a bit messy at the very least.

Also, since you will have a multi-lingual mod, you shouldn't add long strings of text into method invocations. Define string variables and use those instead.

As far as adding names and stuff into text, this needs to be done with the CyTranslator class or it won't work with the XML and translations and stuff in the game. (Otherwise you're on the right track as far as Python as such goes. But it won't work satisfactorily with CivIV.) Example:
Code:
Translator = CyTranslator()
...
goldenAgeMessage = "The Senate notes that you have succeeded in your mission and rewards you with [B]%s1[/B] turns of Golden Age!"
...
self.Message = goldenAgeMessage
...
turns = str(self.Reward)
message = Translator.getText(self.Message, [B](turns,)[/B])
showPopup(self.Header, message)
The "%s1" bit indicates the first string value to be included into the string by the CyTranslator.getText() method. (The second one would be defined as "%s2".) The built-in str() method convert the integer value self.Reward into a valid string type.

Later you can define all the strings in the XML and simply use a XML tag like "XML_TEXT_SENATE_MISSION_GOLDEN_AGE" for the Python strings variables.

One thing you should know about logical operators and boolean expressions is that every expression separated by the command and is evaluated before the interpreter moves on to the next one. Take this expression:
Code:
True and False and False
The sum of this expression is False. But there are three sub-expressions inside the big one (the whole line) separated by and:s - each one is expressed by a boolean value in this example. The first expression (the value True) is evaluated as True, and thus the interpreter will move on the the next expression (the value False). This second expression evaluates to False however, so the entire expression (with the 3 sub-expressions) is immediately evaluated to be False - as the second expression didn't equate to True.

The interesting thing is that that the third expression - the second False value - never even got evaluated! This is actually related to your question, as your conditional statement is also evaluated one expression at a time:
Code:
if isPlotOwner(self.tCoords, self.ePlayer) == False and isPlotCity(self.tCoords) == True:
The entire if statement is one boolean expression - its either True of False. But it contains two sub-expressions:
Code:
isPlotOwner(self.tCoords, self.ePlayer) == False
and
Code:
isPlotCity(self.tCoords) == True
...respectively.

If the return value of isPlotOwner() is True, then its not the same as False. This means that the expression evaluates to False, as True != False. And only if this function returns False and the isPlotCity() function returns True (otherwise False != True) will the entire if statement evaluate to True. So unless both these expressions are True, the condition fails (== False).

So, in other words - if the first check doesn't pass - meaning that the self.ePlayer is indeed the plot owner - then the second check - whether or not there is a city on that plot - is never even evaluated.

And this in turn answers your actual question: The else statement doesn't take into account whether or not the isPlotCity() method is even checked - or what it would return on the if statement if it were to be called. It is only concerned with whether or not the original if statement evaluates to True - or not.

I realize this can be hard to fathom, but if you break things into smaller expressions and imagine the interpreter (the program reading the code) reading it in segments you should be able to figure it out.
 
ok so the code I was worried about would work?

thats good!
 
ok so the code I was worried about would work?

thats good!
As far as I can understand what you're trying to do with it, yes. The logic could be translated into English like this:

"If the plot is not owned by this player AND there is a city on that plot - and only then - would this outcome occur. Otherwise would that outcome occur instead - regardless if there is a city or not on that plot."
 
So, if we're gonna be able to start laying out the classes and their methods - and the external infrastructure for checking and firing the missions - we need to establish some facts about the Mission feature.

All Python modding (well, almost all Python modding) comes down to very precisely defined game events. So we need to know, from the get-go, whether or not its just gonna be the BeginGameTurn event that is involved with the events. Skim through the various events (also found in CvDllPythonEvents in the SDK) to see what is available before excluding any of the options available. Because we need to build this around the events.

On the other hand - the Mission event (with its potential sub-classes) could just be something that occurs on set dates - and that have a end date. Plain, simple and formulaic. But we could do other , non-mission, Senate stuff later, like on-event rewards, calls to address various issues that crop up in a game - like react to rebellions, address flawed civics setups, to recapture lost cities, that sort of thing. The need to be connected to either the game events (like a combat reward), to some other feature in the mod (like a rebellion) or simply be cyclic or random (like a request to change a civic).

So we could pretty much get started once you make these design decisions. I believe that you already have some number of potential types of rewards written down - you could just post that without worrying about the implementation of each quite yet. (Its of course good to have some tools ready to use, so I'm not really discouraging you from making more utils.)

As soon as you post the design will I be able to give you a suggestion for a sample Mission class and its principal methods. It might not look like what you'd expect though, but you'll be able to do with it what you want. This will be your project as far as I'm concerned, but if I'm gonna be able to be of any real assistance it helps to get you organized and started in a well thought-out direction. You'll be completing this on your own, I'm certain about that. :goodjob:

edit: And I'm gonna start testing the Rebellion module right away. If I'm able load the new version of your mod, that is. :p I'm gonna try that now and get back to you as soon as I have something to report.
 
False alarm! (Previous post deleted.)

I ran into problems loading your WBS directly - as I always do to avoid having to load the mod - and thus load all XML and stuff twice. I believe that you simply missed to specify the mod path in the WBS:
Code:
	ModPath=Mods\Jamie'sRome1.3
But I'd still wanna urge you to change the mod folder to something simpler, like JamiesRome1_3 or something. Because the current one seems suboptimal. (The folder has the file suffix 3 to for starters. :rolleyes:)

Other than that, there was a few hiccups with some of the recent changes to Python modules. Nothing severe yet, at least.
 
how do you like the new interface?

I need to think of more ideas for rewards and mission types but then I will get back to you...I do have some interesting ones though dunno if they work...
 
So lets discuss those ideas then! And if you already have some sample reward types in we could start with those and you'd be able to add more later. It will probably just be a matter of writing the helper functions that grant the benefits, and add a method to the Mission class for the new reward type. So this department would be easily expandable later.

Something just came up so I will probably have to continue with testing/debugging tomorrow. :p But I did manage to do some preliminary testing on the cultural rebellion type, and it does indeed spawn units belonging to the strongest cultural opponent - or rebel units if no foreign culture is present (probably only gonna happen with espionage triggered disorder). The messages also works, like do the rebel reinforcements feature. (There is a chance every turn while the rebellion is active that an additional rebel unit will be spawned.)
 
ok then, I only have a few but it should do for now:

rewards
Of course the Four we have already seen: Gold, Units, Golden age, Happiness (which apart from golden age, can be used as penalties. More on this later!) but also some new ones!

The senate grants Rome with certain building upgrades such as walls = +10% defence. Of course this can be changed to only add this to Rome, Italy, Area conquored (as per event) and the entire empire!

The senate builds a certain building in Rome, Italy, Empire etc. I also think that this could be taken to the extent that the player gets to choose where!

The senate gifts a free civic change!

The senate gifts a free tech (isn't the senate nice?)

This is the most daring of the rewards! The senate provides the player with the oppotunity to build a city within a given area ( could be europe, africa, middle east, or more defined) the player must enter the coordinates of the new city (or something simmilar, that maybee too difficult for the players to use...)!!!

some events could even use the soren random number thing to randomly select the reward, for example 0 - 10 = gold etc and certain rewards could be rarer to get!

So... There you go! Think they are all possible? Of course I have to ellaborate on the Missions as well....

Missions
Of course, capture a city.

Build a wonder

capture an intire area (yay)

civic change

declare peace with a friend of the senate (interesting no?)

declare war on the enemies of the senate

expand army/navy (could be linked to the current military situation of the civ say if there are not enough units then tell rome to add more for example

if getTotalLandUnits ()<= 30:
....(popup)
if (getTotalLandUnits ()- 30) >= 1:
give reward

or something simmilar, you could find a better way to do this)

Thats all for the moment! You think it's possible?

(btw I could do somehting simmilar for JMM regarding the apostolic palace!)
 
The senate grants Rome with certain building upgrades such as walls = +10% defence. Of course this can be changed to only add this to Rome, Italy, Area conquored (as per event) and the entire empire!
This should be interesting to code, so that the one main function/method (a method is a function belonging to a class) can grant the building to cities yielded by functions like getCityRome(), getItalianCities() and getAreaCities(). Since there is already a PyPlayer.getCities() method in PyHelpers for the whole empire option we should probably make all of these methods return a list array of valid cities (possibly PyCity instances instead of CyCity).

Regarding the actual "upgrade", I believe that it would be possible to add a good few bonuses to buildings, but whether or not a defensive bonus is possible I wouldn't know without looking into it.

The senate builds a certain building in Rome, Italy, Empire etc. I also think that this could be taken to the extent that the player gets to choose where!
Same as above if some building is to be built in every city. The choosing thing might be doable but this would be uncharted terrain for the both of us. (Basically you put together a list of valid cities without the building, then you make a pop-up with bullet buttons for each city name. By clicking on a "Choose" button the selected data would be returned back to the code that prompted the pop-up, and the list of cities would be accessed once again to get the CyCity instance used for granting the actual building.)

The senate gifts a free civic change!
I'm guessing that this is optional and that the player would get the choice to accept the "reward" or not? Or would it be any civic change? Because I'm not entirely sure how to achieve that. :p (It might basically be possible if we set some custom value, somewhere, to "enabled" and the next time the player gets anarchy, then the anarchy timer is instantly zeroed. Whether or not it works in practice would have to be tested the hard way.)

The senate gifts a free tech (isn't the senate nice?)
Easy-peasy.

This is the most daring of the rewards! The senate provides the player with the oppotunity to build a city within a given area ( could be europe, africa, middle east, or more defined) the player must enter the coordinates of the new city (or something simmilar, that maybee too difficult for the players to use...)!!!
I don't think that the user interface thing with coordinates would be a very good solution. The reward would probably be connected to the purpose of the mission, so the spawned city could be pre-defined. Or there could be a dictionary of historical (colonial?) city sites with names and coordinates. Any valid city site within this array would be added to a list, which in turn generates the multi-option pop-up. Good?

some events could even use the soren random number thing to randomly select the reward, for example 0 - 10 = gold etc and certain rewards could be rarer to get!
Actually, if you look in the Utils module there should be a getRandNum() helper function. You should also look into the isChance() function!

I think we have something to work with here. What about spawning units? Like if you conquer Gaul (by some geographical definition) you get Gallic Swordmen units in all Gallic cities as auxiliaries. Or if you conquer Athens you get Hoplite auxiliaries in every city in your possession originally built by the Greeks/Greek Colonies. (I'm not sure how pre-built cities in the WBS would counted though.) Or if you pass some reform (make some civics change prompted by the Senate before the end date) you get Peasant levies in all Italian cities. And so on. There could also be historical GP spawned as a reward...

And what about granting espionage points towards an enemy. The mission could be to occupy some strategic city or build a Fort on some tile. This would give you an advantage as far as intelligence gathering goes.
 
Thats all for the moment! You think it's possible?
The main question isn't whether or not these conditions are doable (because they seem to be), but rather if all missions have an end date. And if they do - as I mentioned earlier - it would be possible to grant the reward immediately (or at least on the following turn) - instead of on the end date. This would be much more complicated to code however.

And even more importantly - all "missions" will be prompted to the player on set historical dates, right? No random missions or circumstantial missions? (Those could be defined as something else than instances of the Mission class.)
 
well some could be random... :think:

I guess some missions could use the give reward on turn but for byzantium (where the ERE's existance hangs in the balance...) It would be good to have the capture and hold settlement for x turns

The great problem with buttons... the possible amount of cities Rome could have! ahh... hundreds of buttons to make :lol:! I will finish it.... eventually :D (I may misunderstand... you mean with city names on or just a select button?)

so python can be linked with buttons then? coincidently my friend asked me whether python could do that the other day (he is trying c++, but not on a civ4 level) so I can tell him :D

yeah I did think about espionage and I thought maybee a do mission thing on an enemy capital/city

forts sound good!

the multi optional popup for city spawn sounds very good... all we need is another coder to wander by... I guess we need a list then?

I guess the player should choose whether they want an anarchy free civic swap and what they want to swap to... only one swap though for example I would pick Monarchy but I couldn't pick Free Religion aswell.

I guess for the unique units of other civs it would be a case of definining map areas... I could get on to that soon! You are just about right in my opinion about the conquoring areas! Could even be unsenate related (but we can say the senate celebrates your glorius achievements in ____. just to make them look nice :D)

btw: One thing I have always thought of having (since I wanted to remodel the tech tree) want to have the Marius Reform... It could be linked to how many Senate Missions have been completed and how many cities the player has. The reform could basically give all new units +1 experience boost on build, but maybee thats too overpowered. Think it is possible to do that in your customfeatures module?
 
ahh.. I forgot the nice little penalties... and had a little Idea on how we can intice the player to take byzantium (other than to get rewarded)...

Punishments
Gold Deduction (could cause big problems for the player :satan:)
Rebel units :D
Unhappiness
Building demolisment (?)
Anarchy
The Big one:
Spoiler :

The Senate supports: CIVIL WAR!
now, if the player is put between civil war and a free settlement (but not for long...) I would pick Byzantium :lol:


Oh and... Merry Christmas!!!:D
 
well some could be random... :think:
This means that we need differentiated methods for checking the starting condition. The method responsible for checking each mission, like Mission.checkDate(), would have to be able to handle both years and percentages. So there would probably be a new variable/name/attribute/field like bRandom (boolean).

I guess some missions could use the give reward on turn but for byzantium (where the ERE's existance hangs in the balance...) It would be good to have the capture and hold settlement for x turns
Another way to express this could be to have linked missions. Like if you complete the conquer city mission you enable the hold city mission. (Easy enough to do by checking if the player is owning a city on the plot. No need to actually link missions to each-other.)

The great problem with buttons... the possible amount of cities Rome could have! ahh... hundreds of buttons to make :lol:! I will finish it.... eventually :D (I may misunderstand... you mean with city names on or just a select button?)
No, you're probably thinking about some other type of button. What I mean is that the pop-up would have bullet buttons - small white circles in front of each name. The player would chose one of the cities/options by moving a black spot (bullet?) to the circle associated with the selected option.

I believe this is very doable and I did experiment with it once. Its all in the API and I we'll figure it out yet.

yeah I did think about espionage and I thought maybee a do mission thing on an enemy capital/city
I'm not sure whether or not it is possible to detect with Python that a espionage mission has taken place...

the multi optional popup for city spawn sounds very good... all we need is another coder to wander by... I guess we need a list then?
No, we can manage this ourselves too. And what you need to compile a list of coordinates and city names - and perhaps even founding dates. The latter could be used to only offer the player historical colonies (such that were build in the same time-frame) - and to spawn AI Rome free cities (new scenario feature)!

I guess the player should choose whether they want an anarchy free civic swap and what they want to swap to... only one swap though for example I would pick Monarchy but I couldn't pick Free Religion aswell.
I simply think that the Senate would suggest a civics change - like "we need slavery back!" - and the option would be to accept this proposal or not. Not accepting it could of course cause anarchy instead! :eek2:

I guess for the unique units of other civs it would be a case of definining map areas... I could get on to that soon! You are just about right in my opinion about the conquoring areas! Could even be unsenate related (but we can say the senate celebrates your glorius achievements in ____. just to make them look nice :D)
It could be possible to achieve with CyCity.getOriginalOwner() - if the returned value is not the PlayerType of Rome, then the city would be foreign and thus eligible for auxiliary units for the original owner. There could also be a culture points condition - like if the city is more than 50% Roman, then the population would be considered assimilated and not yield any local unit types anymore.

btw: One thing I have always thought of having (since I wanted to remodel the tech tree) want to have the Marius Reform... It could be linked to how many Senate Missions have been completed and how many cities the player has. The reform could basically give all new units +1 experience boost on build, but maybee thats too overpowered. Think it is possible to do that in your customfeatures module?
Sure, but this does add to my workload. Once I'm done with the Rebellion module and the Byzantine thing, I need to focus on another mod that I'm doing all the Python for. So unless you're going to do this yourself it might be awhile...

ahh.. I forgot the nice little penalties... and had a little Idea on how we can intice the player to take byzantium (other than to get rewarded)...
You could add Anarchy and City Disorder to the list of punishments.

Anything else you wanna add to the Senate Mission feature?
 
Back
Top Bottom