Object Oriented / Class based scripting with Arcemu Python Engine (APE) #460
Replies: 5 comments 3 replies
-
Just pushed support for GameObjectScript. Here's an example: This is basically a rewrite of an earlier event based Python script example. import arcemu
from arcemu import GossipMenu
from arcemu import GameObjectScript
class ScourgeTransporterScript( GameObjectScript ):
def __init__( self, go ):
GameObjectScript.__init__( self, go )
def OnSpawn( self ):
go = self.gameobject
print( go.getName() + " (" + str( go.getId() ) + ")" + " spawning" )
def OnDespawn( self ):
go = self.gameobject
print( go.getName() + " (" + str( go.getId() ) + ")" + " despawning" )
def OnActivate( self, player ):
go = self.gameobject
print( go.getName() + " (" + str( go.getId() ) + ")" + " activated" )
menu = GossipMenu( 1, go, arcemu.GOSSIP_AUTOSEND_FALSE )
menu.addItem( arcemu.ICON_CHAT, "Teleport to Goldshire #1", 1, 0 )
menu.addItem( arcemu.ICON_VENDOR, "Teleport to Goldshire #2", 2, 0 )
menu.addItem( arcemu.ICON_DOT, "Teleport to Goldshire #3", 3, 0 )
menu.addItem( arcemu.ICON_CHAT, "Start updates", 4, 0 )
menu.addItem( arcemu.ICON_CHAT, "Stop updates", 5, 0 )
menu.addItem( arcemu.ICON_CHAT, "Modify update interval", 6, 0 )
menu.addItem( arcemu.ICON_CHAT, "Dump location and orientation to the console", 7, 0 )
menu.addItem( arcemu.ICON_CHAT, "Despawn", 8, 0 )
menu.sendToPlayer( player )
def AIUpdate( self ):
go = self.gameobject
print( "AI Update for " + str( go.getId() ) + " (" + go.getName() + ")" )
@staticmethod
def create( go ):
return ScourgeTransporterScript( go )
arcemu.RegisterGameObjectScript( 202243, ScourgeTransporterScript.create ) |
Beta Was this translation helpful? Give feedback.
-
I've just pushed Object Oriented Python gossip script support. Here are some examples: Creatureimport arcemu
from arcemu import GossipMenu
from arcemu import GossipScript
class BennyGossip( GossipScript ):
def __init__( self ):
GossipScript.__init__( self )
def OnHello( self, object, player ):
creature = arcemu.toCreature( object )
print( creature.getName() + " gossip OnHello" )
menu = GossipMenu( 1, object, arcemu.GOSSIP_AUTOSEND_FALSE )
menu.addItem( arcemu.ICON_CHAT, "First menu item", 1, 0 )
menu.addItem( arcemu.ICON_VENDOR, "Second menu item", 2, 0 )
menu.addItem( arcemu.ICON_DOT, "Third menu item", 3, 0 )
menu.sendToPlayer( player )
def OnSelectOption( self, object, player, id, enteredCode ):
GossipMenu.complete( player )
creature = arcemu.toCreature( object )
print( creature.getName() + " gossip OnSelectOption" )
player.sendChatMessage( arcemu.CHAT_MSG_SAY, arcemu.LANG_UNIVERSAL, "I have selected " + str( id ) )
arcemu.RegisterCreatureGossipScript( 19, BennyGossip() ) GameObjectHere OnSelectionOption is the only method used because the OnHello part is in the OnActivate method of the GameObject script (like you can see in the previous post import arcemu
from arcemu import GossipMenu
from arcemu import GossipScript
class ScourgeTransporterGossip( GossipScript ):
def __init__( self ):
GossipScript( self )
def OnSelectOption( self, object, player, id, enteredCode ):
GossipMenu.complete( player )
go = arcemu.toGameObject( object )
if id == 1:
player.teleport( 0, -9459.524414, 76.275986, 56.855736 )
elif id == 2:
player.teleport( 0, -9490.390625, 67.313934, 56.004055 )
elif id == 3:
player.teleport( 0, -9458.459961, 47.227226, 56.605110 )
elif id == 4:
go.RegisterAIUpdateEvent( 1000 )
elif id == 5:
go.RemoveAIUpdateEvent()
elif id == 6:
go.ModifyAIUpdateEvent( 500 )
elif id == 7:
coords = "(" + str( go.getPositionX() ) + "," + str( go.getPositionY() ) + "," + str( go.getPositionZ() ) + ")";
print( "GO coords: " + coords )
print( "GO orientation: " + str( go.getOrientation() ) )
elif id == 8:
go.despawn( 0, 0 )
arcemu.RegisterGameObjectGossipScript( 202243, ScourgeTransporterGossip() ) Itemimport arcemu
from arcemu import GossipMenu
from arcemu import GossipScript
class FlareGunGossip( GossipScript ):
def __init__( self ):
GossipScript.__init__( self )
def OnHello( self, object, player ):
item = arcemu.toItem( object )
menu = GossipMenu( 1, object, arcemu.GOSSIP_AUTOSEND_FALSE )
menu.addItem( arcemu.ICON_CHAT, "First menu item", 1, 0 )
menu.addItem( arcemu.ICON_VENDOR, "Second menu item", 2, 0 )
menu.addItem( arcemu.ICON_DOT, "Third menu item", 3, 0 )
menu.sendToPlayer( player )
def OnSelectOption( self, object, player, id, enteredCode ):
player.sendChatMessage( arcemu.CHAT_MSG_SAY, arcemu.LANG_UNIVERSAL, "I have selected " + str( id ) )
GossipMenu.complete( player )
arcemu.RegisterItemGossipScript( 10444, FlareGunGossip() ) |
Beta Was this translation helpful? Give feedback.
-
Just pushed support for object oriented Python quest scripts. Example: import arcemu
from arcemu import QuestScript
class GoldDustExchange( QuestScript ):
def __init__( self ):
QuestScript.__init__( self )
def OnQuestStart( self, player, quest ):
print( "Started" )
player.sendChatMessage( arcemu.CHAT_MSG_SAY, arcemu.LANG_UNIVERSAL, "Started quest " + str( quest ) )
def OnQuestComplete( self, player, quest ):
print( "Completed" )
player.sendChatMessage( arcemu.CHAT_MSG_SAY, arcemu.LANG_UNIVERSAL, "Completed quest " + str( quest ) )
def OnQuestCancel( self, player ):
print( "Cancelled" )
player.sendChatMessage( arcemu.CHAT_MSG_SAY, arcemu.LANG_UNIVERSAL, "Cancelled quest" )
def OnPlayerItemPickup( self, item, total, player, quest ):
print( "Picked up item " + str( item ) + " total count is " + str( total ) )
player.sendChatMessage( arcemu.CHAT_MSG_SAY, arcemu.LANG_UNIVERSAL, "Picked up item " + str( item ) + " total count is " + str( total ) )
arcemu.RegisterQuestScript( 47, GoldDustExchange() ) |
Beta Was this translation helpful? Give feedback.
-
Just pushed support for object oriented Python Instance scripts. Example: import arcemu
from arcemu import InstanceScript
class TestInstanceScript( InstanceScript ):
def __init__( self ):
InstanceScript.__init__( self )
def Onload( self ):
print( "Instance loading..." )
def OnDestroy( self ):
print( "Instance being destroyed..." )
def OnPlayerDeath( self, player, killer ):
print( "Instance: " + killer.getName() + " has slain " + victim.getName() )
def OnPlayerEnter( self, player ):
print( "Instance: Player " + player.getName() + " has entered " )
def OnCreatureDeath( self, victim, killer ):
print( "Instance: Creature " + victim.getName() + " killed by " + killer.getName() )
def OnGameObjectActivate( self, go, player ):
print( "Instance: GO " + go.getName() + "(" + str( go.getId() ) + ") activated by " + player.getName() )
@staticmethod
def create():
return TestInstanceScript()
arcemu.RegisterInstanceScript( 34, TestInstanceScript.create ) |
Beta Was this translation helpful? Give feedback.
-
Dear all!
Some minutes ago I pushed Object Oriented / Class based CreatureScript support for Arcemu Python Engine (APE).
This means that if one wishes one can use the CreatureScript Python class and it's methods to script the behavior of creatures instead of the event based scripting.
It is important that the event based scripting will remain in the engine, so that is not at all affected by this new feauture.
10+ years ago when I first had the idea of using Python for scripting engine, the motivation behind the idea was the fact that Python is an OO language, so we can use classes for everything and make python scripts similar to Arcemu's "C++ scripts".
This makes it easier to switch between the two, as one doesn't have to learn two ways of thinking.
In the future I will be implementing more of these classes (gameobject, item, gossip, etc).
I'm going to show an example here and then explain.
First the full script:
Reading the code makes it immediately clear how it differs from the event based Lua and Python scripts:
Instead of writing functions and registering them for entity events, we write a script class and register a factory method that will instantiate the script for the creature we registered it for.
Let's break it down:
These lines just import the arcemu Python module, and the CreatureScript class, so that they are usable for the Python interpreter.
Here we inherit from / subclass the CreatureScript class.
The RabbitCreatureScript class thus will have all the methods (event handler methods like OnLoad, OnDied, etc), and members (a reference to the creature) of CreatureScript.
All methods are empty in CreatureScript so if they are not overriden in the subclass nothing happens when they are called.
This is like the constructor method in C++, basically initializes the class instance when it is instantiated. Passes in the unit parameter (which is a reference to the creature which is controlled by the script) for example.
These are the event handler methods. They contain the code that is executed when those events happen.
They override the empty methods in the CreatureScript baseclass.
As this is just an example script, not all methods are used.
This is the static factory method.
It is essential as this is the method that is called by Arcemu when the script is created for the creature.
...and finally this is how the script class is registered for the creature.
The RegisterCreatureScript function takes the creature Id, and a static factory method as parameter:
I hope this is understandable, but if not feel free to ask!
Beta Was this translation helpful? Give feedback.
All reactions