<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://bf2tech.uturista.pt/index.php?action=history&amp;feed=atom&amp;title=Cookbook%3ADynamically_Changing_an_Event_Handler</id>
	<title>Cookbook:Dynamically Changing an Event Handler - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://bf2tech.uturista.pt/index.php?action=history&amp;feed=atom&amp;title=Cookbook%3ADynamically_Changing_an_Event_Handler"/>
	<link rel="alternate" type="text/html" href="https://bf2tech.uturista.pt/index.php?title=Cookbook:Dynamically_Changing_an_Event_Handler&amp;action=history"/>
	<updated>2026-08-06T00:30:45Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.40.1</generator>
	<entry>
		<id>https://bf2tech.uturista.pt/index.php?title=Cookbook:Dynamically_Changing_an_Event_Handler&amp;diff=91&amp;oldid=prev</id>
		<title>Pireax: Created page with &quot;==  Problem  ==  The standard Python code that comes with BF2 includes an event handler that you want to change. You know it&#039;s a Bad Idea™ to screw around with the original...&quot;</title>
		<link rel="alternate" type="text/html" href="https://bf2tech.uturista.pt/index.php?title=Cookbook:Dynamically_Changing_an_Event_Handler&amp;diff=91&amp;oldid=prev"/>
		<updated>2018-06-21T19:29:27Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;==  Problem  ==  The standard Python code that comes with BF2 includes an event handler that you want to change. You know it&amp;#039;s a Bad Idea™ to screw around with the original...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==  Problem  ==&lt;br /&gt;
&lt;br /&gt;
The standard Python code that comes with BF2 includes an event handler that you want to change. You know it&amp;#039;s a Bad Idea™ to screw around with the original source code, so how can you do it?&lt;br /&gt;
&lt;br /&gt;
==  Solution  ==&lt;br /&gt;
&lt;br /&gt;
The solution is to put a &amp;quot;wrapper&amp;quot; around the original event handler, and use some of Python&amp;#039;s more esoteric features to substitute your wrapper function for the original handler.&lt;br /&gt;
&lt;br /&gt;
As an example, let&amp;#039;s take [[Quick_Tips#Prevent_Commander_and_Squad_Leaders_from_being_autobalanced|this]] fix by Metac0m: the default autobalance algorithm used by BF2 will sometimes annoyingly autobalance the commander and squad leaders to the opposite team. The autobalance mechanism is implemented by a handler for the [[Event_Reference#Player_Events|&amp;lt;code&amp;gt;PlayerDeath&amp;lt;/code&amp;gt;]] event in the &amp;lt;code&amp;gt;standard_admin.autobalance&amp;lt;/code&amp;gt; module. Metac0m&amp;#039;s solution: add a couple of lines to the handler, so that when it runs it checks to see if the player who just died was a commander or squad leader, and if they were, it does nothing; otherwise, the handler continues to execute normally. This simple approach works great, but requires modifying the standard BF2 Python code--which can create a mess when, for example, it&amp;#039;s time to upgrade to a new version of BF2.&lt;br /&gt;
&lt;br /&gt;
Instead, here&amp;#039;s a different approach that doesn&amp;#039;t require &amp;#039;&amp;#039;&amp;#039;any&amp;#039;&amp;#039;&amp;#039; modification to the &amp;lt;code&amp;gt;standard_admin.autobalance&amp;lt;/code&amp;gt; module:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import new&lt;br /&gt;
 import standard_admin.autobalance&lt;br /&gt;
 &lt;br /&gt;
 # Define wrapper function that implements our new functionality&lt;br /&gt;
 def newOnPlayerDeath(playerObject, vehicleObject):&lt;br /&gt;
     # If the player is a commander or squad leader, we&amp;#039;re done&lt;br /&gt;
     if playerObject.isCommander(): return None&lt;br /&gt;
     if playerObject.isSquadLeader(): return None&lt;br /&gt;
    &lt;br /&gt;
     # If player is NOT a commander or squad leader, we pass the call on to&lt;br /&gt;
     # the original function&lt;br /&gt;
     onPlayerDeath.origFunc(playerObject, vehicleObject)&lt;br /&gt;
 &lt;br /&gt;
 # Create a new function from the original function&amp;#039;s code object and it&amp;#039;s&lt;br /&gt;
 # namespace, and save it as an attribute of the original function; this&lt;br /&gt;
 # is just so we can access the original function later.&lt;br /&gt;
 wrappedFunc = new.function(standard_admin.autobalance.onPlayerDeath.func_code,&lt;br /&gt;
                            standard_admin.autobalance.onPlayerDeath.func_globals)&lt;br /&gt;
 standard_admin.autobalance.onPlayerDeath.origFunc = wrappedFunc&lt;br /&gt;
 &lt;br /&gt;
 # Replace the code object of the original function with the code object&lt;br /&gt;
 # of our wrapper; this leaves the original function object intact, but with&lt;br /&gt;
 # a different code object.&lt;br /&gt;
 standard_admin.autobalance.onPlayerDeath.func_code = newOnPlayerDeath.func_code&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this code is executed, it dynamically replaces the original &amp;lt;code&amp;gt;PlayerDeath&amp;lt;/code&amp;gt; event handler in &amp;lt;code&amp;gt;standard_admin.autobalance&amp;lt;/code&amp;gt; with a new handler; the the new handler does Metac0m&amp;#039;s checks as to whether the player who died is a commander or squad leader, and if not, it executes the original handler function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  Discussion  ==&lt;br /&gt;
&lt;br /&gt;
There is some serious Python voodoo in this example. Normally, there are better ways of substituting wrapper functions or methods for an original, but they won&amp;#039;t work here because in this case, the original function has &amp;#039;&amp;#039;already&amp;#039;&amp;#039; been registered as an event handler. This means that the BF2 event system already has a reference to the function it&amp;#039;s going to call when the event occurs--so we have to make our changes to the existing handler function object, not just create a new one.&lt;br /&gt;
&lt;br /&gt;
This recipie takes advantage of the fact that a Python function object carries around with it a &amp;lt;code&amp;gt;func_code&amp;lt;/code&amp;gt; attribute that contains a &amp;quot;code object&amp;quot;--the compiled &amp;quot;byte code&amp;quot; that executes the logic of the function. Since the event system is locked in on the original function object, what we do is replace it&amp;#039;s code object with our own &amp;quot;wrapper&amp;quot; code object, leaving everything else about the original function object alone. We then turn the original code object into a new function object, and call that new function from our wrapper.&lt;br /&gt;
&lt;br /&gt;
Confused yet?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  Submitted By  ==&lt;br /&gt;
&lt;br /&gt;
--[http://web.archive.org/web/20080731035930/http://bf2.fun-o-matic.org/index.php/User:Woody Woody]&lt;/div&gt;</summary>
		<author><name>Pireax</name></author>
	</entry>
</feed>