Requesting following features

well good luck with your computer! it seems as though I would be able to reassemble the date() function from your pysenario into one that I can use effectivly (the "1000:8" is very interesting and I will dig into it within the code :p, there's my solution I think!)
 
The actual date() method isn't shown in the code posted. Its belongs to the Trigger class and is only used on initialization. The method actually creates a new CheckDate instance and adds it to an array, with the settings supplied with date().

So you basically need to reverse-engineer the CheckDate class - and the associated helper functions - and turn it into new function for your mod.
 
hmm this might take a while :p in your method is 1000:1 january or is january 0?
 
hmm this might take a while :p in your method is 1000:1 january or is january 0?
The code has the answer, but I do believe that the months are enumerated from 1 to 12.

Holler if you need help with this. I have put aside the weekend for programming.
 
Ok, lets break down the code. Then we can see if you can figure out how to put everything together into your own function(s). Please, do not copy-paste more than single expressions, try to write your own code for this. You'll learn way more and you will end up with something that you understand - that is customized for your needs.

This method takes a string (like "2001:2") and returns a integer date - expressed in months:
Code:
        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)
The for-in loop (lines 2-5) determines whether or not there is a colon anywhere in the string. In that case the string needs to be parsed into a year and and a month. The return line holds all the math and is also indexing both parts of the string.

The *12 is important, as the game actually counts all dates in months - not years. Thus the year needs to be multiplied by 12. The month portion of the string is - as said - enumerated 1-12. This of course doesn't compute, so we have to subtract 1 (turning it to a 0-11 interval) before adding to the year * 12 value.

The conditional statement (lines 6-7) is a backup in case the string is only a year without any month (and thus no colon - or nothing beyond the colon). The condition for returning the date is that it is valid (within scenario calendar) and the return statement simply multiplies the date with 12 to get the month date.

Since you're not making a scripting tool (like I was) you could well simplify your version of the method/function.

This is where the actual date check is done:
Code:
        def checkDate(self, iTurn, iMonth1, iMonth2):
                return ( iTurn == 0 and iMonth1 == -36000 == iMonth2
                         or getDateForTurn(iTurn + 1) >= iMonth1 and getDateForTurn(iTurn) < iMonth2 )
The iTurn value can be fetched with CyGame.getGameTurn() and the iMonth1 and iMonth2 values are the two values making up the date interval. (If only one date is used, then iMonth2 = iMonth1. Again, if you only need single dates, you could simplify things.)

The first or-clause in the return statement basically checks if all the values are valid - the method returns False for invalid values - thus such a Trigger will never fire. So you clearly don't need this, since you're only gonna use valid dates, right? ;)

The second or-clause calls the getDateForTurn() helper function for both dates and checks whether or not current game date is within this interval. With only one date you would use something similar - look what I did with the isDate() function.

Finally, this is the helper that returns the month for the current game turn:
Code:
def getDateForTurn(iTurn):
        return getTurnMonthForGame(iTurn, Game.getStartYear(), Game.getCalendar(), Game.getGameSpeedType())
Note that getTurnMonthForGame() is a built-in SDK function not listed in the Python API (because it doesn't belong to any class). My version is tailored to work with any possible game setup - you on the other hand already know these settings for your mod. So there are opportunities for simplification.

Now, can you make something helpful out of this for your mod? :D
 
Another tip: If you plan on only using the default format of "2001:2" for all dates, then you don't need to iterate through all the characters of the string in order to parse the string into "2001" and "2" respectively.

Instead, there is a string method for automating this:
Code:
date = "2001:2"
tDate = date.partition(":") # returns the tuple ("2001", ":", "2")
year = tDate[0]
month = tDate[2]
Nifty, eh? :)
 
on post 2, depending on whether the date needs to be the turn before the event or otherwise it will either be only month + year definitions or year only definitions aswell (year on their own only happens if the event is fired on turn) it seems as though I could work something out tommorrow (away from my own computer so unless I need any of my files I should be fine (not that I can test there anyway!))
 
Code:
def isDate(date):
    if 0 <= (date%12) < 12:
         if date == getGameMonth(CyGame.getgameturn()):
             return True

def convertMonth(date):
    date = date.partition(":")
    dateYear = int(date[0]) * 12
    dateMonth = int(date[2]) -1
    month = dateYear + dateMonth
    return month

date = "395:1"

def getGameMonth(iTurn):
    getTurnMonthForGame(iTurn, Game.getStartYear(), Game.getCalendar(), Game.getGameSpeedType())

