command.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. """
  2. Commands
  3. Commands describe the input the account can do to the game.
  4. """
  5. import re
  6. import random
  7. from evennia import utils, default_cmds, create_script, logger
  8. from evennia.utils import evtable
  9. from evennia.contrib.health_bar import display_meter
  10. from evennia.utils import inherits_from
  11. from evennia.utils.utils import list_to_string
  12. from evennia.utils.eveditor import EvEditor
  13. from utils.building import create_room, create_exit
  14. from utils.utils import has_tag, fmt_light, fmt_dark, toggle_effect, has_effect, indefinite_article
  15. from typeclasses.exits import BaseDoor
  16. from typeclasses.rooms import IndoorRoom
  17. from typeclasses.objects import Item, EquippableItem
  18. from typeclasses.scripts import Script, CmdActionScript
  19. from world import spells
  20. CMD_SEARCH_TIME = 5
  21. class Command(default_cmds.MuxCommand):
  22. """
  23. Inherit from this if you want to create your own command styles
  24. from scratch. Note that Evennia's default commands inherits from
  25. MuxCommand instead.
  26. Note that the class's `__doc__` string (this text) is
  27. used by Evennia to create the automatic help entry for
  28. the command, so make sure to document consistently here.
  29. Each Command implements the following methods, called
  30. in this order (only func() is actually required):
  31. - at_pre_cmd(): If this returns anything truthy, execution is aborted.
  32. - parse(): Should perform any extra parsing needed on self.args
  33. and store the result on self.
  34. - func(): Performs the actual work.
  35. - at_post_cmd(): Extra actions, often things done after
  36. every command, like prompts.
  37. """
  38. def at_post_cmd(self):
  39. caller = self.caller
  40. prompt = "|_|/°|w%s|n°: " % (caller.location)
  41. caller.msg(prompt=prompt)
  42. # overloading the look command with our custom MuxCommand with at_post_cmd hook
  43. class CmdLook(default_cmds.CmdLook, Command):
  44. pass
  45. class CmdDrop(default_cmds.CmdDrop, Command):
  46. pass
  47. class CmdGet(Command):
  48. """
  49. pick up something
  50. Usage:
  51. get <obj> [from <container>]
  52. Picks up an object from your location and puts it in
  53. your inventory.
  54. """
  55. key = "get"
  56. aliases = "grab"
  57. locks = "cmd:all()"
  58. arg_regex = r"\s|$"
  59. def parse(self):
  60. """
  61. Handle parsing of:
  62. <object> [FROM <container>]
  63. """
  64. self.args = args = self.args.strip().lower()
  65. if "from" in args:
  66. obj, *rest = args.split(" from ", 1)
  67. container = rest[0] if rest else ""
  68. else:
  69. obj = self.args
  70. container = ""
  71. self.obj_name = obj.strip()
  72. self.container_name = container.strip()
  73. def func(self):
  74. """implements the command."""
  75. caller = self.caller
  76. if not self.args or not self.obj_name:
  77. caller.msg("Get what?")
  78. return
  79. if inherits_from(caller.location, IndoorRoom) and not caller.location.db.is_lit:
  80. caller.msg("Its too dark to get anything.")
  81. return
  82. if self.container_name:
  83. container = caller.search(self.container_name, location=caller.location)
  84. obj = caller.search(self.obj_name, location=container)
  85. else:
  86. obj = caller.search(self.obj_name, location=caller.location)
  87. if not obj:
  88. return
  89. if caller == obj:
  90. caller.msg("You can't get yourself.")
  91. return
  92. if not obj.access(caller, "get"):
  93. if obj.db.get_err_msg:
  94. caller.msg(obj.db.get_err_msg)
  95. else:
  96. caller.msg("You can't get that.")
  97. return
  98. # calling at_before_get hook method
  99. if not obj.at_before_get(caller):
  100. return
  101. success = obj.move_to(caller, quiet=True)
  102. if not success:
  103. caller.msg("This can't be picked up.")
  104. else:
  105. caller.msg("You pick up %s." % obj.name)
  106. caller.location.msg_contents(
  107. "%s picks up %s." % (caller.name, obj.name), exclude=caller
  108. )
  109. # calling at_get hook method
  110. obj.at_get(caller)
  111. class CmdCharacter(Command):
  112. """
  113. Show character sheet.
  114. Usage:
  115. character
  116. Displays a list of your current ability values.
  117. """
  118. key = "character"
  119. aliases = ["char"]
  120. lock = "cmd:all()"
  121. help_category = "General"
  122. def func(self):
  123. self.caller.msg(
  124. '\u250B|w' + " {0:27}".format(self.caller.name,) + '|n\u250B|/')
  125. self.caller.msg('-HEALTH' + '-' * 23)
  126. meter = display_meter(self.caller.get_health(), 100,
  127. empty_color="222", align="center", fill_color=["R"])
  128. self.caller.msg(meter)
  129. self.caller.msg('-MANA' + '-' * 25)
  130. meter = display_meter(self.caller.get_mana(), 100,
  131. empty_color="222", align="center", fill_color=["B"])
  132. self.caller.msg(meter + '|/')
  133. str, agi, intel = self.caller.get_abilities()
  134. table = evtable.EvTable(border="tablecols")
  135. table.add_column("STRENGTH", "AGILITY",
  136. "INTELLECT", header="Attributes")
  137. table.add_column("|g%03d|n/100" % str, "|g%03d|n/100" %
  138. agi, "|g%03d|n/100" % intel, header="")
  139. self.caller.msg(table)
  140. class CmdLight(Command):
  141. """
  142. A command to light objects that support it.
  143. Usage:
  144. light <someone>
  145. Light an object in your inventory.
  146. """
  147. key = "light"
  148. aliases = []
  149. lock = "cmd:all()"
  150. help_category = "General"
  151. arg_regex = r"(?:^(?:\s+|\/).*$)|^$"
  152. def func(self):
  153. caller = self.caller
  154. if not self.args:
  155. self.msg("Light what?")
  156. return
  157. else:
  158. target = caller.search(self.args)
  159. if not target:
  160. self.msg("Light what?")
  161. return
  162. if not target.access(caller, 'light'):
  163. self.msg("You cannot do that.")
  164. return
  165. if not has_effect(target, "emit_light"):
  166. toggle_effect(target, "emit_light")
  167. self.msg("You light {}.".format(target.name))
  168. else:
  169. toggle_effect(target, "emit_light")
  170. self.msg("You put off {}.".format(target.name))
  171. if caller.location and inherits_from(caller.location, IndoorRoom):
  172. caller.location.check_light_state()
  173. class CmdSearch(Command):
  174. """
  175. """
  176. key = "search"
  177. aliases = ["ss"]
  178. locks = "cmd:all()"
  179. help_category = "General"
  180. arg_regex = r"(?:^(?:\s+|\/).*$)|^$"
  181. def func(self):
  182. caller = self.caller
  183. if has_effect(caller, "is_busy"):
  184. caller.msg("You are already busy {}.".format(caller.current_action.busy_msg()))
  185. return
  186. if not self.args:
  187. target = caller.location
  188. if not target:
  189. caller.msg("You have no location to search!")
  190. return
  191. else:
  192. target = caller.search(self.args)
  193. if not target:
  194. caller.msg("You cannot search {}!".format(self.args))
  195. return
  196. if target.access(caller, "search"):
  197. toggle_effect(caller, "is_busy")
  198. caller.msg("You search {}.".format(target.get_display_name(caller)))
  199. action_script = create_script("commands.command.CmdSearchComplete", obj=caller, interval=CMD_SEARCH_TIME, attributes=[("target", self.args)])
  200. caller.db.current_action = action_script
  201. else:
  202. caller.msg("You cannot search {}!".format(target.get_display_name(caller)))
  203. class CmdSearchComplete(CmdActionScript):
  204. def at_script_creation(self):
  205. super().at_script_creation()
  206. self.key = "cmd_search_complete"
  207. self.desc = ""
  208. self.db.target = ""
  209. def at_repeat(self):
  210. caller = self.obj
  211. target_string = self.db.target
  212. if has_effect(caller, "is_busy"):
  213. toggle_effect(caller, "is_busy")
  214. if not target_string:
  215. target = caller.location
  216. if not target:
  217. caller.msg("You have no location to search!")
  218. return
  219. else:
  220. target = caller.search(target_string)
  221. if not target:
  222. caller.msg("You cannot search {} anymore!".format(target_string))
  223. return
  224. if target.access(caller, "search"):
  225. items = []
  226. for con in target.contents:
  227. if inherits_from(con, Item) and con.access(caller, "get"):
  228. items.append(con)
  229. if items:
  230. found_item_idx = random.randrange(0, len(items))
  231. found_item = items[found_item_idx]
  232. found_item_name = found_item.get_numbered_name(1, caller)[0]
  233. caller.msg("You find {}.".format(found_item_name))
  234. if not found_item.access(caller, "get"):
  235. if found_item.db.get_err_msg:
  236. caller.msg(found_item.db.get_err_msg)
  237. else:
  238. caller.msg("You can't get that.")
  239. return
  240. # calling at_before_get hook method
  241. if not found_item.at_before_get(caller):
  242. return
  243. success = found_item.move_to(caller, quiet=True)
  244. if not success:
  245. caller.msg("This can't be picked up.")
  246. else:
  247. caller.msg("You pick up %s." % found_item_name)
  248. caller.location.msg_contents(
  249. "%s picks up %s." % (caller.name, found_item_name), exclude=caller
  250. )
  251. # calling at_get hook method
  252. found_item.at_get(caller)
  253. else:
  254. caller.msg("There is nothing to be found here.")
  255. else:
  256. caller.msg("You cannot search {} anymore!".format(target.get_display_name(caller)))
  257. def busy_msg(self):
  258. return "searching {}".format(self.db.target)
  259. class CmdPut(Command):
  260. """
  261. Put an item inside a container
  262. Usage:
  263. put <item> in <container>
  264. """
  265. key = "put"
  266. locks = "cmd:all()"
  267. help_category = "General"
  268. def parse(self):
  269. """
  270. Handle parsing of:
  271. <item> in <container>
  272. """
  273. self.args = args = self.args.strip().lower()
  274. item_name, container_name = "", ""
  275. if " in " in args:
  276. item_name, *rest = args.split(" in ", 1)
  277. container_name = rest[0] if rest else ""
  278. self.item_name = item_name.strip()
  279. self.container_name = container_name.strip()
  280. def func(self):
  281. caller = self.caller
  282. if not self.args or not self.item_name or not self.container_name:
  283. caller.msg("Usage: put <item> in <container>")
  284. return
  285. item = caller.search(self.item_name, typeclass="typeclasses.objects.Item")
  286. if not item:
  287. return
  288. container = caller.search(self.container_name, typeclass="typeclasses.objects.ContainerFeature")
  289. if not container:
  290. return
  291. if not item.access(caller, "get"):
  292. caller.msg("You cannot do that with {}.".format(item.name))
  293. return
  294. if not container.access(caller, "put"):
  295. caller.msg("You cannot access {}.".format(container.name))
  296. return
  297. if has_tag(item, "equipped", "general"):
  298. caller.msg("{} is equipped. Remove it first.".format(item.name))
  299. return
  300. item.move_to(container, use_destination=False)
  301. caller.msg("You put {} inside {}.".format(item.name, container.name))
  302. class CmdOpenCloseDoor(Command):
  303. """
  304. Open and close a door
  305. Usage:
  306. open <door>
  307. close <door>
  308. """
  309. key = "op"
  310. aliases = ["close"]
  311. locks = "cmd:all()"
  312. help_category = "General"
  313. def func(self):
  314. if not self.args:
  315. self.caller.msg("Usage: open||close <door>")
  316. return
  317. door = self.caller.search(self.args)
  318. if not door:
  319. return
  320. if not inherits_from(door, BaseDoor):
  321. self.caller.msg("This is not a door.")
  322. return
  323. if self.cmdstring == "op":
  324. if door.locks.check(self.caller, "traverse"):
  325. self.caller.msg("%s is already open." % door.key)
  326. else:
  327. door.setlock("traverse:true()")
  328. self.caller.msg("You open %s." % door.key)
  329. else: # close
  330. if not door.locks.check(self.caller, "traverse"):
  331. self.caller.msg("%s is already closed." % door.key)
  332. else:
  333. door.setlock("traverse:false()")
  334. self.caller.msg("You close %s." % door.key)
  335. class CmdEquip(Command):
  336. key = "equip"
  337. aliases = ["eq", "remove"]
  338. lock = "cmd:all()"
  339. help_category = "General"
  340. arg_regex = r"\s.+|$"
  341. def func(self):
  342. caller = self.caller
  343. if not self.args:
  344. caller.msg("You cannot do that.")
  345. return
  346. item = caller.search(self.args, location=caller, nofound_string="")
  347. if not item:
  348. caller.msg("You don't have any {}".format(self.args))
  349. return
  350. if inherits_from(item, EquippableItem) and item.access(caller, "equip"):
  351. if self.cmdstring == "remove":
  352. if has_tag(item, "equipped", "general"):
  353. if item.at_unequip(caller, ""):
  354. self.remove(caller, item)
  355. else:
  356. return
  357. else:
  358. caller.msg("{} is not equipped.".format(item.name))
  359. return
  360. else:
  361. if has_tag(item, "equipped", "general"):
  362. caller.msg("{} is already equipped.".format(item.name))
  363. return
  364. slots = [slot for slot in caller.db.equipment.keys() if item.db.slot in slot]
  365. if not slots:
  366. caller.msg("You don't have {} {}".format(indefinite_article(item.db.slot), item.db.slot))
  367. return
  368. selected_slot = slots[0]
  369. # find an empty slot
  370. empty_slots = [slot for slot in slots if not caller.db.equipment[slot]]
  371. if empty_slots:
  372. selected_slot = empty_slots[0]
  373. # remove equipment if slot is already in use
  374. if caller.db.equipment[selected_slot]:
  375. old_equipment = caller.search(caller.db.equipment[selected_slot], location=caller, quiet=True)
  376. if old_equipment:
  377. if old_equipment[0].at_unequip(caller, selected_slot):
  378. self.remove(caller, old_equipment[0])
  379. else:
  380. return
  381. if item.at_equip(caller, selected_slot):
  382. caller.db.equipment[selected_slot] = item.dbref
  383. item.tags.add("equipped", category="general")
  384. caller.msg("You equip |w{}|n on |w{}|n".format(item.name, selected_slot))
  385. caller.location.msg_contents("{} equips |w{}|n on {}".format(caller.name, item.name, selected_slot), exclude=caller)
  386. else:
  387. caller.msg("You cannot equip {}".format(item.name))
  388. def remove(self, caller, item):
  389. selected_slot = [slot for slot in caller.db.equipment.keys() if caller.db.equipment[slot] == item.dbref][0]
  390. caller.msg("You remove {} from {}".format(item, selected_slot))
  391. caller.db.equipment[selected_slot] = None
  392. item.tags.remove("equipped", category="general")
  393. class CmdInventory(Command):
  394. """
  395. view inventory
  396. Usage:
  397. inventory
  398. inv
  399. Shows your inventory.
  400. """
  401. key = "inventory"
  402. aliases = ["inv", "i"]
  403. locks = "cmd:all()"
  404. arg_regex = r"$"
  405. def func(self):
  406. """check inventory"""
  407. items = self.caller.contents
  408. if not items:
  409. string = "You are not carrying anything."
  410. else:
  411. from evennia.utils.ansi import raw as raw_ansi
  412. table = self.styled_table()
  413. for item in items:
  414. effect_string = ""
  415. if has_tag(item, 'equipped', 'general'):
  416. effect_string += "|w⚒|n"
  417. else:
  418. effect_string += "|=a⚒|n"
  419. if has_effect(item, 'emit_light'):
  420. effect_string += "|y☀|n"
  421. else:
  422. effect_string += "|=a☀|n"
  423. table.add_row(
  424. f"|w{item.name}|n",
  425. effect_string,
  426. "{}|n".format(utils.crop(raw_ansi(item.db.desc), width=50) or ""),
  427. )
  428. string = f"|wYou are carrying:\n{table}"
  429. self.caller.msg(string)
  430. class CmdCast(Command):
  431. """
  432. """
  433. key = "cast"
  434. aliases = ["cs"]
  435. lock = "cmd:false()"
  436. help_category = "General"
  437. arg_regex = r"\s.+|$"
  438. def parse(self):
  439. """
  440. Handle parsing of:
  441. ::
  442. <spell> [at <target>]
  443. """
  444. self.args = args = self.args.strip().lower()
  445. spell_name, target_name = "", ""
  446. if " at " in args:
  447. spell_name, *rest = args.split(" at ", 1)
  448. target_name = rest[0] if rest else ""
  449. else:
  450. spell_name = args
  451. self.spell_name = spell_name.strip()
  452. self.target_name = target_name.strip()
  453. def func(self):
  454. caller = self.caller
  455. if not self.args or not self.spell_name:
  456. caller.msg("Usage: cast <spell> [at <target>]")
  457. return
  458. spell_id = self.spell_name.replace(' ', '_')
  459. if self.spell_name not in caller.db.spells:
  460. caller.msg("You cannot cast {}.".format(self.spell_name))
  461. return
  462. if hasattr(spells, "spell_" + spell_id):
  463. spell = getattr(spells, "spell_" + spell_id)
  464. else:
  465. logger.log_err("Cannot find spell {}.".format("spell_" + spell_id))
  466. return
  467. spell(caller, self.target_name)
  468. class CmdTestPy(Command):
  469. key = "testpy"
  470. aliases = ["testpy"]
  471. lock = "cmd:false()"
  472. help_category = "General"
  473. arg_regex = r"\s.+|$"
  474. def func(self):
  475. caller = self.caller
  476. pattern = re.compile(r'''((?:[^ "']|"[^"]*"|'[^']*')+)''')
  477. self.args = pattern.split(self.lhs)[1::2]
  478. # room = create_room(self.args[0].strip(" \"'"), int(self.args[1].strip(" \"'")), int(self.args[2].strip(" \"'")), self.args[3].strip(" \"'"))
  479. # caller.msg(room)
  480. exit = create_exit("exit_empty", caller.location, "north")
  481. caller.msg(exit)
  482. # caller.msg(dkmud_oob=({"testarg": "valuetestarg"}))
  483. # if not self.args:
  484. # target = caller.location
  485. # if not target:
  486. # caller.msg("You have no location to test!")
  487. # return
  488. # else:
  489. # target = caller.search(self.args)
  490. # if not target:
  491. # return
  492. # -------------------------------------------------------------
  493. #
  494. # The default commands inherit from
  495. #
  496. # evennia.commands.default.muxcommand.MuxCommand.
  497. #
  498. # If you want to make sweeping changes to default commands you can
  499. # uncomment this copy of the MuxCommand parent and add
  500. #
  501. # COMMAND_DEFAULT_CLASS = "commands.command.MuxCommand"
  502. #
  503. # to your settings file. Be warned that the default commands expect
  504. # the functionality implemented in the parse() method, so be
  505. # careful with what you change.
  506. #
  507. # -------------------------------------------------------------
  508. # from evennia.utils import utils
  509. #
  510. #
  511. # class MuxCommand(Command):
  512. # """
  513. # This sets up the basis for a MUX command. The idea
  514. # is that most other Mux-related commands should just
  515. # inherit from this and don't have to implement much
  516. # parsing of their own unless they do something particularly
  517. # advanced.
  518. #
  519. # Note that the class's __doc__ string (this text) is
  520. # used by Evennia to create the automatic help entry for
  521. # the command, so make sure to document consistently here.
  522. # """
  523. # def has_perm(self, srcobj):
  524. # """
  525. # This is called by the cmdhandler to determine
  526. # if srcobj is allowed to execute this command.
  527. # We just show it here for completeness - we
  528. # are satisfied using the default check in Command.
  529. # """
  530. # return super().has_perm(srcobj)
  531. #
  532. # def at_pre_cmd(self):
  533. # """
  534. # This hook is called before self.parse() on all commands
  535. # """
  536. # pass
  537. #
  538. # def at_post_cmd(self):
  539. # """
  540. # This hook is called after the command has finished executing
  541. # (after self.func()).
  542. # """
  543. # pass
  544. #
  545. # def parse(self):
  546. # """
  547. # This method is called by the cmdhandler once the command name
  548. # has been identified. It creates a new set of member variables
  549. # that can be later accessed from self.func() (see below)
  550. #
  551. # The following variables are available for our use when entering this
  552. # method (from the command definition, and assigned on the fly by the
  553. # cmdhandler):
  554. # self.key - the name of this command ('look')
  555. # self.aliases - the aliases of this cmd ('l')
  556. # self.permissions - permission string for this command
  557. # self.help_category - overall category of command
  558. #
  559. # self.caller - the object calling this command
  560. # self.cmdstring - the actual command name used to call this
  561. # (this allows you to know which alias was used,
  562. # for example)
  563. # self.args - the raw input; everything following self.cmdstring.
  564. # self.cmdset - the cmdset from which this command was picked. Not
  565. # often used (useful for commands like 'help' or to
  566. # list all available commands etc)
  567. # self.obj - the object on which this command was defined. It is often
  568. # the same as self.caller.
  569. #
  570. # A MUX command has the following possible syntax:
  571. #
  572. # name[ with several words][/switch[/switch..]] arg1[,arg2,...] [[=|,] arg[,..]]
  573. #
  574. # The 'name[ with several words]' part is already dealt with by the
  575. # cmdhandler at this point, and stored in self.cmdname (we don't use
  576. # it here). The rest of the command is stored in self.args, which can
  577. # start with the switch indicator /.
  578. #
  579. # This parser breaks self.args into its constituents and stores them in the
  580. # following variables:
  581. # self.switches = [list of /switches (without the /)]
  582. # self.raw = This is the raw argument input, including switches
  583. # self.args = This is re-defined to be everything *except* the switches
  584. # self.lhs = Everything to the left of = (lhs:'left-hand side'). If
  585. # no = is found, this is identical to self.args.
  586. # self.rhs: Everything to the right of = (rhs:'right-hand side').
  587. # If no '=' is found, this is None.
  588. # self.lhslist - [self.lhs split into a list by comma]
  589. # self.rhslist - [list of self.rhs split into a list by comma]
  590. # self.arglist = [list of space-separated args (stripped, including '=' if it exists)]
  591. #
  592. # All args and list members are stripped of excess whitespace around the
  593. # strings, but case is preserved.
  594. # """
  595. # raw = self.args
  596. # args = raw.strip()
  597. #
  598. # # split out switches
  599. # switches = []
  600. # if args and len(args) > 1 and args[0] == "/":
  601. # # we have a switch, or a set of switches. These end with a space.
  602. # switches = args[1:].split(None, 1)
  603. # if len(switches) > 1:
  604. # switches, args = switches
  605. # switches = switches.split('/')
  606. # else:
  607. # args = ""
  608. # switches = switches[0].split('/')
  609. # arglist = [arg.strip() for arg in args.split()]
  610. #
  611. # # check for arg1, arg2, ... = argA, argB, ... constructs
  612. # lhs, rhs = args, None
  613. # lhslist, rhslist = [arg.strip() for arg in args.split(',')], []
  614. # if args and '=' in args:
  615. # lhs, rhs = [arg.strip() for arg in args.split('=', 1)]
  616. # lhslist = [arg.strip() for arg in lhs.split(',')]
  617. # rhslist = [arg.strip() for arg in rhs.split(',')]
  618. #
  619. # # save to object properties:
  620. # self.raw = raw
  621. # self.switches = switches
  622. # self.args = args.strip()
  623. # self.arglist = arglist
  624. # self.lhs = lhs
  625. # self.lhslist = lhslist
  626. # self.rhs = rhs
  627. # self.rhslist = rhslist
  628. #
  629. # # if the class has the account_caller property set on itself, we make
  630. # # sure that self.caller is always the account if possible. We also create
  631. # # a special property "character" for the puppeted object, if any. This
  632. # # is convenient for commands defined on the Account only.
  633. # if hasattr(self, "account_caller") and self.account_caller:
  634. # if utils.inherits_from(self.caller, "evennia.objects.objects.DefaultObject"):
  635. # # caller is an Object/Character
  636. # self.character = self.caller
  637. # self.caller = self.caller.account
  638. # elif utils.inherits_from(self.caller, "evennia.accounts.accounts.DefaultAccount"):
  639. # # caller was already an Account
  640. # self.character = self.caller.get_puppet(self.session)
  641. # else:
  642. # self.character = None