evennia/game/gamesrc/parents/examples/red_button.py
Griatch c7cbc4854e Reworked object command tables.
Object commands used to require re-adding every call in the script parent's __init__ or factory functions, adding the commands to a new command table directly on the object. Since all other attributes can be set up in at_object_creation(), this was both inconsistent and a bit confusing to work with. There is now a method add_commands() directly defined on all objects. It takes the same arguments as the normal add_command()o but use a reserved attribute to create and update a command table on the object. This has the advantange of completely removing the __init__ call in the script parent, all definitions can now be kept in at_object_creation() and are, more importantly, persistent without having to be recreated every call.
- I updated the examine command to show all the commands defined on an object (if any).
- I updated gamesrc/parents/examples/red_button.py considerably using the new command methodology and also using the updated Events.
.
Griatch
2009-12-03 00:41:53 +00:00

220 lines
7.4 KiB
Python

"""
An example script parent for a nice red button object. It has
custom commands defined on itself that are only useful in relation to this
particular object. See example.py in gamesrc/commands for more info
on the pluggable command system.
Assuming this script remains in gamesrc/parents/examples, create an object
of this type using @create button:examples.red_button
This file also shows the use of the Event system to make the button
send a message to the players at regular intervals. To show the use of
Events, we are tying two types of events to the red button, one which cause ALL
red buttons in the game to blink in sync (gamesrc/events/example.py) and one
event which cause the protective glass lid over the button to close
again some time after it was opened.
Note that if you create a test button you must drop it before you can
see its messages!
"""
import traceback
from game.gamesrc.parents.base.basicobject import BasicObject
from src.objects.models import Object
from src.events import IntervalEvent
from src import scheduler
from src import logger
#
# Events
#
# Importing this will start the blink event ticking, only one
# blink event is used for all red buttons.
import game.gamesrc.events.example
# We also create an object-specific event.
class EventCloselid(IntervalEvent):
"""
This event closes the glass lid over the button
some time after it was opened.
"""
def __init__(self, obj):
"""
Note how we take an object as an argument,
this will allow instances of this event to
operate on this object only.
"""
# we must call super to make sure things work!
super(EventCloselid, self).__init__()
# store the object reference
self.obj_dbref = obj.dbref()
# This is used in e.g. @ps to show what the event does
self.description = "Close lid on %s" % obj
# We make sure that this event survives a reboot
self.persistent = True
# How many seconds from event creation to closing
# the lid
self.interval = 20
# We only run the event one time before it deletes itself.
self.repeats = 1
def event_function(self):
"""
This function is called every self.interval seconds.
Note that we must make sure to handle all errors from
this call to avoid trouble.
"""
try:
# if the lid is open, close it. We have to find the object
# again since it might have changed.
obj = Object.objects.get_object_from_dbref(self.obj_dbref)
if obj.has_flag("LID_OPEN"):
obj.scriptlink.close_lid()
retval = "The glass cover over the button silently closes by itself."
obj.get_location().emit_to_contents(retval)
except:
# send the traceback to the log instead of letting it by.
# It is important that we handle exceptions gracefully here!
logger.log_errmsg(traceback.print_exc())
#
# Object commands
#
# Commands for using the button object. These are added to
# the object in the class_factory function at the
# bottom of this module.
#
def cmd_open_lid(command):
"""
Open the glass lid cover over the button.
"""
# In the case of object commands, you can use this to
# get the object the command is defined on.
obj = command.scripted_obj
if obj.has_flag("LID_OPEN"):
retval = "The lid is already open."
else:
retval = "You lift the lid, exposing the tempting button."
obj.scriptlink.open_lid()
command.source_object.emit_to(retval)
def cmd_close_lid(command):
"""
Close the lid again.
"""
obj = command.scripted_obj
if not obj.has_flag("LID_OPEN"):
retval = "The lid is already open."
else:
retval = "You secure the glass cover over the button."
obj.scriptlink.close_lid()
command.source_object.emit_to(retval)
def cmd_push_button(command):
"""
This is a simple command that handles a user pressing the
button by returning a message. The button can only be
"""
obj = command.scripted_obj
if obj.has_flag("LID_OPEN"):
retval = "You press the button ..."
retval += "\n ..."
retval += "\n BOOOOOM!"
obj.scriptlink.close_lid()
else:
retval = "There is a glass lid covering "
retval += "the button as a safety measure. If you "
retval += "want to press the button you need to open "
retval += "the lid first."
command.source_object.emit_to(retval)
#
# Definition of the object itself
#
class RedButton(BasicObject):
"""
This class describes an evil red button.
It will use the event definition in
game/gamesrc/events/example.py to blink
at regular intervals until the lightbulb
breaks. It also use the EventCloselid event defined
above to close the lid
"""
def at_object_creation(self):
"""
This function is called when object is created. Use this
preferably over __init__.
"""
#get stored object related to this class
obj = self.scripted_obj
obj.set_attribute('desc', "This is a big red button. It has a glass cover.")
obj.set_attribute("breakpoint", 5)
obj.set_attribute("count", 0)
# add the object-based commands to the button
obj.add_command("open lid", cmd_open_lid)
obj.add_command("lift lid", cmd_open_lid)
obj.add_command("close lid", cmd_close_lid)
obj.add_command("push button", cmd_push_button)
obj.add_command("push the button", cmd_push_button)
def open_lid(self):
"""
Open the glass lid and start the timer so it will
soon close again.
"""
self.scripted_obj.set_flag("LID_OPEN")
scheduler.add_event(EventCloselid(self.scripted_obj))
def close_lid(self):
"""
Close the glass lid
"""
self.scripted_obj.unset_flag("LID_OPEN")
def blink(self):
"""
If the event system is active, it will regularly call this
function to make the button blink. Note the use of attributes
to store the variable count and breakpoint in a persistent
way.
"""
obj = self.scripted_obj
try:
count = int(obj.get_attribute_value("count"))
breakpoint = int(obj.get_attribute_value("breakpoint"))
except TypeError:
return
if count <= breakpoint:
if int(count) == int(breakpoint):
string = "The button flashes, then goes dark. "
string += "Looks like the lamp just broke."
else:
string = "The red button flashes, demanding your attention."
count += 1
obj.set_attribute("count", count)
obj.get_location().emit_to_contents(string)
def class_factory(source_obj):
"""
This method is called by any script you retrieve (via the scripthandler). It
creates an instance of the class and returns it transparently.
source_obj: (Object) A reference to the object being scripted (the child).
This is a good place for adding new commands to the button since this is
where it is actually instantiated.
"""
return RedButton(source_obj)