Requesting following features

finished the second event :p here's all my work for today :):

Code:
##AI Rome City flip/Army##
iRomeYear = 0 #Change!
iRomeYear2 = 0 #Change!
tByzantium = (46, 23) #Change!
romanMessage = "TXT_KEY_MODEVENTS_ROMEQUEST_MESSAGE"
pRome = pointer(eRome)
iNumUnits = 1
x = 0
def eventRomeQuest():
    if not isHuman("Rome") and pRome.isAlive():
        if isPlotCity(tByzantium) and isDate(iRomeYear):
            addMessage(romanMessage, (getPlotCity(tByzantium).getName(),), eWhite) #Blue/Cyan?
            for pTile in getCityRadiusTiles(tByzantium):
                spawnUnits(eRome, ePraetorian, pTile, iNumUnits)
                x += 1
            spawnUnits(eRome, getIndex("Unit", "Quintrireme"), getRandomCoords(getCityRadiusTiles(tByzantium, True)), Round((x * iNumUnits)/3, True))
        elif isPlotCity(tByzantium) and isDate(iRomeYear2) and not isPlotOwner(tByzantium, eRome):
            flipCity(eRome, getPlotCity(tByzantium))

##ERE Reinforce##
iNumCities = 4
iReinforceDate = 0 #Change!
tERETop = (0, 0) #Change!
tEREBottom = (0, 0) #Change!
reinforceMessage = "TXT_KEY_MODEVENTS_REINFORCE_MESSAGE"
pByzantium = instance(eByzantium)
iNumUnits = 3
def eventReinforce():
    if getNumPlayerCities(eByzantium) < iNumCities and isDate(iReinforceDate) and pByzantium.isAlive():
        for pCity in findAreaCities(tEREBottom, tERETop):
            if not pCity.isCapital():
                flipCity(eByzantium, pCity)
                spawnCityGarrison(pByzantium, pCity, iNumUnits)
                addMessage(reinforceMessage, (), eWhite) #Blue/Cyan?

and

Code:
def Round(x, bUp):
        """
        Rounds either up or down
        """
        if type(x) == type(1):
                x = float(x)
        iRoundBase = x - round(x)
        if iRoundBase < 0.5 and bUp:
                return int(round(x) + 1)
        elif iRoundBase >= 0.5 and not bUp:
                return int(round(x) - 1)
        else:
                return int(round(x))

def getPlotCity(tCoords):
       return getPlot(tCoords).getPlotCity() 

def getCityRadiusTiles(pCity, bNaval = False):
        lPlots = list()
        if type(pCity) == type((0, 0)):
                pCity = getPlotCity(pCity)
        for iIndex in xrange(19):
                pPlot = getPlot(getCoords(pCity.getCityIndexPlot(iIndex)))
                if not bNaval:
                        if isSpawnValid(pPlot) == False or pPlot.isCity(): continue
                        lPlots.append(pPlot)
                else:
                        if not pPlot.isWater(): continue
                        lPlots.append(pPlot)
        return lPlots

def flipCity(ePlayer, pCity, bConquored = False, bTrade = False):
        instance(ePlayer).get(CyPlayer).acquireCity(pCity, bConquored, bTrade)

you see any problems there?

I am going to have to do some editing of all the mod's events years and coords and indeed fill in the values on this events. When they are tested I will start on player city founding restriction :p
 
You built-in a redundancy here:
Code:
                pPlot = [COLOR="Red"]getPlot(getCoords([/COLOR]pCity.getCityIndexPlot(iIndex)[COLOR="Red"]))[/COLOR]
There is no reason to turn the returned CyPlot instance into a pair of integer coordinates inside a tuple, only to fetch the same CyPlot instance. :p
 
I thought that pCity.getCityIndexPlot(iIndex) would return a city (Must have had a crazy moment :p)
apart from that?
 
