Modular Functions not working

OrionVeteran

Deity
Joined
Dec 25, 2003
Messages
2,443
Location
Newport News VA
Well, I've been playing with my latest effort for the last few days and have run into a problem with making the CvEventManager functions to run calling another Python file from a CvCustomEventManager.py. I'm using the CvCustomEventManager.py file from the Better BTS AI Mod. But, no matter what I do, the following functions will not execute, as they did originally in the CvEventManager.py file:

def onModNetMessage(self, argsList):

def onGameStart(self, argsList):

Do you have any suggestions as to how I can get just a simple message to display from these two functions? If you can suggest a way to get me that far, I think I can take it the rest of the way. The functions are in a file called file called InquisitionEvents and appear here in exactly the same way the are in the CvEventManager.py file:

Spoiler :

Code:
# InquisitionEvents

from CvPythonExtensions import *
import CvScreenEnums
import CvTopCivs
import CvUtil
import PyHelpers
import Popup as PyPopup
# Inquisition Mod
import pickle
import Inquisition
# End Inquisition Mod

# globals
gc = CyGlobalContext()
PyPlayer = PyHelpers.PyPlayer
PyInfo = PyHelpers.PyInfo
game = CyGame()
localText = CyTranslator()

# Inquisition Mod By Orion Veteran
# Modular Python to eliminate Merging 
class InquisitionEvents:

	def onModNetMessage(self, argsList):
		'Called whenever CyMessageControl().sendModNetMessage() is called - this is all for you modders!'
		CyInterface().addMessage(CyGame().getActivePlayer(),True,25,'Message 2!','AS2D_DISCOVERBONUS',1,'Art/Interface/Buttons/TerrainFeatures/Forest.dds',ColorTypes(8),0,0,False,False)

		iData1, iData2, iData3, iData4, iData5 = argsList
		
		print("Modder's net message!")
		
		CvUtil.pyPrint( 'onModNetMessage' )
# Inquisition Mod
		iMessageID = iData1
		
		#Inquisitor's Effect on a City
		if ( iMessageID == self.m_iNetMessage_Inquisitor ):
			
			iPlotX = iData2
			iPlotY = iData3
			iOwner = iData4
			iUnitID = iData5
			
			pPlot = CyMap( ).plot( iPlotX, iPlotY )
			pCity = pPlot.getPlotCity( )
			pPlayer = gc.getPlayer( iOwner )
			pUnit = pPlayer.getUnit( iUnitID )
			
			Inquisition.doInquisitorPersecution( pCity, pUnit )
			
		if iData1 == 200:
			iHPlayer = gc.getGame().getActivePlayer()
			iPlayer = iData2
			#iStateReligion = gc.getPlayer(iPlayer).getStateReligion()
			if iHPlayer != iData2:
				if iHPlayer.isHuman():
					# Get the state religion of the Human Player - Theocracy
					iHStateReligion = gc.getPlayer(iHPlayer).getStateReligion()
					if iHStateReligion == iData3:
						popupInfo = CyPopupInfo()
						popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_PYTHON)
						popupInfo.setData1(iHPlayer)
						popupInfo.setData2(iHStateReligion)
						popupInfo.setText(CyTranslator().getText("Godless infadels have destroyed our Holy City.  Will you stand with your brothers in faith and declare war against the infidel? WARNING! Failure to declare war will result in a state of war between you and any AI player that has theocracy Civic and shares your state religion",()))
						popupInfo.setOnClickedPythonCallback("TheocracyHolyWaronClickedCallback")
						popupInfo.addPythonButton(CyTranslator().getText("Yes, Declare War!", ()), "")	
						popupInfo.addPythonButton(CyTranslator().getText("No, I will not Declare War!", ()), "")
						popupInfo.addPopup(iHPlayer)
			
		if iData1 == 252:
			# DawnOfMan Popup
			popupInfo = CyPopupInfo()
			popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_PYTHON_SCREEN)
			popupInfo.setText(u"showDawnOfMan")
			popupInfo.addPopup(iData2)
			return
# End Inquisition Mod

	def onGameStart(self, argsList):
		'Called at the start of the game'
