mirror of
https://github.com/evennia/evennia.git
synced 2026-03-28 02:36:32 +01:00
As part of this work, I have also written full listings of all available properties on Typeclassed objects (including those inherited in various ways). Should hopefully make things easier to find. One can of course still import things directly from src/ as before. But this is a first step towards removing the "base" objects in game/gamesrc and instead making those accessible through the core API.
757 lines
24 KiB
Python
757 lines
24 KiB
Python
"""
|
|
Generic command module. Pretty much every command should go here for
|
|
now.
|
|
"""
|
|
import time
|
|
from django.conf import settings
|
|
from src.server.sessionhandler import SESSIONS
|
|
from src.utils import utils
|
|
from src.objects.models import ObjectNick as Nick
|
|
from src.commands.default.muxcommand import MuxCommand
|
|
|
|
# limit symbol import for API
|
|
__all__ = ("CmdHome", "CmdLook", "CmdPassword", "CmdNick",
|
|
"CmdInventory", "CmdGet", "CmdDrop", "CmdQuit", "CmdWho",
|
|
"CmdSay", "CmdPose", "CmdEncoding", "CmdAccess",
|
|
"CmdOOCLook", "CmdIC", "CmdOOC")
|
|
|
|
AT_SEARCH_RESULT = utils.mod_import(*settings.SEARCH_AT_RESULT.rsplit('.', 1))
|
|
BASE_PLAYER_TYPECLASS = settings.BASE_PLAYER_TYPECLASS
|
|
|
|
class CmdHome(MuxCommand):
|
|
"""
|
|
home
|
|
|
|
Usage:
|
|
home
|
|
|
|
Teleports the player to their home.
|
|
"""
|
|
|
|
key = "home"
|
|
locks = "cmd:perm(home) or perm(Builders)"
|
|
|
|
def func(self):
|
|
"Implement the command"
|
|
caller = self.caller
|
|
home = caller.home
|
|
if not home:
|
|
caller.msg("You have no home set.")
|
|
else:
|
|
caller.move_to(home)
|
|
caller.msg("There's no place like home ...")
|
|
|
|
class CmdLook(MuxCommand):
|
|
"""
|
|
look
|
|
|
|
Usage:
|
|
look
|
|
look <obj>
|
|
look *<player>
|
|
|
|
Observes your location or objects in your vicinity.
|
|
"""
|
|
key = "look"
|
|
aliases = ["l", "ls"]
|
|
locks = "cmd:all()"
|
|
arg_regex = r"\s.*?|$"
|
|
|
|
def func(self):
|
|
"""
|
|
Handle the looking.
|
|
"""
|
|
caller = self.caller
|
|
args = self.args
|
|
if args:
|
|
# Use search to handle duplicate/nonexistant results.
|
|
looking_at_obj = caller.search(args, use_nicks=True)
|
|
if not looking_at_obj:
|
|
return
|
|
else:
|
|
looking_at_obj = caller.location
|
|
if not looking_at_obj:
|
|
caller.msg("You have no location to look at!")
|
|
return
|
|
|
|
if not hasattr(looking_at_obj, 'return_appearance'):
|
|
# this is likely due to us having a player instead
|
|
looking_at_obj = looking_at_obj.character
|
|
if not looking_at_obj.access(caller, "view"):
|
|
caller.msg("Could not find '%s'." % args)
|
|
return
|
|
# get object's appearance
|
|
caller.msg(looking_at_obj.return_appearance(caller))
|
|
# the object's at_desc() method.
|
|
looking_at_obj.at_desc(looker=caller)
|
|
|
|
class CmdPassword(MuxCommand):
|
|
"""
|
|
@password - set your password
|
|
|
|
Usage:
|
|
@password <old password> = <new password>
|
|
|
|
Changes your password. Make sure to pick a safe one.
|
|
"""
|
|
key = "@password"
|
|
locks = "cmd:all()"
|
|
|
|
def func(self):
|
|
"hook function."
|
|
|
|
caller = self.caller
|
|
if hasattr(caller, "player"):
|
|
caller = caller.player
|
|
|
|
if not self.rhs:
|
|
caller.msg("Usage: @password <oldpass> = <newpass>")
|
|
return
|
|
oldpass = self.lhslist[0] # this is already stripped by parse()
|
|
newpass = self.rhslist[0] # ''
|
|
try:
|
|
uaccount = caller.user
|
|
except AttributeError:
|
|
caller.msg("This is only applicable for players.")
|
|
return
|
|
if not uaccount.check_password(oldpass):
|
|
caller.msg("The specified old password isn't correct.")
|
|
elif len(newpass) < 3:
|
|
caller.msg("Passwords must be at least three characters long.")
|
|
else:
|
|
uaccount.set_password(newpass)
|
|
uaccount.save()
|
|
caller.msg("Password changed.")
|
|
|
|
class CmdNick(MuxCommand):
|
|
"""
|
|
Define a personal alias/nick
|
|
|
|
Usage:
|
|
nick[/switches] <nickname> = [<string>]
|
|
alias ''
|
|
|
|
Switches:
|
|
object - alias an object
|
|
player - alias a player
|
|
clearall - clear all your aliases
|
|
list - show all defined aliases
|
|
|
|
If no switch is given, a command alias is created, used
|
|
to replace strings before sending the command. Give an empty
|
|
right-hand side to clear the nick
|
|
|
|
Creates a personal nick for some in-game object or
|
|
string. When you enter that string, it will be replaced
|
|
with the alternate string. The switches dictate in what
|
|
situations the nick is checked and substituted. If string
|
|
is None, the alias (if it exists) will be cleared.
|
|
Obs - no objects are actually changed with this command,
|
|
if you want to change the inherent aliases of an object,
|
|
use the @alias command instead.
|
|
"""
|
|
key = "nick"
|
|
aliases = ["nickname", "nicks", "@nick", "alias"]
|
|
locks = "cmd:all()"
|
|
|
|
def func(self):
|
|
"Create the nickname"
|
|
|
|
caller = self.caller
|
|
switches = self.switches
|
|
|
|
nicks = Nick.objects.filter(db_obj=caller.dbobj).exclude(db_type="channel")
|
|
if 'list' in switches or self.cmdstring == "nicks":
|
|
string = "{wDefined Nicks:{n"
|
|
cols = [["Type"],["Nickname"],["Translates-to"] ]
|
|
for nick in nicks:
|
|
cols[0].append(nick.db_type)
|
|
cols[1].append(nick.db_nick)
|
|
cols[2].append(nick.db_real)
|
|
for ir, row in enumerate(utils.format_table(cols)):
|
|
if ir == 0:
|
|
string += "\n{w" + "".join(row) + "{n"
|
|
else:
|
|
string += "\n" + "".join(row)
|
|
caller.msg(string)
|
|
return
|
|
if 'clearall' in switches:
|
|
nicks.delete()
|
|
caller.msg("Cleared all aliases.")
|
|
return
|
|
if not self.args or not self.lhs:
|
|
caller.msg("Usage: nick[/switches] nickname = [realname]")
|
|
return
|
|
nick = self.lhs
|
|
real = self.rhs
|
|
|
|
if real == nick:
|
|
caller.msg("No point in setting nick same as the string to replace...")
|
|
return
|
|
|
|
# check so we have a suitable nick type
|
|
if not any(True for switch in switches if switch in ("object", "player", "inputline")):
|
|
switches = ["inputline"]
|
|
string = ""
|
|
for switch in switches:
|
|
oldnick = Nick.objects.filter(db_obj=caller.dbobj, db_nick__iexact=nick, db_type__iexact=switch)
|
|
if not real:
|
|
# removal of nick
|
|
if oldnick:
|
|
# clear the alias
|
|
string += "\nNick '%s' (= '%s') was cleared." % (nick, oldnick[0].db_real)
|
|
caller.nicks.delete(nick, nick_type=switch)
|
|
else:
|
|
string += "\nNo nick '%s' found, so it could not be removed." % nick
|
|
else:
|
|
# creating new nick
|
|
if oldnick:
|
|
string += "\nNick %s changed from '%s' to '%s'." % (nick, oldnick[0].db_real, real)
|
|
else:
|
|
string += "\nNick set: '%s' = '%s'." % (nick, real)
|
|
caller.nicks.add(nick, real, nick_type=switch)
|
|
caller.msg(string)
|
|
|
|
class CmdInventory(MuxCommand):
|
|
"""
|
|
inventory
|
|
|
|
Usage:
|
|
inventory
|
|
inv
|
|
|
|
Shows a player's inventory.
|
|
"""
|
|
key = "inventory"
|
|
aliases = ["inv", "i"]
|
|
locks = "cmd:all()"
|
|
|
|
def func(self):
|
|
"check inventory"
|
|
items = self.caller.contents
|
|
if not items:
|
|
string = "You are not carrying anything."
|
|
else:
|
|
# format item list into nice collumns
|
|
cols = [[],[]]
|
|
for item in items:
|
|
cols[0].append(item.name)
|
|
desc = item.db.desc
|
|
if not desc:
|
|
desc = ""
|
|
cols[1].append(utils.crop(str(desc)))
|
|
# auto-format the columns to make them evenly wide
|
|
ftable = utils.format_table(cols)
|
|
string = "You are carrying:"
|
|
for row in ftable:
|
|
string += "\n " + "{C%s{n - %s" % (row[0], row[1])
|
|
self.caller.msg(string)
|
|
|
|
class CmdGet(MuxCommand):
|
|
"""
|
|
get
|
|
|
|
Usage:
|
|
get <obj>
|
|
|
|
Picks up an object from your location and puts it in
|
|
your inventory.
|
|
"""
|
|
key = "get"
|
|
aliases = "grab"
|
|
locks = "cmd:all()"
|
|
|
|
def func(self):
|
|
"implements the command."
|
|
|
|
caller = self.caller
|
|
|
|
if not self.args:
|
|
caller.msg("Get what?")
|
|
return
|
|
obj = caller.search(self.args)
|
|
if not obj:
|
|
return
|
|
if caller == obj:
|
|
caller.msg("You can't get yourself.")
|
|
return
|
|
if obj.location == caller:
|
|
caller.msg("You already hold that.")
|
|
return
|
|
if not obj.access(caller, 'get'):
|
|
if obj.db.get_err_msg:
|
|
caller.msg(obj.db.get_err_msg)
|
|
else:
|
|
caller.msg("You can't get that.")
|
|
return
|
|
|
|
obj.move_to(caller, quiet=True)
|
|
caller.msg("You pick up %s." % obj.name)
|
|
caller.location.msg_contents("%s picks up %s." %
|
|
(caller.name,
|
|
obj.name),
|
|
exclude=caller)
|
|
# calling hook method
|
|
obj.at_get(caller)
|
|
|
|
|
|
class CmdDrop(MuxCommand):
|
|
"""
|
|
drop
|
|
|
|
Usage:
|
|
drop <obj>
|
|
|
|
Lets you drop an object from your inventory into the
|
|
location you are currently in.
|
|
"""
|
|
|
|
key = "drop"
|
|
locks = "cmd:all()"
|
|
|
|
def func(self):
|
|
"Implement command"
|
|
|
|
caller = self.caller
|
|
if not self.args:
|
|
caller.msg("Drop what?")
|
|
return
|
|
|
|
results = caller.search(self.args, ignore_errors=True)
|
|
# we process the results ourselves since we want to sift out only
|
|
# those in our inventory.
|
|
results = [obj for obj in results if obj in caller.contents]
|
|
# now we send it into the handler.
|
|
obj = AT_SEARCH_RESULT(caller, self.args, results, False)
|
|
if not obj:
|
|
return
|
|
|
|
obj.move_to(caller.location, quiet=True)
|
|
caller.msg("You drop %s." % (obj.name,))
|
|
caller.location.msg_contents("%s drops %s." %
|
|
(caller.name, obj.name),
|
|
exclude=caller)
|
|
# Call the object script's at_drop() method.
|
|
obj.at_drop(caller)
|
|
|
|
|
|
class CmdQuit(MuxCommand):
|
|
"""
|
|
quit
|
|
|
|
Usage:
|
|
@quit
|
|
|
|
Gracefully disconnect from the game.
|
|
"""
|
|
key = "@quit"
|
|
locks = "cmd:all()"
|
|
|
|
def func(self):
|
|
"hook function"
|
|
for session in self.caller.sessions:
|
|
session.msg("{RQuitting{n. Hope to see you soon again.")
|
|
session.session_disconnect()
|
|
|
|
class CmdWho(MuxCommand):
|
|
"""
|
|
who
|
|
|
|
Usage:
|
|
who
|
|
doing
|
|
|
|
Shows who is currently online. Doing is an alias that limits info
|
|
also for those with all permissions.
|
|
"""
|
|
|
|
key = "who"
|
|
aliases = "doing"
|
|
locks = "cmd:all()"
|
|
|
|
def func(self):
|
|
"""
|
|
Get all connected players by polling session.
|
|
"""
|
|
|
|
caller = self.caller
|
|
session_list = SESSIONS.get_sessions()
|
|
|
|
if self.cmdstring == "doing":
|
|
show_session_data = False
|
|
else:
|
|
show_session_data = caller.check_permstring("Immortals") or caller.check_permstring("Wizards")
|
|
|
|
if show_session_data:
|
|
table = [["Player Name"], ["On for"], ["Idle"], ["Room"], ["Cmds"], ["Host"]]
|
|
else:
|
|
table = [["Player Name"], ["On for"], ["Idle"]]
|
|
|
|
for session in session_list:
|
|
if not session.logged_in:
|
|
continue
|
|
|
|
delta_cmd = time.time() - session.cmd_last_visible
|
|
delta_conn = time.time() - session.conn_time
|
|
plr_pobject = session.get_character()
|
|
if not plr_pobject:
|
|
plr_pobject = session.get_player()
|
|
show_session_data = False
|
|
table = [["Player Name"], ["On for"], ["Idle"]]
|
|
if show_session_data:
|
|
table[0].append(plr_pobject.name[:25])
|
|
table[1].append(utils.time_format(delta_conn, 0))
|
|
table[2].append(utils.time_format(delta_cmd, 1))
|
|
table[3].append(plr_pobject.location.id)
|
|
table[4].append(session.cmd_total)
|
|
table[5].append(session.address[0])
|
|
else:
|
|
table[0].append(plr_pobject.name[:25])
|
|
table[1].append(utils.time_format(delta_conn,0))
|
|
table[2].append(utils.time_format(delta_cmd,1))
|
|
|
|
stable = []
|
|
for row in table: # prettify values
|
|
stable.append([str(val).strip() for val in row])
|
|
ftable = utils.format_table(stable, 5)
|
|
string = ""
|
|
for ir, row in enumerate(ftable):
|
|
if ir == 0:
|
|
string += "\n" + "{w%s{n" % ("".join(row))
|
|
else:
|
|
string += "\n" + "".join(row)
|
|
nplayers = (SESSIONS.player_count())
|
|
if nplayers == 1:
|
|
string += '\nOne player logged in.'
|
|
else:
|
|
string += '\n%d players logged in.' % nplayers
|
|
|
|
caller.msg(string)
|
|
|
|
class CmdSay(MuxCommand):
|
|
"""
|
|
say
|
|
|
|
Usage:
|
|
say <message>
|
|
|
|
Talk to those in your current location.
|
|
"""
|
|
|
|
key = "say"
|
|
aliases = ['"', "'"]
|
|
locks = "cmd:all()"
|
|
|
|
def func(self):
|
|
"Run the say command"
|
|
|
|
caller = self.caller
|
|
|
|
if not self.args:
|
|
caller.msg("Say what?")
|
|
return
|
|
|
|
speech = self.args
|
|
|
|
# calling the speech hook on the location
|
|
speech = caller.location.at_say(caller, speech)
|
|
|
|
# Feedback for the object doing the talking.
|
|
caller.msg('You say, "%s{n"' % speech)
|
|
|
|
# Build the string to emit to neighbors.
|
|
emit_string = '{c%s{n says, "%s{n"' % (caller.name,
|
|
speech)
|
|
caller.location.msg_contents(emit_string,
|
|
exclude=caller)
|
|
|
|
|
|
class CmdPose(MuxCommand):
|
|
"""
|
|
pose - strike a pose
|
|
|
|
Usage:
|
|
pose <pose text>
|
|
pose's <pose text>
|
|
|
|
Example:
|
|
pose is standing by the wall, smiling.
|
|
-> others will see:
|
|
Tom is standing by the wall, smiling.
|
|
|
|
Describe an script being taken. The pose text will
|
|
automatically begin with your name.
|
|
"""
|
|
key = "pose"
|
|
aliases = [":", "emote"]
|
|
locks = "cmd:all()"
|
|
|
|
def parse(self):
|
|
"""
|
|
Custom parse the cases where the emote
|
|
starts with some special letter, such
|
|
as 's, at which we don't want to separate
|
|
the caller's name and the emote with a
|
|
space.
|
|
"""
|
|
args = self.args
|
|
if args and not args[0] in ["'", ",", ":"]:
|
|
args = " %s" % args.strip()
|
|
self.args = args
|
|
|
|
def func(self):
|
|
"Hook function"
|
|
if not self.args:
|
|
msg = "Do what?"
|
|
self.caller.msg(msg)
|
|
else:
|
|
msg = "%s%s" % (self.caller.name, self.args)
|
|
self.caller.location.msg_contents(msg)
|
|
|
|
class CmdEncoding(MuxCommand):
|
|
"""
|
|
encoding - set a custom text encoding
|
|
|
|
Usage:
|
|
@encoding/switches [<encoding>]
|
|
|
|
Switches:
|
|
clear - clear your custom encoding
|
|
|
|
|
|
This sets the text encoding for communicating with Evennia. This is mostly an issue only if
|
|
you want to use non-ASCII characters (i.e. letters/symbols not found in English). If you see
|
|
that your characters look strange (or you get encoding errors), you should use this command
|
|
to set the server encoding to be the same used in your client program.
|
|
|
|
Common encodings are utf-8 (default), latin-1, ISO-8859-1 etc.
|
|
|
|
If you don't submit an encoding, the current encoding will be displayed instead.
|
|
"""
|
|
|
|
key = "@encoding"
|
|
aliases = "@encode"
|
|
locks = "cmd:all()"
|
|
|
|
def func(self):
|
|
"""
|
|
Sets the encoding.
|
|
"""
|
|
caller = self.caller
|
|
if hasattr(caller, 'player'):
|
|
caller = caller.player
|
|
|
|
if 'clear' in self.switches:
|
|
# remove customization
|
|
old_encoding = caller.db.encoding
|
|
if old_encoding:
|
|
string = "Your custom text encoding ('%s') was cleared." % old_encoding
|
|
else:
|
|
string = "No custom encoding was set."
|
|
del caller.db.encoding
|
|
elif not self.args:
|
|
# just list the encodings supported
|
|
pencoding = caller.db.encoding
|
|
string = ""
|
|
if pencoding:
|
|
string += "Default encoding: {g%s{n (change with {w@encoding <encoding>{n)" % pencoding
|
|
encodings = settings.ENCODINGS
|
|
if encodings:
|
|
string += "\nServer's alternative encodings (tested in this order):\n {g%s{n" % ", ".join(encodings)
|
|
if not string:
|
|
string = "No encodings found."
|
|
else:
|
|
# change encoding
|
|
old_encoding = caller.db.encoding
|
|
encoding = self.args
|
|
caller.db.encoding = encoding
|
|
string = "Your custom text encoding was changed from '%s' to '%s'." % (old_encoding, encoding)
|
|
caller.msg(string.strip())
|
|
|
|
class CmdAccess(MuxCommand):
|
|
"""
|
|
access - show access groups
|
|
|
|
Usage:
|
|
access
|
|
|
|
This command shows you the permission hierarchy and
|
|
which permission groups you are a member of.
|
|
"""
|
|
key = "access"
|
|
aliases = ["groups", "hierarchy"]
|
|
locks = "cmd:all()"
|
|
|
|
def func(self):
|
|
"Load the permission groups"
|
|
|
|
caller = self.caller
|
|
hierarchy_full = settings.PERMISSION_HIERARCHY
|
|
string = "\n{wPermission Hierarchy{n (climbing):\n %s" % ", ".join(hierarchy_full)
|
|
hierarchy = [p.lower() for p in hierarchy_full]
|
|
|
|
if self.caller.player.is_superuser:
|
|
cperms = "<Superuser>"
|
|
pperms = "<Superuser>"
|
|
else:
|
|
cperms = ", ".join(caller.permissions)
|
|
pperms = ", ".join(caller.player.permissions)
|
|
|
|
string += "\n{wYour access{n:"
|
|
string += "\nCharacter {c%s{n: %s" % (caller.key, cperms)
|
|
if hasattr(caller, 'player'):
|
|
string += "\nPlayer {c%s{n: %s" % (caller.player.key, pperms)
|
|
caller.msg(string)
|
|
|
|
# OOC commands
|
|
|
|
class CmdOOCLook(CmdLook):
|
|
"""
|
|
ooc look
|
|
|
|
Usage:
|
|
look
|
|
|
|
This is an OOC version of the look command. Since a
|
|
Player doesn't have an in-game existence, there is no
|
|
concept of location or "self". If we are controlling
|
|
a character, pass control over to normal look.
|
|
|
|
"""
|
|
|
|
key = "look"
|
|
aliases = ["l", "ls"]
|
|
locks = "cmd:all()"
|
|
help_category = "General"
|
|
|
|
def func(self):
|
|
"implement the ooc look command"
|
|
|
|
self.character = None
|
|
if utils.inherits_from(self.caller, "src.objects.objects.Object"):
|
|
# An object of some type is calling. Convert to player.
|
|
#print self.caller, self.caller.__class__
|
|
self.character = self.caller
|
|
if hasattr(self.caller, "player"):
|
|
self.caller = self.caller.player
|
|
|
|
if not self.character:
|
|
string = "You are out-of-character (OOC). "
|
|
string += "Use {w@ic{n to get back to the game, {whelp{n for more info."
|
|
self.caller.msg(string)
|
|
else:
|
|
self.caller = self.character # we have to put this back for normal look to work.
|
|
super(CmdOOCLook, self).func()
|
|
|
|
class CmdIC(MuxCommand):
|
|
"""
|
|
Switch control to an object
|
|
|
|
Usage:
|
|
@ic <character>
|
|
|
|
Go in-character (IC) as a given Character.
|
|
|
|
This will attempt to "become" a different object assuming you have
|
|
the right to do so. You cannot become an object that is already
|
|
controlled by another player. In principle <character> can be
|
|
any in-game object as long as you have access right to puppet it.
|
|
"""
|
|
|
|
key = "@ic"
|
|
locks = "cmd:all()" # must be all() or different puppeted objects won't be able to access it.
|
|
aliases = "@puppet"
|
|
help_category = "General"
|
|
|
|
def func(self):
|
|
"""
|
|
Simple puppet method
|
|
"""
|
|
caller = self.caller
|
|
if utils.inherits_from(caller, "src.objects.objects.Object"):
|
|
caller = caller.player
|
|
|
|
new_character = None
|
|
if not self.args:
|
|
new_character = caller.db.last_puppet
|
|
if not new_character:
|
|
caller.msg("Usage: @ic <character>")
|
|
return
|
|
if not new_character:
|
|
# search for a matching character
|
|
new_character = caller.search(self.args, global_search=True)
|
|
if not new_character:
|
|
# the search method handles error messages etc.
|
|
return
|
|
if new_character.player:
|
|
if new_character.player == caller:
|
|
caller.msg("{RYou already are {c%s{n." % new_character.name)
|
|
else:
|
|
caller.msg("{c%s{r is already acted by another player.{n" % new_character.name)
|
|
return
|
|
if not new_character.access(caller, "puppet"):
|
|
caller.msg("{rYou may not become %s.{n" % new_character.name)
|
|
return
|
|
old_char = None
|
|
if caller.character:
|
|
# save the old character. We only assign this to last_puppet if swap is successful.
|
|
old_char = caller.character
|
|
if caller.swap_character(new_character):
|
|
new_character.msg("\n{gYou become {c%s{n.\n" % new_character.name)
|
|
caller.db.last_puppet = old_char
|
|
if not new_character.location:
|
|
# this might be due to being hidden away at logout; check
|
|
loc = new_character.db.prelogout_location
|
|
if not loc: # still no location; use home
|
|
loc = new_character.home
|
|
new_character.location = loc
|
|
if new_character.location:
|
|
new_character.location.msg_contents("%s has entered the game." % new_character.key, exclude=[new_character])
|
|
new_character.location.at_object_receive(new_character, new_character.location)
|
|
new_character.execute_cmd("look")
|
|
else:
|
|
caller.msg("{rYou cannot become {C%s{n." % new_character.name)
|
|
|
|
class CmdOOC(MuxCommand):
|
|
"""
|
|
@ooc - go ooc
|
|
|
|
Usage:
|
|
@ooc
|
|
|
|
Go out-of-character (OOC).
|
|
|
|
This will leave your current character and put you in a incorporeal OOC state.
|
|
"""
|
|
|
|
key = "@ooc"
|
|
locks = "cmd:all()" # this must be all(), or different puppeted objects won't be able to access it.
|
|
aliases = "@unpuppet"
|
|
help_category = "General"
|
|
|
|
def func(self):
|
|
"Implement function"
|
|
|
|
caller = self.caller
|
|
|
|
if utils.inherits_from(caller, "src.objects.objects.Object"):
|
|
caller = self.caller.player
|
|
|
|
if not caller.character:
|
|
string = "You are already OOC."
|
|
caller.msg(string)
|
|
return
|
|
|
|
caller.db.last_puppet = caller.character
|
|
# save location as if we were disconnecting from the game entirely.
|
|
if caller.character.location:
|
|
caller.character.location.msg_contents("%s has left the game." % caller.character.key, exclude=[caller.character])
|
|
caller.character.db.prelogout_location = caller.character.location
|
|
caller.character.location = None
|
|
|
|
# disconnect
|
|
caller.character.player = None
|
|
caller.character = None
|
|
|
|
caller.msg("\n{GYou go OOC.{n\n")
|
|
caller.execute_cmd("look")
|