Requesting following features

so what do you think is the problem with the XP then?
 
Oh, you missed my post above? It depends on your code, of course. A good place to start would be to make sure that the grantExtraXP() function is fired in the first place.

Also, keep an eye out for exceptions, as they will disable Python code in a seemingly unpredictable way.
 
Some practical debugging: In the grantExtraXP() function, add this line (directly under the def line):
Code:
print "this is grantExtraXP() calling!"
If you enable debugging messages in the .ini file you should see the string value printed into the PythonDbg.log file any time a unit is built. This indicates that the code has fired. If there is no message, then at least you know that the function call isn't being made.
 
do I need to enable this?

Establish connection to Python Debugger
HAPDebugger = 0
 
I don't think so... :p
 
:lol: I just realized that we created two boolean custom values for the same thing. I didn't realize that the one was connected to the other. So you only need to set one flag for this event. :p

I suggest you redo the marius code and use the extra XP flag to determine whether or not the event itself has fired. Because once it has, you simply switch it from False to True. Then can we figure out why the actual XP isn't being distributed.
 
I have a problem with this:

getPlayerData(pointer("Rome", playerID), "bExtraXP")

why player data? all you are telling to do is return bExtraXP so I propose that instead of this:

Code:
def isRomeExtraXP():
	"""
	Returns True if the "bExtraXP" flag has been set. Otherwise returns False.
	"""
	return getPlayerData(pointer("Rome", playerID), "bExtraXP")
       
def grantExtraXP(pUnit):
        print "this is grantExtraXP() calling!"
	if isRomeExtraXP() and pUnit.getOwner() == pointer("Rome", playerID):
		pUnit.setExperience(iRomeExtraXP, iRomeExtraXP)

that it would work better as...

Code:
def grantExtraXP(pUnit):
        print "this is grantExtraXP() calling!"
	if getMariusFired() == True and pUnit.getOwner() == pointer("Rome", playerID):
		pUnit.setExperience(iRomeExtraXP, iRomeExtraXP)
with those kill functions esle where....

because to me this makes alot more sense than using the player thing...

in fact I have such a problem with it that I believe player data is the problem :p will test now...
 
not thats not it... but current marius et al code:
Code:
#Data Storage!#
def setupCounter():
    setGlobalData("iMissionCounter", 0)

def setupKill():
    setGlobalData("bMariusFired", False)

def increaseMissionCounter():
    iMissionCounter = getGlobalData("iMissionCounter")
    setGlobalData("iMissionCounter", iMissionCounter + 1)

def killMariusCode():
    setGlobalData("bMariusFired", True)

def setRomeExtraXP():
	"""
	Sets a boolean flag to True that can be accessed though the name "bExtraXP" 
	or with the function isRomeExtraxP.
	"""
	setPlayerData(pointer("Rome", playerID), "bExtraXP", True)

def getMariusFired():
    return getGlobalData("bMariusFired")

##Marius Reform##
iMissionsNeeded = 0
iCitiesNeeded = 10
mariusHeader = "Marius Reform"
mariusMessage1 = "An old soldier called Marius has called for the Roman Army to be reorganized, this means that as of now, all your cities give units +1 experience on build!"
mariusMessage2 = "A man called Marius has called for the Roman Army to be reformed!"
def eventMarius():
    if getNumPlayerCities(eRome) >= iCitiesNeeded and getGlobalData("iMissionCounter") >= iMissionsNeeded and getMariusFired() == False:
        if isHuman("Rome") == True:
            showPopup(mariusHeader, mariusMessage1)
        addMessage(mariusMessage2, (), eWhite)
        setRomeExtraXP()
        print "this is eventMarius() calling!"
        killMariusCode()

and
Code:
def isRomeExtraXP():
	"""
	Returns True if the "bExtraXP" flag has been set. Otherwise returns False.
	"""
	return getPlayerData(pointer("Rome", playerID), "bExtraXP") currently unused :p
       
def grantExtraXP(pUnit):
        print "this is grantExtraXP() calling!"
	if isMariusFired() == True and pUnit.getOwner() == pointer("Rome", playerID):
		pUnit.setExperience(iRomeExtraXP, iRomeExtraXP)

excuding my change of grantExtraXP(:rolleyes:) do you see anything wrong with this?

btw I cant find the debug files?
 
Player data is really a dictionary of values that gets saved with a CyPlayer object, while global data is a dictionary saved with the CyGame object. So it would be possible to store the same value for each player without creating an additional array within the global data. But what you use is really not important - as long as DataStorage works as intended.

