[PYTHONCOMP] Civ4lerts: Alert messages about in game events

Thanks for the quick reply, there Dr.

I wonder if it might be smartest for me to learn how to fold mine into yours, so that I'll be better prepared to handle future elegant mods as well as those that I've already learned how to fuse together.

If the technique is "simple" enough to learn, maybe I should think of using the elegant approach to recompile my mod at the time the next patch comes out. I've been sweating it out, wondering just how hard it will be to rebuild my mod for the next patch. It seems the elegant approach in your mod is the way to go to modularize all my forked mods when I port over to the forthcoming new patch.

Anyway, you responded so quickly I wanted to let you know, in a timely way, that I'll appreciate the help you're able to provide.

Thanks!
Spocko
 
As you mentioned, there are two approaches you can take:

  • use my custom event handler and merge your handlers ito it
  • use your custom event handler and merge my alerts into it

I'll start with the first option, because as you'll eventually read, it's much easier. The main thing you need to do is register your event manager's handler functions with my event manager. You would do this with calls like in the the example below. Note that although I think these code snippets are correct, I haven't actually run it and tested them, so there may be minor errors and typos.

Code:
    def __init__(self, eventManager):
        # initialize base class
	self.parent = CvEventManager.CvEventManager
	self.parent.__init__(self)
	eventManager.addEventHandler("unitMove", self.onUnitMove)
	eventManager.addEventHandler("unitCreated", self.onUnitCreated)
	eventManager.addEventHandler("unitKilled", self.onUnitKilled)
	# ... repeat for all event handlers ...
	eventManager.addEventHandler("religionSpread", self.onReligionSpread)

The string names of the event handlers can be found in the original CvEventManager class where EventHandlerMap is initialized (around line 73-ish). As you can see from the above examples, most of the time the pattern is to remove "on" from the handler function, but that isn't always true, so make sure you check the names. It's particularly inconsistent when you're dealing with the onGame* and Save/Load types of events.

Then call your event manager's constructor from my CvCustomEventManager __init__ function. Let's assume for the sake of discussion that you rename your class to CvSpockoEventManager.

Code:
        CvSpockoEventManager.CvSpockoEventManager(self)

The only obvious problem I see with this approach, based on a quick scan of your code, is the self.Events[7501] thing you're doing to install the popup handler. The easiest solution would probably be to just stick that line right in my __init__ function. So to sum up, you would wind up with a CvCustomEventManager constructor that looks something like this.

Code:
    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 <--
        Civ4lerts.Civ4lerts(self)
        CvSpockoEventManager.CvSpockoEventManager(self)
	self.Events[7501] = ('FreeTechPopup', self.__eventFreeTechApply , self.__eventFreeTechBegin)

I think that's it. Done. It should work.

Alternatively, if you wanted to keep your event manager and call out to my handler functions, you could do that as well. I think that will require more code and/or will be more complicated, but I'm obviously biased. The main reason for the difficulty is that the deep class hierarchy of my alerts, while it makes it easy to add new alerts with a minimal amount of new code, it also makes it somewhat harder to quickly see what event handler functions are used by each alert. It also means that there are quite a few places where you would need to make changes to my code to let them interact with a different event manager.

For example, let's take the CityPendingGrowth alert to start with. That class implements an onCityPendingGrowth function, but that's not a "real" event handler. It's faked by the base class. If you look at the base class, you'll see that it implements an onCityDoTurn function. We'll need to plug that into your event manager. You would need to implement something like this.

Code:
    def onCityDoTurn(self, argsList):
        cityPendingGrowth.onCityDoTurn(argsList)

And at the beginning of your module in the same place where you initialize FreeTech and TechWindow, also create a CityPendingGrowth object.

Code:
cityPendingGrowth = Civ4lerts.CityPendingGrowth()

But notice that the CityPendingGrowth constructor expects a single argument -- the event manager. It will use that argument to register its event handlers. So that code needs to be removed in order to let it work with a more conventional event manager. You need to remove the eventManager argument from the AbstractAlert, AbstractCityPendingGrowth, and CityPendingGrowth classes. You also need to remove the addEventHandler call from the AbstractCityPendingGrowth class. You would wind up with an AbstractCityPendingGrowth constructor like this.

Code:
    def __init__(self, *args, **kwargs): 
        super(AbstractCityPendingGrowth, self).__init__(*args, **kwargs)