When they are tested I will start on player city founding restriction :p
Yeah, about that. I'm not gonna spoil your fun, but I though I've give you a hand anyways. If you add this to CvGameUtils you have some maneuver-room:
Code:
	def cannotFoundCity(self,argsList):
		iPlayer, iPlotX, iPlotY = argsList
		return [COLOR="Red"]([/COLOR] self.cities.isInvalidSite(iPlayer, (iPlotX, iPlotY))
		         [COLOR="Red"]or self.custom.isRestricted(iPlayer, (iPlotX, iPlotY)) )[/COLOR]
Now, you can simply add this dummy function in CustomFeatures:
Code:
def isRestricted(ePlayer, tCoords):
    return False
By having the function return something else than the default False value I added above, you will be able to restrict a player from building cities. The map tile coordinates are of course found inside tCoords.
 
I thought that pCity.getCityIndexPlot(iIndex) would return a city (Must have had a crazy moment :p)
Are you able to understand everything going on in the Python API? Because if something is unclear you could just ask. I actually think I understand it fully by now. :p

apart from that?
I guess it looks alright. :goodjob: You simply have to test and debug - the big programmers job. :p
 
I didn't look in the API for the getCity(...) just used it from your post, but as I look at it now it obviously returns a plot but I guess the way you had it documented in your post it confused me subconsiously :lol: :crazyeye:

not sure I completly understand how your helper works :p
 
not sure I completly understand how your helper works :p
What helper? isRestricted()? Its not a helper, its a shell of a function for you to style into whatever it is you wanna do with player city founding restrictions. Between the definition line and the return line you add the logic that in the end determined what the function would return (not False by default, obviously - thats just a dummy value for you go change).
 
I think I understand and if I don't I'm sure I will work it out :p

Also: My new calendar works in months instead of years (the months are not divisible by 12) and your isDate() function always seems to make the event happen the turn AFTER the defined time :crazyeye:

In the case of the new ERE date (395ad) it would therefore have to be fired on the date 392 ad in the month October (instead of default January :p) how does the isDate() function handle months or can't it?
 
Also: My new calendar works in months instead of years (the months are not divisible by 12) and your isDate() function always seems to make the event happen the turn AFTER the defined time :crazyeye:

In the case of the new ERE date (395ad) it would therefore have to be fired on the date 392 ad in the month October (instead of default January :p) how does the isDate() function handle months or can't it?
This may be a matter of design, since I personally want events to take place only when the actual date has passed. But I'm not sure if this is what you mean or if the functions isn't doing what its supposed to.

I don't have your files and I can't seem to find isDate() in my own stuff, but if you post it we could have a look and try some things out. It should be as easy as changing one operator in one expression, but we'll see.

How are you defining the dates, by the way? Are you using integer years with a calendar that is using months?
 
Without knowing what exactly you want and what exactly you're currently doing, here is something you could try out (note both edits on the same line!):
Code:
def isDate(iDate):
    return cyGame.getTurnYear(cyGame.getGameTurn() +1) [B][COLOR="Red"]>=[/COLOR][/B] iDate and cyGame.getGameTurnYear() [COLOR="Red"][B]<[/B][/COLOR] iDate
Now, this is the original function from another mod, so you probably can't copy-paste the whole thing.
 
well the function is usually called by the year before, as you know, and is asually called by

isDate(1233)

