ModModder's Guide

And no such lines in the onUnitPillage function so i was guessing it's not working anyway...

Hmm... that is very odd indeed.

I'll have to investigate this; I know the pieces I added have worked before, but maybe something happened and for some reason that compatibility was rolled back?

Edit: Gah! You're completely right; it doesn't work. Seriously, why remove something like that, especially without telling team members?
 
I just downloaded FallUnder module for RifE:

The strange thing is that in this mod there is also a file with eventBlaBla.py in it:

eventFallUnder.py

contend:
Spoiler eventFallUnder.py (FallUnder) :
Code:
from CvPythonExtensions import *
from BasicFunctions import *
import CustomFunctions
import PyHelpers

# globals
cf = CustomFunctions.CustomFunctions()
gc = CyGlobalContext()
PyInfo = PyHelpers.PyInfo

def onBuildingBuilt(self, argsList):
	'Building Completed'
	pCity, iBuildingType = argsList
	if iBuildingType == gc.getInfoTypeForString("BUILDING_GUILD_MEDICOS"):
			pCity.setHasCorporation( gc.getInfoTypeForString("CORPORATION_ORDINE_MEDICOS"), True, True, False)

def onBeginPlayerTurn(self, argsList):
	'Called at the beginning of a players turn'
	iGameTurn, iPlayer = argsList
	pPlayer = gc.getPlayer(iPlayer)
	iAlignment = gc.getPlayer(iPlayer).getAlignment()
	iEthicalAlignment = gc.getPlayer(iPlayer).getEthicalAlignment()
	iGood = gc.getInfoTypeForString('ALIGNMENT_GOOD')
	iNeutral = gc.getInfoTypeForString('ALIGNMENT_NEUTRAL')
	iLawful = gc.getInfoTypeForString('ETHICAL_ALIGNMENT_LAWFUL')
	iEthicalNeutral = gc.getInfoTypeForString('ETHICAL_ALIGNMENT_NEUTRAL')
	if pPlayer.hasTrait(gc.getInfoTypeForString('TRAIT_BARBARIAN')) and iGameTurn >= 20:
		eTeam = gc.getTeam(gc.getPlayer(gc.getORC_PLAYER()).getTeam())
		iTeam = pPlayer.getTeam()
		if eTeam.isAtWar(iTeam) == False:
			iPenalty = 0
			if (iAlignment == iGood):
				iPenalty += 5
			elif (iAlignment == iNeutral):
				iPenalty += 2
			if (iEthicalAlignment == iLawful):
				iPenalty += 5
			elif (iEthicalAlignment == iEthicalNeutral):
				iPenalty += 2
			iPenalty = ((iPenalty ** 2)-10) / .9
			if (iPenalty > CyGame().getSorenRandNum(100, "Barbs Attack")):
				eTeam.declareWar(iTeam, false, WarPlanTypes.WARPLAN_LIMITED)
				if (iPlayer == CyGame().getActivePlayer() and pPlayer.isHuman()):
					cf.addPopup(CyTranslator().getText("TXT_KEY_POPUP_BARBARIAN_DECLARE_WAR",()), 'art/interface/popups/Barbarian.dds')

so if that what Valkrionn wrote in this thread in post #287 - post #290 is true, the eventFallUnder.py shouldn't work ether...

Spoiler :
Yes it is; The file must be preceded by 'event'. As in, name it eventBlaBla.py.
No. EventManager and GameUtils can be preceded by anything, or nothing at all.

In fact, if your EventManager code is preceded by event, it will not fire; It will ignore it, thinking it is meant for RandomEventInterface.


Maybe there really was some kind of rolled back?
 
The FallUnder file won't work. Nor will the Mekara file. I mentioned it months ago to Jheral, and he said he would change it... Evidently he neglected to do so. :mischief:

Proof, from the modular python code in CvEventManager.

Code:
# Is it spell file ?
if pythonFileSource.replace ( '.py', '' ).replace ( '\\', '/' ).split ( '/' ) [ -1 ].upper()[0:5] == "SPELL":
	continue
# Is it event file ?
if pythonFileSource.replace ( '.py', '' ).replace ( '\\', '/' ).split ( '/' ) [ -1 ].upper()[0:5] == "EVENT":
	continue

As you can see, any file prefixed by spell (any case) or event (again, any case) will fail to load for EventManager.


I'm not sure when/why pillage was made non-modular, however. Or it may be that Jheral was remembering it being modular when it wasn't. :lol:

Honestly, last I remember on that was that he had tested it with the code in core files, and we needed to make it modular. Seems that never happened due to classes.
 
Another question:

Sometimes I want that a unit gets a certain promotion. This promotion should have a certain "duration" e.g. at one time it should stay 12 turns and in another situation it only should stay 5 turns (depending on gamespeed, stuff and wth...)
At the moment I'm doing this with different spells using <iPromotionDuration>XYZ</iPromotionDuration> but I don't like this methode.
Is there a way to do this with python like the way I can say how long the duration of a unit is ( pUnit.setDuration(XYZ) for promotions )?
 