# ###############################################
#            Orion's Game Options Status
# ###############################################				
		iPlayerNum = 0
		iHumanCount = 0
		if (gc.getGame().getGameTurnYear() == gc.getDefineINT("START_YEAR") and not gc.getGame().isOption(GameOptionTypes.GAMEOPTION_ADVANCED_START)):
			for iPlayer in range(gc.getMAX_PLAYERS()):
				player = gc.getPlayer(iPlayer)
				if player.isAlive():
					iPlayerNum = iPlayerNum + 1
					if player.isHuman():
						iHumanCount = iHumanCount + 1
						if iHumanCount == 1:
							# Orion's Game Options Status Popup
							Inquisition.DisplayOCCStatus(iPlayer)
							# DawnOfMan Popup
							CyMessageControl().sendModNetMessage(252, iPlayer, -1, -1, -1)
							break
# End Orion's Game Options Status popup

		else:
			CyInterface().setSoundSelectionReady(true)

		if gc.getGame().isPbem():
			for iPlayer in range(gc.getMAX_PLAYERS()):
				player = gc.getPlayer(iPlayer)
				if (player.isAlive() and player.isHuman()):
					popupInfo = CyPopupInfo()
					popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_DETAILS)
					popupInfo.setOption1(true)
					popupInfo.addPopup(iPlayer)

		CvAdvisorUtils.resetNoLiberateCities()



Respectfully,

Orion Veteran :cool:
 
Did you add your event manager to CvCustomEventManager? You need to add two lines to it.

1. Import your module:

Code:
import InquisitionEvents

2. Create your event manager and hook it up to CvCEM. Look in the constructor for CvCEM (__init__ function) and at the bottom add

Code:
InquisitionEvents.InquisitionEvents(self)

There are probably one or more lines that look like this already there, otherwise it wouldn't be using CvCEM. This tells your event manager to add its events to CvCEM.

3. Now in InquisitionEvents.py, you must add a constructor to hook up those events:

Code:
class InquisitionEvents
	[B]def __init__(self, eventMgr):
		eventMgr.addEventHandler("ModNetMessage", self.onModNetMessage)
		eventMgr.addEventHandler("GameStart", self.onGameStart)[/B]

I don't have the code in front of me, so make sure you have the exact spelling including case for the event handler types and the correct function name to add an event handler to CvCEM. I believe it looked just like the one for CvEM.
 
3. Now in InquisitionEvents.py, you must add a constructor to hook up those events:
I don't have the code in front of me, so make sure you have the exact spelling including case for the event handler types and the correct function name to add an event handler to CvCEM. I believe it looked just like the one for CvEM.

I had steps 1 and 2 done previously in one scenario, just as you said. Apparently, it is step 3 that I can't get right. I've played with variations of this, as the game starts with out any errors, but the code in the two functions still won't execute.

Spoiler :

Code:
from CvPythonExtensions import *
import CvUtil
import PyHelpers
import Popup as PyPopup
import pickle
import Inquisition

# globals
gc = CyGlobalContext()
PyPlayer = PyHelpers.PyPlayer
PyInfo = PyHelpers.PyInfo
game = CyGame()
localText = CyTranslator()

class InquisitionEvents:

	def __init__(self, eventMgr):
	
		self.eventMgr = eventMgr
		
		eventMgr.addEventHandler("ModNetMessage", self.onModNetMessage)	
		eventMgr.addEventHandler("GameStart", self.onGameStart)


Respectfully,

Orion Veteran :cool:
 
You need to figure out if your __init__ function si being called or not. Add a CvUtil.PyPrint() call as the first line and check PythonDbg.log to see that it's printed. Next, double-check the event type names in CvEventManager. Finally, post the top part of CvCEM that shows you importing your module and calling the constructor (the two lines I posted). Maybe add some print statements there too.

Whenever I'm not sure if some code is being called, I add a print statement to it. If it doesn't show, it isn't being called.
 
You need to figure out if your __init__ function si being called or not. Add a CvUtil.PyPrint() call as the first line and check PythonDbg.log to see that it's printed. Next, double-check the event type names in CvEventManager. Finally, post the top part of CvCEM that shows you importing your module and calling the constructor (the two lines I posted). Maybe add some print statements there too.

Whenever I'm not sure if some code is being called, I add a print statement to it. If it doesn't show, it isn't being called.

You are right. The InquisitionEvents module is not loading, as it does not appear in the PythonDbg.log file. I did a search for CvCustomEventManager and it does not appear in the log file either.

Spoiler :