that should work! (presumeing that a stand alone date like the year 395 would be expressed alternatively as "395:1" and also that the CyGame.getGameTurn() is actually called like that, I wasn't sure because usually the bit before the dot is a plot or a unit when I see it :p)

also problems you can see?

I tested the logic without the civ4 references before hand and the isDate told me true (but that was when I just had "395:1" as you can see) with just the month number with the modulo division check!

>> convertMonth("395:1")%12
0
 
also added this in
Code:
def isDate(date):
    if 0 <= (date%12) < 12[B] and getGameMonth(0) < date < getGameMonth(500)[/B]:
         if date == getGameMonth(CyGame.getgameturn()):
             return True
just incase :P
 
No, that makes little sense. Keep trying! :D

Tell me once you wanna surrender this to me. :p
Spoiler :
Use Game instead of CyGame for the getGameTurn() method. And if you're only gonna use the actual date in the getGameMonth() function you might as well only use it within the getTurnMonthForGame() function, together with all the other CyGame class methods.
Spoiler :
The name Game should already be defined as Game = CyGame() somewhere in your mod's Python modules, and imported to all the others. So using CyGame().someCyGameMethod() would work just the same, but then you're creating a new CyGame instance every single time. In theory this would consume memory, why it makes sense to assign one single instance to a name and then invoke methods on that name.

The same can be said about gc = CyGlobalContext(), which you can find in just about any Python module associated with CivIV. (I however only used that in one module and imported the name to the others.)
 
hmm... what doesn't make sense about it?

first it converts the date (left that bit out :rolleyes:) then it checks to see if it is valid and then checks to see if it is the current month
 
Note that the date -500 is actually the month -6000. And since game dates can be other than single/full years, you always need to check intervals of months. I've already given several examples of how to check whether or not a date is within a interval, and only fire the first time the date is within that interval.

I realize this is confusing stuff. I also got really bogged down with it, once upon a time. Working with this still makes my head spin!
 
but I will define all single dates (such as 395) as having month 1 this gives the same result:

>>> convertMonth("-500:1")
-6000

>>> convertMonth("395:1") == 395 * 12
True

see... I don't understand what the problem with that is?
this line : getGameMonth(0) < date < getGameMonth(500)
checks if the date supplied is between the first month and last month (just incase I make some stupid mistake) and I have added a debugging bit for if it isn't :p

Code:
def isDate(date):
    date = convertMonth(date)
    if 0 <= (date%12) < 12 and getGameMonth(0) < date < getGameMonth(500):
         if date == getGameMonth(Game.getGameTurn()):
             return True
        else:
            return False
    else:
        print "Invalid Date supplied!"

edit: however it won't work if a negative date with a month bigger than 1 is supplied but that is easily fixed and I don't think I need to use one like that in my events (only the year -74:1)
 
Well, I guess you'll just have to try it and prove your point.

One question: Is your historical scenario taking place between the year AD 1 and year AD 500? :confused:
 
Code:
def convertMonth(date):
    date = date.partition(":")
    dateYear = int(date[0]) * 12
    dateMonth = int(date[2]) -1
    if dateYear < 0:
        month = dateYear - dateMonth
    else:
        month = dateYear + dateMonth
    return month

question: is

if x < 1: print "Yes"

valid syntax?

no takes place between the year -341 and 410 but above fix compensates for that :p
 
>>> print convertMonth("-500:2")
-6001

and that is correct :p so AFAIK My function is completly right :p
 
Syntax look alright, but I can't make any sense of your code. I'm glad you're confident, but I believe you're not even near solving this...

I basically already supplied everything you need for getting this to work, so there should be no need to re-invent the wheel. But sorting this out will increase your knowledge of programming, for sure! :goodjob:
 
answered my own question :p pretty usefull to be able to do that, allows for shorter code
Code:
def isDate(date):
    date = convertMonth(date)
    if 0 <= (date%12) < 12 and getGameMonth(0) < date < getGameMonth(500):
        if date == getGameMonth(Game.getGameTurn()): return True
        else: return False
    else: print "Invalid Date supplied!"

def convertMonth(date):
    date = date.partition(":")
    dateYear = int(date[0]) * 12
    dateMonth = int(date[2]) -1
    if dateYear < 0: month = dateYear - dateMonth
    else: month = dateYear + dateMonth
    return month

date = "395:1"

def getGameMonth(iTurn):
    getTurnMonthForGame(iTurn, Game.getStartYear(), Game.getCalendar(), Game.getGameSpeedType())

what don't you understand? I can explain it :p
 
There is no need for me to understand any of it, you just have to test it and sort any issues out.

But this is nonsensical at any rate:
Code:
getGameMonth(0) < date < getGameMonth(500)
Because it will only allow you only fire events between the game dates AD 1 and AD 500. Its broken, so you just skip it.

And your fix for it doesn't make any sense, what-so-ever:
Code:
    if dateYear < 0: month = dateYear - dateMonth
    else: month = dateYear + dateMonth
If you don't believe me, just test it yourself. I can't be bothered with trying to explain why its invalid, but you're welcome to prove me wrong anyway.

As I said, you'll learn a lot by getting this to work. I know I did. :D
 
Back
Top Bottom