Sorry. :p

For future reference (until I get them all modular), you can fairly easily tell which ones are modular and which are not, if you open the main files. Just go to the function in the core files (IE, Assets/Python/CvEventManager.py), find the function you want (onBeginGameTurn), and check the bottom of the function.

If you find something like the following, you're golden.

Code:
## *******************
## Modular Python: ANW 29-may-2010
		
for module in command['onBeginGameTurn']:
	module.onBeginGameTurn(self, argsList)
			
## Modular Python End
## *******************

Otherwise, it's not modular yet, as it wasn't seen as necessary when they were first made modular; Post a request. It takes about 30 seconds to add the code to a function, and update the other necessary places, so it's mostly a matter of actually doing it. ;)


For file naming, all python files must be within a folder named "python" (believe lowercase is important here). For your python to load in CvSpellInterface, the file must be prefixed by "spell" (do not believe case is important, recommend lowercase anyway to be safe). To load in CvRandomEventInterface, prefix with "event" (same case comment as spells).

Both CvEventManager and CvGameUtils load into existing functions rather than add new ones, so they may have any name they like so long as it is prefixed by spell or event.
 
Another question:

Sometimes I want that a unit gets a certain promotion. This promotion should have a certain "duration" e.g. at one time it should stay 12 turns and in another situation it only should stay 5 turns (depending on gamespeed, stuff and wth...)
At the moment I'm doing this with different spells using <iPromotionDuration>XYZ</iPromotionDuration> but I don't like this methode.
Is there a way to do this with python like the way I can say how long the duration of a unit is ( pUnit.setDuration(XYZ) for promotions )?

I'm not sure there is an example in the python (Honestly, I have not even checked), but a quick check of CyUnitInterface in the dll gives the following:

Code:
.def("getPromotionDuration", &CyUnit::getPromotionDuration, "int (int ePromotion)") //(PromotionTypes)
.def("setPromotionDuration", &CyUnit::setPromotionDuration, "void (int ePromotion, int iNewValue)") //(PromotionTypes)

So it seems like you can. You could do this by having the unit start with a promotion, and set the code in onUnitBuilt... Or you could, again, have the unit start with the promotion, but instead attach the code to a PyOnPromoTaken and place the code within Spells. IMO, the second method is better; Lighter weight, will not even fire so much as a check (If unit == MyUnit) for any other units being created. An example would exist in the Hamstalfar Module; Check the Alfar racial.
 
The FallUnder file won't work. Nor will the Mekara file. I mentioned it months ago to Jheral, and he said he would change it... Evidently he neglected to do so. :mischief:

Proof, from the modular python code in CvEventManager.

Code:
# Is it spell file ?
if pythonFileSource.replace ( '.py', '' ).replace ( '\\', '/' ).split ( '/' ) [ -1 ].upper()[0:5] == "SPELL":
	continue
# Is it event file ?
if pythonFileSource.replace ( '.py', '' ).replace ( '\\', '/' ).split ( '/' ) [ -1 ].upper()[0:5] == "EVENT":
	continue

As you can see, any file prefixed by spell (any case) or event (again, any case) will fail to load for EventManager.


I'm not sure when/why pillage was made non-modular, however. Or it may be that Jheral was remembering it being modular when it wasn't. :lol:

Honestly, last I remember on that was that he had tested it with the code in core files, and we needed to make it modular. Seems that never happened due to classes.
Whereas the last I remember on it is running tests with it in it's current modular form and, seeing that it was working as intended, releasing it in an updated module. :p

I suppose it's possible that I did make the changes, but for some reason didn't update the svn properly.
 
Sadly many modules direct adress the graphics to the Moduls/Normal Modules folder so that this modules get broken as when they are set to i.e. First Load.
Is there a way beside that the module user either have to rewrite many lines in the modules or be stuck for using the normal module slot? (BannorChainofCommand and FallUnder are the modules that have to be loaded in any pass)
Also the direct change from 3.pass to any pass in the Module Manger gives a error.
 
The problem there is that as far as I'm aware, you can't really not hardcode the location of the graphics files; the path to them has to begin in the Assets folder, not in the module's own folder. Therefore, the alternatives are a fixed path, or no unique art at all.
 
I dont know how much this will be or if it is posible but:
How about changing the Starting Programm so that it move the Art Files to the normal Modules Folder so the 1st load ect. works even with the fixed Path needed for the graphic Files?
 
That wouldn't work; Different modules store art in different ways. It would all have to be forced into a regularized path.

I thought the last update to the launcher fixed that... (?)
It should really only require a text-replace to change "NormalModules" to "LoadOrderVitalModules\FirstLoad", etc... I thought I remembered ANW mention something like that... Kinda foggy about it, though.
 