Code:
__version__ = "$Revision: 1.4 $"
# $Source: /usr/local/cvsroot/Civ4lerts/src/main/python/CvCustomEventManager.py,v $

import CvEventManager
import InquisitionEvents
# --------- Better BTS AI mod (1/2) -------------
#import AIAutoPlay
#import ChangePlayer
#import Tester

class CvCustomEventManager(CvEventManager.CvEventManager, object):

    """Extends the standard event manager by adding support for multiple
    handlers for each event.
    
    Methods exist for both adding and removing event handlers.  A set method 
    also exists to override the default handlers.  Clients should not depend 
    on event handlers being called in a particular order.
    
    This approach works best with mods that have implemented the design
    pattern suggested on Apolyton by dsplaisted.
    
    http://apolyton.net/forums/showthread.php?threadid=142916
    
    The example given in the 8th post in the thread would be handled by adding
    the following lines to the CvCustomEventManager constructor.  The RealFort,
    TechConquest, and CulturalDecay classes can remain unmodified.
    
        self.addEventHandler("unitMove", rf.onUnitMove)
        self.addEventHandler("improvementBuilt", rf.onImprovementBuilt)
        self.addEventHandler("techAcquired", rf.onTechAcquired)
        self.addEventHandler("cityAcquired", tc.onCityAcquired)
        self.addEventHandler("EndGameTurn", cd.onEndGameTurn)
        
    Note that the naming conventions for the event type strings vary from event
    to event.  Some use initial capitalization, some do not; some eliminate the
    "on..." prefix used in the event handler function name, some do not.  Look
    at the unmodified CvEventManager.py source code to determine the correct
    name for a particular event.
    
    Take care with event handlers that also extend CvEventManager.  Since
    this event manager handles invocation of the base class handler function,
    additional handlers should not also call the base class function themselves.

    """

    def __init__(self, *args, **kwargs):
        super(CvCustomEventManager, self).__init__(*args, **kwargs)
        # map the initial EventHandlerMap values into the new data structure
        for eventType, eventHandler in self.EventHandlerMap.iteritems():
            self.setEventHandler(eventType, eventHandler)
        # --> INSERT EVENT HANDLER INITIALIZATION HERE <--

        # --------- Better BTS AI (2/2) -------------
        InquisitionEvents.InquisitionEvents(self)
        #AIAutoPlay.AIAutoPlay(self)
        #ChangePlayer.ChangePlayer(self)
        #Tester.Tester(self)

 
Did you change EntryPoints/CvEvent(s)Interface.py to use CvCEM in place of CvEM?

I tried that a couple of times. When I did the CvCEM actually loads, but crashes (Syntax error) on line 74, which is our reference to this line:

Code:
InquisitionEvents.InquisitionEvents(self)

Orion Veteran :cool:
 
Hmm, I'd start with a new CvCEM and try again. The code you posted looks fine--I see no syntax error whatsoever. Are you sure it's that line? Maybe remove the commented-out AutoPlay lines for clarity. Double-check names, tho misspellings in names won't be a syntax error but an AttributeError or something else.
 
Hmm, I'd start with a new CvCEM and try again. The code you posted looks fine--I see no syntax error whatsoever. Are you sure it's that line? Maybe remove the commented-out AutoPlay lines for clarity. Double-check names, tho misspellings in names won't be a syntax error but an AttributeError or something else.

I'm absolutely sure the error refers to that line and it was definitely a syntax error.

More thoughts: I have no DLL in my mod. In this configuration, does the CvCEM require a DLL? I did pilfer this CvCEM from the Better BTS AI mod, which has a DLL.

Orion Veteran :cool:
 
Nope, it should not require a new DLL. You might want to grab a CvCEM from a different mod to be sure, but I'm pretty sure BAI uses the normal one. It should have no reason to use a modified version.

Are you sure that the syntax error wasn't in your module? If it was, you would see something like this:

Code:
CvCEM line 74 in __init__():
InquisitionEvents xx in yyyy:

SyntaxError: ...

That's why I'm asking for PythonErr.log. Without that, I can't be of any help to you. Always post PythonErr.log when you have an error.
 
Nope, it should not require a new DLL. You might want to grab a CvCEM from a different mod to be sure, but I'm pretty sure BAI uses the normal one. It should have no reason to use a modified version.

Are you sure that the syntax error wasn't in your module? If it was, you would see something like this:

