2010-08-29 18:46:58 +00:00
|
|
|
"""
|
|
|
|
|
This is the basis of the typeclass system.
|
|
|
|
|
|
|
|
|
|
The idea is have the object as a normal class with the
|
|
|
|
|
database-connection tied to itself through a property.
|
|
|
|
|
|
|
|
|
|
The instances of all the different object types are all tied to their
|
|
|
|
|
own database object stored in the 'dbobj' property. All attribute
|
|
|
|
|
get/set operations are channeled transparently to the database object
|
|
|
|
|
as desired. You should normally never have to worry about the database
|
|
|
|
|
abstraction, just do everything on the TypeClass object.
|
|
|
|
|
|
|
|
|
|
That an object is controlled by a player/user is just defined by its
|
|
|
|
|
'user' property being set. This means a user may switch which object
|
|
|
|
|
they control by simply linking to a new object's user property.
|
|
|
|
|
"""
|
2010-09-04 09:47:38 +00:00
|
|
|
|
2010-08-29 18:46:58 +00:00
|
|
|
from src.typeclasses.typeclass import TypeClass
|
2011-04-30 21:09:19 +00:00
|
|
|
from src.commands import cmdset, command
|
2010-08-29 18:46:58 +00:00
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# Base class to inherit from.
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
class Object(TypeClass):
|
|
|
|
|
"""
|
|
|
|
|
This is the base class for all in-game objects.
|
|
|
|
|
Inherit from this to create different types of
|
|
|
|
|
objects in the game.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def __eq__(self, other):
|
|
|
|
|
"""
|
|
|
|
|
This has be located at this level, having it in the
|
|
|
|
|
parent doesn't work.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
result = other and other.id == self.id
|
|
|
|
|
try:
|
|
|
|
|
uresult = other and (other.user.id == self.user.id)
|
|
|
|
|
except AttributeError:
|
|
|
|
|
uresult = False
|
|
|
|
|
return result or uresult
|
|
|
|
|
|
|
|
|
|
# hooks called by the game engine
|
|
|
|
|
|
2011-03-17 21:43:18 +00:00
|
|
|
def basetype_setup(self):
|
|
|
|
|
"""
|
|
|
|
|
This sets up the default properties of an Object,
|
|
|
|
|
just before the more general at_object_creation.
|
2011-04-23 11:54:08 +00:00
|
|
|
|
|
|
|
|
Don't change this, instead edit at_object_creation() to
|
|
|
|
|
overload the defaults (it is called after this one).
|
2010-08-29 18:46:58 +00:00
|
|
|
"""
|
2011-03-15 16:08:32 +00:00
|
|
|
# the default security setup fallback for a generic
|
|
|
|
|
# object. Overload in child for a custom setup. Also creation
|
2011-03-17 21:43:18 +00:00
|
|
|
# commands may set this (create an item and you should be its
|
|
|
|
|
# controller, for example)
|
|
|
|
|
|
2011-03-15 16:08:32 +00:00
|
|
|
dbref = self.dbobj.dbref
|
2011-03-17 21:43:18 +00:00
|
|
|
|
2011-03-20 19:45:56 +00:00
|
|
|
self.locks.add("control:id(%s) or perm(Immortals)" % dbref) # edit locks/permissions, delete
|
|
|
|
|
self.locks.add("examine:perm(Builders)") # examine properties
|
2011-04-24 11:26:51 +00:00
|
|
|
self.locks.add("view:all()") # look at object (visibility)
|
2011-03-20 19:45:56 +00:00
|
|
|
self.locks.add("edit:perm(Wizards)") # edit properties/attributes
|
|
|
|
|
self.locks.add("delete:perm(Wizards)") # delete object
|
|
|
|
|
self.locks.add("get:all()") # pick up object
|
|
|
|
|
self.locks.add("call:true()") # allow to call commands on this object
|
2011-04-23 11:54:08 +00:00
|
|
|
self.locks.add("puppet:id(%s) or perm(Immortals) or pperm(Immortals)" % dbref) # restricts puppeting of this object
|
2011-03-17 21:43:18 +00:00
|
|
|
|
|
|
|
|
def at_object_creation(self):
|
|
|
|
|
"""
|
|
|
|
|
Called once, when this object is first
|
|
|
|
|
created.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
2010-08-29 18:46:58 +00:00
|
|
|
|
2011-09-03 10:22:19 +00:00
|
|
|
def at_init(self):
|
2011-10-01 22:00:22 +02:00
|
|
|
"""
|
2011-10-01 22:36:55 +02:00
|
|
|
This is always called whenever this object is initiated --
|
|
|
|
|
that is, whenever it its typeclass is cached from memory. This
|
|
|
|
|
happens on-demand first time the object is used or activated
|
|
|
|
|
in some way after being created but also after each server
|
|
|
|
|
restart or reload.
|
2011-09-03 10:22:19 +00:00
|
|
|
"""
|
2011-10-01 22:00:22 +02:00
|
|
|
pass
|
2011-09-03 10:22:19 +00:00
|
|
|
|
2011-08-11 21:16:35 +00:00
|
|
|
def basetype_posthook_setup(self):
|
|
|
|
|
"""
|
|
|
|
|
Called once, after basetype_setup and at_object_creation. This should generally not be overloaded unless
|
|
|
|
|
you are redefining how a room/exit/object works. It allows for basetype-like setup
|
|
|
|
|
after the object is created. An example of this is EXITs, who need to know keys, aliases, locks
|
|
|
|
|
etc to set up their exit-cmdsets.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
|
2011-09-03 10:22:19 +00:00
|
|
|
def at_server_reload(self):
|
|
|
|
|
"""
|
|
|
|
|
This hook is called whenever the server is shutting down for restart/reboot.
|
|
|
|
|
If you want to, for example, save non-persistent properties across a restart,
|
|
|
|
|
this is the place to do it.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def at_server_shutdown(self):
|
|
|
|
|
"""
|
|
|
|
|
This hook is called whenever the server is shutting down fully (i.e. not for
|
|
|
|
|
a restart).
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
|
2011-08-11 21:16:35 +00:00
|
|
|
def at_cmdset_get(self):
|
|
|
|
|
"""
|
|
|
|
|
Called just before cmdsets on this object are requested by the
|
|
|
|
|
command handler. If changes need to be done on the fly to the cmdset
|
|
|
|
|
before passing them on to the cmdhandler, this is the place to do it.
|
|
|
|
|
This is called also if the object currently have no cmdsets.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
|
2010-08-29 18:46:58 +00:00
|
|
|
def at_first_login(self):
|
|
|
|
|
"""
|
|
|
|
|
Only called once, the very first
|
|
|
|
|
time the user logs in.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
def at_pre_login(self):
|
|
|
|
|
"""
|
|
|
|
|
Called every time the user logs in,
|
|
|
|
|
before they are actually logged in.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
def at_post_login(self):
|
|
|
|
|
"""
|
|
|
|
|
Called at the end of the login
|
|
|
|
|
process, just before letting
|
|
|
|
|
them loose.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def at_disconnect(self):
|
|
|
|
|
"""
|
|
|
|
|
Called just before user
|
|
|
|
|
is disconnected.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
# hooks called when moving the object
|
|
|
|
|
|
|
|
|
|
def at_before_move(self, destination):
|
|
|
|
|
"""
|
|
|
|
|
Called just before starting to move
|
|
|
|
|
this object to destination.
|
|
|
|
|
|
|
|
|
|
destination - the object we are moving to
|
|
|
|
|
|
|
|
|
|
If this method returns False/None, the move
|
|
|
|
|
is cancelled before it is even started.
|
|
|
|
|
"""
|
|
|
|
|
#return has_perm(self, destination, "can_move")
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def announce_move_from(self, destination):
|
|
|
|
|
"""
|
|
|
|
|
Called if the move is to be announced. This is
|
|
|
|
|
called while we are still standing in the old
|
|
|
|
|
location.
|
|
|
|
|
|
|
|
|
|
destination - the place we are going to.
|
|
|
|
|
"""
|
|
|
|
|
if not self.location:
|
|
|
|
|
return
|
|
|
|
|
name = self.name
|
|
|
|
|
loc_name = ""
|
|
|
|
|
loc_name = self.location.name
|
|
|
|
|
dest_name = destination.name
|
|
|
|
|
string = "%s is leaving %s, heading for %s."
|
2011-04-08 23:10:04 +00:00
|
|
|
self.location.msg_contents(string % (name, loc_name, dest_name), exclude=self)
|
2010-08-29 18:46:58 +00:00
|
|
|
|
|
|
|
|
def announce_move_to(self, source_location):
|
|
|
|
|
"""
|
|
|
|
|
Called after the move if the move was not quiet. At this
|
|
|
|
|
point we are standing in the new location.
|
|
|
|
|
|
|
|
|
|
source_location - the place we came from
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
name = self.name
|
|
|
|
|
if not source_location and self.location.has_player:
|
|
|
|
|
# This was created from nowhere and added to a player's
|
|
|
|
|
# inventory; it's probably the result of a create command.
|
|
|
|
|
string = "You now have %s in your possession." % name
|
2011-04-08 23:10:04 +00:00
|
|
|
self.location.msg(string)
|
2010-08-29 18:46:58 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
|
|
src_name = "nowhere"
|
|
|
|
|
loc_name = self.location.name
|
|
|
|
|
if source_location:
|
|
|
|
|
src_name = source_location.name
|
|
|
|
|
string = "%s arrives to %s from %s."
|
2011-04-08 23:10:04 +00:00
|
|
|
self.location.msg_contents(string % (name, loc_name, src_name), exclude=self)
|
2010-08-29 18:46:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def at_after_move(self, source_location):
|
|
|
|
|
"""
|
|
|
|
|
Called after move has completed, regardless of quiet mode or not.
|
|
|
|
|
Allows changes to the object due to the location it is now in.
|
|
|
|
|
|
|
|
|
|
source_location - where we came from
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def at_object_leave(self, moved_obj, target_location):
|
|
|
|
|
"""
|
|
|
|
|
Called just before an object leaves from inside this object
|
|
|
|
|
|
|
|
|
|
moved_obj - the object leaving
|
|
|
|
|
target_location - where the object is going.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def at_object_receive(self, moved_obj, source_location):
|
|
|
|
|
"""
|
|
|
|
|
Called after an object has been moved into this object.
|
|
|
|
|
|
|
|
|
|
moved_obj - the object moved into this one
|
|
|
|
|
source_location - where moved_object came from.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
2011-04-24 11:26:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def at_before_traverse(self, traversing_object):
|
|
|
|
|
"""
|
|
|
|
|
Called just before an object uses this object to
|
|
|
|
|
traverse to another object (i.e. this object is a type of Exit)
|
2010-08-29 18:46:58 +00:00
|
|
|
|
2011-04-24 11:26:51 +00:00
|
|
|
The target location should normally be available as self.destination.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def at_after_traverse(self, traversing_object, source_location):
|
|
|
|
|
"""
|
|
|
|
|
Called just after an object successfully used this object to
|
|
|
|
|
traverse to another object (i.e. this object is a type of Exit)
|
|
|
|
|
|
|
|
|
|
The target location should normally be available as self.destination.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def at_failed_traverse(self, traversing_object):
|
|
|
|
|
"""
|
|
|
|
|
This is called if an object fails to traverse this object for some
|
|
|
|
|
reason. It will not be called if the attribute err_traverse is defined,
|
|
|
|
|
that attribute will then be echoed back instead.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
2010-08-29 18:46:58 +00:00
|
|
|
|
|
|
|
|
# hooks called by the default cmdset.
|
|
|
|
|
|
|
|
|
|
def return_appearance(self, pobject):
|
|
|
|
|
"""
|
|
|
|
|
This is a convenient hook for a 'look'
|
|
|
|
|
command to call.
|
|
|
|
|
"""
|
|
|
|
|
if not pobject:
|
|
|
|
|
return
|
|
|
|
|
string = "{c%s{n" % self.name
|
|
|
|
|
desc = self.attr("desc")
|
|
|
|
|
if desc:
|
2011-04-21 16:45:18 +00:00
|
|
|
string += "\n %s" % desc
|
2010-08-29 18:46:58 +00:00
|
|
|
exits = []
|
|
|
|
|
users = []
|
|
|
|
|
things = []
|
2011-06-26 14:35:02 +00:00
|
|
|
for content in [con for con in self.contents if con.access(pobject, 'view')]:
|
2010-08-29 18:46:58 +00:00
|
|
|
if content == pobject:
|
|
|
|
|
continue
|
|
|
|
|
name = content.name
|
2011-04-08 23:10:04 +00:00
|
|
|
if content.destination:
|
2010-08-29 18:46:58 +00:00
|
|
|
exits.append(name)
|
|
|
|
|
elif content.has_player:
|
|
|
|
|
users.append(name)
|
|
|
|
|
else:
|
|
|
|
|
things.append(name)
|
|
|
|
|
if exits:
|
|
|
|
|
string += "\n{wExits:{n " + ", ".join(exits)
|
|
|
|
|
if users or things:
|
|
|
|
|
string += "\n{wYou see: {n"
|
|
|
|
|
if users:
|
|
|
|
|
string += "{c" + ", ".join(users) + "{n "
|
|
|
|
|
if things:
|
|
|
|
|
string += ", ".join(things)
|
|
|
|
|
return string
|
|
|
|
|
|
2011-02-14 18:31:16 +00:00
|
|
|
def at_msg_receive(self, msg, from_obj=None, data=None):
|
2010-08-29 18:46:58 +00:00
|
|
|
"""
|
|
|
|
|
This hook is called whenever someone
|
|
|
|
|
sends a message to this object.
|
|
|
|
|
|
|
|
|
|
Note that from_obj may be None if the sender did
|
|
|
|
|
not include itself as an argument to the obj.msg()
|
|
|
|
|
call - so you have to check for this. .
|
|
|
|
|
|
|
|
|
|
Consider this a pre-processing method before
|
|
|
|
|
msg is passed on to the user sesssion. If this
|
|
|
|
|
method returns False, the msg will not be
|
|
|
|
|
passed on.
|
|
|
|
|
|
|
|
|
|
msg = the message received
|
|
|
|
|
from_obj = the one sending the message
|
|
|
|
|
"""
|
|
|
|
|
return True
|
|
|
|
|
|
2011-02-14 18:31:16 +00:00
|
|
|
def at_msg_send(self, msg, to_obj=None, data=None):
|
2010-08-29 18:46:58 +00:00
|
|
|
"""
|
|
|
|
|
This is a hook that is called when /this/ object
|
|
|
|
|
sends a message to another object with obj.msg()
|
|
|
|
|
while also specifying that it is the one sending.
|
|
|
|
|
|
|
|
|
|
Note that this method is executed on the object
|
|
|
|
|
passed along with the msg() function (i.e. using
|
|
|
|
|
obj.msg(msg, caller) will then launch caller.at_msg())
|
|
|
|
|
and if no object was passed, it will never be called.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def at_desc(self, looker=None):
|
|
|
|
|
"""
|
|
|
|
|
This is called whenever someone looks
|
|
|
|
|
at this object. Looker is the looking
|
|
|
|
|
object.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def at_object_delete(self):
|
|
|
|
|
"""
|
|
|
|
|
Called just before the database object is
|
|
|
|
|
permanently delete()d from the database. If
|
|
|
|
|
this method returns False, deletion is aborted.
|
|
|
|
|
"""
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def at_get(self, getter):
|
|
|
|
|
"""
|
|
|
|
|
Called when this object has been picked up. Obs-
|
|
|
|
|
this method cannot stop the pickup - use permissions
|
|
|
|
|
for that!
|
|
|
|
|
|
|
|
|
|
getter - the object getting this object.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def at_drop(self, dropper):
|
|
|
|
|
"""
|
|
|
|
|
Called when this object has been dropped.
|
|
|
|
|
|
|
|
|
|
dropper - the object which just dropped this object.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
def at_say(self, speaker, message):
|
|
|
|
|
"""
|
|
|
|
|
Called on this object if an object inside this object speaks.
|
|
|
|
|
The string returned from this method is the final form
|
|
|
|
|
of the speech. Obs - you don't have to add things like
|
|
|
|
|
'you say: ' or similar, that is handled by the say command.
|
|
|
|
|
|
|
|
|
|
speaker - the object speaking
|
|
|
|
|
message - the words spoken.
|
|
|
|
|
"""
|
|
|
|
|
return message
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# Base Player object
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
class Character(Object):
|
|
|
|
|
"""
|
|
|
|
|
This is just like the Object except it implements its own
|
|
|
|
|
version of the at_object_creation to set up the script
|
|
|
|
|
that adds the default cmdset to the object.
|
|
|
|
|
"""
|
2011-03-17 21:43:18 +00:00
|
|
|
|
|
|
|
|
def basetype_setup(self):
|
|
|
|
|
"""
|
|
|
|
|
Setup character-specific security
|
2011-04-23 11:54:08 +00:00
|
|
|
|
|
|
|
|
Don't change this, instead edit at_object_creation() to
|
|
|
|
|
overload the defaults (it is called after this one).
|
2011-03-17 21:43:18 +00:00
|
|
|
"""
|
|
|
|
|
super(Character, self).basetype_setup()
|
2011-03-20 19:45:56 +00:00
|
|
|
self.locks.add("get:false()") # noone can pick up the character
|
2011-04-30 21:09:19 +00:00
|
|
|
self.locks.add("call:false()") # no commands can be called on character from outside
|
2011-03-17 21:43:18 +00:00
|
|
|
|
|
|
|
|
# add the default cmdset
|
2011-03-20 19:45:56 +00:00
|
|
|
from settings import CMDSET_DEFAULT
|
2011-03-17 21:43:18 +00:00
|
|
|
self.cmdset.add_default(CMDSET_DEFAULT, permanent=True)
|
2011-03-20 19:45:56 +00:00
|
|
|
# no other character should be able to call commands on the Character.
|
|
|
|
|
self.cmdset.outside_access = False
|
2011-03-17 21:43:18 +00:00
|
|
|
|
2010-08-29 18:46:58 +00:00
|
|
|
def at_object_creation(self):
|
|
|
|
|
"""
|
|
|
|
|
All this does (for now) is to add the default cmdset. Since
|
|
|
|
|
the script is permanently stored to this object (the permanent
|
|
|
|
|
keyword creates a script to do this), we should never need to
|
|
|
|
|
do this again for as long as this object exists.
|
|
|
|
|
"""
|
2011-09-03 10:22:19 +00:00
|
|
|
pass
|
|
|
|
|
|
2010-08-29 18:46:58 +00:00
|
|
|
def at_after_move(self, source_location):
|
|
|
|
|
"Default is to look around after a move."
|
|
|
|
|
self.execute_cmd('look')
|
2011-03-17 21:43:18 +00:00
|
|
|
|
2010-08-29 18:46:58 +00:00
|
|
|
#
|
|
|
|
|
# Base Room object
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
class Room(Object):
|
|
|
|
|
"""
|
|
|
|
|
This is the base room object. It's basically
|
|
|
|
|
like any Object except its location is None.
|
|
|
|
|
"""
|
2011-03-17 21:43:18 +00:00
|
|
|
def basetype_setup(self):
|
2010-08-29 18:46:58 +00:00
|
|
|
"""
|
|
|
|
|
Simple setup, shown as an example
|
|
|
|
|
(since default is None anyway)
|
2011-04-23 11:54:08 +00:00
|
|
|
|
|
|
|
|
Don't change this, instead edit at_object_creation() to
|
|
|
|
|
overload the defaults (it is called after this one).
|
2010-08-29 18:46:58 +00:00
|
|
|
"""
|
2011-03-20 13:24:07 +00:00
|
|
|
|
|
|
|
|
super(Room, self).basetype_setup()
|
2011-09-20 13:44:26 +02:00
|
|
|
self.locks.add("get:false();puppet:false()") # would be weird to puppet a room ...
|
2010-08-29 18:46:58 +00:00
|
|
|
self.location = None
|
|
|
|
|
|
2011-04-30 21:09:19 +00:00
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# Exits
|
|
|
|
|
#
|
|
|
|
|
|
2010-08-29 18:46:58 +00:00
|
|
|
class Exit(Object):
|
|
|
|
|
"""
|
2011-05-01 18:04:15 +00:00
|
|
|
This is the base exit object - it connects a location to
|
|
|
|
|
another. This is done by the exit assigning a "command" on itself
|
|
|
|
|
with the same name as the exit object (to do this we need to
|
|
|
|
|
remember to re-create the command when the object is cached since it must be
|
|
|
|
|
created dynamically depending on what the exit is called). This
|
|
|
|
|
command (which has a high priority) will thus allow us to traverse exits
|
|
|
|
|
simply by giving the exit-object's name on its own.
|
|
|
|
|
|
2010-08-29 18:46:58 +00:00
|
|
|
"""
|
2011-05-01 18:04:15 +00:00
|
|
|
|
|
|
|
|
# Helper classes and methods to implement the Exit. These need not
|
|
|
|
|
# be overloaded unless one want to change the foundation for how
|
|
|
|
|
# Exits work. See the end of the class for hook methods to overload.
|
|
|
|
|
|
|
|
|
|
def create_exit_cmdset(self, exidbobj):
|
|
|
|
|
"""
|
|
|
|
|
Helper function for creating an exit command set + command.
|
|
|
|
|
|
2011-08-11 21:16:35 +00:00
|
|
|
The command of this cmdset has the same name as the Exit object
|
|
|
|
|
and allows the exit to react when the player enter the exit's name,
|
|
|
|
|
triggering the movement between rooms.
|
2011-05-01 18:04:15 +00:00
|
|
|
|
2011-08-11 21:16:35 +00:00
|
|
|
Note that exitdbobj is an ObjectDB instance. This is necessary
|
|
|
|
|
for handling reloads and avoid tracebacks if this is called while
|
|
|
|
|
the typeclass system is rebooting.
|
|
|
|
|
"""
|
2011-05-01 18:04:15 +00:00
|
|
|
class ExitCommand(command.Command):
|
|
|
|
|
"""
|
|
|
|
|
This is a command that simply cause the caller
|
|
|
|
|
to traverse the object it is attached to.
|
|
|
|
|
"""
|
|
|
|
|
locks = "cmd:all()" # should always be set to this.
|
|
|
|
|
obj = None
|
|
|
|
|
|
|
|
|
|
def func(self):
|
|
|
|
|
"Default exit traverse if no syscommand is defined."
|
|
|
|
|
|
|
|
|
|
if self.obj.access(self.caller, 'traverse'):
|
|
|
|
|
# we may traverse the exit.
|
|
|
|
|
|
|
|
|
|
old_location = None
|
|
|
|
|
if hasattr(self.caller, "location"):
|
|
|
|
|
old_location = self.caller.location
|
|
|
|
|
|
|
|
|
|
# call pre/post hooks and move object.
|
|
|
|
|
self.obj.at_before_traverse(self.caller)
|
|
|
|
|
self.caller.move_to(self.obj.destination)
|
|
|
|
|
self.obj.at_after_traverse(self.caller, old_location)
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
if self.obj.db.err_traverse:
|
|
|
|
|
# if exit has a better error message, let's use it.
|
|
|
|
|
self.caller.msg(self.obj.db.err_traverse)
|
|
|
|
|
else:
|
|
|
|
|
# No shorthand error message. Call hook.
|
|
|
|
|
self.obj.at_failed_traverse(self.caller)
|
|
|
|
|
|
|
|
|
|
# create an exit command.
|
|
|
|
|
cmd = ExitCommand()
|
|
|
|
|
cmd.key = exidbobj.db_key.strip().lower()
|
|
|
|
|
cmd.obj = exidbobj
|
|
|
|
|
cmd.aliases = exidbobj.aliases
|
2011-06-26 22:03:09 +00:00
|
|
|
cmd.locks = str(exidbobj.locks)
|
2011-05-01 18:04:15 +00:00
|
|
|
cmd.destination = exidbobj.db_destination
|
|
|
|
|
# create a cmdset
|
|
|
|
|
exit_cmdset = cmdset.CmdSet(None)
|
|
|
|
|
exit_cmdset.key = '_exitset'
|
|
|
|
|
exit_cmdset.priority = 9
|
|
|
|
|
exit_cmdset.duplicates = True
|
|
|
|
|
# add command to cmdset
|
|
|
|
|
exit_cmdset.add(cmd)
|
|
|
|
|
return exit_cmdset
|
|
|
|
|
|
|
|
|
|
# Command hooks
|
2011-03-17 21:43:18 +00:00
|
|
|
def basetype_setup(self):
|
|
|
|
|
"""
|
|
|
|
|
Setup exit-security
|
2011-04-23 11:54:08 +00:00
|
|
|
|
|
|
|
|
Don't change this, instead edit at_object_creation() to
|
2011-05-01 18:04:15 +00:00
|
|
|
overload the default locks (it is called after this one).
|
2011-03-17 21:43:18 +00:00
|
|
|
"""
|
|
|
|
|
super(Exit, self).basetype_setup()
|
2011-04-30 21:09:19 +00:00
|
|
|
|
2011-05-01 18:04:15 +00:00
|
|
|
# setting default locks (overload these in at_object_creation()
|
2011-04-23 11:54:08 +00:00
|
|
|
self.locks.add("puppet:false()") # would be weird to puppet an exit ...
|
2011-04-30 21:09:19 +00:00
|
|
|
self.locks.add("traverse:all()") # who can pass through exit by default
|
2011-08-11 21:16:35 +00:00
|
|
|
self.locks.add("get:false()") # noone can pick up the exit
|
|
|
|
|
|
2011-09-03 10:22:19 +00:00
|
|
|
# an exit should have a destination (this is replaced at creation time)
|
2011-08-11 21:16:35 +00:00
|
|
|
if self.dbobj.location:
|
|
|
|
|
self.destination = self.dbobj.location
|
|
|
|
|
|
|
|
|
|
def at_cmdset_get(self):
|
|
|
|
|
"""
|
|
|
|
|
Called when the cmdset is requested from this object, just before the cmdset is
|
|
|
|
|
actually extracted. If no Exit-cmdset is cached, create it now.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if self.ndb.exit_reset or not self.cmdset.has_cmdset("_exitset", must_be_default=True):
|
|
|
|
|
# we are resetting, or no exit-cmdset was set. Create one dynamically.
|
|
|
|
|
self.cmdset.add_default(self.create_exit_cmdset(self.dbobj), permanent=False)
|
|
|
|
|
self.ndb.exit_reset = False
|
2011-05-01 18:04:15 +00:00
|
|
|
|
|
|
|
|
# this and other hooks are what usually can be modified safely.
|
|
|
|
|
|
|
|
|
|
def at_object_creation(self):
|
|
|
|
|
"Called once, when object is first created (after basetype_setup)."
|
|
|
|
|
pass
|
2011-04-24 11:26:51 +00:00
|
|
|
|
|
|
|
|
def at_failed_traverse(self, traversing_object):
|
|
|
|
|
"""
|
|
|
|
|
This is called if an object fails to traverse this object for some
|
|
|
|
|
reason. It will not be called if the attribute "err_traverse" is defined,
|
|
|
|
|
that attribute will then be echoed back instead as a convenient shortcut.
|
2011-05-01 18:04:15 +00:00
|
|
|
|
|
|
|
|
(See also hooks at_before_traverse and at_after_traverse).
|
2011-04-24 11:26:51 +00:00
|
|
|
"""
|
2011-05-01 18:04:15 +00:00
|
|
|
traversing_object.msg("You cannot go there.")
|