I'm not going to continue this further, because I think I've made my case. Good, bad, for better or for worse, it's just not that easy to make my alerts work with a conventional event manager. I'd recommend the first approach if you want to merge the two.

Basically my event manager is fairly compatible with an old style event manager, but the old style event managers aren't very compatible with my event handlers.
 
It is compatible with 1.61?

THX!
 
THX for your quick reply! Perhaps you should put a notice in the first post... THX again! :goodjob:
 
DaviddesJ said:
Why not "Civilization has new technology available for trade"? Is that more difficult to implement?

Yeah, it is, because you need to worry about "visibility." You only want to mention technologies where you have the prerequisites.

The functions to do that are all there, somewhere, in the Python API's, but I haven't spent the time to figure it all out. To be honest, I haven't really been playing Civ4 much lately, so I haven't been very motivated to do the unimplemented alerts. I'm in the middle of a game right now though, and I have to admit that not having a technology alert is driving me nuts. ;-)
 
Dr Elmer Jiggle said:
Yeah, it is, because you need to worry about "visibility." You only want to mention technologies where you have the prerequisites

The functions to do that are all there, somewhere, in the Python API's, but I haven't spent the time to figure it all out. To be honest, I haven't really been playing Civ4 much lately, so I haven't been very motivated to do the unimplemented alerts..;-)
I got most of the visibility logic from the Exotic Foreign Advisor. ;) The other part that was tough was to only alert about "new" techs.

Dr Elmer Jiggle said:
I'm in the middle of a game right now though, and I have to admit that not having a technology alert is driving me nuts. ;-)
Take a look at MoreCiv4lerts.py
 
Now that your event manager has pop-up capability, are there any plans to incorporate them into Civ4lerts? Or is it something that's as simple as pasting variations of a few lines of code into the appropriate locations?

Thanks in advance.
 
What sort of popup dialogs would you want? Something like "You're city has just grown. [Go to the city screen] [Carry on]"? For the most part I've avoided that, because I find most of the built-in dialogs annoying ("You just built your first archer! Congratulations!" Yeah, yeah, stop nagging me.), but if people want that I don't think it would be hard to do.

FYI, the popup handling was always there. It's build into the standard event manager that comes with the game. All I really added was a function that makes it more obvious how to tap into that capability.
 
Dr Elmer Jiggle said:
What sort of popup dialogs would you want? Something like "You're city has just grown. [Go to the city screen] [Carry on]"? For the most part I've avoided that, because I find most of the built-in dialogs annoying ("You just built your first archer! Congratulations!" Yeah, yeah, stop nagging me.), but if people want that I don't think it would be hard to do.

FYI, the popup handling was always there. It's build into the standard event manager that comes with the game. All I really added was a function that makes it more obvious how to tap into that capability.

Popups for the city messages would be very nice. As long as the user has the option to turn them on and off.
 
Dr Elmer Jiggle said:
What sort of popup dialogs would you want? Something like "You're city has just grown. [Go to the city screen] [Carry on]"? For the most part I've avoided that, because I find most of the built-in dialogs annoying ("You just built your first archer! Congratulations!" Yeah, yeah, stop nagging me.), but if people want that I don't think it would be hard to do.

FYI, the popup handling was always there. It's build into the standard event manager that comes with the game. All I really added was a function that makes it more obvious how to tap into that capability.

What I want it for is to be able to go straight to a city with pending unhappiness or unhealthiness problems, and address the issue immediately, as opposed to forgetting to do so after handling all the other issues that need attention (and it doesn't help when you have a mild case of ADD, either, heh).

At any rate, I should've figured there wasn't an easy answer like, "oh, you just slap a statement, like this generic one here, right into such-and-such a spot." It's about time I ventured from cut-n-paste work to actually enabling myself in Python, though; I knew I'd have to get around to it eventually, and it'll help prepare for cut-n-paste work with the SDK.
 
A Silly Goose said:
What I want it for is to be able to go straight to a city with pending unhappiness or unhealthiness problems, and address the issue immediately, as opposed to forgetting to do so after handling all the other issues that need attention (and it doesn't help when you have a mild case of ADD, either, heh).
Take a look at the Domestic Advisor (F1). You can see the state of those things an click on the icon to left of the city name to just to it. You can work your way through any cities with issues that way. The alerts save you from having to do that every turn.
 
All,

I have this mod installed on my machine and it works fine in single player but when I play multi player it doesn't work.

How do I get it to work with multi player?

Thx
jonpfl
 
Back
Top Bottom