I thought the last update to the launcher fixed that... (?)
It should really only require a text-replace to change "NormalModules" to "LoadOrderVitalModules\FirstLoad", etc... I thought I remembered ANW mention something like that... Kinda foggy about it, though.

well ... you have good memory :D ... i started working on this, but i've never finished that :D
i might return to this, but if i am to do some changes to launcher, i'll first make some changes to the module-versioning check system, since i have no ****ing idea what was the meaning of some labels ... :D (( srsly, i wonder how you was able to understand it, i have no bleeping clue wtf ... :D ))
 
I don't know if you can call this a bug, but here is a problem that I run into today.
I was trying to delete all unnecessary lines in the CIV4EventTriggerInfos.xml file of my module because it is much easier to work with only the needed lines.

I ended up with something like that:
Spoiler part of CIV4EventTriggerInfos.xml :

Code:
        <EventTriggerInfo>
            <Type>EVENTTRIGGER_CIRCUS_HERRAMUS_1</Type>
            <WorldNewsTexts>
                <Text>TXT_KEY_EVENTTRIGGER_CIRCUS_HERRAMUS_1</Text>
            </WorldNewsTexts>
            <TriggerTexts>
                <TriggerText>
                    <Text>TXT_KEY_EVENT_TRIGGER_CIRCUS_HERRAMUS_1</Text>
                    <Era>NONE</Era>
                </TriggerText>
            </TriggerTexts>
            <bSinglePlayer>0</bSinglePlayer>
            <iPercentGamesActive>100</iPercentGamesActive>
            <iWeight>-1</iWeight>
            <iNumPlotsRequired>1</iNumPlotsRequired>
            <bOwnPlot>1</bOwnPlot>
            <BonusesRequired>
                <BonusType>BONUS_HORSE</BonusType>
            </BonusesRequired>
            <Events>
                <Event>CIRCUS_HERRAMUS_1_1</Event>
                <Event>CIRCUS_HERRAMUS_1_2</Event>
                <Event>CIRCUS_HERRAMUS_1_3</Event>
            </Events>
            <AndPreReqs>
                <PrereqTech>TECH_HORSEBACK_RIDING</PrereqTech>
            </AndPreReqs>
            <PythonCanDo>canTriggerCircusHerramus1</PythonCanDo>
        </EventTriggerInfo>


This event works perfectly well if I call it by myself with python but it will not trigger by the civ4BTS event system.
After trying a little bit around I found out that if I leave all the lines with -1 in the EventTriggerInfo it will work with the civ4BTS event system.

Spoiler part of CIV4EventTriggerInfos.xml with -1 :

Code:
        <EventTriggerInfo>
            <Type>EVENTTRIGGER_CIRCUS_HERRAMUS_1</Type>
            <WorldNewsTexts>
                <Text>TXT_KEY_EVENTTRIGGER_CIRCUS_HERRAMUS_1</Text>
            </WorldNewsTexts>
            <TriggerTexts>
                <TriggerText>
                    <Text>TXT_KEY_EVENT_TRIGGER_CIRCUS_HERRAMUS_1</Text>
                    <Era>NONE</Era>
                </TriggerText>
            </TriggerTexts>
            <bSinglePlayer>0</bSinglePlayer>
            <iPercentGamesActive>100</iPercentGamesActive>
            <iWeight>-1</iWeight>
[COLOR="Red"]            <iMaxOurLandmass>-1</iMaxOurLandmass>[/COLOR]
            <iNumPlotsRequired>1</iNumPlotsRequired>
            <bOwnPlot>1</bOwnPlot>
            [COLOR="Red"]<iPlotType>-1</iPlotType>[/COLOR]
            <BonusesRequired>
                <BonusType>BONUS_HORSE</BonusType>
            </BonusesRequired>
            <Events>
                <Event>CIRCUS_HERRAMUS_1_1</Event>
                <Event>CIRCUS_HERRAMUS_1_2</Event>
                <Event>CIRCUS_HERRAMUS_1_3</Event>
            </Events>
            <AndPreReqs>
                <PrereqTech>TECH_HORSEBACK_RIDING</PrereqTech>
            </AndPreReqs>
            <PythonCanDo>canTriggerCircusHerramus1</PythonCanDo>
        </EventTriggerInfo>


My question:
Is there a reason why you have to leave this lines in the code? Would it not be easier if you delete this lines in your code and the "game would assume" to put a -1 as default in it?
(Well, after knowing this it's not a big deal to add these lines but I can imagine that other modders run into the same problem and not knowing why it's not working...)
 
Are there more tags like that? I can change the default easily, just never came up (obviously :p).

Defaults for those tags will be changed in the next version; I made sure there would be no issues in the code before making the change, so it should be fine. ;)

I think the two are the only ones.
btw where can I see the defaults - ( is the default for <bSinglePlayer> = 0 )?

And another question:
Is there a easy way to get information (with python) about what buildings got destroyed by conquering a city?
 
Top Bottom