You should get rid of either bExtraXP or bMariusFired, to simplify the code. Start with that and keep an eye on the logs found in \My Documents\My Games\Beyond the Sword\Logs\ - I'm gonna assume that you enabled logging and exceptions.
 
ok after skimming through the debugg file. I got this:

PY:City Bibracte's culture has expanded
PY:City Thebes's culture has expanded
23 SCREEN TURNED ON

Disabling Map Tab

WB brush selected, iList=0, iIndex=0, type=1

this is eventMarius() calling!

PY:City Athens's culture has expanded
PY:City Syracuse's culture has expanded
PY:OnPreSave
load_module CvDiplomacyInterface

load_module CvDiplomacy

PY:City Londinium's culture has expanded
PY:Thebes has grown
PY:City Trier's culture has expanded
PY:City Scone's culture has expanded

as you can see the marius event has called BUT the give exp has not called...

Maybee it's a problem with datastorage? I guess the only way to find out is using missioncounter (if my byzantium prompt is completed...)
 
Once more: What does the call from CvEventManager to CustomFatures.grantExtraXP() look like? Because it isn't happening - otherwise you'd be seeing the print-out in the debug log.
 
Also, you need to build a unit for the grantExtraXP() function to be called. It doesn't fire when the event occurs.

Or is the idea to (also?) grant extra XP to all existing units? :confused:
 
I do build a unit... this is testing proceedure...

Add in 10Cities... next turn marius popup + message fires, good. Start building warrior in tarentum... finishes... check for xp... none...

only on build not current units

what call? what is meant to be in eventmanager (apart from in onUnitBuilt)?
 
Can you copy-paste your onUnitBuilt() method from the Event Manager, please? Because it isn't working. (You should be on the lookout for exceptions.)

Also make sure you have enabled the unitBuild callup in PythonCallbackDefines.xml - if there is one such setting.
 
Code:
	<Define>
		<DefineName>USE_CANNOT_FOUND_CITY_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CAN_FOUND_CITIES_ON_WATER_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_IS_PLAYER_RESEARCH_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CAN_RESEARCH_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CANNOT_DO_CIVIC_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CAN_DO_CIVIC_CALLBACK</DefineName>
		<iDefineIntVal>1</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CANNOT_CONSTRUCT_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CAN_CONSTRUCT_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CAN_DECLARE_WAR_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CANNOT_RESEARCH_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_GET_UNIT_COST_MOD_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_GET_BUILDING_COST_MOD_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_GET_CITY_FOUND_VALUE_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CANNOT_HANDLE_ACTION_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CAN_BUILD_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CANNOT_TRAIN_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CAN_TRAIN_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_UNIT_CANNOT_MOVE_INTO_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_CANNOT_SPREAD_RELIGION_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_FINISH_TEXT_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_ON_UNIT_SET_XY_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_ON_UNIT_SELECTED_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_ON_UPDATE_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_ON_UNIT_CREATED_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>
	<Define>
		<DefineName>USE_ON_UNIT_LOST_CALLBACK</DefineName>
		<iDefineIntVal>0</iDefineIntVal>
	</Define>

you can choose from these :D

Code:
	def onUnitBuilt(self, argsList):
		'Unit Completed'
		city = argsList[0]
		unit = argsList[1]
		player = PyPlayer(city.getOwner())
		CvAdvisorUtils.unitBuiltFeats(city, unit)
		
		if (not self.__LOG_UNITBUILD):
			return
		CvUtil.pyPrint('%s was finished by Player %d Civilization %s' 
			%(PyInfo.UnitInfo(unit.getUnitType()).getDescription(), player.getID(), player.getCivilizationName()))

		Custom.grantExtraXP(unit)
 
This is the most likely suspect:
Code:
		if (not self.__LOG_UNITBUILD):
			return
Unless that condition isn't met the method exits with the return command - before ever reaching your function call.

So you basically put the function call before the exit condition.
 
The return command always exits a function/method. I was struggling with this exact issue with the event manager some 6 months ago, so its always good to be able to learn from others experience/mistakes. :D

Look where I put my function calls in CvEventManager; Its after all the variables have been defined, but before any other statements. Because most of the time you don't have to bother with what the present code does - just make sure your stuff gets fired before anything else happens. :goodjob:

And not cluttering up the event manager even more is at the heart of my own Python mod design philosophy. Because all of the code in your mod basically been possible to cram into it and CvGameUtils, but I really don't see the benefit of this approach. Imagine finding something in there, with Firaxi's, mine and your code intertwined...
 
Back
Top Bottom