Code:
CvCEM line 74 in __init__():
InquisitionEvents xx in yyyy:

SyntaxError: ...

That's why I'm asking for PythonErr.log. Without that, I can't be of any help to you. Always post PythonErr.log when you have an error.

Here is what the log file shows.

Spoiler :

Code:
Traceback (most recent call last):
ERR: Call function onEvent failed. Can't find module CvEventInterface
  File "<string>", line 1, in ?
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
  File "<string>", line 52, in load_module
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
  File "CvEventInterface", line 13, in ?
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
  File "<string>", line 35, in load_module
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
  File "<string>", line 13, in _get_code
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
  File "
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
CvCustomEventManager
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
", line 
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
74
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface

ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
    
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
InquisitionEvents.InquisitionEvents(self)
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
    
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
^
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
SyntaxError
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
: 
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
invalid syntax
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface

ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
Failed to load python module CvEventInterface.
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface
ERR: Call function onEvent failed. Can't find module CvEventInterface


Orion :cool:
 
It's hard to tell with the ERR: lines interleaved with the stack trace, but it looks like the line has inappropriate line endings. Did you copy and paste the line from what I posted? Again, I recommend retyping it from scratch.

If that doesn't work, attach the files in a ZIP instead of posting. That way I can see exactly what they contain.
 
It's hard to tell with the ERR: lines interleaved with the stack trace, but it looks like the line has inappropriate line endings. Did you copy and paste the line from what I posted? Again, I recommend retyping it from scratch.

If that doesn't work, attach the files in a ZIP instead of posting. That way I can see exactly what they contain.

I have more details on why the python crashed the CvCEM on the line:

Code:
InquisitionEvents.InquisitionEvents(self)

The error is: NameError, name 'self' is not defined

Is there a way to further define 'self' in this function?

Code:
class CvCustomEventManager(CvEventManager.CvEventManager):
	def __init__(self, *args, **kwargs):
		super(CvCustomEventManager, self).__init__(*args, **kwargs)
		# map the initial EventHandlerMap values into the new data structure
		for eventType, eventHandler in self.EventHandlerMap.iteritems():
			self.setEventHandler(eventType, eventHandler)
                # --> INSERT EVENT HANDLER INITIALIZATION HERE <--

                # --------- Better BTS AI (2/2) -------------
                InquisitionEvents.InquisitionEvents(self)


Orion Veteran :cool:
 
You can see that you are using self on the line immediately above:

Code:
self.setEventHandler(eventType, eventHandler)

I have no idea why it would suddenly stop working on the next line. It is declared to be the first parameter to the __init__() function. Are you sure about this?
 
You can see that you are using self on the line immediately above:

Code:
self.setEventHandler(eventType, eventHandler)

I have no idea why it would suddenly stop working on the next line. It is declared to be the first parameter to the __init__() function. Are you sure about this?

Yup. This error is coming up consistently now.

Here's the zip file:
 

Attachments

  • Python.zip
    54.7 KB · Views: 47
That line and the comment lines above it are using spaces instead of tabs to indent. Never mix tabs and spaces. Change them to use tabs using an editor that lets you see them or one which has a "tabify" command.
 
That line and the comment lines above it are using spaces instead of tabs to indent. Never mix tabs and spaces. Change them to use tabs using an editor that lets you see them or one which has a "tabify" command.

I noticed that also and physically changed them with Notepad++ to tabs and saved the file. Are you saying it reverted back to spaces?

I think you are right. It's time to create a new file.

Orion Veteran :cool:
 
Go to Settings : Preferences... and select the Edit Components tab. Make sure that Replace by space is not checked.
 
I have replace the CvCEM file, with a new one. I double checked to inusure every line has tabs now and not spaces. Grrrr.....

Now it dies on a line above:

Code:
super(CvCustomEventManager, self).__init__(*args, **kwargs)
[CODE]

Type Error
Super() argument 1 must be type, not classobj

After a whole day, this is really getting frustrating.  :crazyeye:


I fixed it!  I had to correct the following line:

class CvCustomEventManager(CvEventManager.CvEventManager, object):

it was missing the ,object at the end.

Finally!!!  Now I takes me into InquisitionEvents, which I can work on.

Thanks for being so patient and a big help.  :thanx:

Sincerely,

Orion :cool:
 
Top Bottom