so how is the month aspect used because I want it to happen exactly on the right year (of course the function could be edited to happen on the right year (or is that what your function does now?) I could always use the game turn functions instead when I am on my computer I cangive more info...
 
It seems that this function is for full years only. But I did augment it in PyScenario to accommodate fractions of years. I'd have to look-up how I solved, but its doable none-the-less. So, you don't need to resort to figuring out what date is what game turn. This is what scripting is for; avoiding to do menial, repetitive labor. There should never be any reason for that.

Did you try the solution I suggested above?
 
not yet but you realise I have a program thaat lists every turn and corrosponding dates :p

I know all the turns I need and their dates but I await your reply anyway!
 
Like I said before; its your mod and you can totally have it your way. You'll figure out what I'm talking about, eventually. But for now you're good with any solution, as long as it solves the problem.
 
It just dawned on me that there is built-in support for disabling units for some number of turns, meaning that the Catapult Construction code could be simplified. Also, it seems that it might be possible to use Python to give AI units orders. So if I only had the time, I could probably improve things a lot... :p
 
hmmm do you have the time? :p

Also it dawned on me eariler I don't have a clue how to define dates! how does it wokred with months instead of years?
 
Sadly, no. I need to finish my own project before I have to move out of this apartment. After that I may not even have a gaming computer in the foreseeable future...
 
(see second part of post :p)

surely you would take your computer with you?
 
I don't have time to look into this right at this moment, but this is what I have in my PyScenario application:
Spoiler :
Code:
class CheckDate(Conditions):

        def __init__(self, date1, date2):
                self.setMonth(date1, date2)
                self.notTurnTrigger = False

        def setMonth(self, date1, date2):
                self.month1 = self.getMonth(date1)
                if isValid(date2):
                        self.month2 = self.getMonth(date2)
                else:
                        self.month2 = self.month1

        def getMonth(self, date):
                if isStr(date):
                        return self.getStringDate(date)
                else:
                        return int(date) * 12

        def getStringDate(self, date):
                for iLetter in range(len(date)):
                        if date[iLetter] == ":":
                                return int(date[:iLetter]) * 12 + max(0, int(date[iLetter + 1:]) - 1)
                if iStartYear <= float(date) <= 2020:
                        return int(float(date) * 12)

        def check(self, pContext):
                pContext.debug(("CheckDate.check()", getDateForTurn(pContext.args[0]), self.month1, self.month2), None)
                return self.checkDate(pContext.args[0], self.month1, self.month2)

        def checkDate(self, iTurn, iMonth1, iMonth2):
                return ( iTurn == 0 and iMonth1 == -36000 == iMonth2
                         or getDateForTurn(iTurn + 1) >= iMonth1 and getDateForTurn(iTurn) < iMonth2 )
Code:
def getTurnForMonth(iMonth):
        return getGameTurnForMonth(iMonth, Game.getStartYear(), Game.getCalendar(), Game.getGameSpeedType())

def getDateForTurn(iTurn):
        return getTurnMonthForGame(iTurn, Game.getStartYear(), Game.getCalendar(), Game.getGameSpeedType())
Now, the answer to your question may lie in there, somewhere. :D

For reference, the CheckDate class is accessed by the date() method, which is documented in the PyScenario documentation:
Spoiler :
date( date1, date2=None )
This Condition is the main method for triggering scenario events with PyScenario. It takes one obligatory and one optional setting consisting of game dates. The most basic way to use the method is to simply supply a integer game year date. Then the Trigger will fire once at that date (or on the first turn beyond that date) and automatically expire thereafter. Example: date(-120) (Note that BC dates are represented by negative integer values while AD values are positive.)

Another use involves the second setting and changing it to a actual game date instead of the default value (None). Then the method will check for any game turn within an interval of game turns corresponding to those dates. Example: date(-120,50)

It should be noted that while there are only integer years on Normal game speed, there will be fractional years that are divided into months on slower game speed settings. So it is also possible to use floating point values to represent fractional years. Example: date(1901.0,1911.5) (Note that decimal fractions will be translated into a 12 month scale. Also note that you can't actually use a comma character as a decimal comma. Use period instead.)

It is also valid to use string values as date settings, and then it is also possible to specify the month (1-12) without using a decimal fraction. Example: date("1999:12")

And lastly, you can mish-match different kinds of values for the date settings as you want. As long as it makes sense it should also work, but beware of omitting quotation-marks for string values. (You could in fact only use string values as a rule of thumb, if you want.)
 
surely you would take your computer with you?
You see many homeless people with a desktop computer under their arm? ;) I may get a modern laptop, eventually, but my current one is antiquated and mostly for email. :p So we can still stay in touch. :lol:
 
Back
Top Bottom