From 655de3b654b0de39d5dfa7a8d192f26ae4275920 Mon Sep 17 00:00:00 2001 From: Griatch Date: Tue, 9 Nov 2021 23:11:19 +0100 Subject: [PATCH] Updated HTML docs --- docs/0.9.5/.buildinfo | 2 +- docs/0.9.5/Default-Commands.html | 34 +- docs/0.9.5/_sources/Default-Commands.md.txt | 34 +- .../api/evennia.commands.default.account.html | 2 +- ...evennia.commands.default.batchprocess.html | 2 +- .../evennia.commands.default.building.html | 6 +- .../api/evennia.commands.default.comms.html | 4 +- .../api/evennia.commands.default.general.html | 10 +- .../api/evennia.commands.default.system.html | 8 +- .../evennia.commands.default.unloggedin.html | 2 +- docs/0.9.5/api/evennia.contrib.chargen.html | 2 +- docs/0.9.5/api/evennia.contrib.clothing.html | 2 +- .../api/evennia.contrib.email_login.html | 2 +- .../api/evennia.contrib.extended_room.html | 2 +- ...vennia.contrib.ingame_python.commands.html | 2 +- docs/0.9.5/api/evennia.contrib.rpsystem.html | 2 +- ...b.tutorial_examples.cmdset_red_button.html | 6 +- ...vennia.contrib.tutorial_world.objects.html | 8 +- .../evennia.contrib.tutorial_world.rooms.html | 4 +- docs/0.9.5/api/evennia.utils.eveditor.html | 2 +- docs/0.9.5/api/evennia.utils.evmore.html | 2 +- docs/1.0-dev/.buildinfo | 2 +- docs/1.0-dev/Components/Attributes.html | 688 ++++++++++++------ docs/1.0-dev/Components/Default-Commands.html | 32 +- docs/1.0-dev/Components/Objects.html | 8 +- docs/1.0-dev/Howto/Coding-FAQ.html | 4 +- docs/1.0-dev/Howto/Gametime-Tutorial.html | 6 +- .../Starting/Part3/A-Sittable-Object.html | 4 +- .../Howto/Tutorial-Aggressive-NPCs.html | 4 +- .../_modules/evennia/accounts/accounts.html | 12 +- .../evennia/commands/default/admin.html | 26 +- .../evennia/commands/default/building.html | 20 +- .../evennia/commands/default/general.html | 28 +- .../evennia/commands/default/system.html | 1 + .../evennia/commands/default/tests.html | 2 +- .../1.0-dev/_modules/evennia/comms/comms.html | 10 +- .../evennia/contrib/custom_gametime.html | 27 +- .../_modules/evennia/contrib/rpsystem.html | 6 +- .../_modules/evennia/contrib/slow_exit.html | 2 +- .../_modules/evennia/contrib/traits.html | 6 +- .../evennia/contrib/turnbattle/tb_basic.html | 2 +- .../evennia/contrib/turnbattle/tb_equip.html | 6 +- .../evennia/contrib/turnbattle/tb_items.html | 2 +- .../evennia/contrib/turnbattle/tb_magic.html | 2 +- .../evennia/contrib/turnbattle/tb_range.html | 14 +- .../contrib/tutorial_world/objects.html | 2 +- .../_modules/evennia/contrib/wilderness.html | 10 +- .../_modules/evennia/objects/objects.html | 66 +- .../_modules/evennia/scripts/scripts.html | 23 +- .../_modules/evennia/server/deprecations.html | 4 + .../_modules/evennia/server/inputfuncs.html | 40 +- .../_modules/evennia/server/portal/mxp.html | 11 +- .../evennia/server/portal/webclient.html | 14 +- .../evennia/server/portal/webclient_ajax.html | 20 + .../evennia/typeclasses/attributes.html | 121 ++- .../_modules/evennia/typeclasses/tags.html | 18 +- docs/1.0-dev/_modules/evennia/utils/ansi.html | 14 +- .../evennia/web/utils/general_context.html | 71 +- .../_modules/evennia/web/utils/tests.html | 38 +- .../_sources/Components/Attributes.md.txt | 658 +++++++++++------ .../Components/Default-Commands.md.txt | 32 +- .../_sources/Components/Objects.md.txt | 8 +- docs/1.0-dev/_sources/Howto/Coding-FAQ.md.txt | 4 +- .../_sources/Howto/Gametime-Tutorial.md.txt | 5 +- .../Starting/Part3/A-Sittable-Object.md.txt | 4 +- .../Howto/Tutorial-Aggressive-NPCs.md.txt | 4 +- .../api/evennia.accounts.accounts.html | 12 + .../1.0-dev/api/evennia.commands.command.html | 2 +- ...evennia.commands.default.batchprocess.html | 4 +- .../evennia.commands.default.building.html | 27 +- .../api/evennia.commands.default.comms.html | 8 +- .../api/evennia.commands.default.general.html | 26 +- .../api/evennia.commands.default.system.html | 13 +- .../evennia.commands.default.unloggedin.html | 12 +- docs/1.0-dev/api/evennia.comms.comms.html | 11 + docs/1.0-dev/api/evennia.contrib.barter.html | 4 +- .../1.0-dev/api/evennia.contrib.clothing.html | 4 +- .../api/evennia.contrib.custom_gametime.html | 26 +- .../api/evennia.contrib.email_login.html | 12 +- .../evennia.contrib.evscaperoom.commands.html | 20 +- ...vennia.contrib.ingame_python.commands.html | 4 +- .../1.0-dev/api/evennia.contrib.rpsystem.html | 22 +- .../api/evennia.contrib.test_traits.html | 18 +- docs/1.0-dev/api/evennia.contrib.traits.html | 6 +- .../evennia.contrib.turnbattle.tb_basic.html | 4 +- .../evennia.contrib.turnbattle.tb_equip.html | 12 +- .../evennia.contrib.turnbattle.tb_items.html | 4 +- .../evennia.contrib.turnbattle.tb_magic.html | 4 +- .../evennia.contrib.turnbattle.tb_range.html | 22 +- ....contrib.tutorial_examples.red_button.html | 16 +- ...vennia.contrib.tutorial_world.objects.html | 16 +- .../evennia.contrib.tutorial_world.rooms.html | 4 +- .../api/evennia.contrib.wilderness.html | 4 +- docs/1.0-dev/api/evennia.objects.objects.html | 190 ++++- docs/1.0-dev/api/evennia.scripts.scripts.html | 7 +- .../api/evennia.server.inputfuncs.html | 13 +- .../evennia.server.portal.webclient_ajax.html | 14 + .../api/evennia.typeclasses.attributes.html | 67 +- .../1.0-dev/api/evennia.typeclasses.tags.html | 8 +- docs/1.0-dev/api/evennia.utils.ansi.html | 6 + docs/1.0-dev/api/evennia.utils.eveditor.html | 4 +- docs/1.0-dev/api/evennia.utils.evmenu.html | 4 +- docs/1.0-dev/api/evennia.utils.evmore.html | 4 +- .../evennia.web.utils.general_context.html | 18 +- docs/1.0-dev/api/evennia.web.utils.tests.html | 10 - docs/1.0-dev/genindex.html | 158 ++-- docs/1.0-dev/objects.inv | Bin 124552 -> 124751 bytes docs/1.0-dev/searchindex.js | 2 +- docs/1.0-dev/toc.html | 18 +- 109 files changed, 2106 insertions(+), 953 deletions(-) diff --git a/docs/0.9.5/.buildinfo b/docs/0.9.5/.buildinfo index 6e728d38a6..d872e8b3fb 100644 --- a/docs/0.9.5/.buildinfo +++ b/docs/0.9.5/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: d9dce5655627bbc3b289deb13b5ed2ba +config: eb5c4bd50b1e47098ad02aad6b87e391 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/0.9.5/Default-Commands.html b/docs/0.9.5/Default-Commands.html index 86c07404cc..1477f1514b 100644 --- a/docs/0.9.5/Default-Commands.html +++ b/docs/0.9.5/Default-Commands.html @@ -55,19 +55,19 @@ with
  • __unloggedin_look_command [l, look] (cmdset: UnloggedinCmdSet, help-category: General)

  • about [version] (cmdset: CharacterCmdSet, help-category: System)

  • -
  • access [hierarchy, groups] (cmdset: CharacterCmdSet, help-category: General)

  • -
  • accounts [listaccounts, account] (cmdset: CharacterCmdSet, help-category: System)

  • -
  • addcom [chanalias, aliaschan] (cmdset: AccountCmdSet, help-category: Comms)

  • +
  • access [groups, hierarchy] (cmdset: CharacterCmdSet, help-category: General)

  • +
  • accounts [account, listaccounts] (cmdset: CharacterCmdSet, help-category: System)

  • +
  • addcom [aliaschan, chanalias] (cmdset: AccountCmdSet, help-category: Comms)

  • alias [setobjalias] (cmdset: CharacterCmdSet, help-category: Building)

  • allcom (cmdset: AccountCmdSet, help-category: Comms)

  • batchcode [batchcodes] (cmdset: CharacterCmdSet, help-category: Building)

  • -
  • batchcommands [batchcmd, batchcommand] (cmdset: CharacterCmdSet, help-category: Building)

  • +
  • batchcommands [batchcommand, batchcmd] (cmdset: CharacterCmdSet, help-category: Building)

  • cboot (cmdset: AccountCmdSet, help-category: Comms)

  • ccreate [channelcreate] (cmdset: AccountCmdSet, help-category: Comms)

  • cdesc (cmdset: AccountCmdSet, help-category: Comms)

  • cdestroy (cmdset: AccountCmdSet, help-category: Comms)

  • cemit [cmsg] (cmdset: AccountCmdSet, help-category: Comms)

  • -
  • channels [comlist, clist, chanlist, channellist, all channels] (cmdset: AccountCmdSet, help-category: Comms)

  • +
  • channels [all channels, chanlist, channellist, comlist, clist] (cmdset: AccountCmdSet, help-category: Comms)

  • charcreate (cmdset: AccountCmdSet, help-category: General)

  • chardelete (cmdset: AccountCmdSet, help-category: General)

  • clock (cmdset: AccountCmdSet, help-category: Comms)

  • @@ -85,8 +85,8 @@ with dig (cmdset: CharacterCmdSet, help-category: Building)

  • drop (cmdset: CharacterCmdSet, help-category: General)

  • encoding [encode] (cmdset: UnloggedinCmdSet, help-category: General)

  • -
  • examine [exam, ex] (cmdset: AccountCmdSet, help-category: Building)

  • -
  • find [locate, search] (cmdset: CharacterCmdSet, help-category: Building)

  • +
  • examine [ex, exam] (cmdset: AccountCmdSet, help-category: Building)

  • +
  • find [search, locate] (cmdset: CharacterCmdSet, help-category: Building)

  • get [grab] (cmdset: CharacterCmdSet, help-category: General)

  • give (cmdset: CharacterCmdSet, help-category: General)

  • grapevine2chan (cmdset: AccountCmdSet, help-category: Comms)

  • @@ -95,35 +95,35 @@ with home (cmdset: CharacterCmdSet, help-category: General)

  • ic [puppet] (cmdset: AccountCmdSet, help-category: General)

  • info (cmdset: UnloggedinCmdSet, help-category: General)

  • -
  • inventory [inv, i] (cmdset: CharacterCmdSet, help-category: General)

  • +
  • inventory [i, inv] (cmdset: CharacterCmdSet, help-category: General)

  • irc2chan (cmdset: AccountCmdSet, help-category: Comms)

  • ircstatus (cmdset: AccountCmdSet, help-category: Comms)

  • link (cmdset: CharacterCmdSet, help-category: Building)

  • lock [locks] (cmdset: CharacterCmdSet, help-category: Building)

  • -
  • look [ls, l] (cmdset: AccountCmdSet, help-category: General)

  • -
  • look [ls, l] (cmdset: CharacterCmdSet, help-category: General)

  • +
  • look [l, ls] (cmdset: AccountCmdSet, help-category: General)

  • +
  • look [l, ls] (cmdset: CharacterCmdSet, help-category: General)

  • mvattr (cmdset: CharacterCmdSet, help-category: Building)

  • name [rename] (cmdset: CharacterCmdSet, help-category: Building)

  • nick [nicks, nickname] (cmdset: AccountCmdSet, help-category: General)

  • -
  • objects [listobjs, listobjects, db, stats] (cmdset: CharacterCmdSet, help-category: System)

  • +
  • objects [listobjects, db, stats, listobjs] (cmdset: CharacterCmdSet, help-category: System)

  • ooc [unpuppet] (cmdset: AccountCmdSet, help-category: General)

  • open (cmdset: CharacterCmdSet, help-category: Building)

  • option [options] (cmdset: AccountCmdSet, help-category: General)

  • page [tell] (cmdset: AccountCmdSet, help-category: Comms)

  • password (cmdset: AccountCmdSet, help-category: General)

  • -
  • pose [emote, :] (cmdset: CharacterCmdSet, help-category: General)

  • +
  • pose [:, emote] (cmdset: CharacterCmdSet, help-category: General)

  • py [!] (cmdset: AccountCmdSet, help-category: System)

  • quell [unquell] (cmdset: AccountCmdSet, help-category: General)

  • quit (cmdset: AccountCmdSet, help-category: General)

  • -
  • quit [q, qu] (cmdset: UnloggedinCmdSet, help-category: General)

  • +
  • quit [qu, q] (cmdset: UnloggedinCmdSet, help-category: General)

  • reload [restart] (cmdset: AccountCmdSet, help-category: System)

  • reset [reboot] (cmdset: AccountCmdSet, help-category: System)

  • rss2chan (cmdset: AccountCmdSet, help-category: Comms)

  • -
  • say [’, “] (cmdset: CharacterCmdSet, help-category: General)

  • +
  • say [”, ‘] (cmdset: CharacterCmdSet, help-category: General)

  • screenreader (cmdset: UnloggedinCmdSet, help-category: General)

  • script [addscript] (cmdset: CharacterCmdSet, help-category: Building)

  • -
  • scripts [globalscript, listscripts] (cmdset: CharacterCmdSet, help-category: System)

  • -
  • server [serverload, serverprocess] (cmdset: CharacterCmdSet, help-category: System)

  • +
  • scripts [listscripts, globalscript] (cmdset: CharacterCmdSet, help-category: System)

  • +
  • server [serverprocess, serverload] (cmdset: CharacterCmdSet, help-category: System)

  • service [services] (cmdset: CharacterCmdSet, help-category: System)

  • sessions (cmdset: SessionCmdSet, help-category: General)

  • set (cmdset: CharacterCmdSet, help-category: Building)

  • @@ -138,7 +138,7 @@ with tickers (cmdset: CharacterCmdSet, help-category: System)

  • time [uptime] (cmdset: CharacterCmdSet, help-category: System)

  • tunnel [tun] (cmdset: CharacterCmdSet, help-category: Building)

  • -
  • typeclass [swap, update, parent, type] (cmdset: CharacterCmdSet, help-category: Building)

  • +
  • typeclass [swap, type, parent, update] (cmdset: CharacterCmdSet, help-category: Building)

  • unlink (cmdset: CharacterCmdSet, help-category: Building)

  • whisper (cmdset: CharacterCmdSet, help-category: General)

  • who [doing] (cmdset: AccountCmdSet, help-category: General)

  • diff --git a/docs/0.9.5/_sources/Default-Commands.md.txt b/docs/0.9.5/_sources/Default-Commands.md.txt index 67c7fe6753..51aaf413b3 100644 --- a/docs/0.9.5/_sources/Default-Commands.md.txt +++ b/docs/0.9.5/_sources/Default-Commands.md.txt @@ -16,19 +16,19 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using - [**__unloggedin_look_command** [l, look]](evennia.commands.default.unloggedin.CmdUnconnectedLook) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_) - [**about** [version]](evennia.commands.default.system.CmdAbout) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) -- [**access** [hierarchy, groups]](evennia.commands.default.general.CmdAccess) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) -- [**accounts** [listaccounts, account]](evennia.commands.default.system.CmdAccounts) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) -- [**addcom** [chanalias, aliaschan]](evennia.commands.default.comms.CmdAddCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) +- [**access** [groups, hierarchy]](evennia.commands.default.general.CmdAccess) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) +- [**accounts** [account, listaccounts]](evennia.commands.default.system.CmdAccounts) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) +- [**addcom** [aliaschan, chanalias]](evennia.commands.default.comms.CmdAddCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**alias** [setobjalias]](evennia.commands.default.building.CmdSetObjAlias) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**allcom**](evennia.commands.default.comms.CmdAllCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**batchcode** [batchcodes]](evennia.commands.default.batchprocess.CmdBatchCode) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) -- [**batchcommands** [batchcmd, batchcommand]](evennia.commands.default.batchprocess.CmdBatchCommands) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) +- [**batchcommands** [batchcommand, batchcmd]](evennia.commands.default.batchprocess.CmdBatchCommands) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**cboot**](evennia.commands.default.comms.CmdCBoot) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**ccreate** [channelcreate]](evennia.commands.default.comms.CmdChannelCreate) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**cdesc**](evennia.commands.default.comms.CmdCdesc) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**cdestroy**](evennia.commands.default.comms.CmdCdestroy) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**cemit** [cmsg]](evennia.commands.default.comms.CmdCemit) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) -- [**channels** [comlist, clist, chanlist, channellist, all channels]](evennia.commands.default.comms.CmdChannels) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) +- [**channels** [all channels, chanlist, channellist, comlist, clist]](evennia.commands.default.comms.CmdChannels) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**charcreate**](evennia.commands.default.account.CmdCharCreate) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) - [**chardelete**](evennia.commands.default.account.CmdCharDelete) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) - [**clock**](evennia.commands.default.comms.CmdClock) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) @@ -46,8 +46,8 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using - [**dig**](evennia.commands.default.building.CmdDig) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**drop**](evennia.commands.default.general.CmdDrop) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**encoding** [encode]](evennia.commands.default.unloggedin.CmdUnconnectedEncoding) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_) -- [**examine** [exam, ex]](evennia.commands.default.building.CmdExamine) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Building_) -- [**find** [locate, search]](evennia.commands.default.building.CmdFind) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) +- [**examine** [ex, exam]](evennia.commands.default.building.CmdExamine) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Building_) +- [**find** [search, locate]](evennia.commands.default.building.CmdFind) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**get** [grab]](evennia.commands.default.general.CmdGet) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**give**](evennia.commands.default.general.CmdGive) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**grapevine2chan**](evennia.commands.default.comms.CmdGrapevine2Chan) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) @@ -56,35 +56,35 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using - [**home**](evennia.commands.default.general.CmdHome) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**ic** [puppet]](evennia.commands.default.account.CmdIC) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) - [**info**](evennia.commands.default.unloggedin.CmdUnconnectedInfo) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_) -- [**inventory** [inv, i]](evennia.commands.default.general.CmdInventory) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) +- [**inventory** [i, inv]](evennia.commands.default.general.CmdInventory) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**irc2chan**](evennia.commands.default.comms.CmdIRC2Chan) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**ircstatus**](evennia.commands.default.comms.CmdIRCStatus) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**link**](evennia.commands.default.building.CmdLink) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**lock** [locks]](evennia.commands.default.building.CmdLock) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) -- [**look** [ls, l]](evennia.commands.default.account.CmdOOCLook) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) -- [**look** [ls, l]](evennia.commands.default.general.CmdLook) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) +- [**look** [l, ls]](evennia.commands.default.account.CmdOOCLook) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) +- [**look** [l, ls]](evennia.commands.default.general.CmdLook) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**mvattr**](evennia.commands.default.building.CmdMvAttr) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**name** [rename]](evennia.commands.default.building.CmdName) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**nick** [nicks, nickname]](evennia.commands.default.general.CmdNick) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) -- [**objects** [listobjs, listobjects, db, stats]](evennia.commands.default.system.CmdObjects) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) +- [**objects** [listobjects, db, stats, listobjs]](evennia.commands.default.system.CmdObjects) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) - [**ooc** [unpuppet]](evennia.commands.default.account.CmdOOC) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) - [**open**](evennia.commands.default.building.CmdOpen) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**option** [options]](evennia.commands.default.account.CmdOption) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) - [**page** [tell]](evennia.commands.default.comms.CmdPage) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**password**](evennia.commands.default.account.CmdPassword) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) -- [**pose** [emote, :]](evennia.commands.default.general.CmdPose) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) +- [**pose** [:, emote]](evennia.commands.default.general.CmdPose) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**py** [!]](evennia.commands.default.system.CmdPy) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_) - [**quell** [unquell]](evennia.commands.default.account.CmdQuell) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) - [**quit**](evennia.commands.default.account.CmdQuit) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) -- [**quit** [q, qu]](evennia.commands.default.unloggedin.CmdUnconnectedQuit) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_) +- [**quit** [qu, q]](evennia.commands.default.unloggedin.CmdUnconnectedQuit) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_) - [**reload** [restart]](evennia.commands.default.system.CmdReload) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_) - [**reset** [reboot]](evennia.commands.default.system.CmdReset) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_) - [**rss2chan**](evennia.commands.default.comms.CmdRSS2Chan) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) -- [**say** [', "]](evennia.commands.default.general.CmdSay) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) +- [**say** [", ']](evennia.commands.default.general.CmdSay) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**screenreader**](evennia.commands.default.unloggedin.CmdUnconnectedScreenreader) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_) - [**script** [addscript]](evennia.commands.default.building.CmdScript) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) -- [**scripts** [globalscript, listscripts]](evennia.commands.default.system.CmdScripts) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) -- [**server** [serverload, serverprocess]](evennia.commands.default.system.CmdServerLoad) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) +- [**scripts** [listscripts, globalscript]](evennia.commands.default.system.CmdScripts) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) +- [**server** [serverprocess, serverload]](evennia.commands.default.system.CmdServerLoad) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) - [**service** [services]](evennia.commands.default.system.CmdService) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) - [**sessions**](evennia.commands.default.account.CmdSessions) (cmdset: [SessionCmdSet](evennia.commands.default.cmdset_session.SessionCmdSet), help-category: _General_) - [**set**](evennia.commands.default.building.CmdSetAttribute) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) @@ -99,7 +99,7 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using - [**tickers**](evennia.commands.default.system.CmdTickers) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) - [**time** [uptime]](evennia.commands.default.system.CmdTime) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) - [**tunnel** [tun]](evennia.commands.default.building.CmdTunnel) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) -- [**typeclass** [swap, update, parent, type]](evennia.commands.default.building.CmdTypeclass) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) +- [**typeclass** [swap, type, parent, update]](evennia.commands.default.building.CmdTypeclass) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**unlink**](evennia.commands.default.building.CmdUnLink) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**whisper**](evennia.commands.default.general.CmdWhisper) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**who** [doing]](evennia.commands.default.account.CmdWho) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) diff --git a/docs/0.9.5/api/evennia.commands.default.account.html b/docs/0.9.5/api/evennia.commands.default.account.html index d998c2f3e5..b0883f258d 100644 --- a/docs/0.9.5/api/evennia.commands.default.account.html +++ b/docs/0.9.5/api/evennia.commands.default.account.html @@ -72,7 +72,7 @@ method. Otherwise all text will be returned to all connected sessions.

    -aliases = ['ls', 'l']
    +aliases = ['l', 'ls']
    diff --git a/docs/0.9.5/api/evennia.commands.default.batchprocess.html b/docs/0.9.5/api/evennia.commands.default.batchprocess.html index 161ff09962..eddc3b8e06 100644 --- a/docs/0.9.5/api/evennia.commands.default.batchprocess.html +++ b/docs/0.9.5/api/evennia.commands.default.batchprocess.html @@ -77,7 +77,7 @@ skipping, reloading etc.

    -aliases = ['batchcmd', 'batchcommand']
    +aliases = ['batchcommand', 'batchcmd']
    diff --git a/docs/0.9.5/api/evennia.commands.default.building.html b/docs/0.9.5/api/evennia.commands.default.building.html index 69f6811aed..e11b1ddcc8 100644 --- a/docs/0.9.5/api/evennia.commands.default.building.html +++ b/docs/0.9.5/api/evennia.commands.default.building.html @@ -1185,7 +1185,7 @@ server settings.

    -aliases = ['swap', 'update', 'parent', 'type']
    +aliases = ['swap', 'type', 'parent', 'update']
    @@ -1354,7 +1354,7 @@ If object is not specified, the current location is examined.

    -aliases = ['exam', 'ex']
    +aliases = ['ex', 'exam']
    @@ -1480,7 +1480,7 @@ one is given.

    -aliases = ['locate', 'search']
    +aliases = ['search', 'locate']
    diff --git a/docs/0.9.5/api/evennia.commands.default.comms.html b/docs/0.9.5/api/evennia.commands.default.comms.html index b32c6dccc3..8adceb2c70 100644 --- a/docs/0.9.5/api/evennia.commands.default.comms.html +++ b/docs/0.9.5/api/evennia.commands.default.comms.html @@ -66,7 +66,7 @@ aliases to an already joined channel.

    -aliases = ['chanalias', 'aliaschan']
    +aliases = ['aliaschan', 'chanalias']
    @@ -221,7 +221,7 @@ Use addcom/delcom to join and leave channels

    -aliases = ['comlist', 'clist', 'chanlist', 'channellist', 'all channels']
    +aliases = ['all channels', 'chanlist', 'channellist', 'comlist', 'clist']
    diff --git a/docs/0.9.5/api/evennia.commands.default.general.html b/docs/0.9.5/api/evennia.commands.default.general.html index 6e57fe233a..6a2ff1ebf1 100644 --- a/docs/0.9.5/api/evennia.commands.default.general.html +++ b/docs/0.9.5/api/evennia.commands.default.general.html @@ -109,7 +109,7 @@ look *<account&g
    -aliases = ['ls', 'l']
    +aliases = ['l', 'ls']
    @@ -247,7 +247,7 @@ inv

    -aliases = ['inv', 'i']
    +aliases = ['i', 'inv']
    @@ -497,7 +497,7 @@ placing it in their inventory.

    -aliases = ["'", '"']
    +aliases = ['"', "'"]
    @@ -593,7 +593,7 @@ automatically begin with your name.

    -aliases = ['emote', ':']
    +aliases = [':', 'emote']
    @@ -647,7 +647,7 @@ which permission groups you are a member of.

    -aliases = ['hierarchy', 'groups']
    +aliases = ['groups', 'hierarchy']
    diff --git a/docs/0.9.5/api/evennia.commands.default.system.html b/docs/0.9.5/api/evennia.commands.default.system.html index 9ab9d84d9a..cea181430d 100644 --- a/docs/0.9.5/api/evennia.commands.default.system.html +++ b/docs/0.9.5/api/evennia.commands.default.system.html @@ -296,7 +296,7 @@ required since whole classes of scripts often have the same name.

    -aliases = ['globalscript', 'listscripts']
    +aliases = ['listscripts', 'globalscript']
    @@ -351,7 +351,7 @@ given, <nr> defaults to 10.

    -aliases = ['listobjs', 'listobjects', 'db', 'stats']
    +aliases = ['listobjects', 'db', 'stats', 'listobjs']
    @@ -558,7 +558,7 @@ the released memory will instead be re-used by the program.

    -aliases = ['serverload', 'serverprocess']
    +aliases = ['serverprocess', 'serverload']
    @@ -611,7 +611,7 @@ If not given, <nr> defaults to 10.

    -aliases = ['listaccounts', 'account']
    +aliases = ['account', 'listaccounts']
    diff --git a/docs/0.9.5/api/evennia.commands.default.unloggedin.html b/docs/0.9.5/api/evennia.commands.default.unloggedin.html index 41ee893a06..b0571f8116 100644 --- a/docs/0.9.5/api/evennia.commands.default.unloggedin.html +++ b/docs/0.9.5/api/evennia.commands.default.unloggedin.html @@ -165,7 +165,7 @@ version is a bit more complicated.

    -aliases = ['q', 'qu']
    +aliases = ['qu', 'q']
    diff --git a/docs/0.9.5/api/evennia.contrib.chargen.html b/docs/0.9.5/api/evennia.contrib.chargen.html index f372385159..9e00f6eb52 100644 --- a/docs/0.9.5/api/evennia.contrib.chargen.html +++ b/docs/0.9.5/api/evennia.contrib.chargen.html @@ -79,7 +79,7 @@ at them with this command.

    -aliases = ['ls', 'l']
    +aliases = ['l', 'ls']
    diff --git a/docs/0.9.5/api/evennia.contrib.clothing.html b/docs/0.9.5/api/evennia.contrib.clothing.html index 8724097a0d..0246dce8b4 100644 --- a/docs/0.9.5/api/evennia.contrib.clothing.html +++ b/docs/0.9.5/api/evennia.contrib.clothing.html @@ -600,7 +600,7 @@ inv

    -aliases = ['inv', 'i']
    +aliases = ['i', 'inv']
    diff --git a/docs/0.9.5/api/evennia.contrib.email_login.html b/docs/0.9.5/api/evennia.contrib.email_login.html index 8577fc2f54..26d20d1ca5 100644 --- a/docs/0.9.5/api/evennia.contrib.email_login.html +++ b/docs/0.9.5/api/evennia.contrib.email_login.html @@ -173,7 +173,7 @@ version is a bit more complicated.

    -aliases = ['q', 'qu']
    +aliases = ['qu', 'q']
    diff --git a/docs/0.9.5/api/evennia.contrib.extended_room.html b/docs/0.9.5/api/evennia.contrib.extended_room.html index 49101e5261..474c34e256 100644 --- a/docs/0.9.5/api/evennia.contrib.extended_room.html +++ b/docs/0.9.5/api/evennia.contrib.extended_room.html @@ -278,7 +278,7 @@ look *<account&g
    -aliases = ['ls', 'l']
    +aliases = ['l', 'ls']
    diff --git a/docs/0.9.5/api/evennia.contrib.ingame_python.commands.html b/docs/0.9.5/api/evennia.contrib.ingame_python.commands.html index c8d2332063..7740a38017 100644 --- a/docs/0.9.5/api/evennia.contrib.ingame_python.commands.html +++ b/docs/0.9.5/api/evennia.contrib.ingame_python.commands.html @@ -54,7 +54,7 @@
    -aliases = ['@calls', '@callbacks', '@callback']
    +aliases = ['@callback', '@calls', '@callbacks']
    diff --git a/docs/0.9.5/api/evennia.contrib.rpsystem.html b/docs/0.9.5/api/evennia.contrib.rpsystem.html index 0b6404cbe1..afb5f48ed3 100644 --- a/docs/0.9.5/api/evennia.contrib.rpsystem.html +++ b/docs/0.9.5/api/evennia.contrib.rpsystem.html @@ -625,7 +625,7 @@ a different language.

    -aliases = ["'", '"']
    +aliases = ['"', "'"]
    diff --git a/docs/0.9.5/api/evennia.contrib.tutorial_examples.cmdset_red_button.html b/docs/0.9.5/api/evennia.contrib.tutorial_examples.cmdset_red_button.html index 51a571867d..f5a2bd252d 100644 --- a/docs/0.9.5/api/evennia.contrib.tutorial_examples.cmdset_red_button.html +++ b/docs/0.9.5/api/evennia.contrib.tutorial_examples.cmdset_red_button.html @@ -107,7 +107,7 @@ push the lid of the button away.

    -aliases = ['press button', 'push', 'press']
    +aliases = ['press', 'press button', 'push']
    @@ -155,7 +155,7 @@ lid-state respectively.

    -aliases = ['smash', 'smash lid', 'break lid']
    +aliases = ['break lid', 'smash', 'smash lid']
    @@ -284,7 +284,7 @@ of causing the lamp to break.

    -aliases = ['listen', 'feel', 'ex', 'examine', 'get', 'l']
    +aliases = ['listen', 'examine', 'get', 'ex', 'l', 'feel']
    diff --git a/docs/0.9.5/api/evennia.contrib.tutorial_world.objects.html b/docs/0.9.5/api/evennia.contrib.tutorial_world.objects.html index bbfd706ea7..44ab316d69 100644 --- a/docs/0.9.5/api/evennia.contrib.tutorial_world.objects.html +++ b/docs/0.9.5/api/evennia.contrib.tutorial_world.objects.html @@ -353,7 +353,7 @@ of the object. We overload it with our own version.

    -aliases = ['burn', 'light']
    +aliases = ['light', 'burn']
    @@ -479,7 +479,7 @@ shift green root up/down

    -aliases = ['shiftroot', 'pull', 'move', 'push']
    +aliases = ['push', 'pull', 'move', 'shiftroot']
    @@ -527,7 +527,7 @@ yellow/green - horizontal roots

    -aliases = ['press button', 'button', 'push button']
    +aliases = ['button', 'push button', 'press button']
    @@ -692,7 +692,7 @@ parry - forgoes your attack but will make you harder to hit on next

    -aliases = ['slash', 'hit', 'stab', 'parry', 'defend', 'pierce', 'bash', 'kill', 'thrust', 'fight', 'chop']
    +aliases = ['chop', 'hit', 'pierce', 'parry', 'kill', 'thrust', 'bash', 'stab', 'slash', 'defend', 'fight']
    diff --git a/docs/0.9.5/api/evennia.contrib.tutorial_world.rooms.html b/docs/0.9.5/api/evennia.contrib.tutorial_world.rooms.html index f47df8eb9a..a9fee42514 100644 --- a/docs/0.9.5/api/evennia.contrib.tutorial_world.rooms.html +++ b/docs/0.9.5/api/evennia.contrib.tutorial_world.rooms.html @@ -176,7 +176,7 @@ code except for adding in the details.

    -aliases = ['ls', 'l']
    +aliases = ['l', 'ls']
    @@ -822,7 +822,7 @@ to find something.

    -aliases = ['feel', 'fiddle', 'search', 'feel around', 'l']
    +aliases = ['search', 'fiddle', 'feel around', 'l', 'feel']
    diff --git a/docs/0.9.5/api/evennia.utils.eveditor.html b/docs/0.9.5/api/evennia.utils.eveditor.html index b4aa05ddca..5d6a57a2e2 100644 --- a/docs/0.9.5/api/evennia.utils.eveditor.html +++ b/docs/0.9.5/api/evennia.utils.eveditor.html @@ -267,7 +267,7 @@ indentation.

    -aliases = [':I', ':echo', ':y', ':x', ':q!', ':DD', ':u', ':fd', ':uu', '::', ':r', ':S', ':::', ':wq', ':q', ':=', ':dd', ':!', ':<', ':i', ':', ':A', ':f', ':>', ':UU', ':w', ':dw', ':s', ':h', ':fi', ':j', ':p']
    +aliases = [':!', ':fd', ':::', ':i', ':', ':u', ':I', ':S', ':>', ':y', ':A', ':DD', ':fi', ':j', ':dd', ':h', ':echo', ':wq', '::', ':dw', ':q', ':r', ':q!', ':=', ':uu', ':p', ':w', ':UU', ':s', ':x', ':<', ':f']
    diff --git a/docs/0.9.5/api/evennia.utils.evmore.html b/docs/0.9.5/api/evennia.utils.evmore.html index 14b6950326..e7d34f0b87 100644 --- a/docs/0.9.5/api/evennia.utils.evmore.html +++ b/docs/0.9.5/api/evennia.utils.evmore.html @@ -77,7 +77,7 @@ the caller.msg() construct every time the page is updated.

    -aliases = ['n', 'next', 'end', 'a', 'quit', 't', 'e', 'q', 'top', 'back', 'abort', 'b']
    +aliases = ['a', 'next', 'quit', 'end', 'back', 't', 'q', 'e', 'abort', 'top', 'b', 'n']
    diff --git a/docs/1.0-dev/.buildinfo b/docs/1.0-dev/.buildinfo index 12ba66edee..f195402fab 100644 --- a/docs/1.0-dev/.buildinfo +++ b/docs/1.0-dev/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: bf597f1b13a7ac66cd6857c80dafbcd7 +config: a72408074ef7fdbab8dad1aebe94792b tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/1.0-dev/Components/Attributes.html b/docs/1.0-dev/Components/Attributes.html index b90ff07e10..473ce19808 100644 --- a/docs/1.0-dev/Components/Attributes.html +++ b/docs/1.0-dev/Components/Attributes.html @@ -42,212 +42,406 @@

    Attributes

    -

    When performing actions in Evennia it is often important that you store data for later. If you write -a menu system, you have to keep track of the current location in the menu tree so that the player -can give correct subsequent commands. If you are writing a combat system, you might have a -combattant’s next roll get easier dependent on if their opponent failed. Your characters will -probably need to store roleplaying-attributes like strength and agility. And so on.

    -

    Typeclassed game entities (Accounts, Objects, -Scripts and Channels) always have Attributes associated with them. -Attributes are used to store any type of data ‘on’ such entities. This is different from storing -data in properties already defined on entities (such as key or location) - these have very -specific names and require very specific types of data (for example you couldn’t assign a python -list to the key property no matter how hard you tried). Attributes come into play when you -want to assign arbitrary data to arbitrary names.

    -

    Attributes are not secure by default and any player may be able to change them unless you -prevent this behavior.

    -
    -

    The .db and .ndb shortcuts

    -

    To save persistent data on a Typeclassed object you normally use the db (DataBase) operator. Let’s -try to save some data to a Rose (an Object):

    -
        # saving
    -    rose.db.has_thorns = True
    -    # getting it back
    -    is_ouch = rose.db.has_thorns
    +
    # in-game 
    +> set obj/myattr = "test"
     
    +# in code 
    +obj.db.foo = [1,2,3, "bar"]
    +value = obj.db.foo
    +
    +obj.attributes.add("myattr", 1234, category="bar")
    +value = attributes.get("myattr", category="bar")
     
    -

    This looks like any normal Python assignment, but that db makes sure that an Attribute is -created behind the scenes and is stored in the database. Your rose will continue to have thorns -throughout the life of the server now, until you deliberately remove them.

    -

    To be sure to save non-persistently, i.e. to make sure NOT to create a database entry, you use -ndb (NonDataBase). It works in the same way:

    -
        # saving
    -    rose.ndb.has_thorns = True
    -    # getting it back
    -    is_ouch = rose.ndb.has_thorns
    -
    -
    -

    Technically, ndb has nothing to do with Attributes, despite how similar they look. No -Attribute object is created behind the scenes when using ndb. In fact the database is not -invoked at all since we are not interested in persistence. There is however an important reason to -use ndb to store data rather than to just store variables direct on entities - ndb-stored data -is tracked by the server and will not be purged in various cache-cleanup operations Evennia may do -while it runs. Data stored on ndb (as well as db) will also be easily listed by example the -@examine command.

    -

    You can also del properties on db and ndb as normal. This will for example delete an -Attribute:

    -
        del rose.db.has_thorns
    -
    -
    -

    Both db and ndb defaults to offering an all property on themselves. This returns all -associated attributes or non-persistent properties.

    -
         list_of_all_rose_attributes = rose.db.all
    -     list_of_all_rose_ndb_attrs = rose.ndb.all
    -
    -
    -

    If you use all as the name of an attribute, this will be used instead. Later deleting your custom -all will return the default behaviour.

    -
    -
    -

    The AttributeHandler

    -

    The .db and .ndb properties are very convenient but if you don’t know the name of the Attribute -beforehand they cannot be used. Behind the scenes .db actually accesses the AttributeHandler -which sits on typeclassed entities as the .attributes property. .ndb does the same for the -.nattributes property.

    -

    The handlers have normal access methods that allow you to manage and retrieve Attributes and -NAttributes:

    +

    Attributes allow you to to store arbitrary data on objects and make sure the data survives a +server reboot. An Attribute can store pretty much any +Python data structure and data type, like numbers, strings, lists, dicts etc. You can also +store (references to) database objects like characters and rooms.

      -
    • has('attrname') - this checks if the object has an Attribute with this key. This is equivalent -to doing obj.db.attrname.

    • -
    • get(...) - this retrieves the given Attribute. Normally the value property of the Attribute is -returned, but the method takes keywords for returning the Attribute object itself. By supplying an +

    • What can be stored in an Attribute is a must-read +also for experienced developers, to avoid getting surprised. Attributes can store almost everything +but you need to know the quirks.

    • +
    • NAttributes are the in-memory, non-persistent +siblings of Attributes.

    • +
    • Managing Attributes In-game for in-game builder commands.

    • +
    +
    +

    Managing Attributes in Code

    +

    Attributes are usually handled in code. All Typeclassed entities +(Accounts, Objects, Scripts and +Channels) all can (and usually do) have Attributes associated with them. There +are three ways to manage Attributes, all of which can be mixed.

    + +
    +

    Using .db

    +

    The simplest way to get/set Attributes is to use the .db shortcut:

    +
    import evennia 
    +
    +obj = evennia.create_object(key="Foo")
    +
    +obj.db.foo1 = 1234
    +obj.db.foo2 = [1, 2, 3, 4]
    +obj.db.weapon = "sword"
    +obj.db.self_reference = obj   # stores a reference to the obj
    +
    +# (let's assume a rose exists in-game)
    +rose = evennia.search_object(key="rose")[0]  # returns a list, grab 0th element
    +rose.db.has_thorns = True
    +
    +# retrieving  
    +val1 = obj.db.foo1
    +val2 = obj.db.foo2
    +weap = obj.db.weapon 
    +myself = obj.db.self_reference  # retrieve reference from db, get object back
    +
    +is_ouch = rose.db.has_thorns
    +
    +# this will return None, not AttributeError!
    +not_found = obj.db.jiwjpowiwwerw
    +
    +# returns all Attributes on the object 
    +obj.db.all 
    +
    +# delete an Attribute
    +del obj.db.foo2
    +
    +
    +

    Trying to access a non-existing Attribute will never lead to an AttributeError. Instead +you will get None back. The special .db.all will return a list of all Attributes on +the object. You can replace this with your own Attribute all if you want, it will replace the +default all functionality until you delete it again.

    +
    +
    +

    Using .attributes

    +

    If you don’t know the name of the Attribute beforehand you can also use +the AttributeHandler, available as .attributes. With no extra keywords this is identical +to using the .db shortcut (.db is actually using the AttributeHandler internally):

    +
    is_ouch = rose.attributes.get("has_thorns") 
    + 
    +obj.attributes.add("helmet", "Knight's helmet")
    +helmet = obj.attributes.get("helmet")
    +
    +# you can give space-separated Attribute-names (can't do that with .db)
    +obj.attributes.add("my game log", "long text about ...")
    +
    +
    +

    With the AttributeHandler you can also give Attributes a category. By using a category you can +separate same-named Attributes on the same object which can help organization:

    +
    # store (let's say we have gold_necklace and ringmail_armor from before)
    +obj.attributes.add("neck", gold_necklace, category="clothing")
    +obj.attributes.add("neck", ringmail_armor, category="armor")
    +
    +# retrieve later - we'll get back gold_necklace and ringmail_armor
    +neck_clothing = obj.attributes.get("neck", category="clothing")
    +neck_armor = obj.attributes.get("neck", category="armor")
    +
    +
    +

    If you don’t specify a category, the Attribute’s category will be None. Note that +None is also considered a category of its own, so you won’t find None-category Attributes mixed +with Attributes having categories.

    +
    +

    When using .db, you will always use the None category.

    +
    +

    Here are the methods of the AttributeHandler. See +the AttributeHandler API for more details.

    +
      +
    • has(...) - this checks if the object has an Attribute with this key. This is equivalent +to doing obj.db.attrname except you can also check for a specific `category.

    • +
    • get(...) - this retrieves the given Attribute. You can also provide a default value to return +if the Attribute is not defined (instead of None). By supplying an accessing_object to the call one can also make sure to check permissions before modifying -anything.

    • +anything. The raise_exception kwarg allows you to raise an AttributeError instead of returning +None when you access a non-existing Attribute. The strattr kwarg tells the system to store +the Attribute as a raw string rather than to pickle it. While an optimization this should usually +not be used unless the Attribute is used for some particular, limited purpose.

    • add(...) - this adds a new Attribute to the object. An optional lockstring can be supplied here to restrict future access and also the call itself may be checked against locks.

    • remove(...) - Remove the given Attribute. This can optionally be made to check for permission before performing the deletion. - clear(...) - removes all Attributes from object.

    • -
    • all(...) - returns all Attributes (of the given category) attached to this object.

    • +
    • all(category=None) - returns all Attributes (of the given category) attached to this object.

    -

    See this section for more about locking down Attribute -access and editing. The Nattribute offers no concept of access control.

    -

    Some examples:

    -
        import evennia
    -    obj = evennia.search_object("MyObject")
    +

    Examples:

    +
    try:
    +  # raise error if Attribute foo does not exist 
    +  val = obj.attributes.get("foo", raise_exception=True):
    +except AttributeError:
    +   # ...
    +  
    +# return default value if foo2 doesn't exist
    +val2 = obj.attributes.get("foo2", default=[1, 2, 3, "bar"]) 
     
    -    obj.attributes.add("test", "testvalue")
    -    print(obj.db.test)                 # prints "testvalue"
    -    print(obj.attributes.get("test"))  #       "
    -    print(obj.attributes.all())        # prints [<AttributeObject>]
    -    obj.attributes.remove("test")
    +# delete foo if it exists (will silently fail if unset, unless
    +# raise_exception is set)
    +obj.attributes.remove("foo")
    +  
    +# view all clothes on obj
    +all_clothes = obj.attributes.all(category="clothes") 
     
    -
    -

    Properties of Attributes

    -

    An Attribute object is stored in the database. It has the following properties:

    +
    +

    Using AttributeProperty

    +

    There is a third way to set up an Attribute, and that is by setting up an AttributeProperty. This +is done on the class level of your typeclass and allows you to treat Attributes a bit like Django +database Fields.

    +
    # mygame/typeclasses/characters.py
    +
    +from evennia import DefaultCharacter
    +from evennia.typeclasses.attributes import AttributeProperty
    +
    +class Character(DefaultCharacter):
    +
    +    strength = AttributeProperty(default=10, category='stat', autocreate=True)
    +    constitution = AttributeProperty(default=10, category='stat', autocreate=True)
    +    agility = AttributeProperty(default=10, category='stat', autocreate=True)
    +    magic = AttributeProperty(default=10, category='stat', autocreate=True)
    +    
    +    sleepy = AttributeProperty(default=False)
    +    poisoned = AttributeProperty(default=False)
    +    
    +    def at_object_creation(self): 
    +      # ... 
    +
    +
    +

    These “Attribute-properties” will be made available to all instances of the class.

    +
    +

    Important

    +

    If you change the default of an AttributeProperty (and reload), it will +change the default for all instances of that class (it will not override +explicitly changed values).

    +
    +
    char = evennia.search_object(Character, key="Bob")[0]  # returns list, get 0th element
    +
    +# get defaults 
    +strength = char.strength   # will get the default value 10
    +
    +# assign new values (this will create/update new Attributes)
    +char.strength = 12
    +char.constitution = 16
    +char.agility = 8
    +char.magic = 2
    +
    +# you can also do arithmetic etc 
    +char.magic += 2   # char.magic is now 4
    +
    +# check Attributes 
    +strength = char.strength   # this is now 12
    +is_sleepy = char.sleepy 
    +is_poisoned = char.poisoned
    +
    +del char.strength   # wipes the Attribute
    +strength  = char.strengh  # back to the default (10) again
    +
    +
    +

    See the AttributeProperty docs for more +details on arguments.

    +

    An AttributeProperty will not create an Attribute by default. A new Attribute will be created +(or an existing one retrieved/updated) will happen differently depending on how the autocreate +keyword:

      -
    • key - the name of the Attribute. When doing e.g. obj.db.attrname = value, this property is set -to attrname.

    • -
    • value - this is the value of the Attribute. This value can be anything which can be pickled - -objects, lists, numbers or what have you (see -this section for more info). In the -example -obj.db.attrname = value, the value is stored here.

    • -
    • category - this is an optional property that is set to None for most Attributes. Setting this -allows to use Attributes for different functionality. This is usually not needed unless you want -to use Attributes for very different functionality (Nicks is an example of using -Attributes -in this way). To modify this property you need to use the -Attribute Handler.

    • -
    • strvalue - this is a separate value field that only accepts strings. This severely limits the -data possible to store, but allows for easier database lookups. This property is usually not used -except when re-using Attributes for some other purpose (Nicks use it). It is only -accessible via the Attribute Handler.

    • +
    • If autocreate=False (default), an Attribute will be created only if the field is explicitly +assigned a value (even if the value is the same as the default, such as char.strength = 10).

    • +
    • If autocreate=True, an Attribute will be created as soon as the field is accessed in +any way (So both strength = char.strength and char.strength = 10 will both make sure that +an Attribute exists.

    -

    There are also two special properties:

    -
      -
    • attrtype - this is used internally by Evennia to separate Nicks, from Attributes (Nicks -use Attributes behind the scenes).

    • -
    • model - this is a natural-key describing the model this Attribute is attached to. This is on -the form appname.modelclass, like objects.objectdb. It is used by the Attribute and -NickHandler to quickly sort matches in the database. Neither this nor attrtype should normally -need to be modified.

    • -
    -

    Non-database attributes have no equivalence to category nor strvalue, attrtype or model.

    +

    Example:

    +
    # in mygame/typeclasses/objects.py 
    +
    +from evennia import create_object 
    +from evennia import DefaultObject
    +from evennia.typeclasses.attributes import AttributeProperty
    +
    +class Object(DefaultObject):
    +  
    +    value_a = AttributeProperty(default="foo")
    +    value_b = AttributeProperty(default="bar", autocreate=True)
    +    
    +obj = evennia.create_object(key="Dummy")
    +
    +# these will find NO Attributes! 
    +obj.db.value_a 
    +obj.attributes.get("value_a")
    +obj.db.value_b 
    +obj.attributes.get("value_b")
    +
    +# get data from attribute-properties
    +vala = obj.value_a  # returns "foo"
    +valb = obj.value_b  # return "bar" AND creates the Attribute (autocreate)
    +
    +# the autocreate property will now be found 
    +obj.db.value_a                      # still not found 
    +obj.attributes.get("value_a")       #       ''
    +obj.db.value_b                      # now returns "bar" 
    +obj.attributes.get("value_b")       #       ''
    +
    +# assign new values 
    +obj.value_a = 10   # will now create a new Attribute 
    +obj.value_b = 12   # will update the existing Attribute 
    +
    +# both are now found as Attributes 
    +obj.db.value_a                      # now returns 10
    +obj.attributes.get("value_a")       #       ''
    +obj.db.value_b                      # now returns 12
    +obj.attributes.get("value_b")       #       ''
    +
    +
    +

    If you always access your Attributes via the AttributeProperty this does not matter that much +(it’s also a bit of an optimization to not create an actual database Attribute unless the value changed). +But until an Attribute has been created, AttributeProperty fields will not show up with the +examine command or by using the .db or .attributes handlers - so this is a bit inconsistent. +If this is important, you need to ‘initialize’ them by accessing them at least once … something +like this:

    +
    # ... 
    +class Character(DefaultCharacter):
    +
    +    strength = AttributeProperty(12, autocreate=True)
    +    agility = AttributeProperty(12, autocreate=True)
    +
    +
    +    def at_object_creation(self):
    +        # initializing 
    +        self.strength   # by accessing it, the Attribute is auto-created
    +        self.agility    #             ''
    +
    +
    +
    +

    Important

    +

    If you created your AttributeProperty with a category, you must specify the +category in .attributes.get() if you want to find it this way. Remember that +.db always uses a category of None.

    +
    -
    -

    Persistent vs non-persistent

    -

    So persistent data means that your data will survive a server reboot, whereas with -non-persistent data it will not …

    -

    … So why would you ever want to use non-persistent data? The answer is, you don’t have to. Most of -the time you really want to save as much as you possibly can. Non-persistent data is potentially -useful in a few situations though.

    +
    +
    +

    Managing Attributes in-game

    +

    Attributes are mainly used by code. But one can also allow the builder to use Attributes to +‘turn knobs’ in-game. For example a builder could want to manually tweak the “level” Attribute of an +enemy NPC to lower its difficuly.

    +

    When setting Attributes this way, you are severely limited in what can be stored - this is because +giving players (even builders) the ability to store arbitrary Python would be a severe security +problem.

    +

    In game you can set an Attribute like this:

    +
    set myobj/foo = "bar"
    +
    +
    +

    To view, do

    +
    set myobj/foo 
    +
    +
    +

    or see them together with all object-info with

    +
    examine myobj
    +
    +
    +

    The first set-example will store a new Attribute foo on the object myobj and give it the +value “bar”. +You can store numbers, booleans, strings, tuples, lists and dicts this way. But if +you store a list/tuple/dict they must be proper Python structures and may only contain strings +or numbers. If you try to insert an unsupported structure, the input will be converted to a +string.

    +
    set myobj/mybool = True
    +set myobj/mybool = True
    +set myobj/mytuple = (1, 2, 3, "foo")
    +set myobj/mylist = ["foo", "bar", 2]
    +set myobj/mydict = {"a": 1, "b": 2, 3: 4}
    +set mypobj/mystring = [1, 2, foo]   # foo is invalid Python (no quotes)
    +
    +
    +

    For the last line you’ll get a warning and the value instead will be saved as a string "[1, 2, foo]".

    +
    +
    +

    Locking and checking Attributes

    +

    While the set command is limited to builders, individual Attributes are usually not +locked down. You may want to lock certain sensitive Attributes, in particular for games +where you allow player building. You can add such limitations by adding a lock string +to your Attribute. A NAttribute have no locks.

    +

    The relevant lock types are

      -
    • You are worried about database performance. Since Evennia caches Attributes very aggressively, -this is not an issue unless you are reading and writing to your Attribute very often (like many -times per second). Reading from an already cached Attribute is as fast as reading any Python -property. But even then this is not likely something to worry about: Apart from Evennia’s own -caching, modern database systems themselves also cache data very efficiently for speed. Our -default -database even runs completely in RAM if possible, alleviating much of the need to write to disk -during heavy loads.

    • -
    • A more valid reason for using non-persistent data is if you want to lose your state when logging -off. Maybe you are storing throw-away data that are re-initialized at server startup. Maybe you -are implementing some caching of your own. Or maybe you are testing a buggy Script that -does potentially harmful stuff to your character object. With non-persistent storage you can be -sure -that whatever is messed up, it’s nothing a server reboot can’t clear up.

    • -
    • NAttributes have no restrictions at all on what they can store (see next section), since they -don’t need to worry about being saved to the database - they work very well for temporary storage.

    • -
    • You want to implement a fully or partly non-persistent world. Who are we to argue with your -grand vision!

    • +
    • attrread - limits who may read the value of the Attribute

    • +
    • attredit - limits who may set/change this Attribute

    +

    You must use the AttributeHandler to assign the lockstring to the Attribute:

    +
    lockstring = "attread:all();attredit:perm(Admins)"
    +obj.attributes.add("myattr", "bar", lockstring=lockstring)"
    +
    +
    +

    If you already have an Attribute and want to add a lock in-place you can do so +by having the AttributeHandler return the Attribute object itself (rather than +its value) and then assign the lock to it directly:

    +
         lockstring = "attread:all();attredit:perm(Admins)"
    +     obj.attributes.get("myattr", return_obj=True).locks.add(lockstring)
    +
    +
    +

    Note the return_obj keyword which makes sure to return the Attribute object so its LockHandler +could be accessed.

    +

    A lock is no good if nothing checks it – and by default Evennia does not check locks on Attributes. +To check the lockstring you provided, make sure you include accessing_obj and set +default_access=False as you make a get call.

    +
        # in some command code where we want to limit
    +    # setting of a given attribute name on an object
    +    attr = obj.attributes.get(attrname,
    +                              return_obj=True,
    +                              accessing_obj=caller,
    +                              default=None,
    +                              default_access=False)
    +    if not attr:
    +        caller.msg("You cannot edit that Attribute!")
    +        return
    +    # edit the Attribute here
    +
    +
    +

    The same keywords are available to use with obj.attributes.set() and obj.attributes.remove(), +those will check for the attredit lock type.

    What types of data can I save in an Attribute?

    -
    -

    None of the following affects NAttributes, which does not invoke the database at all. There are no -restrictions to what can be stored in a NAttribute.

    -

    The database doesn’t know anything about Python objects, so Evennia must serialize Attribute -values into a string representation in order to store it to the database. This is done using the -pickle module of Python (the only exception is if you use the strattr keyword of the -AttributeHandler to save to the strvalue field of the Attribute. In that case you can only save -strings which will not be pickled).

    -

    It’s important to note that when you access the data in an Attribute you are always de-serializing -it from the database representation every time. This is because we allow for storing -database-entities in Attributes too. If we cached it as its Python form, we might end up with -situations where the database entity was deleted since we last accessed the Attribute. -De-serializing data with a database-entity in it means querying the database for that object and -making sure it still exists (otherwise it will be set to None). Performance-wise this is usually -not a big deal. But if you are accessing the Attribute as part of some big loop or doing a large -amount of reads/writes you should first extract it to a temporary variable, operate on that and -then save the result back to the Attribute. If you are storing a more complex structure like a -dict or a list you should make sure to “disconnect” it from the database before looping over it, -as mentioned in the Retrieving Mutable Objects section -below.

    +values into a string representation before storing it to the database. This is done using the +pickle module of Python.

    +
    +

    The only exception is if you use the strattr keyword of the +AttributeHandler to save to the strvalue field of the Attribute. In that case you can only save +strings and those will not be pickled).

    +

    Storing single objects

    With a single object, we mean anything that is not iterable, like numbers, strings or custom class instances without the __iter__ method.

      -
    • You can generally store any non-iterable Python entity that can be -pickled.

    • -
    • Single database objects/typeclasses can be stored as any other in the Attribute. These can -normally not be pickled, but Evennia will behind the scenes convert them to an internal -representation using their classname, database-id and creation-date with a microsecond precision, -guaranteeing you get the same object back when you access the Attribute later.

    • -
    • If you hide a database object inside a non-iterable custom class (like stored as a variable -inside it), Evennia will not know it’s there and won’t convert it safely. Storing classes with -such hidden database objects is not supported and will lead to errors!

    • +
    • You can generally store any non-iterable Python entity that can be pickled.

    • +
    • Single database objects/typeclasses can be stored, despite them normally not being possible +to pickle. Evennia wil convert them to an internal representation using their classname, +database-id and creation-date with a microsecond precision. When retrieving, the object +instance will be re-fetched from the database using this information.

    • +
    • To convert the database object, Evennia must know it’s there. If you hide a database object +inside a non-iterable class, you will run into errors - this is not supported!

    +
    +
    Valid assignments
    # Examples of valid single-value  attribute data:
     obj.db.test1 = 23
     obj.db.test1 = False
     # a database object (will be stored as an internal representation)
     obj.db.test2 = myobj
    -
    -# example of an invalid, "hidden" dbobject
    -class Invalid(object):
    -    def __init__(self, dbobj):
    -        # no way for Evennia to know this is a dbobj
    -        self.dbobj = dbobj
    -invalid = Invalid(myobj)
    -obj.db.invalid = invalid # will cause error!
     
    +
    +
    +
    Invalid, ‘hidden’ dbobject
    +
    # example of an invalid, "hidden" dbobject
    +class Container:
    +    def __init__(self, mydbobj):
    +        # no way for Evennia to know this is a database object!
    +        self.mydbobj = mydbobj
    +container = Container(myobj)
    +obj.db.invalid = container  # will cause error!
    +
    +
    +

    Storing multiple objects

    @@ -258,11 +452,8 @@ entities you can loop over in a for-loop. Attribute-saving supports the followin
  • Lists, like [1,2,"test", <dbobj>].

  • Dicts, like {1:2, "test":<dbobj>].

  • Sets, like {1,2,"test",<dbobj>}.

  • -
  • - -

    collections.OrderedDict, -like OrderedDict((1,2), ("test", <dbobj>)).

    -
      +
    • collections.OrderedDict, +like OrderedDict((1,2), ("test", <dbobj>)).

    • collections.Deque, like deque((1,2,"test",<dbobj>)).

    • Nestings of any combinations of the above, like lists in dicts or an OrderedDict of tuples, each @@ -334,7 +525,6 @@ function evennia.ut

      from evennia.utils.dbserialize import deserialize
       
       decoupled_mutables = deserialize(nested_mutables)
      -
       

      The result of this operation will be a structure only consisting of normal Python mutables (list @@ -354,52 +544,100 @@ already disconnected from the database from the onset.

      # without affecting the database. -
      -

      Attributes will fetch data fresh from the database whenever you read them, so -if you are performing big operations on a mutable Attribute property (such as looping over a list -or dict) you should make sure to “disconnect” the Attribute’s value first and operate on this -rather than on the Attribute. You can gain dramatic speed improvements to big loops this -way.

      -
    -
    -

    Locking and checking Attributes

    -

    Attributes are normally not locked down by default, but you can easily change that for individual -Attributes (like those that may be game-sensitive in games with user-level building).

    -

    First you need to set a lock string on your Attribute. Lock strings are specified Locks. -The relevant lock types are

    +
    +

    Properties of Attributes

    +

    An Attribute object is stored in the database. It has the following properties:

      -
    • attrread - limits who may read the value of the Attribute

    • -
    • attredit - limits who may set/change this Attribute

    • +
    • key - the name of the Attribute. When doing e.g. obj.db.attrname = value, this property is set +to attrname.

    • +
    • value - this is the value of the Attribute. This value can be anything which can be pickled - +objects, lists, numbers or what have you (see +this section for more info). In the +example +obj.db.attrname = value, the value is stored here.

    • +
    • category - this is an optional property that is set to None for most Attributes. Setting this +allows to use Attributes for different functionality. This is usually not needed unless you want +to use Attributes for very different functionality (Nicks is an example of using +Attributes in this way). To modify this property you need to use the Attribute Handler

    • +
    • strvalue - this is a separate value field that only accepts strings. This severely limits the +data possible to store, but allows for easier database lookups. This property is usually not used +except when re-using Attributes for some other purpose (Nicks use it). It is only +accessible via the Attribute Handler.

    -

    You cannot use the db handler to modify Attribute object (such as setting a lock on them) - The -db handler will return the Attribute’s value, not the Attribute object itself. Instead you use -the AttributeHandler and set it to return the object instead of the value:

    -
         lockstring = "attread:all();attredit:perm(Admins)"
    -     obj.attributes.get("myattr", return_obj=True).locks.add(lockstring)
    +

    There are also two special properties:

    +
      +
    • attrtype - this is used internally by Evennia to separate Nicks, from Attributes (Nicks +use Attributes behind the scenes).

    • +
    • model - this is a natural-key describing the model this Attribute is attached to. This is on +the form appname.modelclass, like objects.objectdb. It is used by the Attribute and +NickHandler to quickly sort matches in the database. Neither this nor attrtype should normally +need to be modified.

    • +
    +

    Non-database attributes are not stored in the database and have no equivalence +to category nor strvalue, attrtype or model.

    +
    +
    +
    +

    In-memory Attributes (NAttributes)

    +

    NAttributes (short of Non-database Attributes) mimic Attributes in most things except they +are non-persistent - they will not survive a server reload.

    +
      +
    • Instead of .db use .ndb.

    • +
    • Instead of .attributes use .nattributes

    • +
    • Instead of AttributeProperty, use NAttributeProperty.

    • +
    +
        rose.ndb.has_thorns = True
    +    is_ouch = rose.ndb.has_thorns
    +
    +    rose.nattributes.add("has_thorns", True)
    +    is_ouch = rose.nattributes.get("has_thorns")
     
    -

    Note the return_obj keyword which makes sure to return the Attribute object so its LockHandler -could be accessed.

    -

    A lock is no good if nothing checks it – and by default Evennia does not check locks on Attributes. -You have to add a check to your commands/code wherever it fits (such as before setting an -Attribute).

    -
        # in some command code where we want to limit
    -    # setting of a given attribute name on an object
    -    attr = obj.attributes.get(attrname,
    -                              return_obj=True,
    -                              accessing_obj=caller,
    -                              default=None,
    -                              default_access=False)
    -    if not attr:
    -        caller.msg("You cannot edit that Attribute!")
    -        return
    -    # edit the Attribute here
    -
    -
    -

    The same keywords are available to use with obj.attributes.set() and obj.attributes.remove(), -those will check for the attredit lock type.

    +

    Differences between Attributes and NAttributes:

    +
      +
    • NAttributes are always wiped on a server reload.

    • +
    • They only exist in memory and never involve the database at all, making them faster to +access and edit than Attributes.

    • +
    • NAttributes can store any Python structure (and database object) without limit.

    • +
    • They can not be set with the standard set command (but they are visible with examine)

    • +
    +

    There are some important reasons we recommend using ndb to store temporary data rather than +the simple alternative of just storing a variable directly on an object:

    +
      +
    • NAttributes are tracked by Evennia and will not be purged in various cache-cleanup operations +the server may do. So using them guarantees that they’ll remain available at least as long as +the server lives.

    • +
    • It’s a consistent style - .db/.attributes and .ndb/.nattributes makes for clean-looking code +where it’s clear how long-lived (or not) your data is to be.

    • +
    +
    +

    Persistent vs non-persistent

    +

    So persistent data means that your data will survive a server reboot, whereas with +non-persistent data it will not …

    +

    … So why would you ever want to use non-persistent data? The answer is, you don’t have to. Most of +the time you really want to save as much as you possibly can. Non-persistent data is potentially +useful in a few situations though.

    +
      +
    • You are worried about database performance. Since Evennia caches Attributes very aggressively, +this is not an issue unless you are reading and writing to your Attribute very often (like many +times per second). Reading from an already cached Attribute is as fast as reading any Python +property. But even then this is not likely something to worry about: Apart from Evennia’s own +caching, modern database systems themselves also cache data very efficiently for speed. Our +default +database even runs completely in RAM if possible, alleviating much of the need to write to disk +during heavy loads.

    • +
    • A more valid reason for using non-persistent data is if you want to lose your state when logging +off. Maybe you are storing throw-away data that are re-initialized at server startup. Maybe you +are implementing some caching of your own. Or maybe you are testing a buggy Script that +does potentially harmful stuff to your character object. With non-persistent storage you can be +sure that whatever is messed up, it’s nothing a server reboot can’t clear up.

    • +
    • NAttributes have no restrictions at all on what they can store, since they +don’t need to worry about being saved to the database - they work very well for temporary storage.

    • +
    • You want to implement a fully or partly non-persistent world. Who are we to argue with your +grand vision!

    • +
    @@ -426,17 +664,25 @@ those will check for the

    Table of Contents

    diff --git a/docs/1.0-dev/Components/Default-Commands.html b/docs/1.0-dev/Components/Default-Commands.html index 35bbfddcc2..b6c2235a69 100644 --- a/docs/1.0-dev/Components/Default-Commands.html +++ b/docs/1.0-dev/Components/Default-Commands.html @@ -62,39 +62,39 @@ with Batch-Processor’s interactive mode.

    diff --git a/docs/1.0-dev/Howto/Tutorial-Aggressive-NPCs.html b/docs/1.0-dev/Howto/Tutorial-Aggressive-NPCs.html index 2013f3736e..6fba951ca0 100644 --- a/docs/1.0-dev/Howto/Tutorial-Aggressive-NPCs.html +++ b/docs/1.0-dev/Howto/Tutorial-Aggressive-NPCs.html @@ -113,12 +113,12 @@ hook in our customized room typeclass to suit our needs.

    Characters, ignoring other NPCs or objects. When triggered the room will look through its contents and inform any NPCs inside by calling their at_char_entered` method.

    You’ll also see that we have added a ‘look’ into this code. This is because, by default, the -at_object_receive is carried out before the character’s at_after_move which, we will now +at_object_receive is carried out before the character’s at_post_move which, we will now overload. This means that a character entering would see the NPC perform its actions before the ‘look’ command. Deactivate the look command in the default Character class within the typeclasses.characters module:

        # Add this hook in any blank area within your Character class.
    -    def at_after_move(self, source_location):
    +    def at_post_move(self, source_location):
             """
             Default is to look around after a move 
             Note:  This has been moved to Room.at_object_receive
    diff --git a/docs/1.0-dev/_modules/evennia/accounts/accounts.html b/docs/1.0-dev/_modules/evennia/accounts/accounts.html
    index f9b8574d8a..df7d012edc 100644
    --- a/docs/1.0-dev/_modules/evennia/accounts/accounts.html
    +++ b/docs/1.0-dev/_modules/evennia/accounts/accounts.html
    @@ -897,6 +897,12 @@
                 `*args` and `**kwargs` are passed on to the base delete
                  mechanism (these are usually not used).
     
    +        Return:
    +            bool: If deletion was successful. Only time it fails would be
    +                if the Account was already deleted. Note that even on a failure,
    +                connected resources (nicks/aliases etc) will still have been
    +                deleted.
    +
             """
             for session in self.sessions.all():
                 # unpuppeting all objects and disconnecting the user, if any
    @@ -912,7 +918,11 @@
             self.attributes.clear()
             self.nicks.clear()
             self.aliases.clear()
    -        super().delete(*args, **kwargs)
    + if not self.pk: + return False + super().delete(*args, **kwargs) + return True
    + # methods inherited from database model diff --git a/docs/1.0-dev/_modules/evennia/commands/default/admin.html b/docs/1.0-dev/_modules/evennia/commands/default/admin.html index f548fe1868..1ea542f8c9 100644 --- a/docs/1.0-dev/_modules/evennia/commands/default/admin.html +++ b/docs/1.0-dev/_modules/evennia/commands/default/admin.html @@ -260,13 +260,18 @@ ipregex = ipregex.replace("*", "[0-9]{1,3}") ipregex = re.compile(r"%s" % ipregex) bantup = ("", ban, ipregex, now, reason) + + ret = yield(f"Are you sure you want to {typ}-ban '|w{ban}|n' [Y]/N?") + if str(ret).lower() in ("no", "n"): + self.caller.msg("Aborted.") + return + # save updated banlist banlist.append(bantup) ServerConfig.objects.conf("server_bans", banlist) - self.caller.msg("%s-Ban |w%s|n was added." % (typ, ban)) + self.caller.msg(f"{typ}-ban '|w{ban}|n' was added. Use |wunban|n to reinstate.") logger.log_sec( - "Banned %s: %s (Caller: %s, IP: %s)." - % (typ, ban.strip(), self.caller, self.session.address) + "Banned {typ}: {ban.strip()} (Caller: {self.caller}, IP: {self.session.address})." ) @@ -308,15 +313,20 @@ elif not (0 < num < len(banlist) + 1): self.caller.msg("Ban id |w%s|x was not found." % self.args) else: - # all is ok, clear ban + # all is ok, ask, then clear ban ban = banlist[num - 1] + value = " ".join([s for s in ban[:2]]) + + ret = yield(f"Are you sure you want to unban {num}: '{value}' [Y]/N?") + if str(ret).lower() in ("n", "no"): + self.caller.msg("Aborted.") + return + del banlist[num - 1] ServerConfig.objects.conf("server_bans", banlist) - value = " ".join([s for s in ban[:2]]) - self.caller.msg("Cleared ban %s: %s" % (num, value)) + self.caller.msg(f"Cleared ban {num}: '{value}'" % (num, value)) logger.log_sec( - "Unbanned: %s (Caller: %s, IP: %s)." - % (value.strip(), self.caller, self.session.address) + "Unbanned: {value.strip()} (Caller: {self.caller}, IP: {self.session.address})." ) diff --git a/docs/1.0-dev/_modules/evennia/commands/default/building.html b/docs/1.0-dev/_modules/evennia/commands/default/building.html index e4751f0c62..70458f478d 100644 --- a/docs/1.0-dev/_modules/evennia/commands/default/building.html +++ b/docs/1.0-dev/_modules/evennia/commands/default/building.html @@ -3400,6 +3400,13 @@ Teleports an object somewhere. If no object is given, you yourself are teleported to the target location. + + To lock an object from being teleported, set its `teleport` lock, it will be + checked with the caller. To block + a destination from being teleported to, set the destination's `teleport_here` + lock - it will be checked with the thing being teleported. Admins and + higher permissions can always teleport. + """ key = "tel" @@ -3481,6 +3488,18 @@ caller.msg("%s is already at %s." % (obj_to_teleport, destination)) return + # check any locks + if not (caller.permissions.check("Admin") or obj_to_teleport.access(caller, "teleport")): + caller.msg(f"{obj_to_teleport} 'teleport'-lock blocks you from teleporting " + "it anywhere.") + return + + if not (caller.permissions.check("Admin") + or destination.access(obj_to_teleport, "teleport_here")): + caller.msg(f"{destination} 'teleport_here'-lock blocks {obj_to_teleport} from " + "moving there.") + return + # try the teleport if not obj_to_teleport.location: # teleporting from none-location @@ -3498,7 +3517,6 @@ caller.msg("Teleportation failed.") -
    [docs]class CmdTag(COMMAND_DEFAULT_CLASS): """ handles the tags of an object diff --git a/docs/1.0-dev/_modules/evennia/commands/default/general.html b/docs/1.0-dev/_modules/evennia/commands/default/general.html index b7b2cb9ef2..f1551e1ef3 100644 --- a/docs/1.0-dev/_modules/evennia/commands/default/general.html +++ b/docs/1.0-dev/_modules/evennia/commands/default/general.html @@ -471,8 +471,8 @@ caller.msg("You can't get that.") return - # calling at_before_get hook method - if not obj.at_before_get(caller): + # calling at_pre_get hook method + if not obj.at_pre_get(caller): return success = obj.move_to(caller, quiet=True) @@ -521,8 +521,8 @@ if not obj: return - # Call the object script's at_before_drop() method. - if not obj.at_before_drop(caller): + # Call the object script's at_pre_drop() method. + if not obj.at_pre_drop(caller): return success = obj.move_to(caller.location, quiet=True) @@ -574,8 +574,8 @@ caller.msg("You are not holding %s." % to_give.key) return - # calling at_before_give hook method - if not to_give.at_before_give(caller, target): + # calling at_pre_give hook method + if not to_give.at_pre_give(caller, target): return # give object @@ -630,6 +630,9 @@ aliases = ['"', "'"] locks = "cmd:all()" + # don't require a space after `say/'/"` + arg_regex = None +
    [docs] def func(self): """Run the say command""" @@ -641,14 +644,14 @@ speech = self.args - # Calling the at_before_say hook on the character - speech = caller.at_before_say(speech) + # Calling the at_pre_say hook on the character + speech = caller.at_pre_say(speech) # If speech is empty, stop here if not speech: return - # Call the at_after_say hook on the character + # Call the at_post_say hook on the character caller.at_say(speech, msg_self=True)
    @@ -687,7 +690,7 @@ return # Call a hook to change the speech before whispering - speech = caller.at_before_say(speech, whisper=True, receivers=receivers) + speech = caller.at_pre_say(speech, whisper=True, receivers=receivers) # no need for self-message if we are whispering to ourselves (for some reason) msg_self = None if caller in receivers else True @@ -714,6 +717,11 @@ key = "pose" aliases = [":", "emote"] locks = "cmd:all()" + arg_regex = "" + + # we want to be able to pose without whitespace between + # the command/alias and the pose (e.g. :pose) + arg_regex = None
    [docs] def parse(self): """ diff --git a/docs/1.0-dev/_modules/evennia/commands/default/system.html b/docs/1.0-dev/_modules/evennia/commands/default/system.html index bad8fafbeb..cea6f38caa 100644 --- a/docs/1.0-dev/_modules/evennia/commands/default/system.html +++ b/docs/1.0-dev/_modules/evennia/commands/default/system.html @@ -394,6 +394,7 @@ switch_options = ("time", "edit", "clientraw", "noecho") locks = "cmd:perm(py) or perm(Developer)" help_category = "System" + arg_regex = ""
    [docs] def func(self): """hook function""" diff --git a/docs/1.0-dev/_modules/evennia/commands/default/tests.html b/docs/1.0-dev/_modules/evennia/commands/default/tests.html index 42fcb71410..a8a6442cbc 100644 --- a/docs/1.0-dev/_modules/evennia/commands/default/tests.html +++ b/docs/1.0-dev/_modules/evennia/commands/default/tests.html @@ -805,7 +805,7 @@ self.call(admin.CmdWall(), "Test", "Announcing to all connected sessions ...")
    [docs] def test_ban(self): - self.call(admin.CmdBan(), "Char", "Name-Ban char was added.")
    + self.call(admin.CmdBan(), "Char", "Name-ban 'char' was added. Use unban to reinstate.")
    [docs] def test_force(self): cid = self.char2.id diff --git a/docs/1.0-dev/_modules/evennia/comms/comms.html b/docs/1.0-dev/_modules/evennia/comms/comms.html index 47959e5e11..19882d649b 100644 --- a/docs/1.0-dev/_modules/evennia/comms/comms.html +++ b/docs/1.0-dev/_modules/evennia/comms/comms.html @@ -443,12 +443,20 @@ """ Deletes channel. + Returns: + bool: If deletion was successful. Only time it can fail would be + if channel was already deleted. Even if it were to fail, all subscribers + will be disconnected. + """ self.attributes.clear() self.aliases.clear() for subscriber in self.subscriptions.all(): self.disconnect(subscriber) - super().delete()
    + if not self.pk: + return False + super().delete() + return True
    [docs] def channel_prefix(self): """ diff --git a/docs/1.0-dev/_modules/evennia/contrib/custom_gametime.html b/docs/1.0-dev/_modules/evennia/contrib/custom_gametime.html index 5b22fe87c0..ea41291a7d 100644 --- a/docs/1.0-dev/_modules/evennia/contrib/custom_gametime.html +++ b/docs/1.0-dev/_modules/evennia/contrib/custom_gametime.html @@ -169,7 +169,7 @@ return rtime
    -
    [docs]def realtime_to_gametime(secs=0, mins=0, hrs=0, days=0, weeks=0, months=0, yrs=0, format=False): +
    [docs]def realtime_to_gametime(secs=0, mins=0, hrs=0, days=1, weeks=1, months=1, yrs=0, format=False): """ This method calculates how much in-game time a real-world time interval would correspond to. This is usually a lot less @@ -183,10 +183,24 @@ time (float or tuple): The gametime difference or the same time split up into time units. - Example: + Note: + days/weeks/months start from 1 (there is no day/week/month 0). This makes it + consistent with the real world datetime. + + Raises: + ValueError: If trying to add a days/weeks/months of <=0. + + Example: realtime_to_gametime(days=2) -> number of game-world seconds """ + if days <= 0 or weeks <= 0 or months <= 0: + raise ValueError("realtime_to_gametime: days/weeks/months cannot be set <= 0, " + "they start from 1.") + + # days/weeks/months start from 1, we need to adjust them to work mathematically. + days, weeks, months = days - 1, weeks - 1, months - 1 + gtime = TIMEFACTOR * ( secs + mins * 60 @@ -242,6 +256,9 @@ Returns: The number of real seconds before the given game time is up. + Notes: + day/week/month start from 1, not from 0 (there is no month 0 for example) + """ current = gametime.gametime(absolute=True) units = sorted(set(UNITS.values()), reverse=True) @@ -253,9 +270,13 @@ units.append(1) higher_unit = None for unit, value in kwargs.items(): + if unit in ("day", "week", "month"): + # these start from 1 so we must adjust + value -= 1 + # Get the unit's index if unit not in UNITS: - raise ValueError("unknown unit".format(unit)) + raise ValueError(f"Unknown unit '{unit}'. Allowed: {', '.join(UNITS)}") seconds = UNITS[unit] index = units.index(seconds) diff --git a/docs/1.0-dev/_modules/evennia/contrib/rpsystem.html b/docs/1.0-dev/_modules/evennia/contrib/rpsystem.html index eb0d119b3a..12ac6fbb57 100644 --- a/docs/1.0-dev/_modules/evennia/contrib/rpsystem.html +++ b/docs/1.0-dev/_modules/evennia/contrib/rpsystem.html @@ -976,6 +976,7 @@ key = "emote" aliases = [":"] locks = "cmd:all()" + arg_regex = ""
    [docs] def func(self): "Perform the emote." @@ -1003,6 +1004,7 @@ key = "say" aliases = ['"', "'"] locks = "cmd:all()" + arg_regex = ""
    [docs] def func(self): "Run the say command" @@ -1014,7 +1016,7 @@ return # calling the speech modifying hook - speech = caller.at_before_say(self.args) + speech = caller.at_pre_say(self.args) # preparing the speech with sdesc/speech parsing. targets = self.caller.location.contents send_emote(self.caller, targets, speech, anonymous_add=None)
    @@ -1658,7 +1660,7 @@ # initializing sdesc self.sdesc.add("A normal person")
    -
    [docs] def at_before_say(self, message, **kwargs): +
    [docs] def at_pre_say(self, message, **kwargs): """ Called before the object says or whispers anything, return modified message. diff --git a/docs/1.0-dev/_modules/evennia/contrib/slow_exit.html b/docs/1.0-dev/_modules/evennia/contrib/slow_exit.html index 1334bc2bc6..c7125c4ea9 100644 --- a/docs/1.0-dev/_modules/evennia/contrib/slow_exit.html +++ b/docs/1.0-dev/_modules/evennia/contrib/slow_exit.html @@ -103,7 +103,7 @@ "This callback will be called by utils.delay after move_delay seconds." source_location = traversing_object.location if traversing_object.move_to(target_location): - self.at_after_traverse(traversing_object, source_location) + self.at_post_traverse(traversing_object, source_location) else: if self.db.err_traverse: # if exit has a better error message, let's use it. diff --git a/docs/1.0-dev/_modules/evennia/contrib/traits.html b/docs/1.0-dev/_modules/evennia/contrib/traits.html index 4a6a577331..0348c8fd70 100644 --- a/docs/1.0-dev/_modules/evennia/contrib/traits.html +++ b/docs/1.0-dev/_modules/evennia/contrib/traits.html @@ -771,10 +771,10 @@ class Character(DefaultCharacter): - strength = TraitProperty("str", "Strength", trait_type="static", base=10, mod=2) - hunting = TraitProperty(self, "hunting", "Hunting Skill", trait_type="counter", + strength = TraitProperty(name="STR", trait_type="static", base=10, mod=2) + hunting = TraitProperty("Hunting Skill", trait_type="counter", base=10, mod=1, max=100) - health = TraitProperty("health", "Health", trait_type="gauge", min=0, base=100) + health = TraitProperty(trait_type="gauge", min=0, base=100) """ diff --git a/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_basic.html b/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_basic.html index a87fa416db..a3ebecd80f 100644 --- a/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_basic.html +++ b/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_basic.html @@ -366,7 +366,7 @@ can be changed at creation and factor into combat calculations. """
    -
    [docs] def at_before_move(self, destination): +
    [docs] def at_pre_move(self, destination): """ Called just before starting to move this object to destination. diff --git a/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_equip.html b/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_equip.html index ad3cc30e2d..c6da6c330e 100644 --- a/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_equip.html +++ b/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_equip.html @@ -632,7 +632,7 @@ -4 ) # Amount to modify defense value (pos = harder to hit, neg = easier)
    -
    [docs] def at_before_drop(self, dropper): +
    [docs] def at_pre_drop(self, dropper): """ Can't drop in combat. """ @@ -649,7 +649,7 @@ dropper.db.worn_armor = None dropper.location.msg_contents("%s removes %s." % (dropper, self))
    -
    [docs] def at_before_give(self, giver, getter): +
    [docs] def at_pre_give(self, giver, getter): """ Can't give away in combat. """ @@ -693,7 +693,7 @@ can be changed at creation and factor into combat calculations. """
    -
    [docs] def at_before_move(self, destination): +
    [docs] def at_pre_move(self, destination): """ Called just before starting to move this object to destination. diff --git a/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_items.html b/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_items.html index 11a86d9e39..5f614a816a 100644 --- a/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_items.html +++ b/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_items.html @@ -575,7 +575,7 @@ can be changed at creation and factor into combat calculations. """
    -
    [docs] def at_before_move(self, destination): +
    [docs] def at_pre_move(self, destination): """ Called just before starting to move this object to destination. diff --git a/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_magic.html b/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_magic.html index 5e897556f8..d9d5bbafbc 100644 --- a/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_magic.html +++ b/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_magic.html @@ -395,7 +395,7 @@ self.db.max_mp = 20 # Set maximum MP to 20 self.db.mp = self.db.max_mp # Set current MP to maximum
    -
    [docs] def at_before_move(self, destination): +
    [docs] def at_pre_move(self, destination): """ Called just before starting to move this object to destination. diff --git a/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_range.html b/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_range.html index 8447798c1d..3d699a0023 100644 --- a/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_range.html +++ b/docs/1.0-dev/_modules/evennia/contrib/turnbattle/tb_range.html @@ -843,7 +843,7 @@ can be changed at creation and factor into combat calculations. """
    -
    [docs] def at_before_move(self, destination): +
    [docs] def at_pre_move(self, destination): """ Called just before starting to move this object to destination. @@ -877,7 +877,7 @@ objects on your own turn. """ -
    [docs] def at_before_drop(self, dropper): +
    [docs] def at_pre_drop(self, dropper): """ Called by the default `drop` command before this object has been dropped. @@ -913,7 +913,7 @@ Notes: This hook cannot stop the drop from happening. Use - permissions or the at_before_drop() hook for that. + permissions or the at_pre_drop() hook for that. """ # If dropper is currently in combat @@ -922,7 +922,7 @@ self.db.combat_range = {} dropper.location.db.combat_turnhandler.join_rangefield(self, anchor_obj=dropper)
    -
    [docs] def at_before_get(self, getter): +
    [docs] def at_pre_get(self, getter): """ Called by the default `get` command before this object has been picked up. @@ -961,7 +961,7 @@ Notes: This hook cannot stop the pickup from happening. Use - permissions or the at_before_get() hook for that. + permissions or the at_pre_get() hook for that. """ # If gotten, erase range values @@ -976,7 +976,7 @@ if is_in_combat(getter): spend_action(getter, 1, action_name="get") # Use up one action.
    -
    [docs] def at_before_give(self, giver, getter): +
    [docs] def at_pre_give(self, giver, getter): """ Called by the default `give` command before this object has been given. @@ -1020,7 +1020,7 @@ Notes: This hook cannot stop the give from happening. Use - permissions or the at_before_give() hook for that. + permissions or the at_pre_give() hook for that. """ # Spend an action if in combat diff --git a/docs/1.0-dev/_modules/evennia/contrib/tutorial_world/objects.html b/docs/1.0-dev/_modules/evennia/contrib/tutorial_world/objects.html index 991a5bc651..559a06f915 100644 --- a/docs/1.0-dev/_modules/evennia/contrib/tutorial_world/objects.html +++ b/docs/1.0-dev/_modules/evennia/contrib/tutorial_world/objects.html @@ -795,7 +795,7 @@ # call the parent to continue execution (will use the desc we just set) return super().return_appearance(caller)
    -
    [docs] def at_after_traverse(self, traverser, source_location): +
    [docs] def at_post_traverse(self, traverser, source_location): """ This is called after we traversed this exit. Cleans up and resets the puzzle. diff --git a/docs/1.0-dev/_modules/evennia/contrib/wilderness.html b/docs/1.0-dev/_modules/evennia/contrib/wilderness.html index 83a9c36728..08c8891362 100644 --- a/docs/1.0-dev/_modules/evennia/contrib/wilderness.html +++ b/docs/1.0-dev/_modules/evennia/contrib/wilderness.html @@ -391,7 +391,7 @@ # ... but that other wilderness room belongs to another # wilderness map create_new_room = True - old_room.wilderness.at_after_object_leave(obj) + old_room.wilderness.at_post_object_leave(obj) else: for item in old_room.contents: if item.has_account: @@ -495,7 +495,7 @@ # And finally put this room away in storage self.db.unused_rooms.append(room) -
    [docs] def at_after_object_leave(self, obj): +
    [docs] def at_post_object_leave(self, obj): """ Called after an object left this wilderness map. Used for cleaning up. @@ -595,7 +595,7 @@ target_location (Object): Where `moved_obj` is going. """ - self.wilderness.at_after_object_leave(moved_obj)
    + self.wilderness.at_post_object_leave(moved_obj)
    [docs] def set_active_coordinates(self, new_coordinates, obj): """ @@ -742,7 +742,7 @@ ): return False - if not traversing_object.at_before_move(None): + if not traversing_object.at_pre_move(None): return False traversing_object.location.msg_contents( "{} leaves to {}".format(traversing_object.key, new_coordinates), @@ -756,7 +756,7 @@ exclude=[traversing_object], ) - traversing_object.at_after_move(None) + traversing_object.at_post_move(None) return True
    diff --git a/docs/1.0-dev/_modules/evennia/objects/objects.html b/docs/1.0-dev/_modules/evennia/objects/objects.html index ce04e11aea..c126898f15 100644 --- a/docs/1.0-dev/_modules/evennia/objects/objects.html +++ b/docs/1.0-dev/_modules/evennia/objects/objects.html @@ -884,7 +884,7 @@ moving to a None location. If you want to run hooks, run them manually (and make sure they can manage None locations). move_hooks (bool): If False, turn off the calling of move-related hooks - (at_before/after_move etc) with quiet=True, this is as quiet a move + (at_pre/post_move etc) with quiet=True, this is as quiet a move as can be done. Keyword Args: @@ -901,13 +901,13 @@ The `DefaultObject` hooks called (if `move_hooks=True`) are, in order: - 1. `self.at_before_move(destination)` (if this returns False, move is aborted) + 1. `self.at_pre_move(destination)` (if this returns False, move is aborted) 2. `source_location.at_object_leave(self, destination)` 3. `self.announce_move_from(destination)` 4. (move happens here) 5. `self.announce_move_to(source_location)` 6. `destination.at_object_receive(self, source_location)` - 7. `self.at_after_move(source_location)` + 7. `self.at_post_move(source_location)` """ def logerr(string="", err=None): @@ -934,10 +934,10 @@ # Before the move, call eventual pre-commands. if move_hooks: try: - if not self.at_before_move(destination, **kwargs): + if not self.at_pre_move(destination, **kwargs): return False except Exception as err: - logerr(errtxt.format(err="at_before_move()"), err) + logerr(errtxt.format(err="at_pre_move()"), err) return False # Save the old location @@ -987,9 +987,9 @@ # (usually calling 'look') if move_hooks: try: - self.at_after_move(source_location, **kwargs) + self.at_post_move(source_location, **kwargs) except Exception as err: - logerr(errtxt.format(err="at_after_move"), err) + logerr(errtxt.format(err="at_post_move"), err) return False return True
    @@ -1288,7 +1288,7 @@ self.aliases.batch_add(*cdict["aliases"]) if cdict.get("location"): cdict["location"].at_object_receive(self, None) - self.at_after_move(None) + self.at_post_move(None) if cdict.get("tags"): # this should be a list of tags, tuples (key, category) or (key, category, data) self.tags.batch_add(*cdict["tags"]) @@ -1496,7 +1496,7 @@ # hooks called when moving the object -
    [docs] def at_before_move(self, destination, **kwargs): +
    [docs] def at_pre_move(self, destination, **kwargs): """ Called just before starting to move this object to destination. @@ -1517,6 +1517,9 @@ # return has_perm(self, destination, "can_move") return True
    + # deprecated alias + at_before_move = at_pre_move +
    [docs] def announce_move_from(self, destination, msg=None, mapping=None, **kwargs): """ Called if the move is to be announced. This is @@ -1627,7 +1630,7 @@ destination.msg_contents(string, exclude=(self,), from_obj=self, mapping=mapping)
    -
    [docs] def at_after_move(self, source_location, **kwargs): +
    [docs] def at_post_move(self, source_location, **kwargs): """ Called after move has completed, regardless of quiet mode or not. Allows changes to the object due to the location it is @@ -1641,6 +1644,9 @@ """ pass
    + # deprecated + at_after_move = at_post_move +
    [docs] def at_object_leave(self, moved_obj, target_location, **kwargs): """ Called just before an object leaves from inside this object @@ -1674,7 +1680,7 @@ normally by calling `traversing_object.move_to(target_location)`. It is normally only implemented by Exit objects. If it returns False (usually - because `move_to` returned False), `at_after_traverse` below + because `move_to` returned False), `at_post_traverse` below should not be called and instead `at_failed_traverse` should be called. @@ -1687,7 +1693,7 @@ """ pass
    -
    [docs] def at_after_traverse(self, traversing_object, source_location, **kwargs): +
    [docs] def at_post_traverse(self, traversing_object, source_location, **kwargs): """ Called just after an object successfully used this object to traverse to another object (i.e. this object is a type of @@ -1704,6 +1710,9 @@ """ pass
    + # deprecated + at_after_traverse = at_post_traverse +
    [docs] def at_failed_traverse(self, traversing_object, **kwargs): """ This is called if an object fails to traverse this object for @@ -1945,7 +1954,7 @@ """ pass
    -
    [docs] def at_before_get(self, getter, **kwargs): +
    [docs] def at_pre_get(self, getter, **kwargs): """ Called by the default `get` command before this object has been picked up. @@ -1964,6 +1973,9 @@ """ return True
    + # deprecated + at_before_get = at_pre_get +
    [docs] def at_get(self, getter, **kwargs): """ Called by the default `get` command when this object has been @@ -1976,12 +1988,12 @@ Notes: This hook cannot stop the pickup from happening. Use - permissions or the at_before_get() hook for that. + permissions or the at_pre_get() hook for that. """ pass
    -
    [docs] def at_before_give(self, giver, getter, **kwargs): +
    [docs] def at_pre_give(self, giver, getter, **kwargs): """ Called by the default `give` command before this object has been given. @@ -2002,6 +2014,9 @@ """ return True
    + # deprecated + at_before_give = at_pre_give +
    [docs] def at_give(self, giver, getter, **kwargs): """ Called by the default `give` command when this object has been @@ -2015,12 +2030,12 @@ Notes: This hook cannot stop the give from happening. Use - permissions or the at_before_give() hook for that. + permissions or the at_pre_give() hook for that. """ pass
    -
    [docs] def at_before_drop(self, dropper, **kwargs): +
    [docs] def at_pre_drop(self, dropper, **kwargs): """ Called by the default `drop` command before this object has been dropped. @@ -2046,6 +2061,9 @@ return False return True
    + # deprecated + at_before_drop = at_pre_drop +
    [docs] def at_drop(self, dropper, **kwargs): """ Called by the default `drop` command when this object has been @@ -2058,12 +2076,12 @@ Notes: This hook cannot stop the drop from happening. Use - permissions or the at_before_drop() hook for that. + permissions or the at_pre_drop() hook for that. """ pass
    -
    [docs] def at_before_say(self, message, **kwargs): +
    [docs] def at_pre_say(self, message, **kwargs): """ Before the object says something. @@ -2088,6 +2106,9 @@ """ return message
    + # deprecated + at_before_say = at_pre_say +
    [docs] def at_say( self, message, @@ -2383,7 +2404,7 @@ # add the default cmdset self.cmdset.add_default(settings.CMDSET_CHARACTER, persistent=True)
    -
    [docs] def at_after_move(self, source_location, **kwargs): +
    [docs] def at_post_move(self, source_location, **kwargs): """ We make sure to look around after a move. @@ -2391,6 +2412,9 @@ if self.location.access(self, "view"): self.msg(text=(self.at_look(self.location), {"type": "look"}))
    + # deprecated + at_after_move = at_post_move +
    [docs] def at_pre_puppet(self, account, session=None, **kwargs): """ Return the character from storage in None location in `at_post_unpuppet`. @@ -2855,7 +2879,7 @@ """ source_location = traversing_object.location if traversing_object.move_to(target_location): - self.at_after_traverse(traversing_object, source_location) + self.at_post_traverse(traversing_object, source_location) else: if self.db.err_traverse: # if exit has a better error message, let's use it. diff --git a/docs/1.0-dev/_modules/evennia/scripts/scripts.html b/docs/1.0-dev/_modules/evennia/scripts/scripts.html index d888b04737..42c4b5ab07 100644 --- a/docs/1.0-dev/_modules/evennia/scripts/scripts.html +++ b/docs/1.0-dev/_modules/evennia/scripts/scripts.html @@ -491,11 +491,18 @@ is if wanting to delete the script from the at_stop method - setting this will then avoid an infinite recursion. + Returns: + bool: If deletion was successful or not. Only time this can fail would be if + the script was already previously deleted, or `at_script_delete` returns + False. + """ + if not self.pk or not self.at_script_delete(): + return False if stop_task: self._stop_task() - self.at_script_delete() super().delete() + return True def at_script_creation(self): """ @@ -506,10 +513,13 @@ def at_script_delete(self): """ - Called when script is deleted, after at_stop. + Called when script is deleted, before the script timer stops. + + Returns: + bool: If False, deletion is aborted. """ - pass + return True def is_valid(self): """ @@ -769,10 +779,13 @@
    [docs] def at_script_delete(self): """ - Called when the Script is deleted, after at_stop(). + Called when the Script is deleted, before stopping the timer. + + Returns: + bool: If False, the deletion is aborted. """ - pass
    + return True
    [docs] def at_server_reload(self): """ diff --git a/docs/1.0-dev/_modules/evennia/server/deprecations.html b/docs/1.0-dev/_modules/evennia/server/deprecations.html index fdd0583fed..cd2f41fecc 100644 --- a/docs/1.0-dev/_modules/evennia/server/deprecations.html +++ b/docs/1.0-dev/_modules/evennia/server/deprecations.html @@ -194,6 +194,10 @@ print(" [Devel: settings.IN_GAME_ERRORS is True. Turn off in production.]") if settings.ALLOWED_HOSTS == ["*"]: print(" [Devel: settings.ALLOWED_HOSTS set to '*' (all). Limit in production.]") + if settings.SERVER_HOSTNAME == "localhost": + print(" [Devel: settings.SERVER_HOSTNAME is set to 'localhost'. " + "Update to the actual hostname in production.]") + for dbentry in settings.DATABASES.values(): if "psycopg" in dbentry.get("ENGINE", ""): print( diff --git a/docs/1.0-dev/_modules/evennia/server/inputfuncs.html b/docs/1.0-dev/_modules/evennia/server/inputfuncs.html index a9a7cc45f2..78cd507c5e 100644 --- a/docs/1.0-dev/_modules/evennia/server/inputfuncs.html +++ b/docs/1.0-dev/_modules/evennia/server/inputfuncs.html @@ -82,10 +82,24 @@ _SA = object.__setattr__ +_STRIP_INCOMING_MXP = settings.MXP_ENABLED and settings.MXP_OUTGOING_ONLY +_STRIP_MXP = None + + + def _NA(o): return "N/A" +def _maybe_strip_incoming_mxp(txt): + global _STRIP_MXP + if _STRIP_INCOMING_MXP: + if not _STRIP_MXP: + from evennia.utils.ansi import strip_mxp as _STRIP_MXP + return _STRIP_MXP(txt) + return txt + + _ERROR_INPUT = "Inputfunc {name}({session}): Wrong/unrecognized input: {inp}" @@ -118,6 +132,9 @@ if txt.strip() in _IDLE_COMMAND: session.update_session_counters(idle=True) return + + txt = _maybe_strip_incoming_mxp(txt) + if session.account: # nick replacement puppet = session.puppet @@ -156,6 +173,9 @@ if txt.strip() in _IDLE_COMMAND: session.update_session_counters(idle=True) return + + txt = _maybe_strip_incoming_mxp(txt) + kwargs.pop("options", None) # Trigger the execute_cmd method of the corresponding bot. session.account.execute_cmd(session=session, txt=txt, **kwargs) @@ -166,6 +186,9 @@ """ Echo test function """ + if _STRIP_INCOMING_MXP: + txt = strip_mxp(txt) + session.data_out(text="Echo returns: %s" % args)
    @@ -658,12 +681,21 @@ # client specific -
    [docs]def external_discord_hello(session, *args, **kwargs): +def _not_implemented(session, *args, **kwargs): """ - Sent by Mudlet as a greeting; added here to avoid - logging a missing inputfunc for it. + Dummy used to swallow missing-inputfunc errors for + common clients. """ - pass
    + pass + + +# GMCP External.Discord.Hello is sent by Mudlet as a greeting +# (see https://wiki.mudlet.org/w/Manual:Technical_Manual) +external_discord_hello = _not_implemented + + +# GMCP Client.Gui is sent by Mudlet for gui setup. +client_gui = _not_implemented
    diff --git a/docs/1.0-dev/_modules/evennia/server/portal/mxp.html b/docs/1.0-dev/_modules/evennia/server/portal/mxp.html index eea795c6ca..93802b541d 100644 --- a/docs/1.0-dev/_modules/evennia/server/portal/mxp.html +++ b/docs/1.0-dev/_modules/evennia/server/portal/mxp.html @@ -58,6 +58,7 @@ """ import re +from django.conf import settings LINKS_SUB = re.compile(r"\|lc(.*?)\|lt(.*?)\|le", re.DOTALL) URL_SUB = re.compile(r"\|lu(.*?)\|lt(.*?)\|le", re.DOTALL) @@ -104,7 +105,8 @@ """ self.protocol = protocol self.protocol.protocol_flags["MXP"] = False - self.protocol.will(MXP).addCallbacks(self.do_mxp, self.no_mxp)
    + if settings.MXP_ENABLED: + self.protocol.will(MXP).addCallbacks(self.do_mxp, self.no_mxp)
    [docs] def no_mxp(self, option): """ @@ -125,8 +127,11 @@ option (Option): Not used. """ - self.protocol.protocol_flags["MXP"] = True - self.protocol.requestNegotiation(MXP, b"") + if settings.MXP_ENABLED: + self.protocol.protocol_flags["MXP"] = True + self.protocol.requestNegotiation(MXP, b"") + else: + self.protocol.wont(MXP) self.protocol.handshake_done()
    diff --git a/docs/1.0-dev/_modules/evennia/server/portal/webclient.html b/docs/1.0-dev/_modules/evennia/server/portal/webclient.html index a87e5814d4..fa56393ee3 100644 --- a/docs/1.0-dev/_modules/evennia/server/portal/webclient.html +++ b/docs/1.0-dev/_modules/evennia/server/portal/webclient.html @@ -97,7 +97,8 @@
    [docs] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.protocol_key = "webclient/websocket"
    + self.protocol_key = "webclient/websocket" + self.browserstr = ""
    [docs] def get_client_session(self): """ @@ -109,7 +110,8 @@ """ try: - self.csessid = self.http_request_uri.split("?", 1)[1] + # client will connect with wsurl?csessid&browserid + webarg = self.http_request_uri.split("?", 1)[1] except IndexError: # this may happen for custom webclients not caring for the # browser session. @@ -121,6 +123,11 @@ self.csessid = None logger.log_trace(str(self)) return None + + self.csessid, *browserstr = webarg.split("&", 1) + if browserstr: + self.browserstr = str(browserstr[0]) + if self.csessid: return _CLIENT_SESSIONS(session_key=self.csessid)
    @@ -162,7 +169,8 @@ self.sessid = old_session.sessid self.sessionhandler.disconnect(old_session) - self.protocol_flags["CLIENTNAME"] = "Evennia Webclient (websocket)" + browserstr = f":{self.browserstr}" if self.browserstr else "" + self.protocol_flags["CLIENTNAME"] = f"Evennia Webclient (websocket{browserstr})" self.protocol_flags["UTF-8"] = True self.protocol_flags["OOB"] = True diff --git a/docs/1.0-dev/_modules/evennia/server/portal/webclient_ajax.html b/docs/1.0-dev/_modules/evennia/server/portal/webclient_ajax.html index 5c57ba7b33..607e3b7969 100644 --- a/docs/1.0-dev/_modules/evennia/server/portal/webclient_ajax.html +++ b/docs/1.0-dev/_modules/evennia/server/portal/webclient_ajax.html @@ -173,6 +173,19 @@ """ return html.escape(request.args[b"csessid"][0].decode("utf-8"))
    +
    [docs] def get_browserstr(self, request): + """ + Get browser-string out of the request. + + Args: + request (Request): Incoming request object. + Returns: + str: The browser name. + + + """ + return html.escape(request.args[b"browserstr"][0].decode("utf-8"))
    +
    [docs] def at_login(self): """ Called when this session gets authenticated by the server. @@ -225,6 +238,7 @@ """ csessid = self.get_client_sessid(request) + browserstr = self.get_browserstr(request) remote_addr = request.getClientIP() @@ -248,6 +262,7 @@ sess.init_session("ajax/comet", remote_addr, self.sessionhandler) sess.csessid = csessid + sess.browserstr = browserstr csession = _CLIENT_SESSIONS(session_key=sess.csessid) uid = csession and csession.get("webclient_authenticated_uid", False) if uid: @@ -262,6 +277,11 @@ self.keep_alive = LoopingCall(self._keepalive) self.keep_alive.start(_KEEPALIVE, now=False) + browserstr = f":{browserstr}" if browserstr else "" + sess.protocol_flags["CLIENTNAME"] = f"Evennia Webclient (ajax{browserstr})" + sess.protocol_flags["UTF-8"] = True + sess.protocol_flags["OOB"] = True + # actually do the connection sess.sessionhandler.connect(sess) diff --git a/docs/1.0-dev/_modules/evennia/typeclasses/attributes.html b/docs/1.0-dev/_modules/evennia/typeclasses/attributes.html index 1580c7ba18..eb223b16e9 100644 --- a/docs/1.0-dev/_modules/evennia/typeclasses/attributes.html +++ b/docs/1.0-dev/_modules/evennia/typeclasses/attributes.html @@ -203,6 +203,123 @@ value = property(__value_get, __value_set, __value_del)
    +
    [docs]class AttributeProperty: + """ + Attribute property descriptor. Allows for specifying Attributes as Django-like 'fields' + on the class level. Note that while one can set a lock on the Attribute, + there is no way to *check* said lock when accessing via the property - use + the full AttributeHandler if you need to do access checks. + + Example: + :: + + class Character(DefaultCharacter): + foo = AttributeProperty(default="Bar") + + """ + attrhandler_name = "attributes" + +
    [docs] def __init__(self, default=None, category=None, strattr=False, lockstring="", + autocreate=False): + """ + Initialize an Attribute as a property descriptor. + + Keyword Args: + default (any): A default value if the attr is not set. + category (str): The attribute's category. If unset, use class default. + strattr (bool): If set, this Attribute *must* be a simple string, and will be + stored more efficiently. + lockstring (str): This is not itself useful with the property, but only if + using the full AttributeHandler.get(accessing_obj=...) to access the + Attribute. + autocreate (bool): If an un-found Attr should lead to auto-creating the + Attribute (with the default value). If `False`, the property will + return the default value until it has been explicitly set. This means + less database accesses, but also means the property will have no + corresponding Attribute if wanting to access it directly via the + AttributeHandler (it will also not show up in `examine`). + + """ + self._default = default + self._category = category + self._strattr = strattr + self._lockstring = lockstring + self._autocreate = autocreate + self._key = ""
    + + def __set_name__(self, cls, name): + """ + Called when descriptor is first assigned to the class. It is called with + the name of the field. + + """ + self._key = name + + def __get__(self, instance, owner): + """ + Called when the attrkey is retrieved from the instance. + + """ + value = self._default + try: + value = ( + getattr(instance, self.attrhandler_name) + .get(key=self._key, + default=self._default, + category=self._category, + strattr=self._strattr, + raise_exception=self._autocreate) + ) + except AttributeError: + if self._autocreate: + # attribute didn't exist and autocreate is set + self.__set__(instance, self._default) + else: + raise + finally: + return value + + def __set__(self, instance, value): + """ + Called when assigning to the property (and when auto-creating an Attribute). + + """ + ( + getattr(instance, self.attrhandler_name) + .add(self._key, + value, + category=self._category, + lockstring=self._lockstring, + strattr=self._strattr) + ) + + def __delete__(self, instance): + """ + Called when running `del` on the field. Will remove/clear the Attribute. + + """ + ( + getattr(instance, self.attrhandler_name) + .remove(key=self._key, + category=self._category) + )
    + + +
    [docs]class NAttributeProperty(AttributeProperty): + """ + NAttribute property descriptor. Allows for specifying NAttributes as Django-like 'fields' + on the class level. + + Example: + :: + + class Character(DefaultCharacter): + foo = NAttributeProperty(default="Bar") + + """ + attrhandler_name = "nattributes"
    + +
    [docs]class Attribute(IAttribute, SharedMemoryModel): """ This attribute is stored via Django. Most Attributes will be using this class. @@ -1024,11 +1141,11 @@ key (str or list, optional): the attribute identifier or multiple attributes to get. if a list of keys, the method will return a list. - category (str, optional): the category within which to - retrieve attribute(s). default (any, optional): The value to return if an Attribute was not defined. If set, it will be returned in a one-item list. + category (str, optional): the category within which to + retrieve attribute(s). return_obj (bool, optional): If set, the return is not the value of the Attribute but the Attribute object itself. strattr (bool, optional): Return the `strvalue` field of diff --git a/docs/1.0-dev/_modules/evennia/typeclasses/tags.html b/docs/1.0-dev/_modules/evennia/typeclasses/tags.html index 4f19a455c3..15f0271980 100644 --- a/docs/1.0-dev/_modules/evennia/typeclasses/tags.html +++ b/docs/1.0-dev/_modules/evennia/typeclasses/tags.html @@ -334,12 +334,12 @@ self._cache = {} self._catcache = {}
    -
    [docs] def add(self, tag=None, category=None, data=None): +
    [docs] def add(self, key=None, category=None, data=None): """ Add a new tag to the handler. Args: - tag (str or list): The name of the tag to add. If a list, + key (str or list): The name of the tag to add. If a list, add several Tags. category (str, optional): Category of Tag. `None` is the default category. data (str, optional): Info text about the tag(s) added. @@ -352,11 +352,11 @@ will be created. """ - if not tag: + if not key: return if not self._cache_complete: self._fullcache() - for tagstr in make_iter(tag): + for tagstr in make_iter(key): if not tagstr: continue tagstr = str(tagstr).strip().lower() @@ -371,12 +371,12 @@ getattr(self.obj, self._m2m_fieldname).add(tagobj) self._setcache(tagstr, category, tagobj)
    -
    [docs] def has(self, tag=None, category=None, return_list=False): +
    [docs] def has(self, key=None, category=None, return_list=False): """ Checks if the given Tag (or list of Tags) exists on the object. Args: - tag (str or iterable): The Tag key or tags to check for. + key (str or iterable): The Tag key or tags to check for. If `None`, search by category. category (str, optional): Limit the check to Tags with this category (note, that `None` is the default category). @@ -391,8 +391,8 @@ """ ret = [] category = category.strip().lower() if category is not None else None - if tag: - for tag_str in make_iter(tag): + if key: + for tag_str in make_iter(key): tag_str = tag_str.strip().lower() ret.extend(bool(tag) for tag in self._getcache(tag_str, category)) elif category: @@ -559,7 +559,7 @@ keys[tup[1]].append(tup[0]) data[tup[1]] = tup[2] # overwrite previous for category, key in keys.items(): - self.add(tag=key, category=category, data=data.get(category, None))
    + self.add(key=key, category=category, data=data.get(category, None))
    def __str__(self): return ",".join(self.all())
    diff --git a/docs/1.0-dev/_modules/evennia/utils/ansi.html b/docs/1.0-dev/_modules/evennia/utils/ansi.html index 4ad5640b7e..18985bfbe9 100644 --- a/docs/1.0-dev/_modules/evennia/utils/ansi.html +++ b/docs/1.0-dev/_modules/evennia/utils/ansi.html @@ -117,6 +117,8 @@ from evennia.utils.utils import to_str +MXP_ENABLED = settings.MXP_ENABLED + # ANSI definitions @@ -627,6 +629,14 @@ return parser.strip_unsafe_tokens(string)
    +
    [docs]def strip_mxp(string, parser=ANSI_PARSER): + """ + Strip MXP markup. + + """ + return parser.strip_mxp(string)
    + +
    [docs]def raw(string): """ Escapes a string into a form which won't be colorized by the ansi @@ -836,8 +846,8 @@ decoded = True if not decoded: # Completely new ANSI String - clean_string = parser.parse_ansi(string, strip_ansi=True, mxp=True) - string = parser.parse_ansi(string, xterm256=True, mxp=True) + clean_string = parser.parse_ansi(string, strip_ansi=True, mxp=MXP_ENABLED) + string = parser.parse_ansi(string, xterm256=True, mxp=MXP_ENABLED) elif clean_string is not None: # We have an explicit clean string. pass diff --git a/docs/1.0-dev/_modules/evennia/web/utils/general_context.html b/docs/1.0-dev/_modules/evennia/web/utils/general_context.html index 25025d6f6e..325b551718 100644 --- a/docs/1.0-dev/_modules/evennia/web/utils/general_context.html +++ b/docs/1.0-dev/_modules/evennia/web/utils/general_context.html @@ -59,24 +59,45 @@ # Setup lists of the most relevant apps so # the adminsite becomes more readable. +GAME_NAME = None +GAME_SLOGAN = None +SERVER_VERSION = None +SERVER_HOSTNAME = None + +TELNET_ENABLED = None +TELNET_PORTS = None +TELNET_SSL_ENABLED = None +TELNET_SSL_PORTS = None + +SSH_ENABLED = None +SSH_PORTS = None + +WEBCLIENT_ENABLED = None +WEBSOCKET_CLIENT_ENABLED = None +WEBSOCKET_PORT = None +WEBSOCKET_URL = None + +REST_API_ENABLED = False + ACCOUNT_RELATED = ["Accounts"] GAME_ENTITIES = ["Objects", "Scripts", "Comms", "Help"] GAME_SETUP = ["Permissions", "Config"] CONNECTIONS = ["Irc"] WEBSITE = ["Flatpages", "News", "Sites"] -REST_API_ENABLED = False -# Determine the site name and server version -
    [docs]def set_game_name_and_slogan(): + +
    [docs]def load_game_settings(): """ - Sets global variables GAME_NAME and GAME_SLOGAN which are used by - general_context. - - Notes: - This function is used for unit testing the values of the globals. + Load and cache game settings. """ - global GAME_NAME, GAME_SLOGAN, SERVER_VERSION, REST_API_ENABLED + global GAME_NAME, GAME_SLOGAN, SERVER_VERSION, SERVER_HOSTNAME + global TELNET_ENABLED, TELNET_PORTS + global TELNET_SSL_ENABLED, TELNET_SSL_PORTS + global SSH_ENABLED, SSH_PORTS + global WEBCLIENT_ENABLED, WEBSOCKET_CLIENT_ENABLED, WEBSOCKET_PORT, WEBSOCKET_URL + global REST_API_ENABLED + try: GAME_NAME = settings.SERVERNAME.strip() except AttributeError: @@ -86,19 +107,16 @@ GAME_SLOGAN = settings.GAME_SLOGAN.strip() except AttributeError: GAME_SLOGAN = SERVER_VERSION + SERVER_HOSTNAME = settings.SERVER_HOSTNAME - REST_API_ENABLED = settings.REST_API_ENABLED
    + TELNET_ENABLED = settings.TELNET_ENABLED + TELNET_PORTS = settings.TELNET_PORTS + TELNET_SSL_ENABLED = settings.SSL_ENABLED + TELNET_SSL_PORTS = settings.SSL_PORTS -
    [docs]def set_webclient_settings(): - """ - As with set_game_name_and_slogan above, this sets global variables pertaining - to webclient settings. + SSH_ENABLED = settings.SSH_ENABLED + SSH_PORTS = settings.SSH_PORTS - Notes: - Used for unit testing. - - """ - global WEBCLIENT_ENABLED, WEBSOCKET_CLIENT_ENABLED, WEBSOCKET_PORT, WEBSOCKET_URL WEBCLIENT_ENABLED = settings.WEBCLIENT_ENABLED WEBSOCKET_CLIENT_ENABLED = settings.WEBSOCKET_CLIENT_ENABLED # if we are working through a proxy or uses docker port-remapping, the webclient port encoded @@ -108,11 +126,13 @@ os.environ.get("WEBSOCKET_CLIENT_PROXY_PORT", settings.WEBSOCKET_CLIENT_PORT) ) # this is determined dynamically by the client and is less of an issue - WEBSOCKET_URL = settings.WEBSOCKET_CLIENT_URL
    + WEBSOCKET_URL = settings.WEBSOCKET_CLIENT_URL + + REST_API_ENABLED = settings.REST_API_ENABLED
    -set_game_name_and_slogan() -set_webclient_settings() +load_game_settings() + # The main context processor function
    [docs]def general_context(request): @@ -135,11 +155,18 @@ "puppet": puppet, "game_name": GAME_NAME, "game_slogan": GAME_SLOGAN, + "server_hostname": SERVER_HOSTNAME, "evennia_userapps": ACCOUNT_RELATED, "evennia_entityapps": GAME_ENTITIES, "evennia_setupapps": GAME_SETUP, "evennia_connectapps": CONNECTIONS, "evennia_websiteapps": WEBSITE, + "telnet_enabled": TELNET_ENABLED, + "telnet_ports": TELNET_PORTS, + "telnet_ssl_enabled": TELNET_SSL_ENABLED, + "telnet_ssl_ports": TELNET_SSL_PORTS, + "ssh_enabled": SSH_ENABLED, + "ssh_ports": SSH_ENABLED, "webclient_enabled": WEBCLIENT_ENABLED, "websocket_enabled": WEBSOCKET_CLIENT_ENABLED, "websocket_port": WEBSOCKET_PORT, diff --git a/docs/1.0-dev/_modules/evennia/web/utils/tests.html b/docs/1.0-dev/_modules/evennia/web/utils/tests.html index e8b7b41b94..9aee470306 100644 --- a/docs/1.0-dev/_modules/evennia/web/utils/tests.html +++ b/docs/1.0-dev/_modules/evennia/web/utils/tests.html @@ -83,37 +83,15 @@ "websocket_port": "websocket_client_port_testvalue", "websocket_url": "websocket_client_url_testvalue", "rest_api_enabled": True, + "server_hostname": 'localhost', + "ssh_enabled": False, + "ssh_ports": False, + "telnet_enabled": True, + "telnet_ports": [4000], + "telnet_ssl_enabled": False, + "telnet_ssl_ports": [4003], }, - )
    - - # spec being an empty list will initially raise AttributeError in set_game_name_and_slogan to test defaults -
    [docs] @patch("evennia.web.utils.general_context.settings", spec=[]) - @patch("evennia.web.utils.general_context.get_evennia_version") - def test_set_game_name_and_slogan(self, mock_get_version, mock_settings): - mock_get_version.return_value = "version 1" - # test default/fallback values - mock_settings.REST_API_ENABLED = False - general_context.set_game_name_and_slogan() - self.assertEqual(general_context.GAME_NAME, "Evennia") - self.assertEqual(general_context.GAME_SLOGAN, "version 1") - # test values when the settings are defined - mock_settings.SERVERNAME = "test_name" - mock_settings.GAME_SLOGAN = "test_game_slogan" - general_context.set_game_name_and_slogan() - self.assertEqual(general_context.GAME_NAME, "test_name") - self.assertEqual(general_context.GAME_SLOGAN, "test_game_slogan")
    - -
    [docs] @patch("evennia.web.utils.general_context.settings") - def test_set_webclient_settings(self, mock_settings): - mock_settings.WEBCLIENT_ENABLED = "webclient" - mock_settings.WEBSOCKET_CLIENT_URL = "websocket_url" - mock_settings.WEBSOCKET_CLIENT_ENABLED = "websocket_client" - mock_settings.WEBSOCKET_CLIENT_PORT = 5000 - general_context.set_webclient_settings() - self.assertEqual(general_context.WEBCLIENT_ENABLED, "webclient") - self.assertEqual(general_context.WEBSOCKET_URL, "websocket_url") - self.assertEqual(general_context.WEBSOCKET_CLIENT_ENABLED, "websocket_client") - self.assertEqual(general_context.WEBSOCKET_PORT, 5000)
    + )
    diff --git a/docs/1.0-dev/_sources/Components/Attributes.md.txt b/docs/1.0-dev/_sources/Components/Attributes.md.txt index 3c6e373cd8..7d18743a20 100644 --- a/docs/1.0-dev/_sources/Components/Attributes.md.txt +++ b/docs/1.0-dev/_sources/Components/Attributes.md.txt @@ -1,229 +1,427 @@ # Attributes +```python +# in-game +> set obj/myattr = "test" -When performing actions in Evennia it is often important that you store data for later. If you write -a menu system, you have to keep track of the current location in the menu tree so that the player -can give correct subsequent commands. If you are writing a combat system, you might have a -combattant's next roll get easier dependent on if their opponent failed. Your characters will -probably need to store roleplaying-attributes like strength and agility. And so on. - -[Typeclassed](./Typeclasses.md) game entities ([Accounts](./Accounts.md), [Objects](./Objects.md), -[Scripts](./Scripts.md) and [Channels](./Communications.md)) always have *Attributes* associated with them. -Attributes are used to store any type of data 'on' such entities. This is different from storing -data in properties already defined on entities (such as `key` or `location`) - these have very -specific names and require very specific types of data (for example you couldn't assign a python -*list* to the `key` property no matter how hard you tried). `Attributes` come into play when you -want to assign arbitrary data to arbitrary names. - -**Attributes are _not_ secure by default and any player may be able to change them unless you -[prevent this behavior](./Attributes.md#locking-and-checking-attributes).** - -## The .db and .ndb shortcuts - -To save persistent data on a Typeclassed object you normally use the `db` (DataBase) operator. Let's -try to save some data to a *Rose* (an [Object](./Objects.md)): - -```python - # saving - rose.db.has_thorns = True - # getting it back - is_ouch = rose.db.has_thorns +# in code +obj.db.foo = [1,2,3, "bar"] +value = obj.db.foo +obj.attributes.add("myattr", 1234, category="bar") +value = attributes.get("myattr", category="bar") ``` -This looks like any normal Python assignment, but that `db` makes sure that an *Attribute* is -created behind the scenes and is stored in the database. Your rose will continue to have thorns -throughout the life of the server now, until you deliberately remove them. +_Attributes_ allow you to to store arbitrary data on objects and make sure the data survives a +server reboot. An Attribute can store pretty much any +Python data structure and data type, like numbers, strings, lists, dicts etc. You can also +store (references to) database objects like characters and rooms. -To be sure to save **non-persistently**, i.e. to make sure NOT to create a database entry, you use -`ndb` (NonDataBase). It works in the same way: +- [What can be stored in an Attribute](#what-types-of-data-can-i-save-in-an-attribute) is a must-read + also for experienced developers, to avoid getting surprised. Attributes can store _almost_ everything + but you need to know the quirks. +- [NAttributes](#in-memory-attributes-nattributes) are the in-memory, non-persistent + siblings of Attributes. +- [Managing Attributes In-game](#managing-attributes-in-game) for in-game builder commands. -```python - # saving - rose.ndb.has_thorns = True - # getting it back - is_ouch = rose.ndb.has_thorns +## Managing Attributes in Code + +Attributes are usually handled in code. All [Typeclassed](./Typeclasses.md) entities +([Accounts](./Accounts.md), [Objects](./Objects.md), [Scripts](./Scripts.md) and +[Channels](./Channels.md)) all can (and usually do) have Attributes associated with them. There +are three ways to manage Attributes, all of which can be mixed. + +- [Using the `.db` property shortcut](#using-db) +- [Using the `.attributes` manager (`AttributeManager`)](#using-attributes) +- [Using `AttributeProperty` for assigning Attributes in a way similar to Django fields](#using-attributeproperty) + +### Using .db + +The simplest way to get/set Attributes is to use the `.db` shortcut: + +```python +import evennia + +obj = evennia.create_object(key="Foo") + +obj.db.foo1 = 1234 +obj.db.foo2 = [1, 2, 3, 4] +obj.db.weapon = "sword" +obj.db.self_reference = obj # stores a reference to the obj + +# (let's assume a rose exists in-game) +rose = evennia.search_object(key="rose")[0] # returns a list, grab 0th element +rose.db.has_thorns = True + +# retrieving +val1 = obj.db.foo1 +val2 = obj.db.foo2 +weap = obj.db.weapon +myself = obj.db.self_reference # retrieve reference from db, get object back + +is_ouch = rose.db.has_thorns + +# this will return None, not AttributeError! +not_found = obj.db.jiwjpowiwwerw + +# returns all Attributes on the object +obj.db.all + +# delete an Attribute +del obj.db.foo2 +``` +Trying to access a non-existing Attribute will never lead to an `AttributeError`. Instead +you will get `None` back. The special `.db.all` will return a list of all Attributes on +the object. You can replace this with your own Attribute `all` if you want, it will replace the +default `all` functionality until you delete it again. + +### Using .attributes + +If you don't know the name of the Attribute beforehand you can also use +the `AttributeHandler`, available as `.attributes`. With no extra keywords this is identical +to using the `.db` shortcut (`.db` is actually using the `AttributeHandler` internally): + +```python +is_ouch = rose.attributes.get("has_thorns") + +obj.attributes.add("helmet", "Knight's helmet") +helmet = obj.attributes.get("helmet") + +# you can give space-separated Attribute-names (can't do that with .db) +obj.attributes.add("my game log", "long text about ...") ``` -Technically, `ndb` has nothing to do with `Attributes`, despite how similar they look. No -`Attribute` object is created behind the scenes when using `ndb`. In fact the database is not -invoked at all since we are not interested in persistence. There is however an important reason to -use `ndb` to store data rather than to just store variables direct on entities - `ndb`-stored data -is tracked by the server and will not be purged in various cache-cleanup operations Evennia may do -while it runs. Data stored on `ndb` (as well as `db`) will also be easily listed by example the -`@examine` command. +With the `AttributeHandler` you can also give Attributes a `category`. By using a category you can +separate same-named Attributes on the same object which can help organization: -You can also `del` properties on `db` and `ndb` as normal. This will for example delete an -`Attribute`: +```python +# store (let's say we have gold_necklace and ringmail_armor from before) +obj.attributes.add("neck", gold_necklace, category="clothing") +obj.attributes.add("neck", ringmail_armor, category="armor") -```python - del rose.db.has_thorns +# retrieve later - we'll get back gold_necklace and ringmail_armor +neck_clothing = obj.attributes.get("neck", category="clothing") +neck_armor = obj.attributes.get("neck", category="armor") ``` -Both `db` and `ndb` defaults to offering an `all` property on themselves. This returns all -associated attributes or non-persistent properties. +If you don't specify a category, the Attribute's `category` will be `None`. Note that +`None` is also considered a category of its own, so you won't find `None`-category Attributes mixed +with `Attributes` having categories. -```python - list_of_all_rose_attributes = rose.db.all - list_of_all_rose_ndb_attrs = rose.ndb.all -``` +> When using `.db`, you will always use the `None` category. -If you use `all` as the name of an attribute, this will be used instead. Later deleting your custom -`all` will return the default behaviour. +Here are the methods of the `AttributeHandler`. See +the [AttributeHandler API](evennia.typeclasses.attributes.AttributeHandler) for more details. -## The AttributeHandler - -The `.db` and `.ndb` properties are very convenient but if you don't know the name of the Attribute -beforehand they cannot be used. Behind the scenes `.db` actually accesses the `AttributeHandler` -which sits on typeclassed entities as the `.attributes` property. `.ndb` does the same for the -`.nattributes` property. - -The handlers have normal access methods that allow you to manage and retrieve `Attributes` and -`NAttributes`: - -- `has('attrname')` - this checks if the object has an Attribute with this key. This is equivalent - to doing `obj.db.attrname`. -- `get(...)` - this retrieves the given Attribute. Normally the `value` property of the Attribute is - returned, but the method takes keywords for returning the Attribute object itself. By supplying an +- `has(...)` - this checks if the object has an Attribute with this key. This is equivalent + to doing `obj.db.attrname` except you can also check for a specific `category. +- `get(...)` - this retrieves the given Attribute. You can also provide a `default` value to return + if the Attribute is not defined (instead of None). By supplying an `accessing_object` to the call one can also make sure to check permissions before modifying - anything. + anything. The `raise_exception` kwarg allows you to raise an `AttributeError` instead of returning + `None` when you access a non-existing `Attribute`. The `strattr` kwarg tells the system to store + the Attribute as a raw string rather than to pickle it. While an optimization this should usually + not be used unless the Attribute is used for some particular, limited purpose. - `add(...)` - this adds a new Attribute to the object. An optional [lockstring](./Locks.md) can be supplied here to restrict future access and also the call itself may be checked against locks. - `remove(...)` - Remove the given Attribute. This can optionally be made to check for permission before performing the deletion. - `clear(...)` - removes all Attributes from object. -- `all(...)` - returns all Attributes (of the given category) attached to this object. +- `all(category=None)` - returns all Attributes (of the given category) attached to this object. -See [this section](./Attributes.md#locking-and-checking-attributes) for more about locking down Attribute -access and editing. The `Nattribute` offers no concept of access control. +Examples: -Some examples: +```python +try: + # raise error if Attribute foo does not exist + val = obj.attributes.get("foo", raise_exception=True): +except AttributeError: + # ... + +# return default value if foo2 doesn't exist +val2 = obj.attributes.get("foo2", default=[1, 2, 3, "bar"]) -```python - import evennia - obj = evennia.search_object("MyObject") - - obj.attributes.add("test", "testvalue") - print(obj.db.test) # prints "testvalue" - print(obj.attributes.get("test")) # " - print(obj.attributes.all()) # prints [] - obj.attributes.remove("test") +# delete foo if it exists (will silently fail if unset, unless +# raise_exception is set) +obj.attributes.remove("foo") + +# view all clothes on obj +all_clothes = obj.attributes.all(category="clothes") ``` +### Using AttributeProperty -## Properties of Attributes +There is a third way to set up an Attribute, and that is by setting up an `AttributeProperty`. This +is done on the _class level_ of your typeclass and allows you to treat Attributes a bit like Django +database Fields. -An Attribute object is stored in the database. It has the following properties: +```python +# mygame/typeclasses/characters.py -- `key` - the name of the Attribute. When doing e.g. `obj.db.attrname = value`, this property is set - to `attrname`. -- `value` - this is the value of the Attribute. This value can be anything which can be pickled - - objects, lists, numbers or what have you (see - [this section](./Attributes.md#what-types-of-data-can-i-save-in-an-attribute) for more info). In the -example - `obj.db.attrname = value`, the `value` is stored here. -- `category` - this is an optional property that is set to None for most Attributes. Setting this - allows to use Attributes for different functionality. This is usually not needed unless you want - to use Attributes for very different functionality ([Nicks](./Nicks.md) is an example of using -Attributes - in this way). To modify this property you need to use the -[Attribute Handler](./Attributes.md#the-attributehandler). -- `strvalue` - this is a separate value field that only accepts strings. This severely limits the - data possible to store, but allows for easier database lookups. This property is usually not used - except when re-using Attributes for some other purpose ([Nicks](./Nicks.md) use it). It is only - accessible via the [Attribute Handler](./Attributes.md#the-attributehandler). +from evennia import DefaultCharacter +from evennia.typeclasses.attributes import AttributeProperty -There are also two special properties: +class Character(DefaultCharacter): -- `attrtype` - this is used internally by Evennia to separate [Nicks](./Nicks.md), from Attributes (Nicks - use Attributes behind the scenes). -- `model` - this is a *natural-key* describing the model this Attribute is attached to. This is on - the form *appname.modelclass*, like `objects.objectdb`. It is used by the Attribute and - NickHandler to quickly sort matches in the database. Neither this nor `attrtype` should normally - need to be modified. + strength = AttributeProperty(default=10, category='stat', autocreate=True) + constitution = AttributeProperty(default=10, category='stat', autocreate=True) + agility = AttributeProperty(default=10, category='stat', autocreate=True) + magic = AttributeProperty(default=10, category='stat', autocreate=True) + + sleepy = AttributeProperty(default=False) + poisoned = AttributeProperty(default=False) + + def at_object_creation(self): + # ... +``` -Non-database attributes have no equivalence to `category` nor `strvalue`, `attrtype` or `model`. +These "Attribute-properties" will be made available to all instances of the class. -## Persistent vs non-persistent +```{important} +If you change the `default` of an `AttributeProperty` (and reload), it will +change the default for _all_ instances of that class (it will not override +explicitly changed values). +``` -So *persistent* data means that your data will survive a server reboot, whereas with -*non-persistent* data it will not ... +```python +char = evennia.search_object(Character, key="Bob")[0] # returns list, get 0th element -... So why would you ever want to use non-persistent data? The answer is, you don't have to. Most of -the time you really want to save as much as you possibly can. Non-persistent data is potentially -useful in a few situations though. +# get defaults +strength = char.strength # will get the default value 10 -- You are worried about database performance. Since Evennia caches Attributes very aggressively, - this is not an issue unless you are reading *and* writing to your Attribute very often (like many - times per second). Reading from an already cached Attribute is as fast as reading any Python - property. But even then this is not likely something to worry about: Apart from Evennia's own - caching, modern database systems themselves also cache data very efficiently for speed. Our -default - database even runs completely in RAM if possible, alleviating much of the need to write to disk - during heavy loads. -- A more valid reason for using non-persistent data is if you *want* to lose your state when logging - off. Maybe you are storing throw-away data that are re-initialized at server startup. Maybe you - are implementing some caching of your own. Or maybe you are testing a buggy [Script](./Scripts.md) that - does potentially harmful stuff to your character object. With non-persistent storage you can be -sure - that whatever is messed up, it's nothing a server reboot can't clear up. -- NAttributes have no restrictions at all on what they can store (see next section), since they - don't need to worry about being saved to the database - they work very well for temporary storage. -- You want to implement a fully or partly *non-persistent world*. Who are we to argue with your - grand vision! +# assign new values (this will create/update new Attributes) +char.strength = 12 +char.constitution = 16 +char.agility = 8 +char.magic = 2 + +# you can also do arithmetic etc +char.magic += 2 # char.magic is now 4 + +# check Attributes +strength = char.strength # this is now 12 +is_sleepy = char.sleepy +is_poisoned = char.poisoned + +del char.strength # wipes the Attribute +strength = char.strengh # back to the default (10) again +``` + +See the [AttributeProperty](evennia.typeclasses.attributes.AttributeProperty) docs for more +details on arguments. + +An `AttributeProperty` will _not_ create an `Attribute` by default. A new `Attribute` will be created +(or an existing one retrieved/updated) will happen differently depending on how the `autocreate` +keyword: + +- If `autocreate=False` (default), an `Attribute` will be created only if the field is explicitly + assigned a value (even if the value is the same as the default, such as `char.strength = 10`). +- If `autocreate=True`, an `Attribute` will be created as soon as the field is _accessed_ in + any way (So both `strength = char.strength` and `char.strength = 10` will both make sure that + an `Attribute` exists. + +Example: + +```python +# in mygame/typeclasses/objects.py + +from evennia import create_object +from evennia import DefaultObject +from evennia.typeclasses.attributes import AttributeProperty + +class Object(DefaultObject): + + value_a = AttributeProperty(default="foo") + value_b = AttributeProperty(default="bar", autocreate=True) + +obj = evennia.create_object(key="Dummy") + +# these will find NO Attributes! +obj.db.value_a +obj.attributes.get("value_a") +obj.db.value_b +obj.attributes.get("value_b") + +# get data from attribute-properties +vala = obj.value_a # returns "foo" +valb = obj.value_b # return "bar" AND creates the Attribute (autocreate) + +# the autocreate property will now be found +obj.db.value_a # still not found +obj.attributes.get("value_a") # '' +obj.db.value_b # now returns "bar" +obj.attributes.get("value_b") # '' + +# assign new values +obj.value_a = 10 # will now create a new Attribute +obj.value_b = 12 # will update the existing Attribute + +# both are now found as Attributes +obj.db.value_a # now returns 10 +obj.attributes.get("value_a") # '' +obj.db.value_b # now returns 12 +obj.attributes.get("value_b") # '' +``` + +If you always access your Attributes via the `AttributeProperty` this does not matter that much +(it's also a bit of an optimization to not create an actual database `Attribute` unless the value changed). +But until an `Attribute` has been created, `AttributeProperty` fields will _not_ show up with the +`examine` command or by using the `.db` or `.attributes` handlers - so this is a bit inconsistent. +If this is important, you need to 'initialize' them by accessing them at least once ... something +like this: + + +```python +# ... +class Character(DefaultCharacter): + + strength = AttributeProperty(12, autocreate=True) + agility = AttributeProperty(12, autocreate=True) + + + def at_object_creation(self): + # initializing + self.strength # by accessing it, the Attribute is auto-created + self.agility # '' +``` + +```{important} +If you created your `AttributeProperty` with a `category`, you *must* specify the +category in `.attributes.get()` if you want to find it this way. Remember that +`.db` always uses a `category` of `None`. +``` + +## Managing Attributes in-game + +Attributes are mainly used by code. But one can also allow the builder to use Attributes to +'turn knobs' in-game. For example a builder could want to manually tweak the "level" Attribute of an +enemy NPC to lower its difficuly. + +When setting Attributes this way, you are severely limited in what can be stored - this is because +giving players (even builders) the ability to store arbitrary Python would be a severe security +problem. + +In game you can set an Attribute like this: + + set myobj/foo = "bar" + +To view, do + + set myobj/foo + +or see them together with all object-info with + + examine myobj + +The first `set`-example will store a new Attribute `foo` on the object `myobj` and give it the +value "bar". +You can store numbers, booleans, strings, tuples, lists and dicts this way. But if +you store a list/tuple/dict they must be proper Python structures and may _only_ contain strings +or numbers. If you try to insert an unsupported structure, the input will be converted to a +string. + + set myobj/mybool = True + set myobj/mybool = True + set myobj/mytuple = (1, 2, 3, "foo") + set myobj/mylist = ["foo", "bar", 2] + set myobj/mydict = {"a": 1, "b": 2, 3: 4} + set mypobj/mystring = [1, 2, foo] # foo is invalid Python (no quotes) + +For the last line you'll get a warning and the value instead will be saved as a string `"[1, 2, foo]"`. + +## Locking and checking Attributes + +While the `set` command is limited to builders, individual Attributes are usually not +locked down. You may want to lock certain sensitive Attributes, in particular for games +where you allow player building. You can add such limitations by adding a [lock string](./Locks.md) +to your Attribute. A NAttribute have no locks. + +The relevant lock types are + +- `attrread` - limits who may read the value of the Attribute +- `attredit` - limits who may set/change this Attribute + +You must use the `AttributeHandler` to assign the lockstring to the Attribute: + +```python +lockstring = "attread:all();attredit:perm(Admins)" +obj.attributes.add("myattr", "bar", lockstring=lockstring)" +``` + +If you already have an Attribute and want to add a lock in-place you can do so +by having the `AttributeHandler` return the `Attribute` object itself (rather than +its value) and then assign the lock to it directly: + +```python + lockstring = "attread:all();attredit:perm(Admins)" + obj.attributes.get("myattr", return_obj=True).locks.add(lockstring) +``` + +Note the `return_obj` keyword which makes sure to return the `Attribute` object so its LockHandler +could be accessed. + +A lock is no good if nothing checks it -- and by default Evennia does not check locks on Attributes. +To check the `lockstring` you provided, make sure you include `accessing_obj` and set +`default_access=False` as you make a `get` call. + +```python + # in some command code where we want to limit + # setting of a given attribute name on an object + attr = obj.attributes.get(attrname, + return_obj=True, + accessing_obj=caller, + default=None, + default_access=False) + if not attr: + caller.msg("You cannot edit that Attribute!") + return + # edit the Attribute here +``` + +The same keywords are available to use with `obj.attributes.set()` and `obj.attributes.remove()`, +those will check for the `attredit` lock type. ## What types of data can I save in an Attribute? -> None of the following affects NAttributes, which does not invoke the database at all. There are no -> restrictions to what can be stored in a NAttribute. - The database doesn't know anything about Python objects, so Evennia must *serialize* Attribute -values into a string representation in order to store it to the database. This is done using the -`pickle` module of Python (the only exception is if you use the `strattr` keyword of the -AttributeHandler to save to the `strvalue` field of the Attribute. In that case you can only save -*strings* which will not be pickled). +values into a string representation before storing it to the database. This is done using the +[pickle](https://docs.python.org/library/pickle.html) module of Python. -It's important to note that when you access the data in an Attribute you are *always* de-serializing -it from the database representation every time. This is because we allow for storing -database-entities in Attributes too. If we cached it as its Python form, we might end up with -situations where the database entity was deleted since we last accessed the Attribute. -De-serializing data with a database-entity in it means querying the database for that object and -making sure it still exists (otherwise it will be set to `None`). Performance-wise this is usually -not a big deal. But if you are accessing the Attribute as part of some big loop or doing a large -amount of reads/writes you should first extract it to a temporary variable, operate on *that* and -then save the result back to the Attribute. If you are storing a more complex structure like a -`dict` or a `list` you should make sure to "disconnect" it from the database before looping over it, -as mentioned in the [Retrieving Mutable Objects](./Attributes.md#retrieving-mutable-objects) section -below. +> The only exception is if you use the `strattr` keyword of the +`AttributeHandler` to save to the `strvalue` field of the Attribute. In that case you can _only_ save +*strings* and those will not be pickled). ### Storing single objects With a single object, we mean anything that is *not iterable*, like numbers, strings or custom class instances without the `__iter__` method. -* You can generally store any non-iterable Python entity that can be - [pickled](https://docs.python.org/library/pickle.html). -* Single database objects/typeclasses can be stored as any other in the Attribute. These can - normally *not* be pickled, but Evennia will behind the scenes convert them to an internal - representation using their classname, database-id and creation-date with a microsecond precision, - guaranteeing you get the same object back when you access the Attribute later. -* If you *hide* a database object inside a non-iterable custom class (like stored as a variable - inside it), Evennia will not know it's there and won't convert it safely. Storing classes with - such hidden database objects is *not* supported and will lead to errors! +* You can generally store any non-iterable Python entity that can be pickled. +* Single database objects/typeclasses can be stored, despite them normally not being possible + to pickle. Evennia wil convert them to an internal representation using their classname, + database-id and creation-date with a microsecond precision. When retrieving, the object + instance will be re-fetched from the database using this information. +* To convert the database object, Evennia must know it's there. If you *hide* a database object + inside a non-iterable class, you will run into errors - this is not supported! + +```{code-block} python +:caption: Valid assignments -```python # Examples of valid single-value attribute data: obj.db.test1 = 23 obj.db.test1 = False # a database object (will be stored as an internal representation) obj.db.test2 = myobj +``` +```{code-block} python +:caption: Invalid, 'hidden' dbobject # example of an invalid, "hidden" dbobject -class Invalid(object): - def __init__(self, dbobj): - # no way for Evennia to know this is a dbobj - self.dbobj = dbobj -invalid = Invalid(myobj) -obj.db.invalid = invalid # will cause error! +class Container: + def __init__(self, mydbobj): + # no way for Evennia to know this is a database object! + self.mydbobj = mydbobj +container = Container(myobj) +obj.db.invalid = container # will cause error! ``` ### Storing multiple objects @@ -237,8 +435,7 @@ entities you can loop over in a for-loop. Attribute-saving supports the followin * [Dicts](https://docs.python.org/2/tutorial/datastructures.html#dictionaries), like `{1:2, "test":]`. * [Sets](https://docs.python.org/2/tutorial/datastructures.html#sets), like `{1,2,"test",}`. -* -[collections.OrderedDict](https://docs.python.org/2/library/collections.html#collections.OrderedDict), +* [collections.OrderedDict](https://docs.python.org/2/library/collections.html#collections.OrderedDict), like `OrderedDict((1,2), ("test", ))`. * [collections.Deque](https://docs.python.org/2/library/collections.html#collections.deque), like `deque((1,2,"test",))`. @@ -319,7 +516,6 @@ function `evennia.utils.dbserialize.deserialize`: from evennia.utils.dbserialize import deserialize decoupled_mutables = deserialize(nested_mutables) - ``` The result of this operation will be a structure only consisting of normal Python mutables (`list` @@ -343,53 +539,95 @@ already disconnected from the database from the onset. # without affecting the database. ``` -> Attributes will fetch data fresh from the database whenever you read them, so -> if you are performing big operations on a mutable Attribute property (such as looping over a list -> or dict) you should make sure to "disconnect" the Attribute's value first and operate on this -> rather than on the Attribute. You can gain dramatic speed improvements to big loops this -> way. +## Properties of Attributes +An `Attribute` object is stored in the database. It has the following properties: -## Locking and checking Attributes +- `key` - the name of the Attribute. When doing e.g. `obj.db.attrname = value`, this property is set + to `attrname`. +- `value` - this is the value of the Attribute. This value can be anything which can be pickled - + objects, lists, numbers or what have you (see + [this section](./Attributes.md#what-types-of-data-can-i-save-in-an-attribute) for more info). In the + example + `obj.db.attrname = value`, the `value` is stored here. +- `category` - this is an optional property that is set to None for most Attributes. Setting this + allows to use Attributes for different functionality. This is usually not needed unless you want + to use Attributes for very different functionality ([Nicks](./Nicks.md) is an example of using + Attributes in this way). To modify this property you need to use the [Attribute Handler](#attributes) +- `strvalue` - this is a separate value field that only accepts strings. This severely limits the + data possible to store, but allows for easier database lookups. This property is usually not used + except when re-using Attributes for some other purpose ([Nicks](./Nicks.md) use it). It is only + accessible via the [Attribute Handler](#attributes). -Attributes are normally not locked down by default, but you can easily change that for individual -Attributes (like those that may be game-sensitive in games with user-level building). +There are also two special properties: -First you need to set a *lock string* on your Attribute. Lock strings are specified [Locks](./Locks.md). -The relevant lock types are +- `attrtype` - this is used internally by Evennia to separate [Nicks](./Nicks.md), from Attributes (Nicks + use Attributes behind the scenes). +- `model` - this is a *natural-key* describing the model this Attribute is attached to. This is on + the form *appname.modelclass*, like `objects.objectdb`. It is used by the Attribute and + NickHandler to quickly sort matches in the database. Neither this nor `attrtype` should normally + need to be modified. -- `attrread` - limits who may read the value of the Attribute -- `attredit` - limits who may set/change this Attribute +Non-database attributes are not stored in the database and have no equivalence +to `category` nor `strvalue`, `attrtype` or `model`. -You cannot use the `db` handler to modify Attribute object (such as setting a lock on them) - The -`db` handler will return the Attribute's *value*, not the Attribute object itself. Instead you use -the AttributeHandler and set it to return the object instead of the value: +# In-memory Attributes (NAttributes) + +_NAttributes_ (short of Non-database Attributes) mimic Attributes in most things except they +are **non-persistent** - they will _not_ survive a server reload. + +- Instead of `.db` use `.ndb`. +- Instead of `.attributes` use `.nattributes` +- Instead of `AttributeProperty`, use `NAttributeProperty`. ```python - lockstring = "attread:all();attredit:perm(Admins)" - obj.attributes.get("myattr", return_obj=True).locks.add(lockstring) + rose.ndb.has_thorns = True + is_ouch = rose.ndb.has_thorns + + rose.nattributes.add("has_thorns", True) + is_ouch = rose.nattributes.get("has_thorns") ``` -Note the `return_obj` keyword which makes sure to return the `Attribute` object so its LockHandler -could be accessed. +Differences between `Attributes` and `NAttributes`: -A lock is no good if nothing checks it -- and by default Evennia does not check locks on Attributes. -You have to add a check to your commands/code wherever it fits (such as before setting an -Attribute). +- `NAttribute`s are always wiped on a server reload. +- They only exist in memory and never involve the database at all, making them faster to + access and edit than `Attribute`s. +- `NAttribute`s can store _any_ Python structure (and database object) without limit. +- They can _not_ be set with the standard `set` command (but they are visible with `examine`) -```python - # in some command code where we want to limit - # setting of a given attribute name on an object - attr = obj.attributes.get(attrname, - return_obj=True, - accessing_obj=caller, - default=None, - default_access=False) - if not attr: - caller.msg("You cannot edit that Attribute!") - return - # edit the Attribute here -``` +There are some important reasons we recommend using `ndb` to store temporary data rather than +the simple alternative of just storing a variable directly on an object: -The same keywords are available to use with `obj.attributes.set()` and `obj.attributes.remove()`, -those will check for the `attredit` lock type. +- NAttributes are tracked by Evennia and will not be purged in various cache-cleanup operations + the server may do. So using them guarantees that they'll remain available at least as long as + the server lives. +- It's a consistent style - `.db/.attributes` and `.ndb/.nattributes` makes for clean-looking code + where it's clear how long-lived (or not) your data is to be. + +### Persistent vs non-persistent + +So *persistent* data means that your data will survive a server reboot, whereas with +*non-persistent* data it will not ... + +... So why would you ever want to use non-persistent data? The answer is, you don't have to. Most of +the time you really want to save as much as you possibly can. Non-persistent data is potentially +useful in a few situations though. + +- You are worried about database performance. Since Evennia caches Attributes very aggressively, + this is not an issue unless you are reading *and* writing to your Attribute very often (like many + times per second). Reading from an already cached Attribute is as fast as reading any Python + property. But even then this is not likely something to worry about: Apart from Evennia's own + caching, modern database systems themselves also cache data very efficiently for speed. Our + default + database even runs completely in RAM if possible, alleviating much of the need to write to disk + during heavy loads. +- A more valid reason for using non-persistent data is if you *want* to lose your state when logging + off. Maybe you are storing throw-away data that are re-initialized at server startup. Maybe you + are implementing some caching of your own. Or maybe you are testing a buggy [Script](./Scripts.md) that + does potentially harmful stuff to your character object. With non-persistent storage you can be + sure that whatever is messed up, it's nothing a server reboot can't clear up. +- `NAttribute`s have no restrictions at all on what they can store, since they + don't need to worry about being saved to the database - they work very well for temporary storage. +- You want to implement a fully or partly *non-persistent world*. Who are we to argue with your + grand vision! \ No newline at end of file diff --git a/docs/1.0-dev/_sources/Components/Default-Commands.md.txt b/docs/1.0-dev/_sources/Components/Default-Commands.md.txt index f6ed23fa9c..e2b21b1a2e 100644 --- a/docs/1.0-dev/_sources/Components/Default-Commands.md.txt +++ b/docs/1.0-dev/_sources/Components/Default-Commands.md.txt @@ -14,39 +14,39 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using [Batch-Processor](./Batch-Processors.md)'s interactive mode. ``` -- [**__unloggedin_look_command** [look, l]](evennia.commands.default.unloggedin.CmdUnconnectedLook) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_) +- [**__unloggedin_look_command** [l, look]](evennia.commands.default.unloggedin.CmdUnconnectedLook) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_) - [**about** [version]](evennia.commands.default.system.CmdAbout) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) -- [**access** [hierarchy, groups]](evennia.commands.default.general.CmdAccess) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) -- [**accounts** [listaccounts, account]](evennia.commands.default.system.CmdAccounts) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) +- [**access** [groups, hierarchy]](evennia.commands.default.general.CmdAccess) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) +- [**accounts** [account, listaccounts]](evennia.commands.default.system.CmdAccounts) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) - [**addcom** [chanalias, aliaschan]](evennia.commands.default.comms.CmdAddCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**alias** [setobjalias]](evennia.commands.default.building.CmdSetObjAlias) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**allcom**](evennia.commands.default.comms.CmdAllCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**batchcode** [batchcodes]](evennia.commands.default.batchprocess.CmdBatchCode) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) -- [**batchcommands** [batchcommand, batchcmd]](evennia.commands.default.batchprocess.CmdBatchCommands) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) +- [**batchcommands** [batchcmd, batchcommand]](evennia.commands.default.batchprocess.CmdBatchCommands) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**cboot**](evennia.commands.default.comms.CmdCBoot) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**ccreate** [channelcreate]](evennia.commands.default.comms.CmdChannelCreate) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**cdesc**](evennia.commands.default.comms.CmdCdesc) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**cdestroy**](evennia.commands.default.comms.CmdCdestroy) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) -- [**channel** [channels, chan]](evennia.commands.default.comms.CmdChannel) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) +- [**channel** [chan, channels]](evennia.commands.default.comms.CmdChannel) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**charcreate**](evennia.commands.default.account.CmdCharCreate) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) - [**chardelete**](evennia.commands.default.account.CmdCharDelete) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) - [**clock**](evennia.commands.default.comms.CmdClock) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**cmdsets** [listcmsets]](evennia.commands.default.building.CmdListCmdSets) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**color**](evennia.commands.default.account.CmdColorTest) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) -- [**connect** [con, conn, co]](evennia.commands.default.unloggedin.CmdUnconnectedConnect) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_) +- [**connect** [con, co, conn]](evennia.commands.default.unloggedin.CmdUnconnectedConnect) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_) - [**copy**](evennia.commands.default.building.CmdCopy) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**cpattr**](evennia.commands.default.building.CmdCpAttr) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**create**](evennia.commands.default.building.CmdCreate) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) -- [**create** [cr, cre]](evennia.commands.default.unloggedin.CmdUnconnectedCreate) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_) +- [**create** [cre, cr]](evennia.commands.default.unloggedin.CmdUnconnectedCreate) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_) - [**cwho**](evennia.commands.default.comms.CmdCWho) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**delcom** [delaliaschan, delchanalias]](evennia.commands.default.comms.CmdDelCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**desc** [describe]](evennia.commands.default.building.CmdDesc) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) -- [**destroy** [delete, del]](evennia.commands.default.building.CmdDestroy) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) +- [**destroy** [del, delete]](evennia.commands.default.building.CmdDestroy) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**dig**](evennia.commands.default.building.CmdDig) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**drop**](evennia.commands.default.general.CmdDrop) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**encoding** [encode]](evennia.commands.default.unloggedin.CmdUnconnectedEncoding) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_) -- [**examine** [ex, exam]](evennia.commands.default.building.CmdExamine) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Building_) -- [**find** [search, locate]](evennia.commands.default.building.CmdFind) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) +- [**examine** [exam, ex]](evennia.commands.default.building.CmdExamine) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Building_) +- [**find** [locate, search]](evennia.commands.default.building.CmdFind) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**get** [grab]](evennia.commands.default.general.CmdGet) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**give**](evennia.commands.default.general.CmdGive) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**grapevine2chan**](evennia.commands.default.comms.CmdGrapevine2Chan) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) @@ -55,7 +55,7 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using - [**home**](evennia.commands.default.general.CmdHome) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**ic** [puppet]](evennia.commands.default.account.CmdIC) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) - [**info**](evennia.commands.default.unloggedin.CmdUnconnectedInfo) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_) -- [**inventory** [i, inv]](evennia.commands.default.general.CmdInventory) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) +- [**inventory** [inv, i]](evennia.commands.default.general.CmdInventory) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**irc2chan**](evennia.commands.default.comms.CmdIRC2Chan) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**ircstatus**](evennia.commands.default.comms.CmdIRCStatus) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**link**](evennia.commands.default.building.CmdLink) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) @@ -65,13 +65,13 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using - [**mvattr**](evennia.commands.default.building.CmdMvAttr) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**name** [rename]](evennia.commands.default.building.CmdName) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**nick** [nicks, nickname]](evennia.commands.default.general.CmdNick) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) -- [**objects** [listobjects, stats, db, listobjs]](evennia.commands.default.building.CmdObjects) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) +- [**objects** [listobjects, db, listobjs, stats]](evennia.commands.default.building.CmdObjects) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) - [**ooc** [unpuppet]](evennia.commands.default.account.CmdOOC) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) - [**open**](evennia.commands.default.building.CmdOpen) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**option** [options]](evennia.commands.default.account.CmdOption) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) - [**page** [tell]](evennia.commands.default.comms.CmdPage) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) - [**password**](evennia.commands.default.account.CmdPassword) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) -- [**pose** [emote, :]](evennia.commands.default.general.CmdPose) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) +- [**pose** [:, emote]](evennia.commands.default.general.CmdPose) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**py** [!]](evennia.commands.default.system.CmdPy) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_) - [**quell** [unquell]](evennia.commands.default.account.CmdQuell) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) - [**quit**](evennia.commands.default.account.CmdQuit) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) @@ -79,7 +79,7 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using - [**reload** [restart]](evennia.commands.default.system.CmdReload) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_) - [**reset** [reboot]](evennia.commands.default.system.CmdReset) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_) - [**rss2chan**](evennia.commands.default.comms.CmdRSS2Chan) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_) -- [**say** [", ']](evennia.commands.default.general.CmdSay) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) +- [**say** [', "]](evennia.commands.default.general.CmdSay) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**screenreader**](evennia.commands.default.unloggedin.CmdUnconnectedScreenreader) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_) - [**scripts** [script]](evennia.commands.default.building.CmdScripts) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) - [**server** [serverload, serverprocess]](evennia.commands.default.system.CmdServerLoad) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) @@ -93,12 +93,12 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using - [**spawn** [olc]](evennia.commands.default.building.CmdSpawn) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**style**](evennia.commands.default.account.CmdStyle) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) - [**tag** [tags]](evennia.commands.default.building.CmdTag) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) -- [**tasks** [task, delays]](evennia.commands.default.system.CmdTasks) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) +- [**tasks** [delays, task]](evennia.commands.default.system.CmdTasks) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) - [**tel** [teleport]](evennia.commands.default.building.CmdTeleport) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**tickers**](evennia.commands.default.system.CmdTickers) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) - [**time** [uptime]](evennia.commands.default.system.CmdTime) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_) - [**tunnel** [tun]](evennia.commands.default.building.CmdTunnel) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) -- [**typeclass** [swap, typeclasses, update, type, parent]](evennia.commands.default.building.CmdTypeclass) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) +- [**typeclass** [swap, update, type, typeclasses, parent]](evennia.commands.default.building.CmdTypeclass) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**unlink**](evennia.commands.default.building.CmdUnLink) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_) - [**whisper**](evennia.commands.default.general.CmdWhisper) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_) - [**who** [doing]](evennia.commands.default.account.CmdWho) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_) diff --git a/docs/1.0-dev/_sources/Components/Objects.md.txt b/docs/1.0-dev/_sources/Components/Objects.md.txt index 816a913245..d30c41738c 100644 --- a/docs/1.0-dev/_sources/Components/Objects.md.txt +++ b/docs/1.0-dev/_sources/Components/Objects.md.txt @@ -170,14 +170,14 @@ object). 1. The Exit command triggers `at_traverse(obj, destination)` on the Exit object. 1. In `at_traverse`, `object.move_to(destination)` is triggered. This triggers the following hooks, in order: - 1. `obj.at_before_move(destination)` - if this returns False, move is aborted. - 1. `origin.at_before_leave(obj, destination)` + 1. `obj.at_pre_move(destination)` - if this returns False, move is aborted. + 1. `origin.at_pre_leave(obj, destination)` 1. `obj.announce_move_from(destination)` 1. Move is performed by changing `obj.location` from source location to `destination`. 1. `obj.announce_move_to(source)` 1. `destination.at_object_receive(obj, source)` - 1. `obj.at_after_move(source)` -1. On the Exit object, `at_after_traverse(obj, source)` is triggered. + 1. `obj.at_post_move(source)` +1. On the Exit object, `at_post_traverse(obj, source)` is triggered. If the move fails for whatever reason, the Exit will look for an Attribute `err_traverse` on itself and display this as an error message. If this is not found, the Exit will instead call diff --git a/docs/1.0-dev/_sources/Howto/Coding-FAQ.md.txt b/docs/1.0-dev/_sources/Howto/Coding-FAQ.md.txt index f3ef01a66a..d38f689a7a 100644 --- a/docs/1.0-dev/_sources/Howto/Coding-FAQ.md.txt +++ b/docs/1.0-dev/_sources/Howto/Coding-FAQ.md.txt @@ -35,12 +35,12 @@ for more info. **Q:** How does one keep a character from using any exit, if they meet a certain condition? (I.E. in combat, immobilized, etc.) -**A:** The `at_before_move` hook is called by Evennia just before performing any move. If it returns +**A:** The `at_pre_move` hook is called by Evennia just before performing any move. If it returns `False`, the move is aborted. Let's say we want to check for an [Attribute](../Components/Attributes.md) `cantmove`. Add the following code to the `Character` class: ```python -def at_before_move(self, destination): +def at_pre_move(self, destination): "Called just before trying to move" if self.db.cantmove: # replace with condition you want to test self.msg("Something is preventing you from moving!") diff --git a/docs/1.0-dev/_sources/Howto/Gametime-Tutorial.md.txt b/docs/1.0-dev/_sources/Howto/Gametime-Tutorial.md.txt index 274b7c09c5..00c65cbbee 100644 --- a/docs/1.0-dev/_sources/Howto/Gametime-Tutorial.md.txt +++ b/docs/1.0-dev/_sources/Howto/Gametime-Tutorial.md.txt @@ -216,7 +216,10 @@ TIME_UNITS = { ``` Notice we have set a time epoch of 0. Using a custom calendar, we will come up with a nice display -of time on our own. In our case the game time starts at year 0, month 0, day 0, and at midnight. +of time on our own. In our case the game time starts at year 0, month 1, day 1, and at midnight. + +> Year, hour, minute and sec starts from 0, month, week and day starts from 1, this makes them +> behave consistently with the standard time. Note that while we use "month", "week" etc in the settings, your game may not use those terms in- game, instead referring to them as "cycles", "moons", "sand falls" etc. This is just a matter of you diff --git a/docs/1.0-dev/_sources/Howto/Starting/Part3/A-Sittable-Object.md.txt b/docs/1.0-dev/_sources/Howto/Starting/Part3/A-Sittable-Object.md.txt index 22f47abfe9..b92e6e75ba 100644 --- a/docs/1.0-dev/_sources/Howto/Starting/Part3/A-Sittable-Object.md.txt +++ b/docs/1.0-dev/_sources/Howto/Starting/Part3/A-Sittable-Object.md.txt @@ -36,7 +36,7 @@ This requires a change to our Character typeclass. Open `mygame/typeclasses/char class Character(DefaultCharacter): # ... - def at_before_move(self, destination): + def at_pre_move(self, destination): """ Called by self.move_to when trying to move somewhere. If this returns False, the move is immediately cancelled. @@ -49,7 +49,7 @@ class Character(DefaultCharacter): ``` When moving somewhere, [character.move_to](evennia.objects.objects.DefaultObject.move_to) is called. This in turn -will call `character.at_before_move`. Here we look for an Attribute `is_resting` (which we will assign below) +will call `character.at_pre_move`. Here we look for an Attribute `is_resting` (which we will assign below) to determine if we are stuck on the chair or not. ## Making the Chair itself diff --git a/docs/1.0-dev/_sources/Howto/Tutorial-Aggressive-NPCs.md.txt b/docs/1.0-dev/_sources/Howto/Tutorial-Aggressive-NPCs.md.txt index b17e6519e8..26abe4e34b 100644 --- a/docs/1.0-dev/_sources/Howto/Tutorial-Aggressive-NPCs.md.txt +++ b/docs/1.0-dev/_sources/Howto/Tutorial-Aggressive-NPCs.md.txt @@ -81,14 +81,14 @@ This room checks the typeclass of objects entering it (using `utils.inherits_fro contents and inform any `NPCs inside by calling their `at_char_entered` method. You'll also see that we have added a 'look' into this code. This is because, by default, the -`at_object_receive` is carried out *before* the character's `at_after_move` which, we will now +`at_object_receive` is carried out *before* the character's `at_post_move` which, we will now overload. This means that a character entering would see the NPC perform its actions before the 'look' command. Deactivate the look command in the default `Character` class within the `typeclasses.characters` module: ```python # Add this hook in any blank area within your Character class. - def at_after_move(self, source_location): + def at_post_move(self, source_location): """ Default is to look around after a move Note: This has been moved to Room.at_object_receive diff --git a/docs/1.0-dev/api/evennia.accounts.accounts.html b/docs/1.0-dev/api/evennia.accounts.accounts.html index fa5f494d41..ef3959edd4 100644 --- a/docs/1.0-dev/api/evennia.accounts.accounts.html +++ b/docs/1.0-dev/api/evennia.accounts.accounts.html @@ -521,6 +521,18 @@ errors (list): List of error messages in string form

    *args and **kwargs are passed on to the base delete

    mechanism (these are usually not used).

    +
    +
    Returns
    +

    bool

    +
    +
    If deletion was successful. Only time it fails would be

    if the Account was already deleted. Note that even on a failure, +connected resources (nicks/aliases etc) will still have been +deleted.

    +
    +
    +

    +
    +
    diff --git a/docs/1.0-dev/api/evennia.commands.command.html b/docs/1.0-dev/api/evennia.commands.command.html index 42770db86f..a389b2fee0 100644 --- a/docs/1.0-dev/api/evennia.commands.command.html +++ b/docs/1.0-dev/api/evennia.commands.command.html @@ -150,7 +150,7 @@ replace this without disabling auto_help.

    -arg_regex = None
    +arg_regex = re.compile('^[ /]+.*$|$', re.IGNORECASE)
    diff --git a/docs/1.0-dev/api/evennia.commands.default.batchprocess.html b/docs/1.0-dev/api/evennia.commands.default.batchprocess.html index 18dbb610ba..b2b331300f 100644 --- a/docs/1.0-dev/api/evennia.commands.default.batchprocess.html +++ b/docs/1.0-dev/api/evennia.commands.default.batchprocess.html @@ -78,7 +78,7 @@ skipping, reloading etc.

    -aliases = ['batchcommand', 'batchcmd']
    +aliases = ['batchcmd', 'batchcommand']
    @@ -109,7 +109,7 @@ skipping, reloading etc.

    -search_index_entry = {'aliases': 'batchcommand batchcmd', 'category': 'building', 'key': 'batchcommands', 'tags': '', 'text': '\n build from batch-command file\n\n Usage:\n batchcommands[/interactive] <python.path.to.file>\n\n Switch:\n interactive - this mode will offer more control when\n executing the batch file, like stepping,\n skipping, reloading etc.\n\n Runs batches of commands from a batch-cmd text file (*.ev).\n\n '}
    +search_index_entry = {'aliases': 'batchcmd batchcommand', 'category': 'building', 'key': 'batchcommands', 'tags': '', 'text': '\n build from batch-command file\n\n Usage:\n batchcommands[/interactive] <python.path.to.file>\n\n Switch:\n interactive - this mode will offer more control when\n executing the batch file, like stepping,\n skipping, reloading etc.\n\n Runs batches of commands from a batch-cmd text file (*.ev).\n\n '}
    diff --git a/docs/1.0-dev/api/evennia.commands.default.building.html b/docs/1.0-dev/api/evennia.commands.default.building.html index b1613334d8..284d9cf022 100644 --- a/docs/1.0-dev/api/evennia.commands.default.building.html +++ b/docs/1.0-dev/api/evennia.commands.default.building.html @@ -532,7 +532,7 @@ You can specify the /force switch to bypass this confirmation.

    -aliases = ['delete', 'del']
    +aliases = ['del', 'delete']
    @@ -573,7 +573,7 @@ You can specify the /force switch to bypass this confirmation.

    -search_index_entry = {'aliases': 'delete del', 'category': 'building', 'key': 'destroy', 'tags': '', 'text': '\n permanently delete objects\n\n Usage:\n destroy[/switches] [obj, obj2, obj3, [dbref-dbref], ...]\n\n Switches:\n override - The destroy command will usually avoid accidentally\n destroying account objects. This switch overrides this safety.\n force - destroy without confirmation.\n Examples:\n destroy house, roof, door, 44-78\n destroy 5-10, flower, 45\n destroy/force north\n\n Destroys one or many objects. If dbrefs are used, a range to delete can be\n given, e.g. 4-10. Also the end points will be deleted. This command\n displays a confirmation before destroying, to make sure of your choice.\n You can specify the /force switch to bypass this confirmation.\n '}
    +search_index_entry = {'aliases': 'del delete', 'category': 'building', 'key': 'destroy', 'tags': '', 'text': '\n permanently delete objects\n\n Usage:\n destroy[/switches] [obj, obj2, obj3, [dbref-dbref], ...]\n\n Switches:\n override - The destroy command will usually avoid accidentally\n destroying account objects. This switch overrides this safety.\n force - destroy without confirmation.\n Examples:\n destroy house, roof, door, 44-78\n destroy 5-10, flower, 45\n destroy/force north\n\n Destroys one or many objects. If dbrefs are used, a range to delete can be\n given, e.g. 4-10. Also the end points will be deleted. This command\n displays a confirmation before destroying, to make sure of your choice.\n You can specify the /force switch to bypass this confirmation.\n '}
    @@ -1277,7 +1277,7 @@ server settings.

    -aliases = ['swap', 'typeclasses', 'update', 'type', 'parent']
    +aliases = ['swap', 'update', 'type', 'typeclasses', 'parent']
    @@ -1308,7 +1308,7 @@ server settings.

    -search_index_entry = {'aliases': 'swap typeclasses update type parent', 'category': 'building', 'key': 'typeclass', 'tags': '', 'text': "\n set or change an object's typeclass\n\n Usage:\n typeclass[/switch] <object> [= typeclass.path]\n typeclass/prototype <object> = prototype_key\n\n typeclasses or typeclass/list/show [typeclass.path]\n swap - this is a shorthand for using /force/reset flags.\n update - this is a shorthand for using the /force/reload flag.\n\n Switch:\n show, examine - display the current typeclass of object (default) or, if\n given a typeclass path, show the docstring of that typeclass.\n update - *only* re-run at_object_creation on this object\n meaning locks or other properties set later may remain.\n reset - clean out *all* the attributes and properties on the\n object - basically making this a new clean object.\n force - change to the typeclass also if the object\n already has a typeclass of the same name.\n list - show available typeclasses. Only typeclasses in modules actually\n imported or used from somewhere in the code will show up here\n (those typeclasses are still available if you know the path)\n prototype - clean and overwrite the object with the specified\n prototype key - effectively making a whole new object.\n\n Example:\n type button = examples.red_button.RedButton\n type/prototype button=a red button\n\n If the typeclass_path is not given, the current object's typeclass is\n assumed.\n\n View or set an object's typeclass. If setting, the creation hooks of the\n new typeclass will be run on the object. If you have clashing properties on\n the old class, use /reset. By default you are protected from changing to a\n typeclass of the same name as the one you already have - use /force to\n override this protection.\n\n The given typeclass must be identified by its location using python\n dot-notation pointing to the correct module and class. If no typeclass is\n given (or a wrong typeclass is given). Errors in the path or new typeclass\n will lead to the old typeclass being kept. The location of the typeclass\n module is searched from the default typeclass directory, as defined in the\n server settings.\n\n "}
    +search_index_entry = {'aliases': 'swap update type typeclasses parent', 'category': 'building', 'key': 'typeclass', 'tags': '', 'text': "\n set or change an object's typeclass\n\n Usage:\n typeclass[/switch] <object> [= typeclass.path]\n typeclass/prototype <object> = prototype_key\n\n typeclasses or typeclass/list/show [typeclass.path]\n swap - this is a shorthand for using /force/reset flags.\n update - this is a shorthand for using the /force/reload flag.\n\n Switch:\n show, examine - display the current typeclass of object (default) or, if\n given a typeclass path, show the docstring of that typeclass.\n update - *only* re-run at_object_creation on this object\n meaning locks or other properties set later may remain.\n reset - clean out *all* the attributes and properties on the\n object - basically making this a new clean object.\n force - change to the typeclass also if the object\n already has a typeclass of the same name.\n list - show available typeclasses. Only typeclasses in modules actually\n imported or used from somewhere in the code will show up here\n (those typeclasses are still available if you know the path)\n prototype - clean and overwrite the object with the specified\n prototype key - effectively making a whole new object.\n\n Example:\n type button = examples.red_button.RedButton\n type/prototype button=a red button\n\n If the typeclass_path is not given, the current object's typeclass is\n assumed.\n\n View or set an object's typeclass. If setting, the creation hooks of the\n new typeclass will be run on the object. If you have clashing properties on\n the old class, use /reset. By default you are protected from changing to a\n typeclass of the same name as the one you already have - use /force to\n override this protection.\n\n The given typeclass must be identified by its location using python\n dot-notation pointing to the correct module and class. If no typeclass is\n given (or a wrong typeclass is given). Errors in the path or new typeclass\n will lead to the old typeclass being kept. The location of the typeclass\n module is searched from the default typeclass directory, as defined in the\n server settings.\n\n "}
    @@ -1461,7 +1461,7 @@ If object is not specified, the current location is examined.

    -aliases = ['ex', 'exam']
    +aliases = ['exam', 'ex']
    @@ -1558,7 +1558,7 @@ non-persistent data stored on object

    -search_index_entry = {'aliases': 'ex exam', 'category': 'building', 'key': 'examine', 'tags': '', 'text': '\n get detailed information about an object\n\n Usage:\n examine [<object>[/attrname]]\n examine [*<account>[/attrname]]\n\n Switch:\n account - examine an Account (same as adding *)\n object - examine an Object (useful when OOC)\n\n The examine command shows detailed game info about an\n object and optionally a specific attribute on it.\n If object is not specified, the current location is examined.\n\n Append a * before the search string to examine an account.\n\n '}
    +search_index_entry = {'aliases': 'exam ex', 'category': 'building', 'key': 'examine', 'tags': '', 'text': '\n get detailed information about an object\n\n Usage:\n examine [<object>[/attrname]]\n examine [*<account>[/attrname]]\n\n Switch:\n account - examine an Account (same as adding *)\n object - examine an Object (useful when OOC)\n\n The examine command shows detailed game info about an\n object and optionally a specific attribute on it.\n If object is not specified, the current location is examined.\n\n Append a * before the search string to examine an account.\n\n '}
    @@ -1592,7 +1592,7 @@ one is given.

    -aliases = ['search', 'locate']
    +aliases = ['locate', 'search']
    @@ -1623,7 +1623,7 @@ one is given.

    -search_index_entry = {'aliases': 'search locate', 'category': 'building', 'key': 'find', 'tags': '', 'text': '\n search the database for objects\n\n Usage:\n find[/switches] <name or dbref or *account> [= dbrefmin[-dbrefmax]]\n locate - this is a shorthand for using the /loc switch.\n\n Switches:\n room - only look for rooms (location=None)\n exit - only look for exits (destination!=None)\n char - only look for characters (BASE_CHARACTER_TYPECLASS)\n exact - only exact matches are returned.\n loc - display object location if exists and match has one result\n startswith - search for names starting with the string, rather than containing\n\n Searches the database for an object of a particular name or exact #dbref.\n Use *accountname to search for an account. The switches allows for\n limiting object matches to certain game entities. Dbrefmin and dbrefmax\n limits matches to within the given dbrefs range, or above/below if only\n one is given.\n '}
    +search_index_entry = {'aliases': 'locate search', 'category': 'building', 'key': 'find', 'tags': '', 'text': '\n search the database for objects\n\n Usage:\n find[/switches] <name or dbref or *account> [= dbrefmin[-dbrefmax]]\n locate - this is a shorthand for using the /loc switch.\n\n Switches:\n room - only look for rooms (location=None)\n exit - only look for exits (destination!=None)\n char - only look for characters (BASE_CHARACTER_TYPECLASS)\n exact - only exact matches are returned.\n loc - display object location if exists and match has one result\n startswith - search for names starting with the string, rather than containing\n\n Searches the database for an object of a particular name or exact #dbref.\n Use *accountname to search for an account. The switches allows for\n limiting object matches to certain game entities. Dbrefmin and dbrefmax\n limits matches to within the given dbrefs range, or above/below if only\n one is given.\n '}
    @@ -1658,6 +1658,11 @@ reference. A puppeted object cannot be moved to None.

    Teleports an object somewhere. If no object is given, you yourself are teleported to the target location.

    +

    To lock an object from being teleported, set its teleport lock, it will be +checked with the caller. To block +a destination from being teleported to, set the destination’s teleport_here +lock - it will be checked with the thing being teleported. Admins and +higher permissions can always teleport.

    key = 'tel'
    @@ -1707,7 +1712,7 @@ teleported to the target location.

    -search_index_entry = {'aliases': 'teleport', 'category': 'building', 'key': 'tel', 'tags': '', 'text': "\n teleport object to another location\n\n Usage:\n tel/switch [<object> to||=] <target location>\n\n Examples:\n tel Limbo\n tel/quiet box = Limbo\n tel/tonone box\n\n Switches:\n quiet - don't echo leave/arrive messages to the source/target\n locations for the move.\n intoexit - if target is an exit, teleport INTO\n the exit object instead of to its destination\n tonone - if set, teleport the object to a None-location. If this\n switch is set, <target location> is ignored.\n Note that the only way to retrieve\n an object from a None location is by direct #dbref\n reference. A puppeted object cannot be moved to None.\n loc - teleport object to the target's location instead of its contents\n\n Teleports an object somewhere. If no object is given, you yourself are\n teleported to the target location.\n "}
    +search_index_entry = {'aliases': 'teleport', 'category': 'building', 'key': 'tel', 'tags': '', 'text': "\n teleport object to another location\n\n Usage:\n tel/switch [<object> to||=] <target location>\n\n Examples:\n tel Limbo\n tel/quiet box = Limbo\n tel/tonone box\n\n Switches:\n quiet - don't echo leave/arrive messages to the source/target\n locations for the move.\n intoexit - if target is an exit, teleport INTO\n the exit object instead of to its destination\n tonone - if set, teleport the object to a None-location. If this\n switch is set, <target location> is ignored.\n Note that the only way to retrieve\n an object from a None location is by direct #dbref\n reference. A puppeted object cannot be moved to None.\n loc - teleport object to the target's location instead of its contents\n\n Teleports an object somewhere. If no object is given, you yourself are\n teleported to the target location.\n\n To lock an object from being teleported, set its `teleport` lock, it will be\n checked with the caller. To block\n a destination from being teleported to, set the destination's `teleport_here`\n lock - it will be checked with the thing being teleported. Admins and\n higher permissions can always teleport.\n\n "}
    @@ -1819,7 +1824,7 @@ given, <nr> defaults to 10.

    -aliases = ['listobjects', 'stats', 'db', 'listobjs']
    +aliases = ['listobjects', 'db', 'listobjs', 'stats']
    @@ -1845,7 +1850,7 @@ given, <nr> defaults to 10.

    -search_index_entry = {'aliases': 'listobjects stats db listobjs', 'category': 'system', 'key': 'objects', 'tags': '', 'text': '\n statistics on objects in the database\n\n Usage:\n objects [<nr>]\n\n Gives statictics on objects in database as well as\n a list of <nr> latest objects in database. If not\n given, <nr> defaults to 10.\n '}
    +search_index_entry = {'aliases': 'listobjects db listobjs stats', 'category': 'system', 'key': 'objects', 'tags': '', 'text': '\n statistics on objects in the database\n\n Usage:\n objects [<nr>]\n\n Gives statictics on objects in database as well as\n a list of <nr> latest objects in database. If not\n given, <nr> defaults to 10.\n '}
    diff --git a/docs/1.0-dev/api/evennia.commands.default.comms.html b/docs/1.0-dev/api/evennia.commands.default.comms.html index e646ca1605..0791f04cd9 100644 --- a/docs/1.0-dev/api/evennia.commands.default.comms.html +++ b/docs/1.0-dev/api/evennia.commands.default.comms.html @@ -196,7 +196,7 @@ ban mychannel1,mychannel2= EvilUser : Was banned for spamming.

    -aliases = ['channels', 'chan']
    +aliases = ['chan', 'channels']
    @@ -722,7 +722,7 @@ don’t actually sub to yet.

    -search_index_entry = {'aliases': 'channels chan', 'category': 'comms', 'key': 'channel', 'tags': '', 'text': "\n Use and manage in-game channels.\n\n Usage:\n channel channelname <msg>\n channel channel name = <msg>\n channel (show all subscription)\n channel/all (show available channels)\n channel/alias channelname = alias[;alias...]\n channel/unalias alias\n channel/who channelname\n channel/history channelname [= index]\n channel/sub channelname [= alias[;alias...]]\n channel/unsub channelname[,channelname, ...]\n channel/mute channelname[,channelname,...]\n channel/unmute channelname[,channelname,...]\n\n channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n channel/desc channelname = description\n channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n channel/ban channelname (list bans)\n channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]\n channel/unban[/quiet] channelname[, channelname, ...] = subscribername\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n\n # subtopics\n\n ## sending\n\n Usage: channel channelname msg\n channel channel name = msg (with space in channel name)\n\n This sends a message to the channel. Note that you will rarely use this\n command like this; instead you can use the alias\n\n channelname <msg>\n channelalias <msg>\n\n For example\n\n public Hello World\n pub Hello World\n\n (this shortcut doesn't work for aliases containing spaces)\n\n See channel/alias for help on setting channel aliases.\n\n ## alias and unalias\n\n Usage: channel/alias channel = alias[;alias[;alias...]]\n channel/unalias alias\n channel - this will list your subs and aliases to each channel\n\n Set one or more personal aliases for referencing a channel. For example:\n\n channel/alias warrior's guild = warrior;wguild;warchannel;warrior guild\n\n You can now send to the channel using all of these:\n\n warrior's guild Hello\n warrior Hello\n wguild Hello\n warchannel Hello\n\n Note that this will not work if the alias has a space in it. So the\n 'warrior guild' alias must be used with the `channel` command:\n\n channel warrior guild = Hello\n\n Channel-aliases can be removed one at a time, using the '/unalias' switch.\n\n ## who\n\n Usage: channel/who channelname\n\n List the channel's subscribers. Shows who are currently offline or are\n muting the channel. Subscribers who are 'muting' will not see messages sent\n to the channel (use channel/mute to mute a channel).\n\n ## history\n\n Usage: channel/history channel [= index]\n\n This will display the last |c20|n lines of channel history. By supplying an\n index number, you will step that many lines back before viewing those 20 lines.\n\n For example:\n\n channel/history public = 35\n\n will go back 35 lines and show the previous 20 lines from that point (so\n lines -35 to -55).\n\n ## sub and unsub\n\n Usage: channel/sub channel [=alias[;alias;...]]\n channel/unsub channel\n\n This subscribes you to a channel and optionally assigns personal shortcuts\n for you to use to send to that channel (see aliases). When you unsub, all\n your personal aliases will also be removed.\n\n ## mute and unmute\n\n Usage: channel/mute channelname\n channel/unmute channelname\n\n Muting silences all output from the channel without actually\n un-subscribing. Other channel members will see that you are muted in the /who\n list. Sending a message to the channel will automatically unmute you.\n\n ## create and destroy\n\n Usage: channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n\n Creates a new channel (or destroys one you control). You will automatically\n join the channel you create and everyone will be kicked and loose all aliases\n to a destroyed channel.\n\n ## lock and unlock\n\n Usage: channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n\n Note: this is an admin command.\n\n A lockstring is on the form locktype:lockfunc(). Channels understand three\n locktypes:\n listen - who may listen or join the channel.\n send - who may send messages to the channel\n control - who controls the channel. This is usually the one creating\n the channel.\n\n Common lockfuncs are all() and perm(). To make a channel everyone can\n listen to but only builders can talk on, use this:\n\n listen:all()\n send: perm(Builders)\n\n ## boot and ban\n\n Usage:\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n channel/ban channelname[, channelname, ...] = subscribername [: reason]\n channel/unban channelname[, channelname, ...] = subscribername\n channel/unban channelname\n channel/ban channelname (list bans)\n\n Booting will kick a named subscriber from channel(s) temporarily. The\n 'reason' will be passed to the booted user. Unless the /quiet switch is\n used, the channel will also be informed of the action. A booted user is\n still able to re-connect, but they'll have to set up their aliases again.\n\n Banning will blacklist a user from (re)joining the provided channels. It\n will then proceed to boot them from those channels if they were connected.\n The 'reason' and `/quiet` works the same as for booting.\n\n Example:\n boot mychannel1 = EvilUser : Kicking you to cool down a bit.\n ban mychannel1,mychannel2= EvilUser : Was banned for spamming.\n\n "}
    +search_index_entry = {'aliases': 'chan channels', 'category': 'comms', 'key': 'channel', 'tags': '', 'text': "\n Use and manage in-game channels.\n\n Usage:\n channel channelname <msg>\n channel channel name = <msg>\n channel (show all subscription)\n channel/all (show available channels)\n channel/alias channelname = alias[;alias...]\n channel/unalias alias\n channel/who channelname\n channel/history channelname [= index]\n channel/sub channelname [= alias[;alias...]]\n channel/unsub channelname[,channelname, ...]\n channel/mute channelname[,channelname,...]\n channel/unmute channelname[,channelname,...]\n\n channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n channel/desc channelname = description\n channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n channel/ban channelname (list bans)\n channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]\n channel/unban[/quiet] channelname[, channelname, ...] = subscribername\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n\n # subtopics\n\n ## sending\n\n Usage: channel channelname msg\n channel channel name = msg (with space in channel name)\n\n This sends a message to the channel. Note that you will rarely use this\n command like this; instead you can use the alias\n\n channelname <msg>\n channelalias <msg>\n\n For example\n\n public Hello World\n pub Hello World\n\n (this shortcut doesn't work for aliases containing spaces)\n\n See channel/alias for help on setting channel aliases.\n\n ## alias and unalias\n\n Usage: channel/alias channel = alias[;alias[;alias...]]\n channel/unalias alias\n channel - this will list your subs and aliases to each channel\n\n Set one or more personal aliases for referencing a channel. For example:\n\n channel/alias warrior's guild = warrior;wguild;warchannel;warrior guild\n\n You can now send to the channel using all of these:\n\n warrior's guild Hello\n warrior Hello\n wguild Hello\n warchannel Hello\n\n Note that this will not work if the alias has a space in it. So the\n 'warrior guild' alias must be used with the `channel` command:\n\n channel warrior guild = Hello\n\n Channel-aliases can be removed one at a time, using the '/unalias' switch.\n\n ## who\n\n Usage: channel/who channelname\n\n List the channel's subscribers. Shows who are currently offline or are\n muting the channel. Subscribers who are 'muting' will not see messages sent\n to the channel (use channel/mute to mute a channel).\n\n ## history\n\n Usage: channel/history channel [= index]\n\n This will display the last |c20|n lines of channel history. By supplying an\n index number, you will step that many lines back before viewing those 20 lines.\n\n For example:\n\n channel/history public = 35\n\n will go back 35 lines and show the previous 20 lines from that point (so\n lines -35 to -55).\n\n ## sub and unsub\n\n Usage: channel/sub channel [=alias[;alias;...]]\n channel/unsub channel\n\n This subscribes you to a channel and optionally assigns personal shortcuts\n for you to use to send to that channel (see aliases). When you unsub, all\n your personal aliases will also be removed.\n\n ## mute and unmute\n\n Usage: channel/mute channelname\n channel/unmute channelname\n\n Muting silences all output from the channel without actually\n un-subscribing. Other channel members will see that you are muted in the /who\n list. Sending a message to the channel will automatically unmute you.\n\n ## create and destroy\n\n Usage: channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n\n Creates a new channel (or destroys one you control). You will automatically\n join the channel you create and everyone will be kicked and loose all aliases\n to a destroyed channel.\n\n ## lock and unlock\n\n Usage: channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n\n Note: this is an admin command.\n\n A lockstring is on the form locktype:lockfunc(). Channels understand three\n locktypes:\n listen - who may listen or join the channel.\n send - who may send messages to the channel\n control - who controls the channel. This is usually the one creating\n the channel.\n\n Common lockfuncs are all() and perm(). To make a channel everyone can\n listen to but only builders can talk on, use this:\n\n listen:all()\n send: perm(Builders)\n\n ## boot and ban\n\n Usage:\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n channel/ban channelname[, channelname, ...] = subscribername [: reason]\n channel/unban channelname[, channelname, ...] = subscribername\n channel/unban channelname\n channel/ban channelname (list bans)\n\n Booting will kick a named subscriber from channel(s) temporarily. The\n 'reason' will be passed to the booted user. Unless the /quiet switch is\n used, the channel will also be informed of the action. A booted user is\n still able to re-connect, but they'll have to set up their aliases again.\n\n Banning will blacklist a user from (re)joining the provided channels. It\n will then proceed to boot them from those channels if they were connected.\n The 'reason' and `/quiet` works the same as for booting.\n\n Example:\n boot mychannel1 = EvilUser : Kicking you to cool down a bit.\n ban mychannel1,mychannel2= EvilUser : Was banned for spamming.\n\n "}
    @@ -875,7 +875,7 @@ ban mychannel1,mychannel2= EvilUser : Was banned for spamming.

    -aliases = ['channels', 'chan']
    +aliases = ['chan', 'channels']
    @@ -895,7 +895,7 @@ ban mychannel1,mychannel2= EvilUser : Was banned for spamming.

    -search_index_entry = {'aliases': 'channels chan', 'category': 'comms', 'key': 'channel', 'tags': '', 'text': "\n Use and manage in-game channels.\n\n Usage:\n channel channelname <msg>\n channel channel name = <msg>\n channel (show all subscription)\n channel/all (show available channels)\n channel/alias channelname = alias[;alias...]\n channel/unalias alias\n channel/who channelname\n channel/history channelname [= index]\n channel/sub channelname [= alias[;alias...]]\n channel/unsub channelname[,channelname, ...]\n channel/mute channelname[,channelname,...]\n channel/unmute channelname[,channelname,...]\n\n channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n channel/desc channelname = description\n channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n channel/ban channelname (list bans)\n channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]\n channel/unban[/quiet] channelname[, channelname, ...] = subscribername\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n\n # subtopics\n\n ## sending\n\n Usage: channel channelname msg\n channel channel name = msg (with space in channel name)\n\n This sends a message to the channel. Note that you will rarely use this\n command like this; instead you can use the alias\n\n channelname <msg>\n channelalias <msg>\n\n For example\n\n public Hello World\n pub Hello World\n\n (this shortcut doesn't work for aliases containing spaces)\n\n See channel/alias for help on setting channel aliases.\n\n ## alias and unalias\n\n Usage: channel/alias channel = alias[;alias[;alias...]]\n channel/unalias alias\n channel - this will list your subs and aliases to each channel\n\n Set one or more personal aliases for referencing a channel. For example:\n\n channel/alias warrior's guild = warrior;wguild;warchannel;warrior guild\n\n You can now send to the channel using all of these:\n\n warrior's guild Hello\n warrior Hello\n wguild Hello\n warchannel Hello\n\n Note that this will not work if the alias has a space in it. So the\n 'warrior guild' alias must be used with the `channel` command:\n\n channel warrior guild = Hello\n\n Channel-aliases can be removed one at a time, using the '/unalias' switch.\n\n ## who\n\n Usage: channel/who channelname\n\n List the channel's subscribers. Shows who are currently offline or are\n muting the channel. Subscribers who are 'muting' will not see messages sent\n to the channel (use channel/mute to mute a channel).\n\n ## history\n\n Usage: channel/history channel [= index]\n\n This will display the last |c20|n lines of channel history. By supplying an\n index number, you will step that many lines back before viewing those 20 lines.\n\n For example:\n\n channel/history public = 35\n\n will go back 35 lines and show the previous 20 lines from that point (so\n lines -35 to -55).\n\n ## sub and unsub\n\n Usage: channel/sub channel [=alias[;alias;...]]\n channel/unsub channel\n\n This subscribes you to a channel and optionally assigns personal shortcuts\n for you to use to send to that channel (see aliases). When you unsub, all\n your personal aliases will also be removed.\n\n ## mute and unmute\n\n Usage: channel/mute channelname\n channel/unmute channelname\n\n Muting silences all output from the channel without actually\n un-subscribing. Other channel members will see that you are muted in the /who\n list. Sending a message to the channel will automatically unmute you.\n\n ## create and destroy\n\n Usage: channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n\n Creates a new channel (or destroys one you control). You will automatically\n join the channel you create and everyone will be kicked and loose all aliases\n to a destroyed channel.\n\n ## lock and unlock\n\n Usage: channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n\n Note: this is an admin command.\n\n A lockstring is on the form locktype:lockfunc(). Channels understand three\n locktypes:\n listen - who may listen or join the channel.\n send - who may send messages to the channel\n control - who controls the channel. This is usually the one creating\n the channel.\n\n Common lockfuncs are all() and perm(). To make a channel everyone can\n listen to but only builders can talk on, use this:\n\n listen:all()\n send: perm(Builders)\n\n ## boot and ban\n\n Usage:\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n channel/ban channelname[, channelname, ...] = subscribername [: reason]\n channel/unban channelname[, channelname, ...] = subscribername\n channel/unban channelname\n channel/ban channelname (list bans)\n\n Booting will kick a named subscriber from channel(s) temporarily. The\n 'reason' will be passed to the booted user. Unless the /quiet switch is\n used, the channel will also be informed of the action. A booted user is\n still able to re-connect, but they'll have to set up their aliases again.\n\n Banning will blacklist a user from (re)joining the provided channels. It\n will then proceed to boot them from those channels if they were connected.\n The 'reason' and `/quiet` works the same as for booting.\n\n Example:\n boot mychannel1 = EvilUser : Kicking you to cool down a bit.\n ban mychannel1,mychannel2= EvilUser : Was banned for spamming.\n\n "}
    +search_index_entry = {'aliases': 'chan channels', 'category': 'comms', 'key': 'channel', 'tags': '', 'text': "\n Use and manage in-game channels.\n\n Usage:\n channel channelname <msg>\n channel channel name = <msg>\n channel (show all subscription)\n channel/all (show available channels)\n channel/alias channelname = alias[;alias...]\n channel/unalias alias\n channel/who channelname\n channel/history channelname [= index]\n channel/sub channelname [= alias[;alias...]]\n channel/unsub channelname[,channelname, ...]\n channel/mute channelname[,channelname,...]\n channel/unmute channelname[,channelname,...]\n\n channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n channel/desc channelname = description\n channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n channel/ban channelname (list bans)\n channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]\n channel/unban[/quiet] channelname[, channelname, ...] = subscribername\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n\n # subtopics\n\n ## sending\n\n Usage: channel channelname msg\n channel channel name = msg (with space in channel name)\n\n This sends a message to the channel. Note that you will rarely use this\n command like this; instead you can use the alias\n\n channelname <msg>\n channelalias <msg>\n\n For example\n\n public Hello World\n pub Hello World\n\n (this shortcut doesn't work for aliases containing spaces)\n\n See channel/alias for help on setting channel aliases.\n\n ## alias and unalias\n\n Usage: channel/alias channel = alias[;alias[;alias...]]\n channel/unalias alias\n channel - this will list your subs and aliases to each channel\n\n Set one or more personal aliases for referencing a channel. For example:\n\n channel/alias warrior's guild = warrior;wguild;warchannel;warrior guild\n\n You can now send to the channel using all of these:\n\n warrior's guild Hello\n warrior Hello\n wguild Hello\n warchannel Hello\n\n Note that this will not work if the alias has a space in it. So the\n 'warrior guild' alias must be used with the `channel` command:\n\n channel warrior guild = Hello\n\n Channel-aliases can be removed one at a time, using the '/unalias' switch.\n\n ## who\n\n Usage: channel/who channelname\n\n List the channel's subscribers. Shows who are currently offline or are\n muting the channel. Subscribers who are 'muting' will not see messages sent\n to the channel (use channel/mute to mute a channel).\n\n ## history\n\n Usage: channel/history channel [= index]\n\n This will display the last |c20|n lines of channel history. By supplying an\n index number, you will step that many lines back before viewing those 20 lines.\n\n For example:\n\n channel/history public = 35\n\n will go back 35 lines and show the previous 20 lines from that point (so\n lines -35 to -55).\n\n ## sub and unsub\n\n Usage: channel/sub channel [=alias[;alias;...]]\n channel/unsub channel\n\n This subscribes you to a channel and optionally assigns personal shortcuts\n for you to use to send to that channel (see aliases). When you unsub, all\n your personal aliases will also be removed.\n\n ## mute and unmute\n\n Usage: channel/mute channelname\n channel/unmute channelname\n\n Muting silences all output from the channel without actually\n un-subscribing. Other channel members will see that you are muted in the /who\n list. Sending a message to the channel will automatically unmute you.\n\n ## create and destroy\n\n Usage: channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n\n Creates a new channel (or destroys one you control). You will automatically\n join the channel you create and everyone will be kicked and loose all aliases\n to a destroyed channel.\n\n ## lock and unlock\n\n Usage: channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n\n Note: this is an admin command.\n\n A lockstring is on the form locktype:lockfunc(). Channels understand three\n locktypes:\n listen - who may listen or join the channel.\n send - who may send messages to the channel\n control - who controls the channel. This is usually the one creating\n the channel.\n\n Common lockfuncs are all() and perm(). To make a channel everyone can\n listen to but only builders can talk on, use this:\n\n listen:all()\n send: perm(Builders)\n\n ## boot and ban\n\n Usage:\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n channel/ban channelname[, channelname, ...] = subscribername [: reason]\n channel/unban channelname[, channelname, ...] = subscribername\n channel/unban channelname\n channel/ban channelname (list bans)\n\n Booting will kick a named subscriber from channel(s) temporarily. The\n 'reason' will be passed to the booted user. Unless the /quiet switch is\n used, the channel will also be informed of the action. A booted user is\n still able to re-connect, but they'll have to set up their aliases again.\n\n Banning will blacklist a user from (re)joining the provided channels. It\n will then proceed to boot them from those channels if they were connected.\n The 'reason' and `/quiet` works the same as for booting.\n\n Example:\n boot mychannel1 = EvilUser : Kicking you to cool down a bit.\n ban mychannel1,mychannel2= EvilUser : Was banned for spamming.\n\n "}
    diff --git a/docs/1.0-dev/api/evennia.commands.default.general.html b/docs/1.0-dev/api/evennia.commands.default.general.html index 271f5c3472..f41f119978 100644 --- a/docs/1.0-dev/api/evennia.commands.default.general.html +++ b/docs/1.0-dev/api/evennia.commands.default.general.html @@ -263,7 +263,7 @@ inv

    -aliases = ['i', 'inv']
    +aliases = ['inv', 'i']
    @@ -294,7 +294,7 @@ inv

    -search_index_entry = {'aliases': 'i inv', 'category': 'general', 'key': 'inventory', 'tags': '', 'text': '\n view inventory\n\n Usage:\n inventory\n inv\n\n Shows your inventory.\n '}
    +search_index_entry = {'aliases': 'inv i', 'category': 'general', 'key': 'inventory', 'tags': '', 'text': '\n view inventory\n\n Usage:\n inventory\n inv\n\n Shows your inventory.\n '}
    @@ -538,7 +538,7 @@ placing it in their inventory.

    -aliases = ['"', "'"]
    +aliases = ["'", '"']
    @@ -546,6 +546,11 @@ placing it in their inventory.

    locks = 'cmd:all()'
    +
    +
    +arg_regex = None
    +
    +
    func()[source]
    @@ -564,7 +569,7 @@ placing it in their inventory.

    -search_index_entry = {'aliases': '" \'', 'category': 'general', 'key': 'say', 'tags': '', 'text': '\n speak as your character\n\n Usage:\n say <message>\n\n Talk to those in your current location.\n '}
    +search_index_entry = {'aliases': '\' "', 'category': 'general', 'key': 'say', 'tags': '', 'text': '\n speak as your character\n\n Usage:\n say <message>\n\n Talk to those in your current location.\n '}
    @@ -644,7 +649,7 @@ automatically begin with your name.

    -aliases = ['emote', ':']
    +aliases = [':', 'emote']
    @@ -652,6 +657,11 @@ automatically begin with your name.

    locks = 'cmd:all()'
    +
    +
    +arg_regex = None
    +
    +
    parse()[source]
    @@ -680,7 +690,7 @@ space.

    -search_index_entry = {'aliases': 'emote :', 'category': 'general', 'key': 'pose', 'tags': '', 'text': "\n strike a pose\n\n Usage:\n pose <pose text>\n pose's <pose text>\n\n Example:\n pose is standing by the wall, smiling.\n -> others will see:\n Tom is standing by the wall, smiling.\n\n Describe an action being taken. The pose text will\n automatically begin with your name.\n "}
    +search_index_entry = {'aliases': ': emote', 'category': 'general', 'key': 'pose', 'tags': '', 'text': "\n strike a pose\n\n Usage:\n pose <pose text>\n pose's <pose text>\n\n Example:\n pose is standing by the wall, smiling.\n -> others will see:\n Tom is standing by the wall, smiling.\n\n Describe an action being taken. The pose text will\n automatically begin with your name.\n "}
    @@ -703,7 +713,7 @@ which permission groups you are a member of.

    -aliases = ['hierarchy', 'groups']
    +aliases = ['groups', 'hierarchy']
    @@ -734,7 +744,7 @@ which permission groups you are a member of.

    -search_index_entry = {'aliases': 'hierarchy groups', 'category': 'general', 'key': 'access', 'tags': '', 'text': '\n show your current game access\n\n Usage:\n access\n\n This command shows you the permission hierarchy and\n which permission groups you are a member of.\n '}
    +search_index_entry = {'aliases': 'groups hierarchy', 'category': 'general', 'key': 'access', 'tags': '', 'text': '\n show your current game access\n\n Usage:\n access\n\n This command shows you the permission hierarchy and\n which permission groups you are a member of.\n '}
    diff --git a/docs/1.0-dev/api/evennia.commands.default.system.html b/docs/1.0-dev/api/evennia.commands.default.system.html index 7ff6d08249..0235905018 100644 --- a/docs/1.0-dev/api/evennia.commands.default.system.html +++ b/docs/1.0-dev/api/evennia.commands.default.system.html @@ -65,7 +65,7 @@ If not given, <nr> defaults to 10.

    -aliases = ['listaccounts', 'account']
    +aliases = ['account', 'listaccounts']
    @@ -96,7 +96,7 @@ If not given, <nr> defaults to 10.

    -search_index_entry = {'aliases': 'listaccounts account', 'category': 'system', 'key': 'accounts', 'tags': '', 'text': '\n Manage registered accounts\n\n Usage:\n accounts [nr]\n accounts/delete <name or #id> [: reason]\n\n Switches:\n delete - delete an account from the server\n\n By default, lists statistics about the Accounts registered with the game.\n It will list the <nr> amount of latest registered accounts\n If not given, <nr> defaults to 10.\n '}
    +search_index_entry = {'aliases': 'account listaccounts', 'category': 'system', 'key': 'accounts', 'tags': '', 'text': '\n Manage registered accounts\n\n Usage:\n accounts [nr]\n accounts/delete <name or #id> [: reason]\n\n Switches:\n delete - delete an account from the server\n\n By default, lists statistics about the Accounts registered with the game.\n It will list the <nr> amount of latest registered accounts\n If not given, <nr> defaults to 10.\n '}
    @@ -330,6 +330,11 @@ should only be accessible by trusted server admins/superusers.|n

    help_category = 'system'
    +
    +
    +arg_regex = re.compile('', re.IGNORECASE)
    +
    +
    func()[source]
    @@ -618,7 +623,7 @@ See |luhttps://ww
    -aliases = ['task', 'delays']
    +aliases = ['delays', 'task']
    @@ -664,7 +669,7 @@ to all the variables defined therein.

    -search_index_entry = {'aliases': 'task delays', 'category': 'system', 'key': 'tasks', 'tags': '', 'text': "\n Display or terminate active tasks (delays).\n\n Usage:\n tasks[/switch] [task_id or function_name]\n\n Switches:\n pause - Pause the callback of a task.\n unpause - Process all callbacks made since pause() was called.\n do_task - Execute the task (call its callback).\n call - Call the callback of this task.\n remove - Remove a task without executing it.\n cancel - Stop a task from automatically executing.\n\n Notes:\n A task is a single use method of delaying the call of a function. Calls are created\n in code, using `evennia.utils.delay`.\n See |luhttps://www.evennia.com/docs/latest/Command-Duration.html|ltthe docs|le for help.\n\n By default, tasks that are canceled and never called are cleaned up after one minute.\n\n Examples:\n - `tasks/cancel move_callback` - Cancels all movement delays from the slow_exit contrib.\n In this example slow exits creates it's tasks with\n `utils.delay(move_delay, move_callback)`\n - `tasks/cancel 2` - Cancel task id 2.\n\n "}
    +search_index_entry = {'aliases': 'delays task', 'category': 'system', 'key': 'tasks', 'tags': '', 'text': "\n Display or terminate active tasks (delays).\n\n Usage:\n tasks[/switch] [task_id or function_name]\n\n Switches:\n pause - Pause the callback of a task.\n unpause - Process all callbacks made since pause() was called.\n do_task - Execute the task (call its callback).\n call - Call the callback of this task.\n remove - Remove a task without executing it.\n cancel - Stop a task from automatically executing.\n\n Notes:\n A task is a single use method of delaying the call of a function. Calls are created\n in code, using `evennia.utils.delay`.\n See |luhttps://www.evennia.com/docs/latest/Command-Duration.html|ltthe docs|le for help.\n\n By default, tasks that are canceled and never called are cleaned up after one minute.\n\n Examples:\n - `tasks/cancel move_callback` - Cancels all movement delays from the slow_exit contrib.\n In this example slow exits creates it's tasks with\n `utils.delay(move_delay, move_callback)`\n - `tasks/cancel 2` - Cancel task id 2.\n\n "}
    diff --git a/docs/1.0-dev/api/evennia.commands.default.unloggedin.html b/docs/1.0-dev/api/evennia.commands.default.unloggedin.html index 549f5be0a6..e02f9b7d6f 100644 --- a/docs/1.0-dev/api/evennia.commands.default.unloggedin.html +++ b/docs/1.0-dev/api/evennia.commands.default.unloggedin.html @@ -62,7 +62,7 @@ connect “account name” “pass word”

    -aliases = ['con', 'conn', 'co']
    +aliases = ['con', 'co', 'conn']
    @@ -97,7 +97,7 @@ there is no object yet before the account has logged in)

    -search_index_entry = {'aliases': 'con conn co', 'category': 'general', 'key': 'connect', 'tags': '', 'text': '\n connect to the game\n\n Usage (at login screen):\n connect accountname password\n connect "account name" "pass word"\n\n Use the create command to first create an account before logging in.\n\n If you have spaces in your name, enclose it in double quotes.\n '}
    +search_index_entry = {'aliases': 'con co conn', 'category': 'general', 'key': 'connect', 'tags': '', 'text': '\n connect to the game\n\n Usage (at login screen):\n connect accountname password\n connect "account name" "pass word"\n\n Use the create command to first create an account before logging in.\n\n If you have spaces in your name, enclose it in double quotes.\n '}
    @@ -121,7 +121,7 @@ create “account name” “pass word”

    -aliases = ['cr', 'cre']
    +aliases = ['cre', 'cr']
    @@ -152,7 +152,7 @@ create “account name” “pass word”

    -search_index_entry = {'aliases': 'cr cre', 'category': 'general', 'key': 'create', 'tags': '', 'text': '\n create a new account account\n\n Usage (at login screen):\n create <accountname> <password>\n create "account name" "pass word"\n\n This creates a new account account.\n\n If you have spaces in your name, enclose it in double quotes.\n '}
    +search_index_entry = {'aliases': 'cre cr', 'category': 'general', 'key': 'create', 'tags': '', 'text': '\n create a new account account\n\n Usage (at login screen):\n create <accountname> <password>\n create "account name" "pass word"\n\n This creates a new account account.\n\n If you have spaces in your name, enclose it in double quotes.\n '}
    @@ -226,7 +226,7 @@ All it does is display the connect screen.

    -aliases = ['look', 'l']
    +aliases = ['l', 'look']
    @@ -252,7 +252,7 @@ All it does is display the connect screen.

    -search_index_entry = {'aliases': 'look l', 'category': 'general', 'key': '__unloggedin_look_command', 'tags': '', 'text': '\n look when in unlogged-in state\n\n Usage:\n look\n\n This is an unconnected version of the look command for simplicity.\n\n This is called by the server and kicks everything in gear.\n All it does is display the connect screen.\n '}
    +search_index_entry = {'aliases': 'l look', 'category': 'general', 'key': '__unloggedin_look_command', 'tags': '', 'text': '\n look when in unlogged-in state\n\n Usage:\n look\n\n This is an unconnected version of the look command for simplicity.\n\n This is called by the server and kicks everything in gear.\n All it does is display the connect screen.\n '}
    diff --git a/docs/1.0-dev/api/evennia.comms.comms.html b/docs/1.0-dev/api/evennia.comms.comms.html index 051421a415..a69153b4e5 100644 --- a/docs/1.0-dev/api/evennia.comms.comms.html +++ b/docs/1.0-dev/api/evennia.comms.comms.html @@ -386,6 +386,17 @@ errors (list): A list of errors in string form, if any.

    delete()[source]

    Deletes channel.

    +
    +
    Returns
    +

    bool

    +
    +
    If deletion was successful. Only time it can fail would be

    if channel was already deleted. Even if it were to fail, all subscribers +will be disconnected.

    +
    +
    +

    +
    +
    diff --git a/docs/1.0-dev/api/evennia.contrib.barter.html b/docs/1.0-dev/api/evennia.contrib.barter.html index bb0a34c478..457c53a0a9 100644 --- a/docs/1.0-dev/api/evennia.contrib.barter.html +++ b/docs/1.0-dev/api/evennia.contrib.barter.html @@ -684,7 +684,7 @@ try to influence the other part in the deal.

    -aliases = ['deal', 'offers']
    +aliases = ['offers', 'deal']
    @@ -710,7 +710,7 @@ try to influence the other part in the deal.

    -search_index_entry = {'aliases': 'deal offers', 'category': 'trading', 'key': 'status', 'tags': '', 'text': "\n show a list of the current deal\n\n Usage:\n status\n deal\n offers\n\n Shows the currently suggested offers on each sides of the deal. To\n accept the current deal, use the 'accept' command. Use 'offer' to\n change your deal. You might also want to use 'say', 'emote' etc to\n try to influence the other part in the deal.\n "}
    +search_index_entry = {'aliases': 'offers deal', 'category': 'trading', 'key': 'status', 'tags': '', 'text': "\n show a list of the current deal\n\n Usage:\n status\n deal\n offers\n\n Shows the currently suggested offers on each sides of the deal. To\n accept the current deal, use the 'accept' command. Use 'offer' to\n change your deal. You might also want to use 'say', 'emote' etc to\n try to influence the other part in the deal.\n "}
    diff --git a/docs/1.0-dev/api/evennia.contrib.clothing.html b/docs/1.0-dev/api/evennia.contrib.clothing.html index 7f1d30a484..4756c281eb 100644 --- a/docs/1.0-dev/api/evennia.contrib.clothing.html +++ b/docs/1.0-dev/api/evennia.contrib.clothing.html @@ -631,7 +631,7 @@ inv

    -aliases = ['i', 'inv']
    +aliases = ['inv', 'i']
    @@ -662,7 +662,7 @@ inv

    -search_index_entry = {'aliases': 'i inv', 'category': 'general', 'key': 'inventory', 'tags': '', 'text': '\n view inventory\n\n Usage:\n inventory\n inv\n\n Shows your inventory.\n '}
    +search_index_entry = {'aliases': 'inv i', 'category': 'general', 'key': 'inventory', 'tags': '', 'text': '\n view inventory\n\n Usage:\n inventory\n inv\n\n Shows your inventory.\n '}
    diff --git a/docs/1.0-dev/api/evennia.contrib.custom_gametime.html b/docs/1.0-dev/api/evennia.contrib.custom_gametime.html index a8b6fe6346..57bbe3970b 100644 --- a/docs/1.0-dev/api/evennia.contrib.custom_gametime.html +++ b/docs/1.0-dev/api/evennia.contrib.custom_gametime.html @@ -130,7 +130,7 @@ match the settings.TIME_UNITS dict keys.

    -evennia.contrib.custom_gametime.realtime_to_gametime(secs=0, mins=0, hrs=0, days=0, weeks=0, months=0, yrs=0, format=False)[source]
    +evennia.contrib.custom_gametime.realtime_to_gametime(secs=0, mins=0, hrs=0, days=1, weeks=1, months=1, yrs=0, format=False)[source]

    This method calculates how much in-game time a real-world time interval would correspond to. This is usually a lot less interesting than the other way around.

    @@ -143,19 +143,27 @@ interesting than the other way around.

    Returns

    time (float or tuple)

    -
    -
    -
    The gametime difference or the same

    time split up into time units.

    -
    -
    -
    -
    Example:

    realtime_to_gametime(days=2) -> number of game-world seconds

    +
    The gametime difference or the same

    time split up into time units.

    +
    +

    Note

    +
    +
    days/weeks/months start from 1 (there is no day/week/month 0). This makes it

    consistent with the real world datetime.

    +
    +
    +
    +
    +
    Raises
    +

    ValueError – If trying to add a days/weeks/months of <=0.

    +
    +
    +

    Example

    +

    realtime_to_gametime(days=2) -> number of game-world seconds

    @@ -194,6 +202,8 @@ return 300 (5 minutes).

    The number of real seconds before the given game time is up.

    +

    Notes

    +

    day/week/month start from 1, not from 0 (there is no month 0 for example)

    diff --git a/docs/1.0-dev/api/evennia.contrib.email_login.html b/docs/1.0-dev/api/evennia.contrib.email_login.html index 972f10c6db..e953dd1735 100644 --- a/docs/1.0-dev/api/evennia.contrib.email_login.html +++ b/docs/1.0-dev/api/evennia.contrib.email_login.html @@ -77,7 +77,7 @@ the module given by settings.CONNECTION_SCREEN_MODULE.

    -aliases = ['con', 'conn', 'co']
    +aliases = ['con', 'co', 'conn']
    @@ -107,7 +107,7 @@ there is no object yet before the account has logged in)

    -search_index_entry = {'aliases': 'con conn co', 'category': 'general', 'key': 'connect', 'tags': '', 'text': '\n Connect to the game.\n\n Usage (at login screen):\n connect <email> <password>\n\n Use the create command to first create an account before logging in.\n '}
    +search_index_entry = {'aliases': 'con co conn', 'category': 'general', 'key': 'connect', 'tags': '', 'text': '\n Connect to the game.\n\n Usage (at login screen):\n connect <email> <password>\n\n Use the create command to first create an account before logging in.\n '}
    @@ -129,7 +129,7 @@ there is no object yet before the account has logged in)

    -aliases = ['cr', 'cre']
    +aliases = ['cre', 'cr']
    @@ -165,7 +165,7 @@ name enclosed in quotes:

    -search_index_entry = {'aliases': 'cr cre', 'category': 'general', 'key': 'create', 'tags': '', 'text': '\n Create a new account.\n\n Usage (at login screen):\n create "accountname" <email> <password>\n\n This creates a new account account.\n\n '}
    +search_index_entry = {'aliases': 'cre cr', 'category': 'general', 'key': 'create', 'tags': '', 'text': '\n Create a new account.\n\n Usage (at login screen):\n create "accountname" <email> <password>\n\n This creates a new account account.\n\n '}
    @@ -229,7 +229,7 @@ All it does is display the connect screen.

    -aliases = ['look', 'l']
    +aliases = ['l', 'look']
    @@ -255,7 +255,7 @@ All it does is display the connect screen.

    -search_index_entry = {'aliases': 'look l', 'category': 'general', 'key': '__unloggedin_look_command', 'tags': '', 'text': '\n This is an unconnected version of the `look` command for simplicity.\n\n This is called by the server and kicks everything in gear.\n All it does is display the connect screen.\n '}
    +search_index_entry = {'aliases': 'l look', 'category': 'general', 'key': '__unloggedin_look_command', 'tags': '', 'text': '\n This is an unconnected version of the `look` command for simplicity.\n\n This is called by the server and kicks everything in gear.\n All it does is display the connect screen.\n '}
    diff --git a/docs/1.0-dev/api/evennia.contrib.evscaperoom.commands.html b/docs/1.0-dev/api/evennia.contrib.evscaperoom.commands.html index 629674796f..c83dc0e9bd 100644 --- a/docs/1.0-dev/api/evennia.contrib.evscaperoom.commands.html +++ b/docs/1.0-dev/api/evennia.contrib.evscaperoom.commands.html @@ -150,7 +150,7 @@ the operation will be general or on the room.

    -aliases = ['chicken out', 'q', 'abort', 'quit']
    +aliases = ['chicken out', 'abort', 'q', 'quit']
    @@ -174,7 +174,7 @@ set in self.parse())

    -search_index_entry = {'aliases': 'chicken out q abort quit', 'category': 'evscaperoom', 'key': 'give up', 'tags': '', 'text': '\n Give up\n\n Usage:\n give up\n\n Abandons your attempts at escaping and of ever winning the pie-eating contest.\n\n '}
    +search_index_entry = {'aliases': 'chicken out abort q quit', 'category': 'evscaperoom', 'key': 'give up', 'tags': '', 'text': '\n Give up\n\n Usage:\n give up\n\n Abandons your attempts at escaping and of ever winning the pie-eating contest.\n\n '}
    @@ -310,7 +310,7 @@ shout

    -aliases = ['shout', 'whisper', ';']
    +aliases = [';', 'whisper', 'shout']
    @@ -339,7 +339,7 @@ set in self.parse())

    -search_index_entry = {'aliases': 'shout whisper ;', 'category': 'general', 'key': 'say', 'tags': '', 'text': '\n Perform an communication action.\n\n Usage:\n say <text>\n whisper\n shout\n\n '}
    +search_index_entry = {'aliases': '; whisper shout', 'category': 'general', 'key': 'say', 'tags': '', 'text': '\n Perform an communication action.\n\n Usage:\n say <text>\n whisper\n shout\n\n '}
    @@ -367,7 +367,7 @@ emote /me points to /box and /lever.

    -aliases = ['pose', ':']
    +aliases = [':', 'pose']
    @@ -406,7 +406,7 @@ set in self.parse())

    -search_index_entry = {'aliases': 'pose :', 'category': 'general', 'key': 'emote', 'tags': '', 'text': '\n Perform a free-form emote. Use /me to\n include yourself in the emote and /name\n to include other objects or characters.\n Use "..." to enact speech.\n\n Usage:\n emote <emote>\n :<emote\n\n Example:\n emote /me smiles at /peter\n emote /me points to /box and /lever.\n\n '}
    +search_index_entry = {'aliases': ': pose', 'category': 'general', 'key': 'emote', 'tags': '', 'text': '\n Perform a free-form emote. Use /me to\n include yourself in the emote and /name\n to include other objects or characters.\n Use "..." to enact speech.\n\n Usage:\n emote <emote>\n :<emote\n\n Example:\n emote /me smiles at /peter\n emote /me points to /box and /lever.\n\n '}
    @@ -429,7 +429,7 @@ looks and what actions is available.

    -aliases = ['e', 'ex', 'unfocus', 'examine']
    +aliases = ['examine', 'e', 'unfocus', 'ex']
    @@ -458,7 +458,7 @@ set in self.parse())

    -search_index_entry = {'aliases': 'e ex unfocus examine', 'category': 'evscaperoom', 'key': 'focus', 'tags': '', 'text': '\n Focus your attention on a target.\n\n Usage:\n focus <obj>\n\n Once focusing on an object, use look to get more information about how it\n looks and what actions is available.\n\n '}
    +search_index_entry = {'aliases': 'examine e unfocus ex', 'category': 'evscaperoom', 'key': 'focus', 'tags': '', 'text': '\n Focus your attention on a target.\n\n Usage:\n focus <obj>\n\n Once focusing on an object, use look to get more information about how it\n looks and what actions is available.\n\n '}
    @@ -520,7 +520,7 @@ set in self.parse())

    -aliases = ['i', 'give', 'inventory', 'inv']
    +aliases = ['inv', 'give', 'i', 'inventory']
    @@ -544,7 +544,7 @@ set in self.parse())

    -search_index_entry = {'aliases': 'i give inventory inv', 'category': 'evscaperoom', 'key': 'get', 'tags': '', 'text': '\n Use focus / examine instead.\n\n '}
    +search_index_entry = {'aliases': 'inv give i inventory', 'category': 'evscaperoom', 'key': 'get', 'tags': '', 'text': '\n Use focus / examine instead.\n\n '}
    diff --git a/docs/1.0-dev/api/evennia.contrib.ingame_python.commands.html b/docs/1.0-dev/api/evennia.contrib.ingame_python.commands.html index d9fcc5df19..087ebbdddf 100644 --- a/docs/1.0-dev/api/evennia.contrib.ingame_python.commands.html +++ b/docs/1.0-dev/api/evennia.contrib.ingame_python.commands.html @@ -55,7 +55,7 @@
    -aliases = ['@calls', '@callback', '@callbacks']
    +aliases = ['@callbacks', '@calls', '@callback']
    @@ -136,7 +136,7 @@ on user permission.

    -search_index_entry = {'aliases': '@calls @callback @callbacks', 'category': 'building', 'key': '@call', 'tags': '', 'text': '\n Command to edit callbacks.\n '}
    +search_index_entry = {'aliases': '@callbacks @calls @callback', 'category': 'building', 'key': '@call', 'tags': '', 'text': '\n Command to edit callbacks.\n '}
    diff --git a/docs/1.0-dev/api/evennia.contrib.rpsystem.html b/docs/1.0-dev/api/evennia.contrib.rpsystem.html index 12e4a93804..58fdcec857 100644 --- a/docs/1.0-dev/api/evennia.contrib.rpsystem.html +++ b/docs/1.0-dev/api/evennia.contrib.rpsystem.html @@ -622,6 +622,11 @@ a different language.

    locks = 'cmd:all()'
    +
    +
    +arg_regex = re.compile('', re.IGNORECASE)
    +
    +
    func()[source]
    @@ -662,7 +667,7 @@ a different language.

    -aliases = ['"', "'"]
    +aliases = ["'", '"']
    @@ -670,6 +675,11 @@ a different language.

    locks = 'cmd:all()'
    +
    +
    +arg_regex = re.compile('', re.IGNORECASE)
    +
    +
    func()[source]
    @@ -688,7 +698,7 @@ a different language.

    -search_index_entry = {'aliases': '" \'', 'category': 'general', 'key': 'say', 'tags': '', 'text': '\n speak as your character\n\n Usage:\n say <message>\n\n Talk to those in your current location.\n '}
    +search_index_entry = {'aliases': '\' "', 'category': 'general', 'key': 'say', 'tags': '', 'text': '\n speak as your character\n\n Usage:\n say <message>\n\n Talk to those in your current location.\n '}
    @@ -827,7 +837,7 @@ Using the command without arguments will list all current recogs.

    -aliases = ['forget', 'recognize']
    +aliases = ['recognize', 'forget']
    @@ -854,7 +864,7 @@ Using the command without arguments will list all current recogs.

    -search_index_entry = {'aliases': 'forget recognize', 'category': 'general', 'key': 'recog', 'tags': '', 'text': '\n Recognize another person in the same room.\n\n Usage:\n recog\n recog sdesc as alias\n forget alias\n\n Example:\n recog tall man as Griatch\n forget griatch\n\n This will assign a personal alias for a person, or forget said alias.\n Using the command without arguments will list all current recogs.\n\n '}
    +search_index_entry = {'aliases': 'recognize forget', 'category': 'general', 'key': 'recog', 'tags': '', 'text': '\n Recognize another person in the same room.\n\n Usage:\n recog\n recog sdesc as alias\n forget alias\n\n Example:\n recog tall man as Griatch\n forget griatch\n\n This will assign a personal alias for a person, or forget said alias.\n Using the command without arguments will list all current recogs.\n\n '}
    @@ -1162,8 +1172,8 @@ characters stand out from other objects.

    -
    -at_before_say(message, **kwargs)[source]
    +
    +at_pre_say(message, **kwargs)[source]

    Called before the object says or whispers anything, return modified message.

    Parameters
    diff --git a/docs/1.0-dev/api/evennia.contrib.test_traits.html b/docs/1.0-dev/api/evennia.contrib.test_traits.html index ba1617002a..95765bfc58 100644 --- a/docs/1.0-dev/api/evennia.contrib.test_traits.html +++ b/docs/1.0-dev/api/evennia.contrib.test_traits.html @@ -457,10 +457,10 @@ under the hood.

    class Character(DefaultCharacter): - strength = TraitProperty("str", "Strength", trait_type="static", base=10, mod=2) - hunting = TraitProperty(self, "hunting", "Hunting Skill", trait_type="counter", + strength = TraitProperty(name="STR", trait_type="static", base=10, mod=2) + hunting = TraitProperty("Hunting Skill", trait_type="counter", base=10, mod=1, max=100) - health = TraitProperty("health", "Health", trait_type="gauge", min=0, base=100) + health = TraitProperty(trait_type="gauge", min=0, base=100)
    @@ -483,10 +483,10 @@ under the hood.

    class Character(DefaultCharacter): - strength = TraitProperty("str", "Strength", trait_type="static", base=10, mod=2) - hunting = TraitProperty(self, "hunting", "Hunting Skill", trait_type="counter", + strength = TraitProperty(name="STR", trait_type="static", base=10, mod=2) + hunting = TraitProperty("Hunting Skill", trait_type="counter", base=10, mod=1, max=100) - health = TraitProperty("health", "Health", trait_type="gauge", min=0, base=100) + health = TraitProperty(trait_type="gauge", min=0, base=100)
    @@ -509,10 +509,10 @@ under the hood.

    class Character(DefaultCharacter): - strength = TraitProperty("str", "Strength", trait_type="static", base=10, mod=2) - hunting = TraitProperty(self, "hunting", "Hunting Skill", trait_type="counter", + strength = TraitProperty(name="STR", trait_type="static", base=10, mod=2) + hunting = TraitProperty("Hunting Skill", trait_type="counter", base=10, mod=1, max=100) - health = TraitProperty("health", "Health", trait_type="gauge", min=0, base=100) + health = TraitProperty(trait_type="gauge", min=0, base=100)
    diff --git a/docs/1.0-dev/api/evennia.contrib.traits.html b/docs/1.0-dev/api/evennia.contrib.traits.html index a438110981..8319c770bb 100644 --- a/docs/1.0-dev/api/evennia.contrib.traits.html +++ b/docs/1.0-dev/api/evennia.contrib.traits.html @@ -567,10 +567,10 @@ under the hood.

    class Character(DefaultCharacter): - strength = TraitProperty("str", "Strength", trait_type="static", base=10, mod=2) - hunting = TraitProperty(self, "hunting", "Hunting Skill", trait_type="counter", + strength = TraitProperty(name="STR", trait_type="static", base=10, mod=2) + hunting = TraitProperty("Hunting Skill", trait_type="counter", base=10, mod=1, max=100) - health = TraitProperty("health", "Health", trait_type="gauge", min=0, base=100) + health = TraitProperty(trait_type="gauge", min=0, base=100)
    diff --git a/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_basic.html b/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_basic.html index d44ad6887a..e0d809c711 100644 --- a/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_basic.html +++ b/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_basic.html @@ -315,8 +315,8 @@ normal hook to overload for most object types.

    -
    -at_before_move(destination)[source]
    +
    +at_pre_move(destination)[source]

    Called just before starting to move this object to destination.

    diff --git a/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_equip.html b/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_equip.html index 2a815029cd..56d517b6c3 100644 --- a/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_equip.html +++ b/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_equip.html @@ -481,8 +481,8 @@ normal hook to overload for most object types.

    -
    -at_before_drop(dropper)[source]
    +
    +at_pre_drop(dropper)[source]

    Can’t drop in combat.

    @@ -493,8 +493,8 @@ normal hook to overload for most object types.

    -
    -at_before_give(giver, getter)[source]
    +
    +at_pre_give(giver, getter)[source]

    Can’t give away in combat.

    @@ -542,8 +542,8 @@ normal hook to overload for most object types.

    -
    -at_before_move(destination)[source]
    +
    +at_pre_move(destination)[source]

    Called just before starting to move this object to destination.

    diff --git a/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_items.html b/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_items.html index 908fdedc8c..2837bd9284 100644 --- a/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_items.html +++ b/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_items.html @@ -410,8 +410,8 @@ normal hook to overload for most object types.

    -
    -at_before_move(destination)[source]
    +
    +at_pre_move(destination)[source]

    Called just before starting to move this object to destination.

    diff --git a/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_magic.html b/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_magic.html index 7b137970be..145ce6a280 100644 --- a/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_magic.html +++ b/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_magic.html @@ -338,8 +338,8 @@ can be changed at creation and factor into combat calculations.

    -
    -at_before_move(destination)[source]
    +
    +at_pre_move(destination)[source]

    Called just before starting to move this object to destination.

    diff --git a/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_range.html b/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_range.html index a4d0779675..d591e283e0 100644 --- a/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_range.html +++ b/docs/1.0-dev/api/evennia.contrib.turnbattle.tb_range.html @@ -582,8 +582,8 @@ normal hook to overload for most object types.

    -
    -at_before_move(destination)[source]
    +
    +at_pre_move(destination)[source]

    Called just before starting to move this object to destination.

    @@ -632,8 +632,8 @@ the object has restrictions in combat - you must be next to an object to get it, must be next to your target to give them something, and can only interact with objects on your own turn.

    -
    -at_before_drop(dropper)[source]
    +
    +at_pre_drop(dropper)[source]

    Called by the default drop command before this object has been dropped.

    @@ -669,12 +669,12 @@ overriding the call (unused by default).

    Notes

    This hook cannot stop the drop from happening. Use -permissions or the at_before_drop() hook for that.

    +permissions or the at_pre_drop() hook for that.

    -
    -at_before_get(getter)[source]
    +
    +at_pre_get(getter)[source]

    Called by the default get command before this object has been picked up.

    @@ -710,12 +710,12 @@ overriding the call (unused by default).

    Notes

    This hook cannot stop the pickup from happening. Use -permissions or the at_before_get() hook for that.

    +permissions or the at_pre_get() hook for that.

    -
    -at_before_give(giver, getter)[source]
    +
    +at_pre_give(giver, getter)[source]

    Called by the default give command before this object has been given.

    @@ -753,7 +753,7 @@ overriding the call (unused by default).

    Notes

    This hook cannot stop the give from happening. Use -permissions or the at_before_give() hook for that.

    +permissions or the at_pre_give() hook for that.

    diff --git a/docs/1.0-dev/api/evennia.contrib.tutorial_examples.red_button.html b/docs/1.0-dev/api/evennia.contrib.tutorial_examples.red_button.html index 0e5bc3b421..606cb07718 100644 --- a/docs/1.0-dev/api/evennia.contrib.tutorial_examples.red_button.html +++ b/docs/1.0-dev/api/evennia.contrib.tutorial_examples.red_button.html @@ -82,7 +82,7 @@ such as when closing the lid and un-blinding a character.

    -aliases = ['press button', 'press', 'push']
    +aliases = ['press', 'push', 'press button']
    @@ -111,7 +111,7 @@ check if the lid is open or closed.

    -search_index_entry = {'aliases': 'press button press push', 'category': 'general', 'key': 'push button', 'tags': '', 'text': '\n Push the red button (lid closed)\n\n Usage:\n push button\n\n '}
    +search_index_entry = {'aliases': 'press push press button', 'category': 'general', 'key': 'push button', 'tags': '', 'text': '\n Push the red button (lid closed)\n\n Usage:\n push button\n\n '}
    @@ -181,7 +181,7 @@ check if the lid is open or closed.

    -aliases = ['break lid', 'smash', 'smash lid']
    +aliases = ['smash lid', 'smash', 'break lid']
    @@ -208,7 +208,7 @@ break.

    -search_index_entry = {'aliases': 'break lid smash smash lid', 'category': 'general', 'key': 'smash glass', 'tags': '', 'text': '\n Smash the protective glass.\n\n Usage:\n smash glass\n\n Try to smash the glass of the button.\n\n '}
    +search_index_entry = {'aliases': 'smash lid smash break lid', 'category': 'general', 'key': 'smash glass', 'tags': '', 'text': '\n Smash the protective glass.\n\n Usage:\n smash glass\n\n Try to smash the glass of the button.\n\n '}
    @@ -308,7 +308,7 @@ be mutually exclusive.

    -aliases = ['press button', 'press', 'push']
    +aliases = ['press', 'push', 'press button']
    @@ -337,7 +337,7 @@ set in self.parse())

    -search_index_entry = {'aliases': 'press button press push', 'category': 'general', 'key': 'push button', 'tags': '', 'text': '\n Push the red button\n\n Usage:\n push button\n\n '}
    +search_index_entry = {'aliases': 'press push press button', 'category': 'general', 'key': 'push button', 'tags': '', 'text': '\n Push the red button\n\n Usage:\n push button\n\n '}
    @@ -435,7 +435,7 @@ be mutually exclusive.

    -aliases = ['listen', 'get', 'ex', 'l', 'examine', 'feel']
    +aliases = ['get', 'listen', 'l', 'ex', 'examine', 'feel']
    @@ -461,7 +461,7 @@ be mutually exclusive.

    -search_index_entry = {'aliases': 'listen get ex l examine feel', 'category': 'general', 'key': 'look', 'tags': '', 'text': "\n Looking around in darkness\n\n Usage:\n look <obj>\n\n ... not that there's much to see in the dark.\n\n "}
    +search_index_entry = {'aliases': 'get listen l ex examine feel', 'category': 'general', 'key': 'look', 'tags': '', 'text': "\n Looking around in darkness\n\n Usage:\n look <obj>\n\n ... not that there's much to see in the dark.\n\n "}
    diff --git a/docs/1.0-dev/api/evennia.contrib.tutorial_world.objects.html b/docs/1.0-dev/api/evennia.contrib.tutorial_world.objects.html index e3e7d4b948..211006e5de 100644 --- a/docs/1.0-dev/api/evennia.contrib.tutorial_world.objects.html +++ b/docs/1.0-dev/api/evennia.contrib.tutorial_world.objects.html @@ -495,7 +495,7 @@ shift green root up/down

    -aliases = ['pull', 'move', 'push', 'shiftroot']
    +aliases = ['shiftroot', 'pull', 'push', 'move']
    @@ -531,7 +531,7 @@ yellow/green - horizontal roots

    -search_index_entry = {'aliases': 'pull move push shiftroot', 'category': 'tutorialworld', 'key': 'shift', 'tags': '', 'text': '\n Shifts roots around.\n\n Usage:\n shift blue root left/right\n shift red root left/right\n shift yellow root up/down\n shift green root up/down\n\n '}
    +search_index_entry = {'aliases': 'shiftroot pull push move', 'category': 'tutorialworld', 'key': 'shift', 'tags': '', 'text': '\n Shifts roots around.\n\n Usage:\n shift blue root left/right\n shift red root left/right\n shift yellow root up/down\n shift green root up/down\n\n '}
    @@ -548,7 +548,7 @@ yellow/green - horizontal roots

    -aliases = ['push button', 'press button', 'button']
    +aliases = ['button', 'push button', 'press button']
    @@ -574,7 +574,7 @@ yellow/green - horizontal roots

    -search_index_entry = {'aliases': 'push button press button button', 'category': 'tutorialworld', 'key': 'press', 'tags': '', 'text': '\n Presses a button.\n '}
    +search_index_entry = {'aliases': 'button push button press button', 'category': 'tutorialworld', 'key': 'press', 'tags': '', 'text': '\n Presses a button.\n '}
    @@ -652,8 +652,8 @@ current root positions.

    -
    -at_after_traverse(traverser, source_location)[source]
    +
    +at_post_traverse(traverser, source_location)[source]

    This is called after we traversed this exit. Cleans up and resets the puzzle.

    @@ -718,7 +718,7 @@ parry - forgoes your attack but will make you harder to hit on next

    -aliases = ['slash', 'stab', 'bash', 'thrust', 'kill', 'pierce', 'chop', 'fight', 'defend', 'hit', 'parry']
    +aliases = ['fight', 'stab', 'hit', 'thrust', 'parry', 'slash', 'defend', 'chop', 'bash', 'kill', 'pierce']
    @@ -744,7 +744,7 @@ parry - forgoes your attack but will make you harder to hit on next

    -search_index_entry = {'aliases': 'slash stab bash thrust kill pierce chop fight defend hit parry', 'category': 'tutorialworld', 'key': 'attack', 'tags': '', 'text': '\n Attack the enemy. Commands:\n\n stab <enemy>\n slash <enemy>\n parry\n\n stab - (thrust) makes a lot of damage but is harder to hit with.\n slash - is easier to land, but does not make as much damage.\n parry - forgoes your attack but will make you harder to hit on next\n enemy attack.\n\n '}
    +search_index_entry = {'aliases': 'fight stab hit thrust parry slash defend chop bash kill pierce', 'category': 'tutorialworld', 'key': 'attack', 'tags': '', 'text': '\n Attack the enemy. Commands:\n\n stab <enemy>\n slash <enemy>\n parry\n\n stab - (thrust) makes a lot of damage but is harder to hit with.\n slash - is easier to land, but does not make as much damage.\n parry - forgoes your attack but will make you harder to hit on next\n enemy attack.\n\n '}
    diff --git a/docs/1.0-dev/api/evennia.contrib.tutorial_world.rooms.html b/docs/1.0-dev/api/evennia.contrib.tutorial_world.rooms.html index 556c09a629..5a62f69995 100644 --- a/docs/1.0-dev/api/evennia.contrib.tutorial_world.rooms.html +++ b/docs/1.0-dev/api/evennia.contrib.tutorial_world.rooms.html @@ -868,7 +868,7 @@ to find something.

    -aliases = ['feel around', 'l', 'search', 'fiddle', 'feel']
    +aliases = ['fiddle', 'l', 'feel around', 'feel', 'search']
    @@ -896,7 +896,7 @@ random chance of eventually finding a light source.

    -search_index_entry = {'aliases': 'feel around l search fiddle feel', 'category': 'tutorialworld', 'key': 'look', 'tags': '', 'text': '\n Look around in darkness\n\n Usage:\n look\n\n Look around in the darkness, trying\n to find something.\n '}
    +search_index_entry = {'aliases': 'fiddle l feel around feel search', 'category': 'tutorialworld', 'key': 'look', 'tags': '', 'text': '\n Look around in darkness\n\n Usage:\n look\n\n Look around in the darkness, trying\n to find something.\n '}
    diff --git a/docs/1.0-dev/api/evennia.contrib.wilderness.html b/docs/1.0-dev/api/evennia.contrib.wilderness.html index 73ea1b8dcc..9e688cb49f 100644 --- a/docs/1.0-dev/api/evennia.contrib.wilderness.html +++ b/docs/1.0-dev/api/evennia.contrib.wilderness.html @@ -317,8 +317,8 @@ are a lot of objects in the map.

    -
    -at_after_object_leave(obj)[source]
    +
    +at_post_object_leave(obj)[source]

    Called after an object left this wilderness map. Used for cleaning up.

    Parameters
    diff --git a/docs/1.0-dev/api/evennia.objects.objects.html b/docs/1.0-dev/api/evennia.objects.objects.html index 0ebfaabfe7..2cf16258fd 100644 --- a/docs/1.0-dev/api/evennia.objects.objects.html +++ b/docs/1.0-dev/api/evennia.objects.objects.html @@ -629,7 +629,7 @@ keyword allows objects to move “inside” exit objects.

    moving to a None location. If you want to run hooks, run them manually (and make sure they can manage None locations).

  • move_hooks (bool) – If False, turn off the calling of move-related hooks -(at_before/after_move etc) with quiet=True, this is as quiet a move +(at_pre/post_move etc) with quiet=True, this is as quiet a move as can be done.

  • @@ -652,13 +652,13 @@ calling move_to.

    The DefaultObject hooks called (if move_hooks=True) are, in order:

      -
    1. self.at_before_move(destination) (if this returns False, move is aborted)

    2. +
    3. self.at_pre_move(destination) (if this returns False, move is aborted)

    4. source_location.at_object_leave(self, destination)

    5. self.announce_move_from(destination)

    6. (move happens here)

    7. self.announce_move_to(source_location)

    8. destination.at_object_receive(self, source_location)

    9. -
    10. self.at_after_move(source_location)

    11. +
    12. self.at_post_move(source_location)

    @@ -962,9 +962,31 @@ based on the access result.

    +
    +
    +at_pre_move(destination, **kwargs)[source]
    +

    Called just before starting to move this object to +destination.

    +
    +
    Parameters
    +
      +
    • destination (Object) – The object we are moving to

    • +
    • **kwargs (dict) – Arbitrary, optional arguments for users +overriding the call (unused by default).

    • +
    +
    +
    Returns
    +

    shouldmove (bool) – If we should move or not.

    +
    +
    +

    Notes

    +

    If this method returns False/None, the move is cancelled +before it is even started.

    +
    +
    -at_before_move(destination, **kwargs)[source]
    +at_before_move(destination, **kwargs)

    Called just before starting to move this object to destination.

    @@ -1040,9 +1062,26 @@ destination: the location of the object after moving.

    +
    +
    +at_post_move(source_location, **kwargs)[source]
    +

    Called after move has completed, regardless of quiet mode or +not. Allows changes to the object due to the location it is +now in.

    +
    +
    Parameters
    +
      +
    • source_location (Object) – Wwhere we came from. This may be None.

    • +
    • **kwargs (dict) – Arbitrary, optional arguments for users +overriding the call (unused by default).

    • +
    +
    +
    +
    +
    -at_after_move(source_location, **kwargs)[source]
    +at_after_move(source_location, **kwargs)

    Called after move has completed, regardless of quiet mode or not. Allows changes to the object due to the location it is now in.

    @@ -1097,7 +1136,7 @@ overriding the call (unused by default).

    normally by calling traversing_object.move_to(target_location). It is normally only implemented by Exit objects. If it returns False (usually -because move_to returned False), at_after_traverse below +because move_to returned False), at_post_traverse below should not be called and instead at_failed_traverse should be called.

    @@ -1112,9 +1151,29 @@ overriding the call (unused by default).

    +
    +
    +at_post_traverse(traversing_object, source_location, **kwargs)[source]
    +

    Called just after an object successfully used this object to +traverse to another object (i.e. this object is a type of +Exit)

    +
    +
    Parameters
    +
      +
    • traversing_object (Object) – The object traversing us.

    • +
    • source_location (Object) – Where traversing_object came from.

    • +
    • **kwargs (dict) – Arbitrary, optional arguments for users +overriding the call (unused by default).

    • +
    +
    +
    +

    Notes

    +

    The target location should normally be available as self.destination.

    +
    +
    -at_after_traverse(traversing_object, source_location, **kwargs)[source]
    +at_after_traverse(traversing_object, source_location, **kwargs)

    Called just after an object successfully used this object to traverse to another object (i.e. this object is a type of Exit)

    @@ -1339,9 +1398,31 @@ overriding the call (unused by default).

    +
    +
    +at_pre_get(getter, **kwargs)[source]
    +

    Called by the default get command before this object has been +picked up.

    +
    +
    Parameters
    +
      +
    • getter (Object) – The object about to get this object.

    • +
    • **kwargs (dict) – Arbitrary, optional arguments for users +overriding the call (unused by default).

    • +
    +
    +
    Returns
    +

    shouldget (bool) – If the object should be gotten or not.

    +
    +
    +

    Notes

    +

    If this method returns False/None, the getting is cancelled +before it is even started.

    +
    +
    -at_before_get(getter, **kwargs)[source]
    +at_before_get(getter, **kwargs)

    Called by the default get command before this object has been picked up.

    @@ -1377,12 +1458,35 @@ overriding the call (unused by default).

    Notes

    This hook cannot stop the pickup from happening. Use -permissions or the at_before_get() hook for that.

    +permissions or the at_pre_get() hook for that.

    +
    + +
    +
    +at_pre_give(giver, getter, **kwargs)[source]
    +

    Called by the default give command before this object has been +given.

    +
    +
    Parameters
    +
      +
    • giver (Object) – The object about to give this object.

    • +
    • getter (Object) – The object about to get this object.

    • +
    • **kwargs (dict) – Arbitrary, optional arguments for users +overriding the call (unused by default).

    • +
    +
    +
    Returns
    +

    shouldgive (bool) – If the object should be given or not.

    +
    +
    +

    Notes

    +

    If this method returns False/None, the giving is cancelled +before it is even started.

    -at_before_give(giver, getter, **kwargs)[source]
    +at_before_give(giver, getter, **kwargs)

    Called by the default give command before this object has been given.

    @@ -1420,12 +1524,34 @@ overriding the call (unused by default).

    Notes

    This hook cannot stop the give from happening. Use -permissions or the at_before_give() hook for that.

    +permissions or the at_pre_give() hook for that.

    +
    + +
    +
    +at_pre_drop(dropper, **kwargs)[source]
    +

    Called by the default drop command before this object has been +dropped.

    +
    +
    Parameters
    +
      +
    • dropper (Object) – The object which will drop this object.

    • +
    • **kwargs (dict) – Arbitrary, optional arguments for users +overriding the call (unused by default).

    • +
    +
    +
    Returns
    +

    shoulddrop (bool) – If the object should be dropped or not.

    +
    +
    +

    Notes

    +

    If this method returns False/None, the dropping is cancelled +before it is even started.

    -at_before_drop(dropper, **kwargs)[source]
    +at_before_drop(dropper, **kwargs)

    Called by the default drop command before this object has been dropped.

    @@ -1461,12 +1587,40 @@ overriding the call (unused by default).

    Notes

    This hook cannot stop the drop from happening. Use -permissions or the at_before_drop() hook for that.

    +permissions or the at_pre_drop() hook for that.

    +
    + +
    +
    +at_pre_say(message, **kwargs)[source]
    +

    Before the object says something.

    +

    This hook is by default used by the ‘say’ and ‘whisper’ +commands as used by this command it is called before the text +is said/whispered and can be used to customize the outgoing +text from the object. Returning None aborts the command.

    +
    +
    Parameters
    +

    message (str) – The suggested say/whisper text spoken by self.

    +
    +
    Keyword Arguments
    +
      +
    • whisper (bool) – If True, this is a whisper rather than +a say. This is sent by the whisper command by default. +Other verbal commands could use this hook in similar +ways.

    • +
    • receivers (Object or iterable) – If set, this is the target or targets for the +say/whisper.

    • +
    +
    +
    Returns
    +

    message (str) – The (possibly modified) text to be spoken.

    +
    +
    -at_before_say(message, **kwargs)[source]
    +at_before_say(message, **kwargs)

    Before the object says something.

    This hook is by default used by the ‘say’ and ‘whisper’ commands as used by this command it is called before the text @@ -1652,9 +1806,15 @@ method (unless you want to fundamentally change how a Character object works).

    +
    +
    +at_post_move(source_location, **kwargs)[source]
    +

    We make sure to look around after a move.

    +
    +
    -at_after_move(source_location, **kwargs)[source]
    +at_after_move(source_location, **kwargs)

    We make sure to look around after a move.

    diff --git a/docs/1.0-dev/api/evennia.scripts.scripts.html b/docs/1.0-dev/api/evennia.scripts.scripts.html index e65b75b82c..a2e229d370 100644 --- a/docs/1.0-dev/api/evennia.scripts.scripts.html +++ b/docs/1.0-dev/api/evennia.scripts.scripts.html @@ -137,7 +137,12 @@ overriding the call (unused by default).

    at_script_delete()[source]
    -

    Called when the Script is deleted, after at_stop().

    +

    Called when the Script is deleted, before stopping the timer.

    +
    +
    Returns
    +

    bool – If False, the deletion is aborted.

    +
    +
    diff --git a/docs/1.0-dev/api/evennia.server.inputfuncs.html b/docs/1.0-dev/api/evennia.server.inputfuncs.html index ac5f2e60ad..3b59e621b7 100644 --- a/docs/1.0-dev/api/evennia.server.inputfuncs.html +++ b/docs/1.0-dev/api/evennia.server.inputfuncs.html @@ -339,9 +339,16 @@ This will be integrated into the session settings

    -evennia.server.inputfuncs.external_discord_hello(session, *args, **kwargs)[source]
    -

    Sent by Mudlet as a greeting; added here to avoid -logging a missing inputfunc for it.

    +evennia.server.inputfuncs.external_discord_hello(session, *args, **kwargs) +

    Dummy used to swallow missing-inputfunc errors for +common clients.

    +
    + +
    +
    +evennia.server.inputfuncs.client_gui(session, *args, **kwargs)
    +

    Dummy used to swallow missing-inputfunc errors for +common clients.

    diff --git a/docs/1.0-dev/api/evennia.server.portal.webclient_ajax.html b/docs/1.0-dev/api/evennia.server.portal.webclient_ajax.html index 2d74dcae63..cbab24baab 100644 --- a/docs/1.0-dev/api/evennia.server.portal.webclient_ajax.html +++ b/docs/1.0-dev/api/evennia.server.portal.webclient_ajax.html @@ -125,6 +125,20 @@ implement default like this:

    +
    +
    +get_browserstr(request)[source]
    +

    Get browser-string out of the request.

    +
    +
    Parameters
    +

    request (Request) – Incoming request object.

    +
    +
    Returns
    +

    str – The browser name.

    +
    +
    +
    +
    at_login()[source]
    diff --git a/docs/1.0-dev/api/evennia.typeclasses.attributes.html b/docs/1.0-dev/api/evennia.typeclasses.attributes.html index d4bd4f129f..ffea1f0fca 100644 --- a/docs/1.0-dev/api/evennia.typeclasses.attributes.html +++ b/docs/1.0-dev/api/evennia.typeclasses.attributes.html @@ -180,6 +180,69 @@ of a .pk field as a sign that the Attribute was deleted.

    +
    +
    +class evennia.typeclasses.attributes.AttributeProperty(default=None, category=None, strattr=False, lockstring='', autocreate=False)[source]
    +

    Bases: object

    +

    Attribute property descriptor. Allows for specifying Attributes as Django-like ‘fields’ +on the class level. Note that while one can set a lock on the Attribute, +there is no way to check said lock when accessing via the property - use +the full AttributeHandler if you need to do access checks.

    +

    Example:

    +
    class Character(DefaultCharacter):
    +    foo = AttributeProperty(default="Bar")
    +
    +
    +
    +
    +attrhandler_name = 'attributes'
    +
    + +
    +
    +__init__(default=None, category=None, strattr=False, lockstring='', autocreate=False)[source]
    +

    Initialize an Attribute as a property descriptor.

    +
    +
    Keyword Arguments
    +
      +
    • default (any) – A default value if the attr is not set.

    • +
    • category (str) – The attribute’s category. If unset, use class default.

    • +
    • strattr (bool) – If set, this Attribute must be a simple string, and will be +stored more efficiently.

    • +
    • lockstring (str) – This is not itself useful with the property, but only if +using the full AttributeHandler.get(accessing_obj=…) to access the +Attribute.

    • +
    • autocreate (bool) – If an un-found Attr should lead to auto-creating the +Attribute (with the default value). If False, the property will +return the default value until it has been explicitly set. This means +less database accesses, but also means the property will have no +corresponding Attribute if wanting to access it directly via the +AttributeHandler (it will also not show up in examine).

    • +
    +
    +
    +
    + +
    + +
    +
    +class evennia.typeclasses.attributes.NAttributeProperty(default=None, category=None, strattr=False, lockstring='', autocreate=False)[source]
    +

    Bases: evennia.typeclasses.attributes.AttributeProperty

    +

    NAttribute property descriptor. Allows for specifying NAttributes as Django-like ‘fields’ +on the class level.

    +

    Example:

    +
    class Character(DefaultCharacter):
    +    foo = NAttributeProperty(default="Bar")
    +
    +
    +
    +
    +attrhandler_name = 'nattributes'
    +
    + +
    +
    class evennia.typeclasses.attributes.Attribute(*args, **kwargs)[source]
    @@ -973,11 +1036,11 @@ the return is a list of booleans.

  • key (str or list, optional) – the attribute identifier or multiple attributes to get. if a list of keys, the method will return a list.

  • -
  • category (str, optional) – the category within which to -retrieve attribute(s).

  • default (any, optional) – The value to return if an Attribute was not defined. If set, it will be returned in a one-item list.

  • +
  • category (str, optional) – the category within which to +retrieve attribute(s).

  • return_obj (bool, optional) – If set, the return is not the value of the Attribute but the Attribute object itself.

  • strattr (bool, optional) – Return the strvalue field of diff --git a/docs/1.0-dev/api/evennia.typeclasses.tags.html b/docs/1.0-dev/api/evennia.typeclasses.tags.html index ca9583d8d6..3cbbef98f5 100644 --- a/docs/1.0-dev/api/evennia.typeclasses.tags.html +++ b/docs/1.0-dev/api/evennia.typeclasses.tags.html @@ -253,12 +253,12 @@ stored on and with a tagtype given by self.handlertype

    -add(tag=None, category=None, data=None)[source]
    +add(key=None, category=None, data=None)[source]

    Add a new tag to the handler.

    Parameters
      -
    • tag (str or list) – The name of the tag to add. If a list, +

    • key (str or list) – The name of the tag to add. If a list, add several Tags.

    • category (str, optional) – Category of Tag. None is the default category.

    • data (str, optional) – Info text about the tag(s) added. @@ -275,12 +275,12 @@ will be created.

      -has(tag=None, category=None, return_list=False)[source]
      +has(key=None, category=None, return_list=False)[source]

      Checks if the given Tag (or list of Tags) exists on the object.

      Parameters
        -
      • tag (str or iterable) – The Tag key or tags to check for. +

      • key (str or iterable) – The Tag key or tags to check for. If None, search by category.

      • category (str, optional) – Limit the check to Tags with this category (note, that None is the default category).

      • diff --git a/docs/1.0-dev/api/evennia.utils.ansi.html b/docs/1.0-dev/api/evennia.utils.ansi.html index 47da37c5fe..ba908a142f 100644 --- a/docs/1.0-dev/api/evennia.utils.ansi.html +++ b/docs/1.0-dev/api/evennia.utils.ansi.html @@ -383,6 +383,12 @@ ANSI-bytecodes in the string.

        (notably linebreaks and tags)

      +
      +
      +evennia.utils.ansi.strip_mxp(string, parser=<evennia.utils.ansi.ANSIParser object>)[source]
      +

      Strip MXP markup.

      +
      +
      evennia.utils.ansi.raw(string)[source]
      diff --git a/docs/1.0-dev/api/evennia.utils.eveditor.html b/docs/1.0-dev/api/evennia.utils.eveditor.html index 0a16e33ff4..46661baef7 100644 --- a/docs/1.0-dev/api/evennia.utils.eveditor.html +++ b/docs/1.0-dev/api/evennia.utils.eveditor.html @@ -277,7 +277,7 @@ indentation.

      -aliases = [':dd', ':h', ':echo', ':f', ':', ':fi', ':q', ':s', ':fd', ':i', ':::', ':=', ':j', ':x', ':q!', ':wq', ':!', ':r', ':w', ':A', ':p', ':dw', ':uu', ':UU', ':<', ':I', '::', ':S', ':>', ':u', ':DD', ':y']
      +aliases = [':uu', ':echo', ':u', ':r', '::', ':w', ':j', ':>', ':q!', ':A', ':=', ':p', ':', ':S', ':x', ':!', ':f', ':y', ':i', ':wq', ':UU', ':h', ':dw', ':::', ':I', ':fd', ':s', ':dd', ':fi', ':q', ':<', ':DD']
      @@ -305,7 +305,7 @@ efficient presentation.

      -search_index_entry = {'aliases': ':dd :h :echo :f : :fi :q :s :fd :i ::: := :j :x :q! :wq :! :r :w :A :p :dw :uu :UU :< :I :: :S :> :u :DD :y', 'category': 'general', 'key': ':editor_command_group', 'tags': '', 'text': '\n Commands for the editor\n '}
      +search_index_entry = {'aliases': ':uu :echo :u :r :: :w :j :> :q! :A := :p : :S :x :! :f :y :i :wq :UU :h :dw ::: :I :fd :s :dd :fi :q :< :DD', 'category': 'general', 'key': ':editor_command_group', 'tags': '', 'text': '\n Commands for the editor\n '}
      diff --git a/docs/1.0-dev/api/evennia.utils.evmenu.html b/docs/1.0-dev/api/evennia.utils.evmenu.html index 12b64025c3..547c011dbf 100644 --- a/docs/1.0-dev/api/evennia.utils.evmenu.html +++ b/docs/1.0-dev/api/evennia.utils.evmenu.html @@ -943,7 +943,7 @@ single question.

      -aliases = ['y', 'no', 'abort', 'yes', 'n', 'a', '__nomatch_command']
      +aliases = ['yes', 'abort', 'a', 'n', '__nomatch_command', 'y', 'no']
      @@ -969,7 +969,7 @@ single question.

      -search_index_entry = {'aliases': 'y no abort yes n a __nomatch_command', 'category': 'general', 'key': '__noinput_command', 'tags': '', 'text': '\n Handle a prompt for yes or no. Press [return] for the default choice.\n\n '}
      +search_index_entry = {'aliases': 'yes abort a n __nomatch_command y no', 'category': 'general', 'key': '__noinput_command', 'tags': '', 'text': '\n Handle a prompt for yes or no. Press [return] for the default choice.\n\n '}
    diff --git a/docs/1.0-dev/api/evennia.utils.evmore.html b/docs/1.0-dev/api/evennia.utils.evmore.html index db489c0b61..36e5df9b3d 100644 --- a/docs/1.0-dev/api/evennia.utils.evmore.html +++ b/docs/1.0-dev/api/evennia.utils.evmore.html @@ -78,7 +78,7 @@ the caller.msg() construct every time the page is updated.

    -aliases = ['quit', 't', 'abort', 'previous', 'end', 'n', 'p', 'a', 'e', 'next', 'q', 'top']
    +aliases = ['previous', 'abort', 'top', 'quit', 't', 'e', 'next', 'n', 'end', 'a', 'q', 'p']
    @@ -104,7 +104,7 @@ the caller.msg() construct every time the page is updated.

    -search_index_entry = {'aliases': 'quit t abort previous end n p a e next q top', 'category': 'general', 'key': '__noinput_command', 'tags': '', 'text': '\n Manipulate the text paging. Catch no-input with aliases.\n '}
    +search_index_entry = {'aliases': 'previous abort top quit t e next n end a q p', 'category': 'general', 'key': '__noinput_command', 'tags': '', 'text': '\n Manipulate the text paging. Catch no-input with aliases.\n '}
    diff --git a/docs/1.0-dev/api/evennia.web.utils.general_context.html b/docs/1.0-dev/api/evennia.web.utils.general_context.html index 03b8dfb79b..90b0be2533 100644 --- a/docs/1.0-dev/api/evennia.web.utils.general_context.html +++ b/docs/1.0-dev/api/evennia.web.utils.general_context.html @@ -47,21 +47,9 @@ context without having to repeatedly include it.

    For this to work, this file is included in the settings file, in the TEMPLATES[“OPTIONS”][“context_processors”] list.

    -
    -evennia.web.utils.general_context.set_game_name_and_slogan()[source]
    -

    Sets global variables GAME_NAME and GAME_SLOGAN which are used by -general_context.

    -

    Notes

    -

    This function is used for unit testing the values of the globals.

    -
    - -
    -
    -evennia.web.utils.general_context.set_webclient_settings()[source]
    -

    As with set_game_name_and_slogan above, this sets global variables pertaining -to webclient settings.

    -

    Notes

    -

    Used for unit testing.

    +
    +evennia.web.utils.general_context.load_game_settings()[source]
    +

    Load and cache game settings.

    diff --git a/docs/1.0-dev/api/evennia.web.utils.tests.html b/docs/1.0-dev/api/evennia.web.utils.tests.html index 80a052946f..ca342d8063 100644 --- a/docs/1.0-dev/api/evennia.web.utils.tests.html +++ b/docs/1.0-dev/api/evennia.web.utils.tests.html @@ -56,16 +56,6 @@ test_general_context()[source]
    -
    -
    -test_set_game_name_and_slogan(mock_get_version, mock_settings)[source]
    -
    - -
    -
    -test_set_webclient_settings(mock_settings)[source]
    -
    -
  • diff --git a/docs/1.0-dev/genindex.html b/docs/1.0-dev/genindex.html index 2a11da5b3e..aa1f19ea92 100644 --- a/docs/1.0-dev/genindex.html +++ b/docs/1.0-dev/genindex.html @@ -249,6 +249,8 @@
  • (evennia.server.webserver.WSGIWebServer method)
  • (evennia.typeclasses.attributes.AttributeHandler method) +
  • +
  • (evennia.typeclasses.attributes.AttributeProperty method)
  • (evennia.typeclasses.attributes.DbHolder method)
  • @@ -1295,8 +1297,6 @@
  • ansi_map (evennia.utils.ansi.ANSIParser attribute)
  • - - + -
  • at_after_object_leave() (evennia.contrib.wilderness.WildernessScript method) +
  • at_after_traverse() (evennia.objects.objects.DefaultObject method)
  • -
  • at_after_traverse() (evennia.contrib.tutorial_world.objects.CrumblingWall method) - -
  • at_again_position() (evennia.contrib.evscaperoom.objects.BasePositionable method)
  • at_already_closed() (evennia.contrib.evscaperoom.objects.Openable method) @@ -1485,48 +1491,16 @@
  • (evennia.contrib.evscaperoom.objects.Usable method)
  • -
  • at_before_drop() (evennia.contrib.turnbattle.tb_equip.TBEArmor method) - -
  • -
  • at_before_get() (evennia.contrib.turnbattle.tb_range.TBRangeObject method) - -
  • -
  • at_before_give() (evennia.contrib.turnbattle.tb_equip.TBEArmor method) - -
  • -
  • at_before_move() (evennia.contrib.turnbattle.tb_basic.TBBasicCharacter method) - -
  • -
  • at_before_say() (evennia.contrib.rpsystem.ContribRPCharacter method) - -
  • at_cannot_apply() (evennia.contrib.evscaperoom.objects.BaseApplicable method)
  • CmdLookBridge (class in evennia.contrib.tutorial_world.rooms) -
  • -
  • CmdLookDark (class in evennia.contrib.tutorial_world.rooms)
  • +
  • load_game_settings() (in module evennia.web.utils.general_context) +
  • load_module_prototypes() (in module evennia.prototypes.prototypes)
  • load_state() (evennia.contrib.evscaperoom.state.StateHandler method) @@ -12826,6 +12870,8 @@
  • (evennia.typeclasses.models.TypedObject property)
  • +
  • NAttributeProperty (class in evennia.typeclasses.attributes) +
  • nattributes (evennia.server.serversession.ServerSession attribute) + -
  • -
  • set_game_name_and_slogan() (in module evennia.web.utils.general_context) -
  • set_gamedir() (in module evennia.server.evennia_launcher)
  • set_key() (evennia.commands.command.Command method) @@ -15921,8 +15965,6 @@
  • set_task() (evennia.contrib.ingame_python.scripts.EventHandler method)
  • set_trace() (in module evennia) -
  • -
  • set_webclient_settings() (in module evennia.web.utils.general_context)
  • setdesc() (evennia.contrib.simpledoor.SimpleDoor method)
  • @@ -16335,7 +16377,11 @@
  • strip_control_sequences() (in module evennia.utils.utils)
  • strip_mxp() (evennia.utils.ansi.ANSIParser method) + +
  • strip_raw_ansi() (in module evennia.utils.ansi)
  • strip_raw_codes() (evennia.utils.ansi.ANSIParser method) @@ -17595,16 +17641,12 @@
  • test_set_attribute() (evennia.web.api.tests.TestEvenniaRESTApi method)
  • test_set_focus() (evennia.contrib.evscaperoom.tests.TestEvscaperoomCommands method) -
  • -
  • test_set_game_name_and_slogan() (evennia.web.utils.tests.TestGeneralContext method)
  • test_set_help() (evennia.commands.default.tests.TestHelp method)
  • test_set_home() (evennia.commands.default.tests.TestBuilding method)
  • test_set_obj_alias() (evennia.commands.default.tests.TestBuilding method) -
  • -
  • test_set_webclient_settings() (evennia.web.utils.tests.TestGeneralContext method)
  • test_setting() (evennia.contrib.test_traits.TraitHandlerTest method)
  • diff --git a/docs/1.0-dev/objects.inv b/docs/1.0-dev/objects.inv index 640b067c1034ed39ef017a19a753a85d71b2b5b3..5bd5d99227a5a9d3f2c19536bae196b2ab9375b5 100644 GIT binary patch delta 113538 zcmaHyQ*@@k+qP@lHmA1TPTQHzy5#k{y}xogF%}ogF>CogFr#9gE@z4QlJ}0B(n6)n6OuB%m!6 zK!X+npq(!Uka-6I7#j-#6kd5}K^NH_A+u!Zu;+OvfdIpJLV$qt5+xHC%$pI-slln0 zXRg`dQqfO!fcd(!nQb;rLdp6^4I}r=hLYQd3#qmn8B}7&7;K>0QV3=QRV0eZ@>u`1 zxcI32^{{9e=wPT};VGf9{utkYJzNg+L~3GTp3s0@1AYnPo?wQf1c2Ut2=$@Ab-LX}&5#o0CsP^;ku<-3 z{ue5ZPfUc17VIyoJSeHiX(5-!hya?zN`=>&NR6a2g^o^g8Wx!N02Ky@*3lspu7}WI zcs}Smuf+rvxZuH(o3s=GO5UJ{pr7?%C_Gw$O<=P{H@g{jCBNrjQeFQx8MJV zEubHA#8ynq@*hkD0)ZTde|Zy}jK??c6mH9X+ zS`$S@8HKqrkU&~a#R04Z zKPdotN*ljg6!;_+1jHayk19|%M}u>PX4m;BHK_~cKwKLQj(`|arplbUtTHTMB3QU6 zNfge?#hO&FM89l;wPz_OAB4#I1y+kjV=D?Wk(&BJw40Gigmvf~C%oqmnRmJ+K}U1h zDtiVCD?%R}i(w($0PC@Jw`C=?zX4<>+Z&_KS_#`>q+#LQWNHht^Cn;e4(lkCFwXKi zkRFvwo8Bkst<2=%T@0p3qKkK}>zM&(Si``Hh*x2EPxQWxHKnKEtu37=OJYCv+p&x6 z6#0O&L8nP_0-E1ynl>eD2UZM7!Wsz+w}80wvZIx~5dhFKMA8l+ zB19#b5)76eD!9W{d4VUo2sxZtTN(UX@xf@<+*u2>-!z`WYLnJl zw)K;GmT*U`sgSzHhZG~sJ575h zsU!9AwMq8(r%$4bEuPk*EkM6)HVJVsYvyjuPT>qR+$g;w3EX|2U4TF#%I(ZUlB}9( ztyZSA-R$YT>|}BEciqa$)iRRE^4``&SciOsh-q#?sw*nQ4L;N!GqoT>t?aNKg;C`f zw4ucE_@jRbbWJ9&B8My3==u83qLPAEX(GsfgO{ax zOt$l_H$T%js1Rt}C)lMNjgZ+Lt(@K#?u#kvOhvY8Z-MBP=r6pLi<9WcblnFaWLZKn zMZ}<GFgorASuhyARv?q6`MdFqb@{GPSs>_zY?Znk-BSw=r zW=50GUBl_urRd9c0QANar7^f2@zgh?(&OPPyR%q&XJNH14hAHx8JFq{{ROcgJ`Kfj zCI#$TKC*|7ZNdsXViesDK2u%e7JTarB5Zo^aQFmI%?B&UQ$TFh{LQS-5mVXyuI#Sc zeG_$f2W1s)DAqHCQtQlV;2TPOc7b31q*>o~=xHME*@+ue#{2o7g9z8IsZT0Rv*a>8 zuN!73i#grOh)TnlilsyW7HIGZlpj|8go?wuZ2Q(`viyl$(7cf0sYf;T;S&AOq zmtN9Z%l+j-bk>_k*O56aA6v%NIWrQ_WI~g179mC=%YlJKQ<)1DN6>^Wx#wg|Rd`l6>?cGJq~2K<8r(H(CXAr?A4?IHs4AXBVz6u;wH@Qfk`rI z>};&++Xqq;)4Lr-*4zbf;7ya!aU*67iLsi3M;(tq;7w#fHlXw43g@RSc0c!Extry^ z3Y}#@Rd@s$t8@-Imgohvs#a(1D0cp2EBCqa12Ei9i9P`25*~cZ)TMqdTJeXRainTL zticj3TCvxkVH2;AUDK<42^D?l`u+bR07=fG3t3W*Y?pW?pA6|N@E039BT#(ME%kj< zxY-vqj($A9FT6;xtiSejLO%yJkvo$ht@yA3wvp3V>u?tpYiaFn^P!*BrfzS{42_t` zY3ALm-2=m)d>quJ41=C*F_-x`LseKjkYk3VnJKIM@{cr++P-G)SEu?f42nDRU!j3feB?aTFsPV=-XWHT<4+P=?jXqVnl8 z@=8Dg*T*3M;ZHtA;j?L_)WtG2{Dn4JyR1AedfV2syz+wMW_qv!oMujuL`i{EvYRSq z>LaZ*$c@;X)j3Q~-0D8&EZRad3%fM=`D>%Xmw=K~bunY5N`N6J!TQU5#?A{slT!Nm zX>ZLsBVP`mywrUHLV1-+A~l?g#ZW3D9)qQcXEmVBM)dd7k4h7`bGZl7sg$gfpE`^g z{9bpjSuY2NT?3uY(DlDF7MUMZ&#v(ASLMvMeDk8wNwoygD!H^ZXR_i|I3qf|ML*YK1{T_-9$ zCX8BWOR(O5WwM(Nxu*`zH#}p<;}ZUqZxSs^kIIjSr&z5J<*pKiIiq_4?p;|5LY`ez z^(qGYa~*)jC+P*H?m05gS0t-7opkB7)FEkeKh6T`u3{Y;td{W)%@aAXF7f--g0~++ zU``da@}wfi=xu(fK$P$LSXtFN7upCWS!JqM({D504UnxRK13Z9S(UY>o|aw=Pa-6^ zr@;RDo6NP?=JxYA{q1iDfU)Z(`^2Q`QCjcF(x+Zoh5xRILG0d~YM=eunN{v~hI*Ys zp5IVaMw6l{a1v(kETyj^jX%7RXLyKJV}QOTTG8S4e?2{dX(4p+kIB`l z1I5PK{!9W` zTty`vdHkCB!9G1IlR}wvT7h99X`+){rBY-&pFP%qn^;`;*FLtQ@IfAEx$lG~lMMW2 z+=N?=D5M>!iJNMJhQTLU1RjyCwRr}w`|tId>AowYyZGs&$@DS4^g#)_{A{@3i*xjL z4YI~(JjU7n;qu%RVBXcKb$#hBkxB7JW>X*r&4u?{j*&#nEf?APYW02OPL3Big>Vuw ztbC^f`+*Z;nqB57VESjE=Wz5_NJyawwT0U4mX||Y*RNy$j^`q7<~ezJO6q}_+w>o! z8J4_he*3rwXZ*oFCqt2vQ1js`a)c9%B}`!+QYz%p(<$iV0FRRy;8feNiyHXw|?|d7Ac~Jbco8|U>r^l`Z)n!!O2mQ=v~lP736%te(nI{^6TgTgp3K#X zsq4HwJ&}AuLz+%j*yqB$CJMwCzMQj{R>^ayq0{O#@Y^~^cr_zgT|_I1{<(-s3k}It z^Y1z5;SeR{y^x*V{quh*#0cRfT<}!vUyM9_(<$j62h69a_r*D&YdRsyF4Z);e=ncB zr-M^S)i>-82mcg*5cPUqL#izHx&M{EsY@eqRBWKU!ekaiJ`vT z4_VWI0l>ozQXeJA`%l4Db*UJw<@6gf>h-&7Qbvo@EH#Az4=d`PYffVitWuTfb64Pl z1<@2wgLZr|X}tnU^Lv)ZdiG#mO67#}zlIUyc1LDL35u!JMwmMfACJ09?vA>S?ej~u zIL3`n>6j!Y4@UUgauAx!(pe~_kR)C9$Lyey06?rPt=c>f-FRS%gu&7QnVG$5m0!t6 zjf37`$(dAfa>Pj;W$W*DQB`F(?^)Tt2ENF<;7U97HL^D)IOPH6WKVpqbo-tA0$T~S z0+0MG#z`GXq5W0^LFtX-P;u8@?;@}`cK_lhk(b*cf0Oc%<3cPvMOS*0z z&+I80CdOhoXq%W#871!=z_3jGvIUn6z-m_S?1Vif>tZXDvAyE<4{PJ)bSZQ_hn3Ov zRRgR1I(0P3UBj7ORVsC_LwZ!b?i->D7zlgy+(Qqu`UHO5WWSqzpC_vn`gZ-z2&iBN zW#m6xRDl7rekYbLN|a9dGa7(rO7gx_rhF!I4#V8Qi=lu+E|Uu^xwnBh^1~o2K)2!= zMTIGecMZUB*5@=i9Oi5kLp4Xe9=GpR_Y3C`ozx>z-sP0c3q037X<_z5k7I5RvYAs7 zeSOI3V21N2EcrSJ5W0!wH}-P5cYL!H;i9@2Z=`oe4dV4MIdFyzrV zg|UeXBwbyaa5JZkJx1eY>B!tLVTKwDK&tq$23%g~r!a7`x?AWiA!P?Gl|_dxG;Oey z3|g_+X*_*{5Jo*xuSjG2CeHOYwO)zaZpG@qJ&4U&wgZ2~+y)(H5vfs9NRfnQ#nM z7o-8}PGX!$B!-S5Fer@>Ac2bYMyf=b;R+yi#ML4#a*2D4x^u?JB4ybCO7X;dpz7Hb zXiw`AOWAw%QA``5Mcuk(Hm{v}?0An7$=Kgm zT9iG(9SoQPdI(OOW4{sr48N3$8vDIlo2!~Dp=?IN##%p z{35l`;F%H8463ERJ`&IR0mW*kBEI;fH6OMhmBbYx&I>k(9pw7UAR$?rj9r(l@r%Je z&$fR~rviW6N_|iOFY!lmg0F?DEs=QT;dAkYpj*&SpOF!$?(N3!^D+cfK~6*wnlO?&?pLn(S%2xyb4D) zyJiW2CXC#NMrSg_xxhm=YTlCoc~-lCE_n<)hYO;1}x0F1yJ* zrRthD?)v=j?Nybaz{y%6SHL3kl~Z1$1oHeR!scPAk6;>Ij#;Zn=A0Qpt};0@+#F+= zq)6-W1C7SI3NhqS=10DwpMhobhXFydnI`r?wogqa4hr%ihXe^35in6;&cm1o>dpqR z%#pSD&l6!yG7huSH!wzImFXlLHVOODs4!Y{NiylFruijNr~q33%sTLIK~E!-kr0#HG!rs&N}t}oax^pP-zw;R);hrhD(>*yO2!m1ZN^&x zx)Bo&(H$hepZO0-aLIu3PY^TK#Ni_i%w)sS+**nGFBMPSb0k5ToCOD~;-94eev-N^ zt;V{=nbYFc^%!tM?^z%2ljn%CdhW|hPs<$0H zRVIVDM75s(Bp5wjM6yFO@Ea)rNe{I2opNTo2m$8N{3qQQCbVDA*NQ%RqX%m_-^^;V zzM;-!pra8Ai1*tcA{=rdcclFh6m~IPLzKFxGi2qP7I1A-$F?Q8C z^4Q(NhDy62+^K@U>f9}Z?2_;9kZWi9*Rx@t2L8QO64SpT+(DY?`Iaz6=ls!+7t3yT%IIhjPdP@aGwi!{!lR3HF@Mk<>H)dUHo`Z}JY{6(332XA5uE zO_M6Qe%b|{O@-A1LKm|nD|%n^N`C~Cj!<7X!YpM8>GZZa?$P@@AER2;+y)m+dQ|HIKOOoA zh~2+k`Jq!Foc_8Zvmg`Srua)P-aDB`UKLaQKT*9S`_L^bq+_Bx zo2{qtOfX5f?}MXB@plB&Bu+;PdR5LkNHz>5X5~BwK=8N{5!keK!H70}`p)*}hz(6( zG43oP9T1y@gUewdJ*kYK=^P7~dNZzoPFSI_xZ5PnHqF_D%lZY2d-s80gpZwwy?Qz) ztm{+0=RS8O~5MqM{Hek4w5RUy4f5dLcXb5+Nawbr^iD>|XX zN^=_RrSN5UVcZk!4%lK0loBte#|%5n>?N~jsMn@Qw>pXlm4J%=GlURSu0vfiSVAhr zfJY)84h5+W?DY>c*Ec7uQqiASxnx8S83aB9woMAq&UHzBEtk0impEW5oe&34bn<(C z{7J2mGEm&ik-ZDjaE1d_$r>V6DHbtbw4nLvj0dT<*%v4Q7jgDEtf9cgjtN%68zojE z7cf&cuMm004p-3@1RH_zYjN{Ib1l4zLy*>j>%M7qYeV44ysL5G)f$8~ z1h-*RCbC!M#Oh*ei2r2DODj&7+$iyHn+E3&E(yF1^A`B zCr_1pR^oew?TkdIzw42#W6AGiTHJ7fS}MO&;iRL&!A-cr4JYnl;H58O#8Su6vX&c% z^WC_@D@B>Izzo~Pt+9wRzTohxi3E>QkbxgB#4REmn^SZI6CCjk@3Wi^TRb}Qlf}4* z7Ew#u?|c!KKUzvDvO!`I=!wzc0cZ*^#|nxTK}!nM=wqrLy^?8+EYPq2RpZ=b@=RJD zO0c5|Ch%1BhYlN!{gEqY-9vS+Oa57Z5S8{G9x{=}uyyX8BWz@kj*!D<%FJvtAyqWN zvY$6<6nuLSlQu!!!Pm)xD&sJ7d2N=3}x&~!Y zw41$NB#ZBbTo(Oe|5s(+X4up9@@M=W#Pbj?c)ExUCsoFbLYXn^W=4fq%$@Z#c?w0F z9Km?42Y9h zUMmG^L6YLjPC!QzWsEkX4~RbBN1r)fhaxA2?Te5U@tafRrrM=pSK)*kA;*(2Ev1&< zQK#2;ivQj`@Y>krckMK^Mt%0JKLog<&vIf{3KP#sY#xxca!LxDG+P|Ma+B{s-!RJ* zGs$+&E=m80-AdJSL-0DgrS|E@4|i{l^_-{JT&0P3pD#t%&Iy_O1XzUQ4O%YwNgB>| z7t7v+vXt3!V|)LMI2+O-we|!(ymlIY#42LYQ~WgbR7$JL4|@v(`k<>df8o z`*lU}!)~frc<=~16AE)Z$w^A-Wj$Y+H40*CuI+Ejb93F43LI6-w6GGwRjdni8m(=S zA|dzIZej(^#cyvz1_1qF1$Q<^{jOtiY82g%!Nj^BNkUW9FvmE(m)@x>cK2SEtSV0U zpNS_ef4?{{U-UeczZaA2&MzZ3?|H30{Xx|0$g+P*8o+)xYm>tr`maG#S5gt&z?W&D6RH~({xw%@O^ZyR}31*t1iE%TTFWKpJ%rIaszHB&cIyq3< z^9zY!b0B-g*S^CbRN-@TBtRy4&2*Ni8aP8^-4A-T>l-_0FMy|(^LEtzkbm7%C{~&S zN_HIsyJ*i0Q2>WVz~Dt$UeGOpsz|Na9oDioMrPS5%t6Ip4AxtQmiFLWb~Pb}(1?#0 zt-eY*ur&PGA2S?f;Ek3US_@*xYS_wny8jwma)$Ts$na-ek!AAX(FHW>CCHVZGpb6u zg;}3P`>6k6PNsFMGigAXxVWwO4n$ijxm5`ol0Hd9902;DbJW=BO{%2K*E}+?Lo-d7 zp94AUdFmGr`hbL*uk%)B{(V7g_6B8XZW^N%IcaV{^=Xzk5h-~c{lx`z+lj|X>Gd#o z-;!h4V2KluIHBQSWOTuEiETIoEK=s4;q*&L<7ToqpxMQ^FUDrPoBR6?(6ON|=V{Mn zZ8hglfAvoxyhSDa4E7#oSZ~QaB&!G1Lg9yg6topS1!T#(LuQ=JNvXxaSU9)@vNY*+aD41*K2-sqvw{W3r2w#|oom z@V=&Y4z`gu5vuun&kO()80geAP2v^dN$SYi0KleBzADFmfxY_J`}G(Eqk4C3@#R4P zHGJs^uK296Rl}3-zCVOEUAMLbo?bi+9R9?T6?76^7;XFnnXJnALCE^d;7WGfvU{$& z+{4~C_f*&0fBO&&JGlZV5s(uMXAe;ka$)z{+S=z)e%eZKhDySFFGl`H?Uc}ywnLy1 z4QQx)61HUwOyOqCzpULUSc>=yV$y&+7&nE*Y0Id+(K9KuDOP(Y|74xO2mgVaIGNCo z#m^i^FLQq}&VZNJ^XVCNhN30)eBTJd=(fn84 z8xYvjuz;9j+zH%?dSur4@;yI6-=~fPDu!RHG`@~+EaN0bDEN$C$tM$>=;((w$TN}x zHbmfv9vGA8j#kBd5BkZBpbdwE7H2s3>JMXKM5VQydA`~EU{&(s&}=J0atD!iZJ-(MaNO|zysS$|y+ z_I!KDZHSAIhIRS&z`Q(@t2eBLEarfJg;%0S^e))cO%Z3~MUogD)3q5`vthNA=k0@J z#{yreJ*Kw3W2uBn-`B~9P6^=ac~{JrYRvh>Q$wh|F^M-YsqW;DZ)XWU6vt`xpdDoe6z;3b2K zrlOH4LPzd&vlt>%>aSAGYSw>r`x=08dN3bUZDF%C3=DJOVzK7 z`sATCYD+Lf;4axki84x@al6yOHKC``*zGvGR?2MI2{gIYxY0lnELy#-=mX!ag2=w_ zY=G1Is)!^fAGXPA$B?BUUQoWOporS(I@)b@()waI4Vr?qOs69Opzl@(m;#SCo^avV zB1Cxg3y@Czq(8zt6buxm@ti>B9Pgw(_wb6EI9xsui+{Ag1oM8pSQf1=t#C0*j!DFq z)DtEQoc2Qg<5W#w(}YuOX`2e)$7(DwzT^)8RmH@FVjEuN7?-AjDcM@hYH?2YqX6mFJxfkvZ zprB7kJQ9>Dte9W%`E)tYg8hk9$Mam&T0OhqGgF*N z5xh$NZ@f4~R&{jb67>2J7X2wY2l$}etv0;XPV6GOBhDlSn6{TZY|#rX!{yHLf0OLsvMq6GDb+T+3z3C}0r5&$5?d3Zdb)Kf zje9NWv!N!Wyg1+MQBW5UKM+6wPDy01Oj@q$d27M8mot^WU*7v!LUg7fHG8q-2oAd2 zGtSk;ngr<<>(Cc@NESP))2H(?aI9t*K($XZfsM}t%1ht!PUixA{rU3BM#U6YF+yu| zi;_}L&@mQr;hzs5p9V>8WUadC34))$5H(i36oo!>F>s)9g&q#U%<=fj^dKrtD(5y|w4{=$ zO&l(r z#k)QyZ8jH3;!9l!Ym#9zSQ{{5yZ3FsOC2SQfQ`UkoCXQtnS4epin6JC4Xv*|U$}a0 zJ*lrUXW2^$8co6(xohb?c_>t^(xYVTlsy>%;O-QmnD{8mz>ohqBi5_pU*+o1qxDuJ z7ry?^7JG0=9#vkpE%0^Xsy)cqo=-jevW+(pm|O3%>YT+tP?vY=`zZ7A@Wd8y;c{U* zqgw74O1j@LBn(BTX7bSV7qYx#Wh%xp`YrdEv}ufz6gW~K#4fF;fhfi+axbo|S^b+B zU_zCE8Rr96af0xm3>1p6>56As>o~S4i;_Mu0aAN#x&rC`5+xKdMrcv|$d*YBW9nL6K|9%5V{>@m14BSu^fCS%4ys0kI>o=1zgsdO% zUdmySo)=P&$4(YHBK`_4Q7v_qai8*1BsLb5T9d?mc#!UPRnKwq1~`BFjB~p8Dt)<& zKA|^Xq_;iKhtCgf&F3BDZYjwZ*YbzM1|Q=(PB$pM6I^e1Lsu!(N~R_gidt-dku$>- ziJ-AW#CDk4l7Z9S`HMFTVT8NGhnrwmW`OmTF$aU0YrjJ;T_5yYV-1S!9KR5{Bt0im z5O;i56g641h9>gO!2K8HYEksS^@0e3*}jxRipyY!DqXi^Rt+yS)?NgzK|dyF#^E4i zRG2$Ut`VK#=bA~9XA_BwzR(^(BE8gy!`Az!J?XUj%j2d9gcC<~z}=OqV(*!+>K|NC z_3LBuvE+cujS$J50Fy5w&{q0ajsuVA<7xq%x$Lm3l_%)~F!iCkb2dar@egN(w4p|) zKiwx9UAA2%q5`ws+V}Nck*<43K%W7$;&2X@nFV;=?Sp%U;bm^XdF3r&uAEJO_yL?Z zrf=wpMBkjVi_IWuiH7KTS<`4YCD7j#IqYTQJ9Rk(`+b9vaTeN!#cgMH6&)OZMkmw{ z*@9tU=bSuTz$&`-S<6kwZh8xd<2IiaA6jL_3)OL%nfz?r>7mDoh4XjKBw7}uO>3c8 zphb&!d!(FKQYL$CsumrvfthUtxE~#>q_<;Hd`8GFTo8H$Plt@&wc{8w{aY@Fpg9+# zJU)hM*{pufwry{%RGDGs?&_Vh!Z7Y{*4nM>RPpfB6~ef2KkF}#eQ%azq*0tnWm=ey zoCywen|&3~6Sy6kp@Nl?vL4RUni`WQB_U*BWb%QaXA|+J;42E4>}I0}LwU)5a<)I= z6BG?_d}6!jm%mS>&l&r}&cyGb3#>H=8c}W-_R21~U~{`$PuoIp%lZ40x@EJfYT9eK z_R*&6E@X|r17F**_$q1*J;PDZ^=8hw$va8z5?8)N@NiF%0Se+@gqzCxum{qUJIMOF z+$9y_zVjYQdBYiiq_Pk{5wFyhjI_1aa;tQYa#Ga;z7L&j9((l1Ghf69v3fu;ed~m* zLyaZJ;ZX0E*NnMI{Y^-K?y&_cQWHaQH@8OSx^|pw+XRL^vyE$FXn;t!1>qHlqo^nG z@&j)SVaL*Vy?{&^=s(j6S?86%iZR$hWG@v*u#26dz;Q1Chb;9}k_g!kj=H=@raBF- z*49TS)RtDY&Cu6H)B1aA1nhk|5j==GI`#mRt8kdURZDW1y^45!JQ6H^lhZMkiZ2VT zt-VYB3!kz)QwfXVulHh%;`NMqXX-|wKh!yMOu7#uUoO9%_|}_#>fT>L*UYu%SeSXg z8PGdlnr)~8rav+ITrZ0MU@sNw`Tn&dmQZU@Jp8x7o5Yw+I$HiWyb3JVfo&>oCvypG8pHO^F!Yapm0Brle=v$J2mX42<*FTwN?om7X*4;) zVMLL7e~yIEh=bMv@e-aTy)40ck{X>8d605(dPP97&Q+#TyDF%-^&bwu^a z?J92Z!ZeXMS+0P;j)*5gT;L;$C89tfsG*;p1mH=T@ZWbnMv=0iS*9?D{Fl=W!78=t z6l#PprzFI$N&Wz!&&z-%>FLf2M~@D6z_TKln&&g9%`(fg=Jh;ZoYS~=SpGXFv zLIPsx^0F606L;TsCIq1VdD~hKS$9gbrTDTr@1ynZJ_&;V%>R7<1?afjDFi7lT(_l_ zx(JzU&@;rYQz{^AM(5<4M{U<{1t+M*e)Q}H%<>vGBVg?YILgB8sR$3k?&S=(sfPY( zY6J~sV@zswLxRO*A^W01+Vi8*`##n|-d~9IY%QzR@o00Y)q6d@4|v#!G>WYBrhLgx zH*C$Nn`raIg6|JHC}yskv|LsQlyrb6*D9`Lo*-%5D$j2&xgMsyYt38mZ?*a4nGJUU zH2S1q6|TXU8rO5D68?3tPm;&gX-aXcZDz z&mv23(>gCIOT2%tXe;>q-0P79h_#QAyF<}Z$Z>~R*(Z3^*Iy4S;93L`ja?%(5wv%| zvZWeWb)AP+Y@L`U>p1i~WDbE?_6kT!qw{Hw?aQ-ZbGJ&LkwpZOej7WPqD z#kGzYbSJY4ulB-IC~@D(-BO~M6|dQSSouHi5+97l5Aq)_l&?NzhFvN{9TyVJTRKjx zvr3+E#bQ6;2k-ug1!J_6Cr!p>uw>ToJzvpn-^KdBY%$GOpLL)DTp=^LwFjVhv(EQ% z-)9N_c}*5S2l4W-*wQDbRi|Y8q?{MlA-;8C7CSD-+4Ge%>i*1z*zCe~2?=&5%X};3 z=Sdb&&R)`eE8=JI(UtP48LvAX%s9Hg0{1&Q?RS&VoIHXJ@+I?tj1PVc?;Uu~h7N-Z zEvveZf$-2mhU?Iux+rHq|rNJx64OgMvV5GTVs`?8VtG+}S% z%tZ8B;>n=&o;7Fz{Kw6UF$=A)mdEBJ7RO)4<{QTkf3XQWEW+74h~JKMH0l=Dt)>{L z)4XZ9GDUeyHx1TQdmrB}V;^V|we1BLMG-a6QCUpBjC$bb3c*`M&MH9`Z!Qc51b*Ss&0?-nKa9RDS^ry=1gQR@ zER7!NUY{RjCbElNEaaN>jxs5;|Ki_& zZaT>Un!S83xhXuj(UBIr(Uq9+HJ3?B_z1yA#JrDAg!IP$IB4R83QAW+1XRd5#MZAj z2!>8d6387$RC8h;31c_vKCyzf{W$yKEgV;0o6vXy8dRU@ixRbDRx?7$Smr{nnKW{s zUB7xnfu=}xhYIqhqEc*zJCK(<*XEZ-cMzism@5p>??bY1C8_jz*9v95KGn;u?S5IG z1fyun-=4c6Ir%Gr#Qe7mgFbBb)q$}oOj?HO4o?TpYQ2BB=};L!JLZG7=%g< zh-L`?HG0-B7nBdw!F&SnjqD7dnGm#E3nJ|X%r zw~4$qqyKoYM&o4PXr+wwz-ZZU9D=DGz**^p+^#&CGtl%~cXqhrB#b`epy0?(aqz*X zAo75U-pbS^S=NZe@Kqb}r>qZteVp?45Ub+eItrO-apj_0tA!PZp6QxKRAvfia(+=% zlx}=MZ7s3t^tG|KjI4zFLep2fTO@_mJbPps4JTH| z1TOZFz_~YmR>jy-ot`75kjz?DT&p>a_{0baBA=0$mJaH5p2lVJwQ(GU8|}HeO1xV; zeN~O7#ja86PnzV6I*(L}hhyEo%?#d(M*{;wJAGeMQLuo|&IRtE6V%YnD3uTl(d8C2$A~53ye=U|Gfjr7>z}ovX6}{>CmuDZXw? z!&P0$hS^2pof>uwDcOw8OTRvVA7%Q06h1zqZ)F zce6ofaA`sB{wK`OqTx3murq4#PkW9wa@o zqj6v~BYcWO5@L;zCeKQor~neKNYJ3qj$VWiEWt63{VQ_Ar7wnZ4f5!qhEm~^X#u|)VoNu^UjtsxMf z&e&zU+S@{Q!u6WMI3+-Qxy%SHRj6N!I?#KhPSfjjILmVZ!4H+ca!Vf&I04zuPZ|x; z^_lms1ZF&G*ASBqYx*|spY@qw2D|l{qJ;m>K461hRXzDjvcH>BpWaC#DluDQBzpP) z6BK;R`dU*S$ULKatyi8MzH!>bU^Rsm`eJ>mhg$~1{$^7dvt?yoZ&8^VbcJa(wGRB}S$L*#@KKg)jJXh7umWNMYND3#v) zDvc8@ZFN#IGErhHEilCh8*W$yLD8bwnl}}*qc?<2<-`X&K#}RNsQ2-DvZ(+37Tl|N z5^6@{U{A<~(|4FO*?ivgm!`~`qu2dW zSe_oO!^%cu_ty=EXD#v{3iSfT;FLR@6UmJNcXcZaMKA*wY+$(w)pJNi$qqDPhH3)< z<%1gKO;ISK0rGyAi6Z%)JumHU{s59yq*5x?PK`n`JpDv!Q%eT5z$3h!WPTbt=79~Aq#?3n zc{=c$b@Un^Du@x%47YQ$_vfqcg2%k~xhe-Xw{~O@@FDZ9F8%D%^z-iK^7OOgjMj~= z5W29@Z1~qJAPs~lL=9M(bJPE|DYnLr7N8a`+7}4ar{`7F&y~T57NZOwr-v9%qs#9m7&`Zd0C-;>*_})84zgF_jnqq2bPcsF&>6kK2hPoe1L3{L^+B}@hhdzKi+7J6Pj$tr{hD=Kd^U)OhIwx3FL*sINDZx$!?~l08x9H+N-=d5A*k-@- z;Ic?d8s5t{(5KZ#OxUOSe@5@KLf&QNI+k&2XlH-bg$ipt*M%xTcMSE4=J`aSA(tK3 zg`&iN#oC}O8ZB^!VsqQ!5Bwaot}sCrIl&=MI8`B)gH@zKtjfrx6z`QGLWE=_g)6E% zp}j&Q6Qbr%L4oX>Nr%%C#RxZ6RM|lTD$s;v?=h0z-t`*6DuR3){xzjIDL2*&1U)Gn zsKW@=7FvRaDiy0iwh(kB#deT8C_C1}Gt&h8jy(<4S|7hq$6Fsi07;9k3;qtwoL=kZ zPbzlL{>-n2poAJ#Y5=2k1PDTA&-aTu^Z8{XZuE|L^7wDg#tdf+lp+47)5Yt2=W>j= zNZn|R@rM+FtJilUKctd4>^S)CHIDlN=Uj5nZLiaZ0%^c(4@Eru zNF9wiPYCj~Cr=18z1?@gqHhpH{cY8vSZZ!N{#a^&=bMi2YA)FE_V?Al<899#4~{vI z4xau5^>;QGFld!>j__9yu-9sHyFF(Mo4T<6Ouz@>FwfT!pNQip*Z%~_{Q4Fk^XprH z*M)BZFr|^p(s?(VbQ4UQ53Zg2Z?EBz4m|FmpwYnJ0>Dp8PBvNlUjxB+Sv-OSbpHV~ z_|QfDtwuaAWl&-yg+Ra0zeDNQ!kS%%ra`wKK>kB@2^``-REbFbL-ic={To$el>bl_ z5dIIWan#<$%~ zGsd_7v6|IN@E@xahyS5Esq@(XXOk0AoE|SwEyAzwz|fA~gT*{oA0bwZC3u1cH)iyc zl%mDFgZd5n#?2U=c~vNMge=o7;p2ngSqGunJ!Ol$fvtY#OtXdggI@gG`J8ftv8Y1A zvA7eW1v>$sC7(|^?C794+*U%t(6dJu!**0|voaLa{MeHNx&22g{G@O4Dv!k(C1R&j zGb`d;yVJt<3DlO4F2^056i|;OP)L@biTB~EtAVFHbnMghOUA*+QByhS$>i=H)!dQ( z#=r9^=#c*B(R<9_9zAIA?a}&8e0ugRY4=lp0A$^NIK$}IkTIw?uhm>ZG>%xrUf8-r zdHLgcG!cy7mW`$RKgTA3W@x+LXZTG%qPYdnFQD%S&;S3}I>+Elf_Lpln`~^`cCyLF z*x0sh8&B+wZQFL9*tTuk*^~c!&U-$c55J!2shX*&sp{(P`@ZgLKEu1NretVlpL5+( z$0e0C%}A)Fmnqm8^~ozJ;Y&helPa@Yiy{Q!VKsl958r<`{xI6V&V?Uzf1QKEY95^S zc5Fxe1Pq$M%TUrbg}aN>t}dL>Cnpg2^cymt-f~oDd^mK&67F5S=Y2#j-?iwqY;|rd zHQQ6Hz{VVL3{>S}{2mZa5#<^qes<*^V0{;b8_3c%QBJGAD_&b#oZ6LWW9Q6oQ%2WW zb|!e8^`0gDR!)AfeeQ1V`DsaR+<^m;>-Fj60QnT%>ar@Iy~4zGCts(e$xvCou;JFs zk&Q~1^g|`c$s`+HCx5cV2bj<)ZC?#O>&2p1ykA{37TPWm@Jlj(=Dpjj3ZBJ1vJomW z(#(!xR7Fj)-W1s$kPpt}gwlQ&%OCHA12Evfr4hNjby^T|5pEgY;^z^E-hVVHd5Wp# z09*qpQ?9nHa>j+v$8`BiZt>)4YTuf7%%RHs8?$(oM%oPx5pDXbfi$Yk$aPn` ze)s~x>MJ#iGX}2y@d(cFF|&Row5}(K@6;1niD9)3n4|D?#dMU^MQRqW^CVk$l-fmm z9A}aJ=KL$pJ48c_{LfNm0Ul>YR6*A6G{@TC`>|hZMNT8^YjF)@Y>{GSC_Tr3M3d_B z#-7ir#a2s8_C7G0nvHu%~F4 zitgH*U#O#uO2{a#k7HF<{d$EM8=_odT7BuoA|n*}@=OzkMTiZ?H%RvSW0o)L9CMPg zd}NULH8LJAP2ORg9x{#HgSl)87!zeF%-Zx77|8Zkm@Yg9P_Za>lNEIaJ;xp7Psg)O zH_?u|EPFHSFjXRoaTkHBznO$IzI<93*V$uiN!v*d$pJ9l_(Fy545!@NwiE?#A|$yA z3J&qKp*7$4k4K2!dd*H7zp{tR3GchUQ`o@6Ib5iK5zP5=&BvRDww_VI=jpJM7#!d| zk#!ai%b5F9#!2t~ZKfhi{3GQ%QA9QsZ>W`Xm0`OEH!d0f=IBM9J`Ve8L3&+8pd)zB z@tKBc_h(W2mkK#ynRRCXZeiye_iLq(s-PJIMQ=+^FE^b6w-6e-?PSnc;+%foLyXJr5)baSv>UC))0Wa@6H zrK;TvLM(-$f!Nn1Zh4l~I$F1PwAGVtk4fV+fMxBTn(gfkPKvD`C$e|xe(16;8J6f% z_c_YwQ%@Cl!AM<{l7oT;fz_SqWouRI6!%2RkfA`xPFTfue6F0h|Dj94#>MFo{T&`s>RmYSY%98@U`o`E$s=u`0427?ZMlneQd z&0rg?bl);LO54Btv(18mMK-xnW4{o9!8Wzt?YggY3PV+A+XFWmg;o7DG4A37E;a78 zeQHbvV``K;l6te=mfP>&weTC||D5;;&wJM^^j!MI={Et* z?LB06P_{de5RQ0$uzv%jW!sFz3y!793KPI0H6deOt*$gk)cKH>cY)l(*>`s~t8=er zwajzxl(V7leMXq)gzdV*>hVUXA^P_09s<%zZ@Xa0WcY+JDOR$lt+Z$zbwg~NA z%4pub^tc7pJYqFpjY*d`yxwlw~le&grVFSc` z-e}Mw!xOY76Q>i}%p*?J2wj)B@|U5-h%E=Y-pD=#Q2*r4g842EGD(*`k2<}Cnh1S% z5#V^QNv|81m$`o_yGNx@BBZUXV4>biWEQ&e^+f!Dd&albpf-MD~Ah6 zg^G%*{}+p@MSy~FN(?_i_+u^=&tPuwPv|fCn3bpi2*gPOqc)MY7YDxjjc6@a*aWMC zH|QJ%qM6%!-b5|D1k7X7zb=NL4NUIE7QH-HlP4tP7z zO;ibNyqoR`u6p)s*%t05jK;aum=p=+n0(6f-@@WqZXPi|hldLUhlUpPav9ICJi9t30!n5B51j(80<%thqUC9HJ~(zJx;6x76)It z(vp4oGfy@gtjtx|SpGUWTKP74yy&P3QC-DuRQhbI9az@NpK%mvp=*~|kKvOQFQeg3Gdbn+28$(O-fQ#DkcSow4Ofkb zbmjBLx|0@|Q-Til7@wkW7NFH54C;KBRSZl&?Sok>>|FpsA`!INYB65?>IHGEwB8t{ zc^)EtR(eYQj>|k0!B)SN7t%)x_J90Ep!n5PUM;s$UWq=mu-fVXf;oq4PTn3UPfK}Y zuHSQ%9HH~GcqG?EpEbe=d8O}22dueux6Q$jD#2iOmDPPEzQJq-_`?jAw*$T2d`U}W z3`}!LEY}%ekF&3SRy>?1pkZy`P*{gPl`*W!?;bzqpk#(ZM6r)au;pauN$g7=qfga2C)yT0c!-daV;BeJmsu0LQ`w?o$< zl5o|?zBDMjq^zQOO!=I*q3z}PK6=??NgJBH6B^`qX-0$NJ0e z_5Kj>=A7T&UFQ>b5|=^t`_(a!3W1d^fK%0pCEzEN#>KWQx5%tQ=CLQltTV*PyaxB$ zdVOUr1hY0}G(_)3bR)db%Oo7MpszZKKg~H77{#-6Wkzv@qM!3~Yh6x$Y&zw6Kl{}c z9R1$pCZ-94@nAiF7x|;->1aCeXl{Burk(=eQ@`mxVb5} zEixz51#-aQN_;Rcz2L>#BKEr1tgbSgv`Do%B6}2@*R!54cV#S0JZ$bQrD})vkZA*G zj}3_0kI0!p$Y-iO*Y~AMzdRAeLL>o|Q8b*6?53X=Gpw@0qpIO_SqWBH5D-X*XQ4pZ z&-fbc`K~zcVmI z>o$7|$FYZStb44*<_d!u4Q#wJRV4+CL%vds3LgB}8u*^sozIX)yB8ET-)`%RN}*=s zP!b)j8~}8=KVw6O|KYXoJ@~CUZ;mq5zqXf!R=51(0raNjCi8qP!BIYQdJ!B5*<-sz z2;zo{CX43FI19lqc?IaBHn{myssNW1jR8s=LIbyBfutv4e2!BI2E zPGt@5+wU0aKHz~h&EL7%wj37f0q>i-{1W;q@%8RWH}+9A%G4tRt}sh@;zYzgd33$h zPJlLrYrKE_z0MYn`-}x>SIC{_(zuW4rnA^y2@M(nXmR7tQre=$+{9=fs!xU+r3*O` zNF>fEFn!{UTP#vc1F_F2=R+b%M|-CB{mHg7!wGAq24d`{2V$<>KTaANO;N)GoS=mp zdJK$v42=QfBYc4e-Um=tKkrJ8j5u_&LUCiUR4h2#PSeMvH-!L1@4t#Fjco;lQ`q)r zqQU7e^$Hiq0cB|!5`6F|vBif=s z?auDWuk_&e+>l4la1(@Bsr)QV07Lz+D1$jQs;}TGg&9|MpTG(QZ}2Jw?Z#W8|QBT6Z=r^OlON8aH3sYF}?i@O{JZ4Z*!y>Cr2#`T2*|*wSlD?KdOe9M4gFK1r_? zZf8qmJZOdV-LIR$P6K+cSznhq;3m}IChV|Nx0#uG%=Ev2zz;y2|0^o^y&2Cvt~3Ej z4XO`p6{?Sz2IU)q>NnrV=)99pgl*gZn5K#GZLYSg3W+Mrin76aeuSf-v~%8Bb+ z=zA~kz7K*NrXI1P`0Ko~1E?|OJ8-(B4?k&gex|~B!kh0)-ZX$$&>Tr$V99sirRKje zg5=+!T>a-qgW>Ck0n4xWOMzK8bRS`oYVd1NW3y(jO0jC=$4`_0Td`U^X!05EiXl5_jrRi=5xPM53>k$vcT z3uY;)Oe`y2DhuS{SRYX;zY*cA!_zYb1e(znZJ?QUSiK16?BXH%7_jmssl`Kx)`(|b?NGQf#e^x1~~W_j*JJF!?V@44>s_bLMO+gyu2 z`gz6v0u)n1abYl)Y-xG~{a!GuVJU8Vk}pmKP)t{1q|s&X)AR_-q4uxl-=%%~6{Nn! z>L3&7f}4-58W)ZmFgQw-Z0n0C>^cNkj4fD+#jmJW*p>gr_OL?sJjL z-2RQ4U3*yyMP7jhMVuk8H(*q69FomxICdo9A$3<$d1^Upu-79=m|R@C##xT`*joh< z-3N8y&YuUL39pxsATK&6l+ai>8nM)jBH*X&B@-3271?9jCwiJ zV7e(YZg?i9IeClud5x_mR8DQ9pH<%Tn}m^M-y?(p=Dc|J8@gLD2X|dh1aHQxPrWv* zw)S`sp`t~^LRSzF;F%Wt{k;Zp*WLgjs4?L4q_2Ly(^}2czOPsKIHq>|`vKMly9px^ zqGC&ukUh)KO)r^zB->ZfBe&7d2s_&k*@!;d|EY0oufw-z{J`>1m>}eIiyeLd`&`T6 z1U_vER#g}s46=F97<4&&ofuiz@Hv2dpgaIQslS6gfyLQot=8zvH69Hrg8+@zLQjjF zh{bNe=rpFb`o!}o2Or9ibm%~oek$p3-U;_?5ma2_-?Q^c%U2NG2WuA9!h={;w7A|_?~ zlQ)t_&H0&pM1v~uAcw{ca%8T+L--~p&oUFXc8Ftdz`^jRZ{c_;Dsc&vVPfJT4P9ES&*%k-2} zK%YI_BI4wt(ozH$CZax*aM$od?(a#K=pO?qYIHva)JX}ixni)?E&;2os}cL899RR+ z2cY-hOq-73?WQ!iptc{6PcWR_-Fdqm1UorQc*wtnqTKF=m2cqE{{e(BWyJo3Jbz%?%{osEciUYIWSbRNfP}ibIXeR~LI7y^t(EQw z;|~WhUHTs2Ie(}%n=COt5wiXAjLh^L{0&s+)p#_-mX8F{o5OZ2egFnB3Cj2$!QbdO z|BU&JOSw_lBK?C#3EirT34NwCNvJNL_^pfE zJd2Y?3_b*}SvCMBlz39BJua}lxD2H5w@jSkhH0&bP-6TIC7_hzDi5{HXvf#7KU!Q4xN$CMWg@+!M_a zFaNC~7f+^P5Jid@XeS4y#Is8NM@}7DfZzu8;=C~E^!;hWpN-j%pAs5`C3o>>v()c1 zj?&<1W6YC~iAL!SI%@m@Fd$xd{1^iXX(E^60Uh7! zvf2Qk=PY3CnUgKcH;?I}u}{D*WeYKe{3;~IZHpo_fTk%uxOBl%zGU7tzPT!PSINu| zEwo(BYQ^&k^puyl9O>3_x+VYPO#|sHM$e||oPX>Ojci70O?`vQZN^E{lxgpd^SL;#C8+9D$xfr-r~PUSRq6NRmvZ6~3@Bb<)2?WG+FsijRrf?{4SAP?0q7b&sGWEV+}incY7 z(TDLv=B~+_1f%(X{7%=+_-%g+VS6O2AGZM$m5(LuI#*YxX&KlWMfFzK@ls0h>;JSJ zm?fwZFcJzqW_s1`vAlY=ct&GL5^WHYcWgF}L(P!!W23dMb--m)7GypJqqIF-5>|ZPzXF>p;75S8xh42}*y=d8 z%!^v-Su8qolK#@~F)SoZubw#4BO#ol4O;R{RZspcP;aC!R(N!~vxVZrxDIrI5E+#_n0L)o%ZWku*XG!A!=8V zIm#Ay@|bD8Wr-tY#)=SC0VU*;$zg}}vhktW;or_yUN~lo#SpCtG>4dP@6B1aI;me- z#IprfsuauLE`{W3tU(S@Kf7yp+6XdnBH$EWsG<=5NOxRqMcNxw19%tx|4fhEbdss) zNLmFCB%;&}BSYyrX*#oiDaz*o7I*eG@F;xaLXc?$gEjaW4blg8+o#tvq_Qq#4&GP! z{&X$d1Ys2g?&*Y+kH+wuy9!J9;qFAZj$l^MD$eFjc3x`AC1GCsiwBAInfZU|xtF#Z(i}(iZk+9^!U|M|80{e`b|`qd#Z$Kon{QydQQE<@K*cCEBQqcV72Ag*9CiKOa5Jvu5i)BX{249!(=kd#aim#lK)D@0Ae+i zi0-1w$=A59$Z)Hn0wTK>fTwb|$QRNZMc?9|A3bX)-EA=hxt*C&;&Xph3Ks&l~* zXg752?aOSo#i00Hc4G8rA07o7_Kmutom${Hu6{YxIqCTc!E0lm)+@(i-Cr^mQ9h64&R8#iPGwv1E zRA+-HI?G$!lI~=%=IY)**R$5(4b^)EqKdM-m&j3t`R*_Yi35TO#eIEdyFKny%J z&jVcu6pv-lUol`b>@cBXNC(44se@Ri5eYl4__<-d=fH6?Va9|v{J$U#1utvW3LR{_ zVCb7+QaCZD+ANkrY?UI@^_`<6eZ$1weN%`^Sp~O^y^w+Fc#+CDqIf1p{URHPL0km* z32LsKV0FC-ajxiqN0784O|HKBY#|05^Xq%Zp~ByJyHS+nt$*d_Zag%a`|)#N^tNv( zzE!Q_^W&r#h^_=~n%%>J*Nf;U3_AYT)95c#czbsvu@K8T#&85^m@P+MN$VH82Praar35;93|O6i9hJq3O|BbS65~=nivLxsBQSw|7@t}q zO7U{rPyG@(Z?=hDip{`8Z4cLa ztH~Is*`5TrxmmAOMG2qmOlAMUv)BoPzy5H$*?0E~s?f4eTSl+_*$JNFO|t#+GrQs? z7Rn>mOIXcd|H&>_3slX&pb?_k=&*R5`Jj;efr;2nqq5J;;c%l&iZIQi?4XLFpJ+7O z5f9lg|!D+ktZT?rN{wyrJ)4&7cCZ$NCG ziwmjl9Fv4+`&lD_P|{$Z00(TvYakOzTmF3xJc_Y#kua6BevHSHSn{iN7h>95TxR5O zdl=S6&4LUe(k-LLGrh;O>(}Vbt6gOW6|?Nepnz4aHTICc(YO=BOA{eB5YaCfdEgC8 zC@BKC1DkgW5+0*xN44CgS$wI3HpVVe1+t*s;3_(h`!UqoIinTcq5ANJTjbWeT+Jak zUFLTyF74bQL|!6p;nx~eFRfb0RPd8sVoRp@7~k8x566@Z#gCWCReMfq$z+6oiA-nv zxtI^M3qZL+P4EP6O~-V+f2AxspBUkgdfxyNV_1bEPYKO7tZN{0h!(G@oQKLXv>e11 zma#Wj1dE+j<2DoSQtjown(6LQWPY!aY<6!PlFM4*I-EeY%dT>&AzxuGd1T!&)39zY zgMRzTD!LwZ9*Gb9L*iv@*NpIc7Fqwfq55lmytMA^l=YjOLbm^ErW$=LS{5u4Nq^R!OMA4$mEcRZVqT5C;(bc{J=#LtyM8 z*<9XG@oq~{gOt1H_7aprtXX-@z-~f=Kzf(;xkV6d;Afiga{-OqfRlV^z=|=T+RD<* z#{AVW)_}!F3UgHX(!3}meEByxR5o?fU`r}iQ_-AFP2*s&4ooe94l2A4Jm`s{A3B8P zDjX=+sCh@pJ_wz=D@k55lri!Rdq>d{@xFz$;8=tvL_qO9IrRw=q!i(xA)yamH!1VU z6-aG}F3gi5tR-qH06s-V-&YI3mq{_x!eu*nxsF>hLbN=G=X8qE>{3g0Db~Vd@t2z^ zOxCL4Z`k(RHI-EG&q|bFh(_L{>`s`+P|P_z+m&f!m(kr05Yj zgAvLnSB+MC(cj7Fw7CULCHfLo-dlRRO4sqC)%1(>s4SP8!DcM=sYFS@2P`{k;DRPC zvo!q#-i)X;5;hAEJ_wv4%*9?1oCzMmoK1lYkA)sz!Co9ZqsU395vgcAq6DmY6lMiy zy+07~va+ljUsaPjv~(!JBbkl%=z$Jf1v|cmyOqp*14l?=E|2pISa;66a69V8kqf+8_>W$v$dF%X!4R!p;m`VPcXe zEc)P-t$Y(<_D1?hFLuj31?7`G-4!U?(2x=?u&vOwpA^zb$Z%7OB0w&cB(BQry!}~S z&8mOva_`~*aIt(!G{}`3<`Wu>9iA^P1mI6MbWm<}jM|hHHjO_3MdRqiAng09mA^g@ z9>H>IBuZg6+1_ioZEOx#g0Mf&X=7pgz}ey{6_X*_PW?oAE3o_;$|^Vo=F_dP2#Pcf zG`ybXV+N0Fo@=*Rk{>l28wJL0Ys4Glj)~?0$cD^61S=j>z1dPC`9s^g z)0O&DHprTg6RO+Q3FksLEJ57Fso2b$-f>H2ujcrZ4(O6UM;dw^IcSi*Q!A+BA7?LIaw%hqN{SQb$*m zsyufvQRt4jhzyexN9rmZnBW)ta<005>~Qf>q`80YZgIToH1WeWZA1+qDnSrefGS)Q zdh(XpF-I?ceF)8{>To21pH;*Es2L?Rz&_86NPy$o2JEp3FUx$cDKcP1VvEw!)b{Tt zvQ=gWp2Sij-^yi}Eu3(Cg_Xx}u9M-9{fBlOE(y8M5XL)>8K|7%#sjeD3R{iP ztJpB!ANLcRW4AaIAI*@tdZu!+_zoglPJ;^Fchu+^u{}2Hd8R98$*mh4VlK>ua(m(% zh7S$4QWRk9zolfXuIl@8=_FL-wIo08?`Zcv0p<_FR#>$-75X>JqUbp_#ni7n&Elit z-l`>`Pn2oi>>bHdYF4NS_!*@}9F}MJ?M>3dOrv0r(Vn4n?xGmvg+fJB^NINRxk(v+ zO8*%4vk)c?Lc6pstCR8nM=0iajQ_O)FY_ftM&eqq$mMoRj)ejnUUaqzsQ34pk09@A% zF@ay&(;6mwS&di`NK2ix0F+O&gxI%|;oHP3s zpD`&UQbupdUfog~C(-KQ3G*v0Kxx!I!bM)fKq)>PgadJJ1jVjyGF&s<@wcK{$W!lh zL#00*CY|$69wGzM21e%`i)^VW%wVq;LAEp*iU!qK6Qh5SjyB@!F#;VS)VURzHsbBJ z5OO+Q06U_%!^>SGMp?28rHR_jV{+LLd_?;#)c{+wF-d=$Onk&+*4D-u5Ka&Yl2C0R z;XIOM)V)|ZA>@m|JvPqC8O!D})u*~@Uy(V?hfURP<-94gtO}%R$~y9Twowor6$>D* zbK0R{2v8nsb4Jic`L!PfHfbs^@0S55cE$kHBDGLXom!jJo;5`7DpQqhH9;Y4N&L}3 ztb9YeN}OtZS=1J2%*9av=(s!^kV**_@*9=;w{Jfke58anq>$xzJ*6`3B=`-0|e?c~| z*Hc(Vvolb2Hn4kExX>0}Wo2tHNs}Z^F^wwk)`9HJCfZB8B89F4qOP3DZVu*CCzBz0 zP>-YR)s77Cg5TJo&7w@Dh<`T5&LB*g%cyE*#*eKcGkO=&xfwiM{JqBFOSr1z&~*7F z|5`a-=Z2qf?{Xy<|2o9W3L8uu&FtfDZU(-Y)`{v~U?g%r3O9vTMZwA~-;K=fDuILV7t*=4$9+NffKjeTuzMbS%EW$Y}XXFR35_CT4gyAyjpI1 zXCx>^y6??8lYcx2H zbOYzNm+cu`KN`Z%nW&wxAM+pBVi)SLF)N0uqDSg7A*-HCfImCxlR>lbOCoFbz~GJY zn~)wO`wfgks}nDw;EnW7I4?Q(Sk3qn;%f+0N7_EztLR<_t+<-JD`<2_+B=pB-d#aU zk?fFGROywfpD3H7DCljQsbUWGhd^8EklA!==-Raq2W1K`n29AMj$yD`wGp_)K`(oF z9H8w!=O~CCAWs#0Ep@9FHIy|iT>B7!dVgSZt!gP}xqDvxq=k%)4h zI6F8sJ?@q+;Kq*6`*e8YiBgd9B+~AvlM~hfcPxkyfUt)@kOmP8YQggp^t&u_qK>gY zppy(6l&jFjGnap@=%2zT*q~Heal;O?iwHhbh|3It>s`NjbISCOJd1fJV44|+g)VYV zkXvDSUzgfg&5zp`d=Ds$UyuG@aepFH2n*!JLSroz&eEFPP?ku~{b#B@DW|194yw}e zJE)wG0q^U-(x8s)g1iJIn*SwTl=FB}Gz}I)fz^fjiqQs42K@}db9GDbL>tj}1r^4- z$tn(G!P;_*pbGERDGgJc*=27IEJ(`hYBx;056705ZckrZ;j~1%3*w)-)Va`DW-3y=@;4 zW;d5#Qugon!!APLD^j~ zAZmnhyPJqzzks+5zWy|IKBC`L-a@3&a^WOsR$twG(2VPX6_&i!6*cS&0P>DLP(AtLx%2nVA-OC&@1Q>!FLXV6Diz@Yd?OlJqE zH3GI+Kp$~aM62C9F?79BFW>SDutN*(;E26w)SP}KnB3VGWoOcfb|RJe{X$;x-?g`@8$wjLaXM} zi`vDAl>CTdJ|@(uQ(X<9kZ+WfIz|Gcc)_?(tYnd6JV3cTG&F}!)?PgTSIoBdP_Vq> zOdlhq7Y}o^`UxA3gHMY|eK1aa(8wMT^dn}sFbY1fY~Hw6aFfD8_kt^WkpdKt!b9Zj za#`*KFXx7u@83t*)NM|WwtrPo2JCOPlxpIi`y{K@l7Pqa(vcBZ7q=V}g^xJ^|OIuz_Tex z+$y>NFXJ4(GYkQL$7BY*UO?^=~4`H)!fnne5&xCU)==0EOH&D7k(L zB_uJooRDM-n@lgDg&Oi5>CL1AZ-#MW{FVst&mI0_#^{$4&i-|G`VG6pyuNmgZde({ z9?CM=^wr5Mks&!&p$e3m8 zX~>NJMq3Ee)BELw>Q7bHUa_T$(s-JUq5~-cf6|{^x$mNYXb+i>o3u%yN@CKq>2fsd zEz5ZL(F*WKlR(aCZzLQ9t7S#(XgjreYnBaWCV?dFQF}JpIty!sJBbn$4o5&|@=MRne zS~F1CA2v*mx>6={#5KE;{f^Ug7X+b~_bs?+@VTu3p)Z~6A@h7#7)$2^8SXGL=xqqK z9;5l0V~HSX#X^JlraZb0RNm(Mp>J<70i$&EQ6TNv$^doKip!@i5?-_3=vD6yPZ2$r zX|M|!JM?(WO<)PF`$-FP7LCs2;o4q{3KdHXFpk&9U^5TsA;sEno{hh z-$sytX6K{K-K2~Br!gp?n$0|Tk9A77id+IMg{U(IPqE$>Xu+;wGPo#f$6mmU^Cu9L zl6!<$w@k_8tF?hA5>6rnVpb@ERx$7q z&1sD2gWj9^D+xJ*>_& z-S&!`{ke!f{$}-ro<(vw!*u`lwYkwh60${16uvBx$CamND9iB=%(syxa*_<)ZDbBs zPO}1rbSH-lhS83rl$78%Gsd#?1eVr+Z#O4dA9+r@KCTtC_C1?nJ7TViIZdi zKfiE+-49MZ%$h&y{Dm$QW9e}bTErKS47Mh<*uyL0H{>7tpUHOORJ`ha1nWt|a-UjB zW}~PdiHM1n6FKq9gQj{oDCI$G2KpIHw$a1S^?6HqK?Tn&8q7MIc>6II({>-z>nE`Q zQk6KfBv(~$T}Y?{XMxlpbh-e@Y9eWXPa{qwZJ&Rk2#~>O6a2cU5B)ez+YiZtfEP+7 zE5-5YrgKi2jIIFO#m4XsL!Nf;lGVXqzd^)yReHKHw=NK&mD9{lJ&JIq_#-rFskQBwv zng@>x_8#}9#Id~iPKZFh$pkY-MRkArSIeS6<2e2({DF$VVl&3&aQ+FY!_r9HwJ&!L zl0$vX)UfPUpHX}qt0WMz=hz4!xA%}4Y*%tVElz0sd$G3xh8PO;cyBsqx)e+dMO8*3 zfQ@ILgY$^-*cvjEZ)A!dh;5ZSM#|+Ir!WyK!uh=;J7V8}j>X>j>>jgUX71dW64 zUmVU<=0ASC%;*eD?-VKYTgc-*)Ja&9h>Nf3*cMk-+ZNwUOiOLO1t3q@|u=Xb003n<0Mbiitl}l4^Q>+Jq*bb85RHj1T*T0P((?#6y%ptt`n4*{tNMg zx`-VX!e(Z%TZ~zsvIP&25aE=B3ckb&Lo8Nd7ApX+GA*!4Sd#6p3$HjW0KYyPJR&n3 z>W@d1Ee26QPBMJpXzmVa`-=>^-YGt(;ox|WAgaIfzNJAyePUs|ivv4WgLTAdzbmeI z9fcgN29DHl2fUmP(pNvj1PJwH5gLW6tb*%lTn2YX_;=+lN9z`#d>{NCt4ViLUyV(J zuZ;0KvJdEX;%|G;N?~r7FTD@qjJz%x(g`G?l1L972{!+I6X8$O{7 zzGiWlJaEG2%xb)fD@!b{Miw%7C^*pHj|ODo6>8MgW7f1&|q0Ongqw|wiOPg%!KqVeG zFC*=X=5;Upt3K<2MAU4!-!L`lNo^K&gD?SIWU+me%yvTi(D~{I~31waR+V; zJ`>q_h|(q*pp!6QHhYh1JKd~wml8Cs>pH&Bz4{8UXmh%)_!f*`IgaRNMG|y=9Ytv@ zJ}adW?#^3rKGaer{k*7ugDrmv2dLSQ4SK9puv+;YaHRekj^EMNq>)Jjn zZa`#c)$3ym_u+IR7~1G}ke3u%3y-7wmFl1&);2t!j!Kyt0}gkbu+*^ky>1H#kL47P zrcnk=-W3Z|N!3sHDSO$AQp``rEQYewoGW)gDg7sf&HLnsi8G9Z3HCGFz1}Yxfy`4B zc<7(DFld(ECIIU$Ak`!cpC79#K@>Rpdx%jYF{RN1jcUajoD0l8i(?iPv}Kg3Lb%er z3NpE?qCMBPSKFD|1+pMT@v5(*WN0r*br8V6fcqC3+i5k8`f0uT(*LAH0+9iFN{NqI{_459E0@kYLRbvha-48&Y z$o9vJeB;fXObv2~JEkT;UEInL&hLSr4-!0^<>*tJy&nI#{KWm<_e6#D+tma2IsnQn zQ{7U{IRu2)b_0;ldI@hg|9r;AmusUWJ|xy5b!KY^%X3P>=Jtg4_0#16qXozIDe+>} zhtF+KG$$@QR8_74AyrO3Qv=|}G#E+C;U5(R;CL#6lCe-P9RZUPyAZZXi8Y@XIygaGr5Q4 z785YfUl6nIT)^$hfhHkLbFK$bf9)KHBJ;6b-5ujg5VJ4sVNSqa6biI4R>x8Jq2j#x z$!x(fd9~&Y0Y4VV;1w{HJE@YN_Oh7Cg4EnVo%#7 zN{>&o_RFlFaTCEgE>No5A^2@)K^u8D9>xGr+uY{dJrk0x&n?p#ux%qW>?qI{}cIELD42O#pr5A@c zxzeuRo*#!yv4E9@-(=4E2f$vsAV=6<25YE}znblFs0sG`1nGqi9})8OuZ@Mp3i~o~ zWv7D$hWqBciX}T<)_wN`tdJP@O7oxF7gh>-QZMS~Hi!}Y-r-F-51axG(;qRq;q=J) zF4n&flIiHOr&s1Ja-fu?r38)fP>84Le4aR(9#*fVr_C6_^QL{pgaD-NFtYl$pKM{b4tTtE&(i0v;-E~O2 za07D6B^CYHVJ1|6@0H)MUFZ>~%59G;TnBEC$guf;+am}MUA4JC?~@@?fBpst>oQiS zw>nQZiDq4G@Y!>|Qn$K_F!7_P%%30Pc0)GPV_M|H(Vt}mnlLZnb#v5Ch)rwDg z)E9%qx3c9{FtkH+DwSZBUSUDVXX-^mc3^Y=u08$$5v5iW&T_QVS>;r6jD)TNIm4*l zC^gtiu`imrbRbt4&Sp>SjR_;;<9dKKj2OpJBeoR#AJ<0UgB`CyC+%p0Ty-vq0X9C5 zLWIOLgn0?xEdcvf%a+sadMk32YFbIrRO^F95%DCIF4RnD_t6XrE6+T~B=yqAcZTdq z{7A!PDxbqQsaOVg!2`dzn=W=`>?);!w)~wh>Mx}~0=yiIli8m+T?GMM=@^h`Zx^vM zBmoGt%es$MqtB}byKG=WKzk{Q&;95QwUCi`#x9?t|LXxxf)DAVolLrj1gK3k{|qK(=; z^^r$78q?|Vr#UhxelNr+U*UO8~Zv9oqbEd+G09N>?C_q&Nwtji}Y%@{R=W;V#> z+$W1Y;9LWoPazpTG1-iBF~XaHCe0Ls<%&kvuM*3rjk8W_C^FaW$~`#MVp zk_jOGcR;ErESBfUERm04frA>v$?^sSOX!lIfbM_E8v<_C>=01jYC3rO@YlZuyE54y z>R`7=`i#>=2wzs?L5ws~&6k!>zbAiPM_SUL9F`Fy~P*Ma`X6Kk? z_!>lXh*UX8Zn7$TB0-%$lguf4vvXd(6jHS{$FRy)ID|c^Sa-_XS++eIu=^(0foi*R1(*RY7f%B5=8C4G`EU8!x3>7*wZ&iKqkDga_hv$YOH%)hu1XfS{C z@=)tV+jQL||(?xnk=`O5dXV(8Zh z8Kt%Gz5Y5g%@gTNv`D1Fb4KkP@?wwDht^@rO}b7o*?!J|Z|HOid!!wtJWhY-3^Q*d zeK>;@yC7FW#=DA?Nw-EauSdO<8fEII9N{lYdcvTCrh^nT@H{Az=sCpzZZaHbe(nqh zx^`I|^shLn#b9DV;Z!n>wzbJ_j`1!3^@E%tnK$G^XecHmz{x87u3Avwxw(X#WLVGA z8f6p;&8db}*wAw4qHBOQxv^Yi^@ab#3kNjhqH-+mK%t0}mup}t=&<&op z6wLlQ|GWYk-9!i)qy{X&v0JcU!EOm(sOSGVE1KF}J7^(sT0sZzSV22rMD^@QoGWJs zji;I&2ex89gfHa3*vV9PirGTqC}s!mSTQ?bM8%vS$uU`+tA7WLr~ZFK4mABiZCkf5 zx2^y0pj|0A=#-{8a7@_TLPdCeXtx~N;Kxmbhc1J7?V6`2?P|3>JZrSh!FeQV9J!MW z_oMR3VkFsrZxZ(cSG4tG3C!d7giW0zRkjQ&f+W2PS(3%MYiwq9N$uDY3Q!i)H9E$X zij||^AZJVDwkI8dA4z{nt$-#@!a53F05C)Jwi|W&aYv|#Uw6#p_VbR>F~0AZ1NQ@8 z6=jl_N$sST*gjG1d@)O;oh{~xZeKo0z$F#z@H9Yh9}5mC57|0GD+%j(R{|bM)@VNh zOQih>JQ15wdAXy%ewN2UmcB&?3&S%RN}6NSE?cZVDmM>k42*x7KqFRTROUZ|98+Ut zR?REt8A|Y~D5d<;yF~ zq01(7-P#mnP#;JZxNUo|*)Bskn`tgn3U{6K0M=+?%M^b+%hg8X3JIRPB{ddyzWWUY z8amHsjB7B#2gbfFOR)wz7lqmw@kiR8uW64`-*p?i9f0#ukh9j^LqlrZeFk@JyN~L+ zY4@?+x9kzR%Z5FIcG#}_$PSzJ0M>1*9t@qFHJ1rgq-Hb4-3F+c+wo#&LK|t)o4x zJ5wpatQ<`v0;iu*fttCMM$ljv$qd!RGtwj9zBtkZ0c5ba0)~`}6%G-(i1BY>w$Fni z+$UM64&FM%CogrlONndPCu(z?%gRFKU--DjVynVSL zB4(2#D7Xh<0=fru7lwFr49{-ya1P6^MMi&weobO+G*@$E_oyWSMRGR<smqd&t z$@akgF-Fkc&sKDGA@5>CT1_G@QwrGa18`i<7MOLzEvq z@bD{vz3F*LKbQv{6f2*;cmlTh#sitUs|=Y&++>MM!XmSHsIvFG@j~L(2JJ)Y+9pTc z%&khM86&mH9_jxc+Su0fBcvfN2=MA-&UWC{w{Nl~Ec?(l40p7LOp26zu3gAEC6sVQhzy&CDX4YeD>3SPBP*3q4RY3{pd6|YJ-@jL|4>F zS~O)9P6251o-G3%DDvCq>9Dc&cQA;0eZL2aVSj@`CZj52v(==k!Gj5&7&?{^iLc8# ziBhQc_6VTJhI4tVsH}e{^;WUM&xtvq`QVF(4um{W;WMEV7YNrlI)u_EIoc3^01=eeg_&*R#(sdL#73s|G z88c!x0v}$&n96H2@aH!4C#|YSQq>48@Py-vmgkoOI!nEdiaoze-bnn7Jdu)^EOV?U z77hL*TTRpNz;Vbc)#)5X?mu6KU$%3Olbu?OL!6a7D;73T#~`*}igA)AxKs76t#h6T5vJ zsL2WD6*+2SMOY#iC3#BTuqxwqV;ehtgaEt)g&ggY0wZNhb! zq^=>UW6{MxSb-;QU*TOc(Jh$|(rU&K!?bL#$JauC-`NBM92)8itRrEO#rGse<%r2s zC=a6|a!`M}leEXB@OVIBAJ=gJu76!e0N6ITlEBNi&_`Qbhp%EpV3RZ$40)cC5WzkP zT;%qqNYEOaB=ArMJSDox)4X*4fjKJf=am##A6LNR)%!<^s?KaVt$GEFTl+1G4-Uky z(3ByH2d03Lzk*`%!GZS`ZjWJ-I{yS56}SEc1zvx}d}`{ZbZ;UAETY_BauFNasniS< zQRe%+O6uf=e9mg3JvzD`A6GHQWO&u~knA%OV^!J!9kOe6wR;){ zX+eL}k}B=zOzgyX2w%ug9hXiC22>UtW)qdG*<`Rwe4;&YddY}L%=%z`odG)HcNy}8 z+CbQ=De%7qcs5Z(Q6$lGN}dvu#+ruSOQ~t*{gn6ocg(h7d{QLyI&{Ke1`buBwKS2M zt3>3GP6}Har?&kl?w1B^99ql!n#6m^j!u6&9jnvV70akZ>Z#MT(QriseL zVvNMQ05ZM5o{h!Wpkzf!iXhGN=ce#V>9LTYk%k+tgvGmNXX4dGe5j1HA_Ks>++@lb6NQ;{2})AsO&MwT zZVeM_TIwjVJVKy9|1?Enf_~LDVCsKB2pa7uU^ORgh%C$#DZR3ix5RHTMPu_yS?08> z_DQIks!vM5S-sUHHMIjD^VbZ6=Sv=iDQ*iNQ+R9UC&d2R`U$m{27kipsnwtGdTIJ6 zte)EcF^`^Oc6jqkSOYfhui%i|z1+h$8QU`(NQc1{#asP>z0xhTxp$@^<+(%V$wYMG6G&qfDZ$3NK$$16ptfe-@Za7$=Fv< zaXBCtfv&+XNx;lLZXq~Hh0lM1Z;%y>erkU$ORil;Tgecq0}gl;@h)xeKtuf|ao!9r zT*E8UlLtNaVIWI(6NU#H+47*bnB!aFrTtSL>QbQ7_~=~NqG-EJiAvKjmk*zXttu)e zJWXpdPc77go*nZS+S$+%2DhCRYQ+gIlA`+KRkIuPJBT#Y60o7nbLD@52YD33Xll6u zABm!7cVu9XEd~|!*G9LP5;{1e+Dltq6DshprQHFaM6JZ+8{!g3g8LYDQMG`y5F67EN?{uFR<1vgEiMEkY-r1694qk%5;` ziKFtpv-)RRT#_(#^)1RUi|J<&4a4;(Dd~vN&ETVKvLLM9v&aP)Kc=B}8qoS=UXqhO zSj2hd;a-!-5hTiok*Ec`Un5Kd>MBPEM}|>CSIIF+L+XE!yt@Q#_Ipw>AZK;U57pFV zp3<-Od(+<4;0C(MxT+;t(Ku-Zjz{!V^>^>Jn*zIYotn&@*=Xp%haV-|IhvnQF*gFj zf@K9^9G9f3+#r_;8?Cx->aR%}M`0O@j$=>WoXjt=<7n$}+L$5?LO1I@Ostvy9wpv& zVLun8o#KDcg17rI+(XB`n2HGKy;y&F8An7hEqGF+%Xs8w`SkArzJx+O0F|y7IP>9Xx+?C)pF57lF*7A&|2f(5gNkvlz5Q z>^jLa2|+zR$OHi<`PnOhH@q`YpGo)5uXyLvx{FXbZ~9i0d6qX>W!k^0e5T!Nn@|2= z!?c%#ycT(4)vXTY00_WuoHQ+M@0v<@QAH+pjPqUyc^4LioOPOCHCW9>pKQ zYf^t70ujp&uv6T-NWq`~9K7d^W*y`VVtsd+VtoicU!G9kU!qWdxkRD<8r+e~lj?6w z*UQV3>t6yYR&{xD{hilWMbf9slkHzGSGMo|e8IAPcfqoKP_n&{%WDnaeIFby&!&C% zmy49@uNNuR->6iVXa2wYm&+9E??HVa$pwE3_OBNz*oQv{Nqv!)^}~0p%8nOmSwDPW z4Zvr`{e!-`>CgXq7`zTRMQ!M&<2{XG4JBhk*@Hf&@A<_0E~s9U<57R|`FtXN2=>VZ z*WmYDyzFA-`%4fWFIKp}262ALy7#vrEH78}s57L!C-{8Q{hb|ex!iW~uR(Q`dsTlg zQ9e2_ej#rcD;;x^%BHH%E#P2f`piB+D@*WawrYJbRTF%7S>k-SEOEZSEOGvFS>pWl zvc&n@Wr_1I!G~(kmW(e)q`wE>UxrBSsmylQ(mACWZX-H#PtgezT*mmYCy*EsUXVbS zG5+fbbRi?YoGTCj_YkEJh%Okn+yLOe0P2qUJ3KvB?gc)w8yb$Bp33Vw>*r{NbGd({c+=V!1r-EIIgLW#} zML24wVqJ>Eb}HE=Ic|NqE@J9^cs%0*%&Ocwe=%;Ql;^t(ljp;Q$@Be%$@71g3zO%s z7bef&E=-<(xiEPy&fPqb>w-MaQ`s(L25?fg%keo+WxF7^^HjJ?@jOo@yCCQDRJcp= zKid<5=eK5Dl*?G+Zl(F|qNMq7QPO;WQPTY7qNMrjMM-lJi`y5nL~%Lm6PL3%aXBj! zm$NK!IcpM^vmkLfs}Yy86mfrf>kyZ@2r<0^acNRr#xU?g*Bvf#(cwZ@94>OX;d18m zFKR;nqGt0iYAXMt=J79T691xR@GolmzMH$h1m{c&^Y`HU@?wO!ENAgjmk=&?{orC3 z4=#7*;6j%TE_cn~QWp#^Wwk&p6 zsO157rsb9FW}{%zceBAR*}E`4CfQY&|YWl8oKzjb2~;b~kyisZXx%9(i=e zrzDkE#9>k$Nt}eJ8j*jq8@*-!fmxEGDGE}PI1qQuRj7q3Nf_r@`Yuf#cG;+lUF59$ zqlOQ)TorXv*-b*%T$5KEMimcF<>_4F%5omK4HXe(0xKb4Xw}Ur>XTB{WZ2eD`sJ$oS39)}o3|U0%61VeLKo4j{V}=j) zch-}bc{l6$Ok9a|Oy-WmIzBPtWUqslFl`8a3GEz{b(~;pzmBF_+9%|S<$=`L?Tb?2 zmjyfqT*+YM8?NOt@YY;VRiyUBrgk7mMr5t<&|oe6v$b3{Gc0R4Ej%TcltGa;W$3hm zqx^V;xJ!RL9l%o(>DXF8MpEEjs~$EK)O6fvMFF-xHs}VMkZj?{xRr=V(fRYWBxWrf6JwxP*}p$uPx#LTy~qOlq4+YuRU zU$UX#8<#@FG8pZQvL?v0pw0`#QkZYNvZFEIa%F$TBO1H77t%e4=_q3rJeF;=_f^*s zSvaa@gs_gRd6Z{lKe*#u#+9;AjJ`Nd|<$){qBrpw$vNHVrK<%D|^Z#~bu? z6o`KVo*qd=k{41Ud;p9=&JY}7{LvAhjXio4S&UQjcmtY_qYlfOO<^2KRfT(kKw-WB z4QFubj!QhZu6Q5x3P%k`E;tT8mjA8rF@0~v;l7V@?{oJ-F$G5OwFmGRe)dzDXLX^h z)bb)qn-;K;(xv5p2d`yV6vCuGHCexXTYXTD=--^WC&$pp5_hrpkVE(K*CeWv~1ir$ncB|=S3kqZR)`G*z#kGIn zac++cyj*ikL~&7cW|fPpW9f$xS$5@QN`N<~Qi{FdKyPjU55~0#$h3wD?AuwA_$dl{ zG59omzbKlPwuS~a+rNULDO1EU7&-Ko9L&KEC~yrrFSLe4yr7;}AkTDQ@|g})91xj| zRo2j%3|H3h*o;^#`Jlb7CA`_V#gc!-V)e$B$z~D9n#*Y8nk9?Tux||qbo<&G4wKQP zEsyyC)0)YA*~gN~d^l@PWV)YiEd!!uv)|RWn#*FWVa#a~ZDIvDa4upk!xd^%T@fx~ z4VS@j&NVc~vmtB9tfocQ5TY4~+c>F_nva6UYCHpc+@>?6!fZG#6TUvTRDOT7xurwX zWrI0Cdu$Klqbk^{xj+D$IA;Kv4wNYY(}61G1OFE|9XNmoNch12xyiGq1bPInPho~_eoo*sXcAnqXFaB?*-weiLB=+lI6N6 zlI1#}?}dk0X>nvaD4x1^>f;Ze_yb)pIA$<|)_Y10@S$##3o3t@ty;+>y|woHV{-L; zHw3;k39C=-P{)lDbePP>@n-8(=pSh9KPp?`zL8AB<9+iPKGg3%!zo?|`l}U9xY%Jv z_g`s%iuZAbG^pQ1Z1uu0`zOe5t^PDThS8s4a&PlbiO@9clnPbL?%O-W9Gm?yFpljP zE0`FKXWm-%}~=%I-0Qcij3 z9eOFJJ7T|#O%aDR@mjllsmU#2ndi0E#IQtK+rkrF-+%r_|NWLXfDWRAh2g2c{z0n& zQUL&bS;rE1oxtrLTfp2`FRiv>`)TDo$d{z5AKJ${u}{dXSU_%{Ln;Fo&?PI_9dt>` zHt7c@yYzoo@Z;-^C!O)HFWzP=f#{-l>t*ZPdSj(bA||2LFYIT zRdj-qDGI*~xW5g_t*WqzN96ABlmbUlW_U35WR4O~P39QAm@-C=tSCN|#Iu6$90i%-x$;_j*ord8cqV1x9bJ@XHOYT!1b1kLkh~>$Y{-4;6bWW~@Z7J? zlVZ1tv-PcN=>bt`PAPCyW`^g=YwcmH%N(OeWkI$vQzV!Q?Ur-Afx;hid#KwFB~F{6N>b|=F?lNO z@})@iNdGSvTff~tJYI`)21{+Ohi(FU6{QIsl?MVEP$9NFe6E`<$j8(^C#n9U+Y%ka zw~xuw6J}W|QvXt*6`&?z`7wXZ5D6;!!FhjxSzHd<2NP@#cFG!;p(Ip`$P02gs(zn? zOC`4AtmV+3E0c+|CXbl~Jrqv`!|Kkzu)QyU-Mu|*I4Iwy3OWyH%@7k2CrR$n!XjY? z84q7>-y{Z|j2)4TM5H=wY&zUe&o{?HP7hl%_^YX^d3s9ToZ;V4CoYVrPPuH|V^Dwh zt^0%lqjgV^IBnf0__&Skgbw$MIB#?(433+^?ORg2Yy~|$_YI&Aj-mTQe5Y#PhsM?T zJ`-B)JJ<6*xMLOnkz}L{Q;80mf3n4uJNHh%?4q9xVq;r3TsG7mp8JN{2ghirLwu(V zwGWNuc=kDPjX|FY?F&0M27PcZRpWoy;;025m+f_g>Aua52{792DTmXxJBG(1@J%FH94s(tH z*+L|a1-dbhc4<(%ET|7NsShwIQt%j#D%i9Jtxao!+a8K%53Y-1sdY}$7~<3J>nUu~ z8Wcf$HQ|FKK`Rj>pslS4_=SHPUdki(cTr01-T^ms>}hZyq1*EHZL~(ORZ@Ujw@GiP zr}sId-X4`Bc_DXfL*) z@EuZ9He&fZED+NF#3swd574Gsto|;Q*2fwq1)}P=VvW+8;0|kI!5mF;On__MI+;c% zBu~Sm>4VUCN;sz452Js(pJW0ajH^Ayu^L<);DC2HWIhHtmZIBzEdWcMxQ6dp@?Cz#T3M^Z0LI1Ob;gxOSvOxTTO$cEWme&M^h@fuBs z@8|RM_`H3j9w)-5k`n^XKT!`C_0#luqLhRgTJ@lR@je&Amll7E*v>z62kXA~8ewB~ zU1J)gerrsF(`ofsFxy>^2D@GKsGK$n{lvo{C1_A3Qu66lHhzb+hUL-u6zWxz_2(Yr zpd?k1XBB}~y$xlVg6?mXY)$U-x!iXD8@Ytr!gsB7{@FnnO zpeD)Dwdo^2JB+7I9X_VHI^p7alVp9(@kHvE(!X~0$X9ROn}@#f}=i4)4M& z+#|N|4*v}G*e6G?$@``#2%QW-=OYX z@D>$S@Vu!pB$u#wqTf?lU-L5lMraFnUV;;Jf3APg1T|J2ej|I@#gNi@_4R@A#Q#-o ze|Ikb02yg$G0nklI1G2G>p{hk4B?AFj#;z`LEBeAM=ZLOa7;D1Wdg3USg@%5;AYGI zQ?#~xd;^jgLxQx*DR9(LkYwLgn#a1_!eZ% zF-Vi_O!dFQV6BnBWT%EZwsUD)%g?@dkrz!Gmj3JdstETasFOM+=OIrrrf9qOGq9gY z%?v&Woz++=huKzJcdS;Ps59187R;d(_Fl0&A?z)xI~mT}1gyM7N1W$W#DTwh77cLW zGddK(+H-Uz!&#ew*_LegtY=h$p%CX%gPs)URRrVVgbPCJ$v#*7XS0H9#urYgt*3vp z*9%~Fdci#_|LP@)lag%>k`>_X%bRV;ch7ppHaFNx@5$JavdoP}xgvwX2v=sP^I%5; zeu4avWO6sC8+`J1%3AHS?!yX^p4o*ANaJ9uI^o zTADGf`KZd8!rF6O#c1ay+Ee=cc!qy2pdG%g$7RXpMM)6&?@!MC?bvHi+$Wu@@7W3a{!Cwr$d&!{q4=dQ6dCo&(@}G|envkI#l^O~<*G zdWCfYQy*D7Hu2v?27?bMGsx1}tWESO?YQjR0$X02`TzA?zRPItzpm%L!nqZ2u?m&-Qaxm(=wVGZR%E|680# zo9%a-`BWT9zTfm;EFfPU1-eC!3yw~_h&wCOVHOU!>BC*vwMDb5Li zdBxK&T5ZFUY!8I~ugcg+0^-lujJ4-8o|h0k>+LhMQAw* zTL4R5NNV`um!WRO+l?IYZ3b^OLjKki@3qh%vdi=5ZPgS-Ue;#v&7%A-@nZ9{e6e{D zFEmo6BrG%b5!m$Xwx)lDA?(Ju%1o+RlrQWB`;zR%rhB20>c~FzJkyK_o zT9snZ$%a|HiK%5v^MWnFbMrcb%nBXGFJTsun5r-Rr>GZ=!hmoh>$QBcQBM|#Wp_oz z-S))g{RCWuB@lnR`cR0k;k&sQER&+8zZYnp5-KuxJdB8j**?*~gd4I2&r7@pRJ^RG-z;PKb=YZ1SdJ&4cWF7JjVBQwfzqt9P5;yJZTl(%avg zBzoTF{RVVe(plnDfa}eFvIiSgFM1iG?oBeP024`OU~GSDCSvoF>{Bw+S(G^+$_>!IbR z>gT=he(Ooq1cYVrN7*0cpU@(|9zxoIR$E63tAYEKzTPC&i~|3=689t7HTykNr&Ej3 zz7s~G{quh$uP_A_--<>(#gPBoR7`V=csE(HA@)-4>y3D|k*_xV)rP*Bl!Ny0v|g$M zA@w$YVhBYO?`SO@k0HCu8X(Lm#CC{r(>2HU{bJnP}3R_y2Q)1-lkI{ zEFO)TC^kvPK0uPOd@mt&J$ESqRp(T;TlIfz(>|M_BvI3vz^Exp=5(+l<}l{j z+_&l#H>2{^hP|4UBb6PqG{m$O9k*qZL4=sg`bGBYj9)(A(C5?iNyRZLDreqg+;iaP z?3sSfj;F?gXhFV+6q{a(jX2IvwY)#R8VFa_q$orQX|DZ&x-RXW8h}_!*&pP)jeJM_ zAN7AuiSmh>;O+JO=L!3zUJ3K{c;MHR^TG3x9Cvht5bpA(<{#jRCf(4aV^lGOVj0D7 zTx8txjQoqTjN7nCCQCXH0ElBRW)JuEKr%U2V>SC!=Ep??F%lGr^w^V;rQ5XWHY}Z* znNz}2U*#!Dr@NZ=o%mMmpC@^FSCfV5`yYS3Hbq}ew}2t+OvY>VR5eBRbdor3j>mV} zMl)J5^fS$j;6|jUnLc(;HvGvXnRa?|#4|`gH4QmHF9sh&1KlNF{xGr+uahG!tGJjA zfIgAyLG<|i(S|>o0mY;}`C+ME670q63{$&J2GJ z8-sWuT7vjJ%pyiT!qwn2zsInqK1;may>Hpl+BT<_B~8NV+V7zQQErsq!{(A@s?F|w z!;#sk|qK7njSP`v2wzzj9-=?>S&nAI*zD<{p)g-g6 zD&J|r+=6fb{qblRjYWv$=Ga;c&`L{=%%;s-`OFpggbu&X})K6nd*GCt!RUf2>WP!L&#Lc%m}C<1kqi05Ns^4 z89;2dn-*lFKsLYkGD~& zn97VsoztR=E?wVPB?<48)X~M zPR{XBw}-j_wRj+BHboq? zGoQ+Gl1-V4@l^60AM398hN}LeESp+g-hD7H2>?*Z$ojq?*%+|D==)EDwEwJ=pSqNs z&9dH3vMbr-i+1cfCr88nu6y=b&ppTjG1vVJe7S~>m4=Ok?;orz_!r^0Y;~(pBH^IX ziG;IqSEFXaTZwO3G`YfwM}<-n(tTfWTJCpn>tzA|6^W~5^RRq4pYY{4Sw(7eyse@GInHzo)65#AJN1@V_eV8)f8cL5 zBCM4Q9-rk;ywpz-X* zv_Oq|+V0>=h1RRChVO+{Q%ojenjyEk*zOn;soOq{ulUH+z#_HVckSfvvYR%Prl8so z_dFijI~630Nfsr>wYUiNi+bJGQ~z}?@(lfUm=t+^r zu){1<9RGhHWyNM6*e-xFPbXv@r4ZuEha35D22CutQw3^2?vZVini74AWh(EDd?Z>N zd$hz&`}RaM+^6JC%=Rw%)YC#NfZVk2HvHYhRK>DbykN8IvpRXY+&w{f#oYAPVkafw zKU1k3(es>hGb6!7?wju6Mm=1RfVzgyx*^Ua`8a>$C-FC++V{*WN(wo1T_$t8t|w`y zGXMDbal@X8DQ*62fnJVQ#kRfet_-v20Oy~~eJ2LCV$a`3JY0~VXsW|NZRj9+cBjOo z6tf8T;)PH?u94!!qBQl;=&K_iO~(HJB6CDN!vvJk2=~6}HJjcMk_}J3k;yla*3k84 zg{XhBz~vp~>&+bfnAA&rhp-%ei=x@3Ni=f;W14#&<3YUY%n7Y2@oGt?niSjb*bwo# z@6;dpOpESt(6ofph}%<0wiRUa-M?{zFgW)kl1`ldnJ+++RdtxAh9B}YuafDrc&7WJ z4B!JD{p1-DpM(|LP=M3?T!;_Hnmiqcd#IptpsWYuoqHCM|yfV zM?*$4ND_YhW(J%eP2yd=+Sz}!jlyi3Y^(5v$AO@KbdfTk5}2X#^H0JTksG5nH1+25 zhNWhvm;TW*{CmGFKd>FHTV|QJ^y9IJB6&IE5=X(353Ge2>{7dt_$IXizOL~2orlBDm< zlVr0KqHtpK9(8O}{&QP|^}$9y8=8-K_CNpqf9nm+C+6W;KIYM~8Idj@O;fQL5h))? zZdg`u$=MLE-iAU7E*qy$lV?I(*ti(qG&7+ZOZR5K!e&n zqAhAK)QGKuoj`o<9)N$9ElrL|EfzY3Q%kK=xX>BSi!+DxrF+iZ;v4ZCB3zd9jTKFn zL}C-`j?}M&2$y!dW6rpZq#)Rz^UWa9MkW$!FA_n@P=!xqp;w=mQf7SM|3H|AP1k~P z1n{Vu^sG|ztu5eAYLt4|Pw|(_)_I(t4R6_xn#6q1o?aEEBp82VT+2WC_Pz=zhe@wF zDTG1CIY}=%J@E?Oea?t74Yuw}8QZ%_*{n?7gfzBRZ&D}+hHpYd!`3`0nPG!&b61Nk zxl7h>!rjv);NgB<-s_S~#8lDM{)l!SrrVkOiIw_Rz0k=eYN{Ak0$iSx?2Gl1=XF(= zVX^HVa^?Ajov?qXli5i?eMb3FRJvYfu7zznGjVtYwW*?Es%9YcWR=0hhEU*?tc*$N zLVSVqgZS4%kfyFDcD9)dB5{5Y|C$RDg=M^641sdP{%;{do-XxaP!TxF4g0^12(5;# zm!pO15}HfILaVM9MxcCR|2G$5Pcqu)rrWB1pE|&8EX;ox??>_X=0W^zF5qv?ahKQS z>7gZK(K@96rGA-g zic|irA*(9PSSn~W>erj5@!M>z5+<1n)-uOeGq=sWJi}}^Y=)KXozj($pEVF?Uz4TM zBY!R<8&=g!=HVK&PAy7Ou}z0{zo1qv4FL45OVU;rtOd$Q7d>5ET%8ojKjfnJh9BvJlk4orl+sgf;s zr9^Ope5q_>mdV`L^qFwW_^xsGY)JqacYm{KO9x{fWP=t~ZW=LQ5gEi?FiXgBQWa_V z4j3?h^BI@?al1jrdBcF<^>>GV?@c*-?9HM!HRX_?M&dA1^iJ)5k+Kk)5eLJWq+(l zSc*^xaI!AXgZi~Z!EQ9MQu0y8NBSpBy_s&>F%C06GHw3_#Fz)Pa}pc&^I-R0o6+Xm zF85aC7Ks1!&tk*B#Qdj!UJ`;EwutuY2Gl&ymS^HWuh>rjO-$mYEjDvRGMk_he}Kr+ z@ZEw-*+WJ}e*>7Fk~B3Y;+X^w`+o_bNwNbele!9cXgX6qm752^lf(l=fCNm_12*yx z%|9YgiJF_Q9qBDqQ;Dtbuh>VEnPp;R`d%bwj}NH_t|A1Lx18WG5A*h z72kh4|3~>0TpLVxSh%Is=tK8&G3{beAJXMdJQ~y46?y?=G&s~1|GlcoQP;eAqEQ3q z&*mWq8rG347O$fjXVtQ5EY#3CP1S^K@XsoA1wVR{WNetPk-Kg4Q+cneXBFXsJ>Br9 z^YkY6rZQai?lYD+8K}Lx0bffSsc0!mmbk z!z<@?;>gkr#{vL5eA8C1dc{u>&q>3M%9Q({Bzy7(uln`z?_+V=?TSl|O_!*1Z@OpmkgBU4k<68CL^IC1 z$f}k>r*FnuN~wxel9_e(sXRa*VvET8Ni=@rvwc!?n80}8kND_aJ_5)hraHuw-0}j)j38qGu@)m{^G?<` z+Mw1C)afAEtcH)$wHIco*w*6lBK9y~`%9RlGTOE@Gi~y!6J@&KQ^FWQcd^`6T4u_b zNwX=^YQay%TYnHj#_Qf{#*X7;>h>c3bkazi8E{32%fepK zU&}jChSc-0VDuMP80di*)QV>5@7rYo#Vj_Bp!~1cE)4 zQJT7cYo}V+(`Dj4sp+tKm((RKv4J`-^<&t(Qw2~CP8z?Kb9U)t`52q5% zVYE_xQwg|XW(oNBUzV(52Pf%(jQXA3aMwt#X-|Y!st0z$lE2<`uQf6WQz8PjsU~M8 z(&;QC09`<$zsTyaJU=e2&e@6PWhB@4BN z48O>mJjVE+sL8w!%ZkiR8FUHM<)^F<;jvslsmoQ9QQ8`Rml;^m&mgn|40-Y;fNW%}Fps-YQR7P^AX{l2hK3w1#9C(#+fYhxaP#lzTiZ`d@Rcrz~! zv)&0eKJCrU+oH2x5P23LY)qS4x>bg1CQSLPICJ@bk?X(mc`s`DtRTu4?v%(tiiynK zwJKfmKL1Z7Eta>B^-_q=gFTqo!qrdL+nYoiWxhRsuy>mMV`H9q1hpyYTD{m*T4{PS zU)(p!^Jk{T?6;k8K*0XA8ozaerelqS{f3F&F6(hv!mjOEuwy5JPG|qvf4Y%R7ldFb z-s#Xfp=0`m@Hr>!qkOmQ&yD(XfsejB|zHt#&VML~L5AZY(Tu`+@+{{6nr%Mvmplr8a`%2> zqEyz^u=W4Xt%WAClqa3`#s`-sw zDl1Pkn_U}4st?m$Pg3ot!bVAd*x|8Nkc_8Uh6h}yz7oRbhB#=RI_(fA$vSj0XB&V5VI30d5RW@51 zFo8&TQY~M5w{x6UsC+A`^y}%B8|u9XJEr2x%}LWo>!w(SO zZzbcsEL-FO6$EJJo-FBMo>=Xkn7V6I2BN6M%b%!!aE$h3t#`tjun`>usDIjwc8#59 zM6JWJm}QD=wWr!bR%8&&!N zd)fFq3vm=wUoPPicG7W+P19WU(p>R0!$>Y8aoYieK{fUAv;&T%Drs*Ev-&8Lx!X&| zU}|AS+|LA~`Mn|OV)Wb-jyA`C${!2pRemJ;0oDn{FxvzDYjPNWH709l@mZ7#6Q(ZD zL;G`qgZaU|k=7w0CEFG84riQ2U@IQIL0bD_AWdG@VYnOUiQTww8euT9lty0(Ln(Pa#}ofv~yd zDQ3izn-JQ604HW2Vm9|@x&1+f0?~XP5uZkuNEg~>Ai-o#5z$5#Up|~+mN~<^4q4~LTXt_S zfBUD?wZ{{gDiiuj(@ff>IDR}ueo!F6WY!0@h9}Q|&G4r)h0_(Vb{POjO>o38>&9~3@j}M#n<(x$HbHrwbYM6z^1CA%_d}$oecm8F< zHdf0iNG}dbn`&Oxo|Au)X_;$r7Dc^QLZ6Oc+Y}SqTPyKS+t$fo(qb88ypvUCo@(Yj z$@n#Y&rS|6jZdeo=8 zb!0mfpWF^YmqtEwf!7XmZ)WL+qSxI3U5#cnJeF0dT?;#&Jun!X>V8- z0Kc&LfHZ!rhKi_=GnJnencB02k90=)K4{u?&|s7{4ral2ru_;HL0crLQN#}O-W2zL zzM6q7dHt=pUocHaO8au(e!)(#2pqi8($pzZn~lzoKD&~Mew94OA%-@t+YqI}>_hGl z9QJHtKwS)SLx!`+Iw43DXm(b2Xou_@yuCs6G|Qjpzjc*ix^x9TTI7}y%@>ONz7msF zz`?-I6r`gnp!*lKMTN7EB15uFkhze5GTRK2`Pu|cRo7Qgn4hM;9_w3hs_o}8aw5c{ zkuR5-jJ1Ny}nRhYHa0K$Sk zJfLfhQAKL=1AOXA({Zt*LMIAYol}BGl2Mf^k>iAAt|=sgs#s@vT(HbA#i9s*F90Y8 zM`Yl+=wAA;DRBK{0>;?+am3;|!gq1IraiYjM-l`Y)5@f#6 zq}t7kL7I77SkKCUha*e{EEmWN*kLhvy26C!^MyPE*NTCD-4^(ne`wp!33gnvzME1q zObICd`B3&x>T5O5US5`duY|u)$PE0#jjWe^cr3a#ZGFafEgo6zdR2i%IMuRl?nPod7GbIzVUS1GFQ2?pzFt1FRyPhlPKjy zFzq2U39vPVWyt$$YUnBk24_0ci|Y1J)zh&;tXf@g1|T2%4>Fww(AYYH#({8(_miFF z89k38GYyni!2JCYIT0}TeF2x#V5xo3C%xNrLq+Ah27-(T0k&g?NTA7V_eB-zEXjOvZ%bt$2>8!U+is zV{hw2f19Rp#w!)y;4B74zL*@=FRX&~hB4r2JUxt0!SnAfC;>4Nm88gsBBSt2PxI6A z20(S73TA6?$cnzUIVohejff28wi%{;lue^kf6DgY!sB3%MvoXpVR0}z$bGx3?w-_8 zT8#sfRE9-ds9bEM${WmwASeuh34s8ZrZ?!{gZDZ7>6MMkl65hry!Z<)+Rl0<60%GA zk~iD36MSdGQ?t!4`xa-c)@RH`L7y^A%4Cv9R(#*qD?hq@>(>VfolzL3I+KlCICEl$ ze-a)GnuD zQ>nB2-VsQ8*XkHVP9f_|q%IcIFjCtwp!|~5on>0JOEMRp`-MBga1N-I7r}<-kAqEaGs0TUuRg*;OI1S?iAIGi|*iQguF6V`liRvGJm;E&@T=Z>ScA_8m z59Q+6!cwmwS2`V|r4S=G1v(wJ!mWSfCf0BSY@fudDJL`UbPasC1HD+ee(Q4e*5&%G zgZk8O9ofx%)z_5iNVO;HE9z?d8PCJRCbjz$JEM^Sg;in(yWfLXqI5eflWMKRVKaxC z1*=~zE#NuvW0s14gIv>{Ogj&H#b&5*q43aq5l(_^^0S|=-(>Q^C0m}`gwZ%d^hB)= zdcrXM|NdW2$y2c-LW$5{e(blx%L%4DiyXVT#R|eC`>U8V@4x@^za-dq!Se4i0gEuR zGyU)cfA>*Yf!`@FAd^0vfwe8Se8qFNwO6#9@@0&6%1KjyW3#3dsuY%{-i9tr^?_c^ zt=lQ#rAm}n@p`-4aUr=co3bzJl@?fVzovw2%d-P`D^}}}p;y4Ee9n9W{*R~Uh-z5; zzZ38Ip)V5)ZE?aTyLvD*($*w;8`!qBr;D5s$#;WxFmXlUvUlSi^1#xdZ>pv|Ta>?jls-FP1rB1$uLT7oDllVUk)r9vsIVV(R^Z&Sgd> zzd|Y_j*T3Bz=4}y4DIUB9+DrIQwVwp!6Q3UVjNH9tE3b>P9f{+PJ^GE^CZJ@$+(%) zmP@j7{?rxYgR_Ae`O-=8l;D&y1wqM$!q)$tpG%%|$+MW>$mefk+C)dTMxAC;`c#5n zp$=?+!BsUe=#U6r;rm&IFvOcIoa%A7Q}&7$r2FCCD@wXaP)-^WYuv*v9V{s467d#5 za-|5EJXaamLuZdlmw*t8pUTJlLL_-6 z)>F3h;$J>y^z0I`I1sEonU3V4#95M=j-UkVbg;_HFwX~Qb`c!PU+a6KOh{oFvm51q zn5*xY`e14QfH-N}PgM{{<7CyY1#zmk57v<`16QNL5N`pkT;hS{V!Qgd>OvCqB58X! zYXDwAwoj6Dd;9rqHzo|rPfjw2hoUcc`*Pp*Pt=~eqIX=e@L*yHnp|*RBgqAlppcA6 zCY0~q{os86MY?o~|LzBi8aMX)s=TXzpYm1)b|mli(siTHxJu%JJD;)tK>0B9#QbM= z{sK+g-o{h{iK`%L5og+>qNiLis82>rHcN(D9GW(>=m}7%FVGU*@DNolNUpDcT(Taz zjurv|MQlxP66ayNR_TbhTQ2HJwPRT~1#J!Lg32zDkt(-<9JH9oz3zet1jv3c}^RBI{t?vdz2!mVB3o|jJL>4L< z^6d{_DQhrIlL*WwDrz+FrSQt!>Ydk#Nicazc(vHpwdmZ=5?uGPd|JHxb3X~wbu14M z#yOIucE)LvxgOJR6~)$n#IsTZTc=lm>HmrXbK)_ofbsD*8;L--8_r9-ULbC6SX`0X zfBW@+qyLTHe*G`JLgoh&9Y`&;M@CdG4Uw}7ZXMP!g?M`gmZS!(89=_>ME|pGJZ~H3 z&})W2XFSG?bLLvEY97kI!UYPP)c(>2uIx-&(xk}==*(4}L5#D1W+HYV|3w!&2#Lsi z#m8I-yBYqL&E=UKWd5o#KUU!BX?S*)e`zaGX1YcvK6qtaet{cR`4k0Y9_k{ARbH9Q zkTz4anWD`OI+h5X4@#1aZXVbLFm0Ax1g@grv7~BIu`A%ZPzC!5y>^9iiV}tu=!Hwn zhSmh*XO+FCM0%=!1`#&(>Dv>O#3NYG1tD1<*Ik8Nt){}410zP}6a=IKSHWf8l;!Re z<>08%Yqu~spy-tpcLbuAK9(5}ttlf^zW80iu|`?R&?W$iZqvsXk)s7>xkRIz8#F&C zucBF7z`Lp+#^1Yq5hYMOBsqEMhVig_5{ifNL?tl<0&0Ad8S)HDD}Fu!zDb7?<@*P-Kb% zb`cbX5u(BiRdqA;dZhrHbH0|7OY|TCgp+LaBmt|Fk@QXuTQQ1)n2~OWLLoIa=MR(Z z^l<@=lV9~Ae_mAEh}?2tR5jg&O%iYNy@cNx{*Ea7GHi>kge{OXWd`5N>32k#Ct7@1 zlVW-~1%(gl01po3E>AC##raY`WmnN+-Bo416XT+~PSR(vy@H?O|GJK7f`K@CKwk3| zT5{vC9a4B-oO`fHFGgWWYA3GO_)Cn`!fGDMq8=Y|8}Zdn(qpjwh(F;=AJ$YgWRFhF zu-de@ZN~bhlN$C_0{JDAarPa56{cs`m@fU|So^w8K$Gt`x|5MS;Bia1GCa=VHIDe; zht3}C+b`w5l#bBu`)Zd6#w`OrO2Z#Am4T2TBZ8>&JFf_$F!-)6v$uwOilDL;Q?-dp zD7t1$(S~w+=&SLmILM{w6m5z**WA}K<=L4`iD;*#>0O)H=1sn9TF`!f(Z<^LP`8hG zjwMZ%=DLOeIPfc?rm4EFRPo^2=B`RKs)PSprcu;dObde;iyDK|HQhEzxyg4!zq6k% z&m+npn4vle@!0lt+DqzShlL+IDT1Icsxhsfk}Nm)CnmiF4`+3`9TQbdd^h5^cst;C zMA@NlZi{iO)A|^L?MDB9jA@bvUNx^+a_iGCC2OW}XsWN_T{X92lkdIweLmkib18eo zK}_Rvt)<^6U@X;Fd{ljcQdwex4%B#I{-=Z&HzWWeM(ooz*55T`pG z@dEQRD<3Z81uX-I26DU#Ve@eS`FP>fK?dnI7B_(5vzR!Gc{`ff5dhVxdBJo|37JZm zbiELLLJJVHEo>%XB6j$nO$7CT}~S`2vp$=RsGDaDH>b8LpkC6k{0l0GkXBnk9&QN^!xX0K+9>O`YPseOM*X$68?@ zYk>V<@g4eHK8caSE*TwDD!PP+r57Dem~p>?M~HN`pS_iC-HcOfUd@aXYaXq$ zQ)RG9wyTED6?7|tAs}gXDh=MF7nBvn2clq1hrbJh?@GvD)J`T*!_0G)pq+i~-Z#P2Iuc=w|YwFAJY>J!*YItiA>cjma@Y(_ySs z7$)a*jw`Nka;pT`DfU6CYNrgtB@@)-J4}ti(S29dRQ_h>12X4+L(iFfjw_FLK7P&7 zzQ?T-&h<6%7t5!2!G0+dIByqreUuvi?D!Bk1cY9HL^&&UzSuI4-eyI(n1?AU7}MTD zNGd2gxQr8D9{&!7Dcj9=28n34OP%P{dRw>K&tkUXjzr;5XEXdjPgC@Xg#s1Tv@T)0 zj-z45@j?bZeT$Di9pu2QX!5U5{%W7AnK5aXXGJ4w%vICN00DSl8$B1ny=0aJ!vgF; z0eIAZd&+eJvL{}L!M_M^!Emv?vLn-G8e(~4 zKReaHhmHR}8r1OZtNrgGP_ltf#31#jAXwUe!sAMn)EC%$_tsX+OfGuh#*1)ixEFjv zSAL@t1EqnxO^?MBzZuyK@8~Je--b^d+oC1uyZM1)Q=EBvG$v2csx@4v#I(-RpuP-u zgT46Tf$w{+VJ-SA69yf zW^uT2wu68U>@oN~`l#Qd&&G>;*X~7V_jP|Cqp*XzF zV5#!%E-b}GmgQYyH4A6-CwO2ki^dke1DmmPRSPyj0Fz*>B=P&Du`he@Y?&OU-ICm* z&0n;@~sn0Io*!{3A7B&8SaK_qk2{!3}n0|YNt9d%C$o8UJ@p% z={+pm%EXA?wyB@wJWb4&EXQPNI6{InE+CR?4^@*{L=l{Lu~H=F!lGh?_ml>IZozFW zgg{Ova~Lp|1;p1D8q`j`Wl6|l0%xl>bIV}|0gZU)eMz-C+RkYx+9b@4cU7MT*eO9H zqz-f;2nTcEurWb_!GlVsXP+V?actH7XnsQo3P|sb)kWOl zNi>eHECe%_m+F)hK6Bvm9(HDbq=D}}8)U{J;~51FQi<7gwY_aU=baWBkUU5FH~9P6 z5AAfa$(GFrPLyx`Fzadq=n3_Rqrc>Rj zJ<$bRx+Lk1ju_yOR&F1fN(>Wt0yXuG`sEgT=<7j+f~GBTSS#r2V#~7<@aH}O??vXb zE1iiB=9)6YOg9`c=f4$ydgdIsPi2GI;W;z%V4}QBL}b+?AbpVG94EheK;v z$X|&dlLRO#`ygR95r&cCz)_|QN!V;o3k{Ap)s&ilp}#A}?L)ajy<%Ky zzoeXn@?G1+TC?&7tq5PJUkhR2Y=(d^r)X-7;%561d{!a)7v4D-cHN!yS4_T>eQQ~U zMhC~WO2YXIB>kNn$mTF>F%~6^Wa$h}GgHp?2g|6yLS;$c~S=7CMLzqc>Zayu%A`H1r(Q0sU0oP}W z-4}4oyAu=Wc6lv%p*>O93*`(6$YrFQ>>F6bz!e}xpGo>}=h*M-_7)uDi8fZ3qxdGs zcxN$~e!kb3lj)pH<;+#%+}(8tVxi2Wynso(yyY+xNI`{v*!8?1r_e+GdLACcv|@W0 zqk=WvwfZ#|WqNQ93o|Kirr&dcqUG1sa_ey+ZlZgyerZu}=I145eT$h-oy<$^)66&_ z;UtIGuxRp140ObZzZ&zQ-ItFK<$O5n)#YVBFPiL42I(0r7_0Q>UL0zjz<)f%55mct zWCd85YR3G3bJITN;;qJqN7w}(Tk#-G-9Md_lkL# z6E*tv!7>?moF6lgm3<>R8I=Iku*|Y+zZHYUr_2zT<$@7JY9b+0jDbMp-v`WuctzJH zX2o<57{FI~u@_%uaw8|uiOE>s@C}h5^9>aei8H!?dHjb=l=w|n>@!IXg+c0AG4@YN z-!LBT?#RRYOf9;&9uv!wAXpY?|0GM3AqNia=Vd~7+M~a69v_Mkg0`W*XHbDy#9!FB zqCu0>XQID22@*dDQiuzOexv~{7EAmEQW}{lzlwhRqJseGcYV9hQ#v6B=Lh^>=!c|? zx*qX=4IBnFypp}BN>h7G`WZ%K+iiQ8uX9-pnneD!*)c}MGB(0Y!bCOwwB?L6hzg6* zMEaK{1m=uQS%*X@68U$|?z(=l5Fm-B3lo+Q*G}b3gd|Zrk~Vu^hIxA$a9Lawup`7L zDd>;Ii~cG?tVDqSTa5Qru+>1e_%~;HINU~mxPXHG*t}-L_Hip3m264aSNG_wY8v&!mT-WZzd?SY zpg$I`Z?(hbH>ix&3RBLo?W-<`K~dlzn^)FEh*^=)UyFS#?nA7QE&kao)%J6^Z;=## z^vC9XtcHbOt{Jl=k$-J=HF^&U&_w!|CFD!hkB6czn=c_L2G#WQ?|u}Y)SEVcU5@#g z7$>~0zLfcoGf(qA8v1HMB)6M36SyOpv3Vg$3d_gnr*Hp_vTDgR@+lg^H#Hvn9Nb-HJ&z=R)3x!G z%)(~4L#I{ps#^ohCC2bDkJBL-cW@x>i>A0INrC`E&J8rraZcuV_@Xi|BmuQLB%qm; zn#6IC_XoN)LnFrJ+8+hCR&QHqFXV|ba#M#c1$1A zF<9KM@BtMM49)xEvys#3)eJbuQl>)*i@U&FxE~0HnsVWojQSLxV;J82)!AQ`Z_1RX zPSj$>i{}Ni8ec%zTkE7WtZ9~YwXYT{2u>XgAuzg-6w}e`-+uk?vHk6T*Z;{hoev_# zb^v#>D3$JYsbyrj05UL<@?^;`ITGTUth_y@mZ{Grp&PNN?>$`igA<+kq1zQQI>kSnEdDqIs6`nV8%sVPjng3Wr9xI z5vv#jXu9E!a3G*Ah7opn!1Xn0J{A4Ko0$h`T*@_&WIzHNLp!w+m%X{nB#9Fr zb}HbY0#?|Uo=4n&aF$Hi_kdT6bD5%*Q4=_C+ZwKBxrP%qg&I^)vrwrXamKM0fyGd< zD1bxBk~2XobkiN2zZ;;qE0p^L{A8tP+c=b?V7Qnsqv~HA`eJ_mz)fLSr%LsRlime- zYG2_F(4oe~d!~|>9iLP8LA+sORS#msIQK&n(X2RgVkO6a2AJ|4rhM~lKr`O;FanGv z6ne?}gG}KRS-k^0vqo8Z7n})|Y_vMGO+s;(tVVOClz?KKAX-PX;L0*iDb`ebOq^^B zaN*TH=ml4!ahhT@kO*w)Fc%bvc?AXA)*mZW`Lx`gjDhD0Mb~NMr5B)!`3i;e)@=?8 zgS4|^T#9jjo!oeGb`+FvcN3K66ht>NJNzv^gK$Vj9y{ot!lS%}y11OPtdr=WabXdW zKnMHtAyn^1Hx-_NXU4^}#$J4!@1FQ0$EDtYgbS7BA3x6V4AN&vky!c#-?elvQpj4+ z8rxo^7wWp|tX1hu)ueR7lHZv8f8-}a7o+(9ILUaBQDSpT66zg*+p*K2f; z5$rvEsw0x*Td%rM%$;|n0f@4O+`b_hz~=l$Om*!dG6+H!3zEyJTDTxw{Qk;P=lb9{ z{fp}JA%8!Vu6E$2vyVK(5qrqXFfXV;9VyFy#TQTCCUcZBpmxcB4x_#oQ$iF$xj)pj z+_xKcxHmex_y%j8YEcKOO$=(VU zFL*rKF2tA$%vdXut$9*6U9*4*r_*v zWnH|#{*lwxC%R=@hdgg_4MxMgwwO6}x!f`$z|v!h0vs{H3=Utea2Ug%V?0ht}x{xCf7y1_XjkCc`DLQ{UFmp2)Q z!TA$itrkC{`nsZr>9??@K1)eKV!Oh10=7 zi%LFWKdcUX_iztWeEs*;vFN=L)lqWD$c&5xwEAEewi&hJEjae;@djk-lV;SI<)yz@ zBI{_(-s3dKfF_}C)aKzD4s1AFe!o97_xsSU1P?9A$}M3(m5 z$fa&k=h_rPIJPZgD{(z!p7?i?YBL%A^@S!|QL1i##G41qmlrATlXtC`r;ymMj0Ikf z(qSxmn(rNs_y$>0uH{1}9uknC&sz#VFu*qp=++~0O2dFD6wUw=vAa%0ICYizLsj;$ znEiAdN~c6XI%Q-!BL!`LRW8Tg@G&TS;m(qfbEMx?<#LPrsl;ism8;wAm~d`Dnof~P{O#BO64ouj?GXC$i2#6lh4-mj1bT`ow>aO4)&OrIJVZ2h2Xs3I_k+gvzCtI%#oXnK`;>}9gURti|MbegD}H86M%q_rfALFufE2bo zNgX%BzP+UlzNXurap|fq48*|=F#fo~HGg3Z z@LPj_>0S`jDYM@IMNVCwzt!Uv0ku*X9L+eCxS63F*Xxb*k<1c+>J;&PP3uIQys5qH zm-3<7*8DzJ)Bjce@JfCxZ}p^4L*=S*Gk=&;wFd?T;G$>_c)$A`z49I)=8O0Zx6c=! zCqFHHs#Jbv%4{+~<2SL~d8rq)*g4nNH`vhWl^6 z%_xTj&{&Dm3#A?}Z#4CYvKEl31;Gcqki$!?jyC63M3@& z=(;-wnBskBDHP*i7#MYdb;AV-HAIn|LGt{&z9gTAoI@^05!{L#yjBP~NC~Ny4n4?Q zP;*F7Jm-}DK(JpD&mpC|a;WZ`m3ke2%r8_DOS_orP-18l=TW}oO{!>I{-3tna7ehu z24Oict~7S)FqdT+)r4{}yKlR)!Pn##CMzE23;}q4IXALdX4Q~EF23k0_wQNwR+wwz z)A|i_TuP5h`aGK7J(`!4UVNFYE1>A_G3d(h2dDz*g3-qZc>nLPR$wTzE zJ`A3Nnqg2T^SS=X)G7uXW3Ed9&8<1?Z#|34aU6be=ae~F3>vS@2cAJPmpL?3>GaZFPh&m}XwG$4S&dxMj zAikA2IDoe@*Kg$txNEfhULD4N&xfiUk7)rj0e^wVq!uug^_?iq8r{H}6R-I79sFWx z9Q&&4JigvyDmCx5`o&R+i+Dv}F6(>+hJY|!qAdDy*-oCbV44xy)ivv*poRrnvES7N z?xZ)?R^STmy8@>aW22Kne@UELkOR5nKR=`U%K5o@6WSUMgz0Ha0NZwd;7w?D&pE9%U^K#lhC7|tp`}WWr)x2hs-qK@6 zk4czhM+^>xXb71f=G`C(K&ZGJQP2MK+cXY|r3+2ozxKM0?5 zTHg`6@XC2@TmT$`G$eVKb_J-wPDBzWB}YTDw_ZmcN&oQ@eRGdcRmQC!oG{_q-c0G5Qa={FaE7*uzEb@|n@K{|-JlyiDcwZ^mv zydKCTVOmFK1E4U1xege8oK<|%j%+h`2`{e;*2MoRZ$oeEQZ=1W3)_0xgMp& zw0HQ~SGycFQKw$z{0(YBnc5^e zRl#ENPhMLT6Sx|3*5X_kyeW$U3s*x{jnCbv;MUiFuIl;ic+RkFzvwF#?nL0-=oeMb z(`@=TVHm-QV-lc#JmV`jYyC-G^1u4)FRAnNvhI2HuSAQ1370fatbSFT54$}oN>pm;2AS8E4e@h?RibJ4-054rJwkIuJc zK_iZTo0)M#-II$+9s`-y|J8U9kK;^qd>C}2l#Y3VYeQOb`ogMwFG7#RGkKg8{37bq zM5rpt`jPl1F=zT`8j`dbj~`0XyvGYh&7o;QMqV}L@8<>J1tsgb`hkuaSh*)C!YB4J zergHkEBa;uq}DY2FgC0jHOY{!n2&239+5A9RWiQyDmfMH*cV`nU3D}_Q_@R#0;|GP z8YJz)2!<6h5ZLV#xH8adx!$AXY_x18+EWq?V`O8weaa*uIa4rBnsdvjLqMFSpLNNb zVo9v*V_|4VzJ-k-Fei8sLvmrKnA{Y1^N(8^_=RXXnw>VP@t1)i{?uP*bqzu~cNSlN zRA{?KRKjD*6BVwmS;)m%@#TgWV!CUPR+dv$gDK}`tzmTpPPm3{M}aJ0MWs6mVqE%r z71k53yq{Z9CJR`)@$8tw#UZFD_OYQkgS^dxfs!zK)_L%F#)944{WlJZr);`AAw{I> zg8}E$@$;eyb`k;Tvs3QH6qARJ(HvQShM0IGz`R);9lPQj$@rzB=vWvXEn(%sT?Ch` zqgsm{x=V!*J`Ubo+JzPOOQ!N6>d2l)TW={z#|BNeTn|p>wx!vA*kgJhJfFlX$}t*Y za2)S~%Rjc|2FE(L3A9>j;M#CPqXt?6dtAg1K&4HXdiAMGK7EIb`3vgk5@6lDFq z8#4L+hXAeBR(t@)DHwRH@Ah(1C$4XJgU4csKOh%W6Jey!XT!MCCbdCWYQg%Utm~G2 zIwS(mB~-0^{|IT8FM<@fI=U735x^TL5N|EVn^H%D_KVgLv@i#+WtI3rSy6y$-?jY| zmmE)|pj`03eyGb6G>*86H;RIP8a2kOMv6>QtSJ~p>o@^?DMO;mHFGR|FxzV7@tKe38%mIitl=**~bl~5VsBXC}iq1I_q2v>w6lnrwTTw%vta!sE~fgrD{e z<14G$b9aqLTm9HiK-r=p?g$Jx718@#1j8aq&5W zoK34#^coR*l@|Qw)KBgUpog$Z^ebhteV|Vx!*)(&EZKS%C@raIGN7SvFuyQ+I1)+s zv6BWqZuo9#7jTY}Qe&eV7ep!V_9-vws^IM?xZy1&5gly!$&^*F)X9QV0MoK2X!_*B z8gRSYzPvjDFp@KWfx_oCfIgQ`Cx8P|CNSb@4HR%s!JJ*i@MuvJD3!DZnJ=z;A}SO! zA-XBF*`6`~P12+ys z#94On{zXO)Yz$2f2akAd!v#R|pEcP_{KZvWm%|{2FK{+mI-<^_UaT32mSQcTZz&tj zTvNlz^6a;NU;o>5cm3P1|HCZ<+$TY2o9a-v?DxXKei)@-2)-^ya^;EFMBzX=b+4uN zu*)vR+!wO6+*<5DamT;B^3Vi`wvrmr_jagkRTa(3ZsI>Efj+^$$Bk+tU@Gz%*&b&N8ym5AL0MaDkN>QEwS>! zztgU5%3Qo(55+DooAz-3a0-ku74JkoHZ|}g1^L-G;sq8284-NDs$gax!QTCimc=3U zM2+;&;Cd&-HThkT2j#z4nO48)-^>0UFEr$rb? zoM9e+#-2CRaw(t7II|wPIO^`9fc2EJV7T&d!>~l0!BcicPfQTE<){U8W#5(KK~yTF zu0v$X%Vz?Afd3@CXO}7uleuUo{|#%fDQ@Ldf~hs(z^hZQ!5==o>e5Z_i19FADdwxY za^J2*;gTf18^ehEMkHpC$VS%Oi}rqiUY)3YNk^Eo{3H^SLT&3YDOHE zl0hP*kBaPBRv8gBqBxqolaF!`x)RG$&gu@ZGke`+B$`_#Cu&7^a{BYJ-XZ~c+AMGx zRDX=_`4;l}$B)BWhJ21G3q*E_t8>SBiK(Q(EoHY->BNpsr{Nb>e2 zM7ne(AisvwN$-d9?odPQ2Ux`(qJxhhx7;#UEe?i1;6_VKi}AeE0jVJ{2~w|shu=Lx zMi+b`iD9-liF1lQeP1>ujfPH(I;dfaYCUBhTcWzf3GRtYF_(HS6OKij zaFUh>lz*C*0dH4r%hMXtlK4VA9BIIR^6OYOyOIK%oEEBE^h=qFK~s(dufK@UKZ}kB zmhSL4CUrte=ZTsITifs4H}*P|>Pf3>Dfa4829P|mn#432Ps&2jjgvxl3BI8;jOTGA z?7pbPVED9%ZJ9Utcr4CC-`p1CSf9A7amc;VNleUQxTIrvVt)WNvR z^$#Zk^647oP;5omT!Rpx8Og~=&hzXI^hbZlgrscO;zA-y0+&_;Y$$=G=WEQFywVi2 z%8F&D2*O^P7M2AtYU-}KyA!s5YDVzZT!EJ{Wny8&Cz*YUqO8<>*2_wSH4EU&G+(Cp zo?}=|QJ26d^H)`1!bBxjUgqLc7|&MUNgd#&xb54|WrG{aXd;o+mt9fyjLn=l;sj;q z`ZnwUFBy?O$7HMmk)~*$pP<|i)ov%CRER{5r;0}Vq=x*`%sss^k`c^*EJXZp-x>x* zKta|jG7N-Ac>wr#uOifz@+dEW1~wtmgg zmInJ&pWPewyEb*_5{X(sltaQzlCAxe9qFaVcR`?mqtOo0Sz+W+DHX!KmKYO!S=za+ zQM_yzwUgGCCcV+V{QVao2%`!#mqyX|Bs^?bXQAj5@d5XAyf{z(Y+M-m=S+rgLwnwG zb4g4{N#FU%0XQJLG?(%2FA9T{xtM&qfAv!vfhMsH>|dDkr{t@Ig=Wf?5sKP~Kqhx( zx`{Sxtt7+*fr18EGhL+yHW=L0VEgi7Fc~>+rs#&fw;^&r4~4#_aiK>;fX@@?jRhW>#@&0n;rm3FEV4DAcC(l?QjAOYg)|l zv^4DpRE0ELV;gCz>K-ojd%>f#Lw}(>)`x5q`24DarDiEbVL`oh)b|Oa?b!UoG>3b!80yMN1$P829EV zW4XU&Hk@mMCXg$FR@jn6744gjMoTd;=$Vm*@q`kE$;}bZ$o>Y3kXy!q^wd8{Y_+)s~whG+u z%P&~lYp1zZ>>I`YDhl9j*@T0xe|MPrFnIochv3h>KqBvjA!7UoeNLi0dfS?qh1C>I~Y3zE5Tcj0cK=sl&xGl^KPm$WjW3sduQXA`@W ztN=FU?W8$`aIjRg>}2IrIlq6GzBz+&n3Dcc$Pw3ochfMgHru#axjZt5PzovJteCCJwjRXHInFriV6@KB|EFqc>^eTX85r+YAbbBGhlM_Vr7 z`)QI7mYI^fZ7mK-ljzSQ)TkT3Wt`z>@FA(Vc?xF#%F-Qt-aEu1T2S+S&l0q9Vn{tn zuFWHm@j7CpCLcG#MP&eJhQu$~j|C7hOtiX~kVEJP3I!j#IWx!H@Nw8NP@#2v@H!P$&^C!38{YR8(-t*0=|NDh=0rNm#rW*W!u z-oOgDBj|eiAMH4ve&y$?#$!&Kg@1nDD34ypscq;uP~#He&!sRl1zEY2K$dxm#@@Zc z=vx1D`ep<2UC&ff}0D zG*f!f38oV3%!m}$KNkY$a4AccenYCU+0UQBfw;C82C+ju6*=gsm%*2dy@RO{5QFv; z1Bu~uZl$4`lj5Si9f4JWX!jwatA)O#KMAo!Kxm`GU>$>lFdEHZwWf;>0FPinvVl>v z)+cNK#U?I2^X_^QGa7+4#@uGkk$ZTtZgZ>sw7js3C%up-#te@JENJ_SD;YFX-1T=I zk$%~PTOOrtXUKOw@;KAXXn$bX>aA_Ag3zo2`a>q&hz}+Tb~RXGF%q}AT%8u^e-PiD7}1j&{`GojOC3gkaM|$^1u?RZ72I-&`ReF zkoS3$CIgZMal_w93Gr4}`iq6Qy7ozS!=C=?>MpYKqW^RvwL62}x+hAjrv{#&8_gYg zq*}+5_N0a&!qxq^SRDC;n#T1tGDcN>N;-@!>+ca=2mq3rdW94pfI&)Nq{-+h_E1^$ zbX<70qoeWyhw|7}+-NIalD#C=Urco=An3_4j%>OFk(d*V8}S@IvDseiZ7XQh+}Yq! zSuB%l+61$_GLX_`IB z7dk30P}A3Xcae&>)lsCxs4bSGmTNfQs==d6^kV}S;UwLEdjPJ%-~bRb()Qhb6mAad ze!BDCatr3Ny^)=zBR*3h>bZZ3781d8mR%MTy+EYCebpTUEDJY0Uup*w5Oncx-MO_{nGVt z9Wh{}9h=6{O|1vf@nY`5X~G<32#|HPA(QC^-zid`HUM@`#&qjq zsFfhwLKD~~pSqu-q+|14H{2TveGX^kp1K)vG31s0q`-|3u|v!?LcGFx^4s1rxE2O(B6JU}no(QW~!S3QU*j1`(Z3!Y|UjLt51)R-9xE zs-^-+q;_E-8Pj=4l&<`jDd{6vNvUI8p|pC){SZ>h`b+T(l^8eDi6Tg#B|1V3_VST~xg z=XZ&Ux_>In;3faN)l0A)iTX%Hfad`j8LnXfeevkS3L@WC)4f>@b*)_u#enGv!?Vh_iYa}qiPGw2mC_4x zlJ5@}3GDh%a%-4Zn~`sGD2%ukcxb1RCIEKcNNMff)QmJ4x+Fy(&2ECkRjL>F&)h4( zoW?mH=t;Zyr-Cw#U}g&HiYj%>pW*j&BAe7l!K;Z#5|IE3azgC_kp_gZ6O5E=enKf; zd-mN5nUk=aJMJcKpA*&+z%fQ>!I`|u+)uX?kbg3S=W!3)aVfk^R=L&Ail>W&&vrk( z&0)jbwJDh*7De-i@)p%1ltzOTu5`Qs#tik7Di0%B%o@7uv-YXt7{*lg zmwU^s!|uno1&Yoz5Z!=3FxFi(4;5}B7O-UyDvAnk;@#DM@YaA~Wq32X-3|jF+t*9R zhT*s`xk8K~&pNuDfGTvLSX7;2iCRPwQe$^A7hwFr+n7AI*C}u?0wg~AGWc+czFWbQ z+m-dtZeRi(s6N=eHt>QDlpf5#9QcDCR0XU%4d_4*$`7gstfU9!A*Q(^_!*y=@`g{x zHMoV~N@h#l^uFtkhNdp9ZzW{VYXSsk0Hp+d2GTNsibJ=y?>J5xZ2~1{sk1bFht(Wrbi z6Gy)HT_+hLIMzUZ_6AFtaI*$K)b01q8j=aL2L1V~2_9awGHu`iI9c|cuG!Mq1k=>@ z0?=i@dv5DFhcVK>Jm*xi8s!*R-pCU5rEvKL1BIACT|rxb-z=p}pme}}CQwqQ*f?ow z?J;pyk_wMxg9&PEbomU_?5lmp>fth(owNMZu&1k<0p%cDRK~agu`fj+8#5@0x>wsT z@}e>LhAHAn_VutzzaK=p2t$j$8aeF17d?crs|}g47v)Dje$l()cvl>fGb;^MzbGJ+ z#K^RG)$iXn^)5WJye$p{%8Bh`znj zOd=;o#^u{Xx75B!r%g{K)~%l!D2<%wgb zOLR4c`JS+U-TO;AwXSr&eB7v9O`Eg3;7;M6Sp!Rx(&kx|lP$R&%Fr%1{1C%^7zZW6 zu=At86Yc?X1@Ljfu%~!La6FcgaG&f59BQ5Y>EOUzW-C=Vsr3VAqu+B8_NBbiH>aT= zHBP-}obbE5eXj*(l~Cy!Vg4zFT369=RX@~TF8Kh~dN>xxRtkZiz*gV~ z3n(tY=B2%*U{HLqeHagNAQ=X_lPM3R#DR&$NdvFPWy`29=M0IAt?!n-;F=lZ`384q zP|GLNJ`*C3>PddV0+`L{hwQ%2r6o;$`Ol$=ST9|ToyS@)a+A!$qDa{YXAou{n>>t> zRw-RHR??J&jR91*i%PCGA(DaBj;#G$m{)M!8tMY{CN*x zgGVq}j`a0&FizgmJZTRYOTa|&hmOPTgHQr1UwuN8bL_BLmf`CVO>5AZ`o6vzk44pH z14%Q2STPu<0Qq%};0bTBQ}i<}0)Riw`mpZtA*#k_n@S*&MQaeXbro{OdYGhBKN z>5r)WvVcr}&0dV|Mh72uUx{3`x5JOHg;3|E$h;82lN7dO?l$ykk-ct#)|$bIztz|; z{M%JX6%Io;Eqq%m%UJbPrv^7)#ppL9zgIpy=<#kuXnLb!)vQ5TZFOrasNM4c)m!0* z3!>~Pi=Ryk+r?cISX$yje=vhwS}5DdOKRIcsaI{;3bu z-&U_?=KM75S%N4(6Kguj@XhP3dz;uM{W*@tzu$H#?a1+iROo^2gUdIUp^-Ka91d=MN5*rfWHRK^67 zjACY;B(q-=u}*aa4D_OHCRzd8Mou>08}5H6LA|wrT@2|Te7p`mdOS^YT*CM(+ocS) z;>5ArRXXShMFS=MyNDiG=jDT0Sl2Q>wYT>waIL70f{u?hLc!VQs|1{(P6~cuI#FUp z6mxxviK!N1mvxO4Lp9e47)a`oBo5ZCb>cFg*eh}*RsGn-I>e|9{L8sWP`*>e5_wdy zg!Z<^L_<(BA=1kiIWK5x&dxKaBIcazP6nLh02KriTm!;$g7O2VmtXG$u%cNZMwVa2 zxtvBcdOdJDNSf(F4kguBCVK=#yBTw%S}-QERC?4YBr3i?|@?i`ohT8BZX*-w=pabdj12# zUy9}y3XBQ~`aIwUv+i$0zYH};x&)z|@Kb<-{^d<%lnzfuGjDS5eWUPhv-9ZzG(S1 zNnNba(9i$M46QdWEqXr)kh_5|kaRc9UUWjV_n zO2jxN`ggWx(i8eD$O!sA;DBp%xg<`vuL**vu=D}Co5N~?=%#Q$4;%vg?V^xcfU(YA zzn(z0>pe)fhQ$_J0Vo7!iac`;x_Rb~lUnjU9T$!%=zx5=)Vty@uyj~qI$k(kxw zYuFNgJ%@TSfNGRj<9LJvBdyW%!bg5Zc1k?35%ZN4LkWzvI2#!lF^$TTCP&EbkBW2U z7e4_)8_P7l-OVkf0|g%)>J^^yp!wWHf`wIPc|g>EgpT&)XR106)JiOvMrv=+u+(V7 zPoVn7DxpHC70E<`jVhtsFEUIuv4;SVs*1w!omatN6M7RDE8bLoy1wl5_V49M>4qc^ zo03vAPw@W==!-#37B0gB&2A5(bnw$U8>+rTS&R@e=xIyY$|OF zOOShJOZ6s{!1CDi4NJEzKIHFM0E$XXJ)1x;b%(%14ZDe7W@nSNtJ$NW`sdY|M~GQGYT^h3T$MpkWNAYz?4p zfdYP7`qm@2**P>^N7s!2j8#i3-e^VTvmT8P7bX(zE?#GI-KCgzE%m2M5Gnld)z=Bw zPfwobeDC%kY6ffs>!mHfG~pAJ4w8f5789=r)^)YS5! z4|Zg9uVUy;B1NU@MvCvW?R(iDvFo67LVkWu_V|GpEGFB7aUW7X#kiMMn*IB48}t62 zGRw&DftuHF%OSX411+<6gZek8c>*}da7GyXYB!GD0Aj7HRP7-#H~>=s908y-l_;IA zqyFHC+(Zqcj+B&-cWW@jsoeS;$D1?%FUPxh1uPNiHFUizG=;ZN6p!! z)NFKF`x;N|uaH~6mwAeng`5V!d(hL_r9Zwm=|Ct!RRVOAm2Rzuj*zIsPih1^E;h{#GhzSfMmc*xJ^4c zTZGfR!8q$d#ZNw5Daj!UNhTwfTG_GGIaRE-y)RXhgvO92tMS;_Tn>77q~TBOT@Ck= znSMh|N}*sMpXn5?L^inbm`o7$&bpVSd4kVry#IN?uXJ%7(yrfETXz6UIn2C;X-sYU z5!-OB;Q;u279Z-oioty!L}Xk6?`HLp=m~z{fk+K+tj?{j)Z;&v)NvLNZ~iOhxZO^< z8YSdt=3LS^0L4$fH)biZT_fm&Ah63t!) zbvm=@ZxH&Y?svpgi{Q!;s(`Z(GIH!No&%2x!SE;T@e;I!z?MyPwZCy}1<~{32x4ZG ztxV8N3hTS?v(`F8G{|zd%NzDLF0au@d*{R2;>kv_wlgKE;YWZ@9;##}s&yrDtF(($ z>+SQ=e%=|wtB10>^GydHgex@y$4mX-H_=|wPzuh+;AL}?!-XSb>zQLoZnLy2XsbmQ z;7Df+)AcQDp_kHnk?YK>tWZwQq+&@v-CNf#2UXkUBIng20^u?ipa${-kHYHDu0(~E zvjxmTFQUllq#od(3wGjL^k3OexGI>ou)9iSel509B|=PBb6~OPt$u|O3FcrZzhL|* z^oy;1kKJq7yl}`FGindaf}C8;1f-Mdb3w00u$nf>G-Xvnr&WIc-6;WbsJk_@*B>l3 zI~T))Mt4u=Rj7194zpVhruUx9NPj85AP#+xSbE9#Uv+>(12PRsbzBt-VG9P1UMFS{ z@(;$}O5y1RA55(m)ROm$3^kR)y-dx7yj?(EUPlGS6E~%&7YglgwZ!J_sN>f#Z0+ zJh-W^NWjgdD~1j|0hyYkz zPSTF_I@R=7VQL+QF`ktWS_Ikv%9TmAuoV(tl|Nv!k2feQ)xGo2Jf#RxI&X3ZCJqFP zK@JX58Ek;`@rpaF0eB1DTd);&;X_XN9a#(~DuPN54z(y{GO5-s{zS4FqR25<_!z?Y zpRfl>hF|QFF~|d&AadSvlxM$iO{bkm*O{4J><0sE5az4u@J2&IN(+eu$;J-^NLCb- zy@mkf5uUv)#ck~FuHa<0ATobhf~F8Fm5Jb5Xk~~rE6TMix#;cpI-CpcSH|@}l1tVu zt0J5PeZF2H{$&}z6P zewKs#E^V;U{cI?12_1&mRGLB2Sy?@_Dc|SVy+z3~gm7e#hf~r!E*Q$Bs(2(`_iiSR zR=XLp>x0NM2cYw=zR9lB$oX2IJ$?0TX^fBLbNf8ypP&a1+nH!a6~|;^hU#HQOr!!Z z^~rA{8Knst`RAC^9C0!;C6~+hBgE%Nje#Z^Ym})Es6{fg8E1&_c(d-59p$%aF9))> z$}0o_PUP z@ErVz7e{8$N<&Rh6nG;M@#$9EJR5*=9|aC7nsx0fHG8_T14~SC{BArX#ufrh)&y9Q z7Zu1LIi?TJ=q1!f5=61nh~Q|eM%Z-E)8Ez)HkK(q2q&0g(obv2e4hJpSX%LDYLSt- zE+mc0IlEwt_vqt&xh+GTE{^Zv^I^(ETo9p71qUT=(z|1~GVqgIFAv@ftl|Ku@lZ4K z3uuz(UNQ?c^_u;PuAmzQVXI%c8Jb=y&D4UWyLmk_2lN-Ni(6A`-X7sGr+^QT}$G|+4PEDM+i2)fVL{2_hH93YRj+v0W;(hV9Y z)e*ki7^OXh+X`^ua?Oq@zF(6%hSDfL-=|Sn>X~Pz#nlinBv2Io_bYGrNdS&FU&avB z+Go^>f*8YHFm(!IsHz{p0Tb}syI@y6{j!%RCujp;kO5uD)T*I{RP{*rMfZlcLVKO! z&zkOP*n(?x_%la^N@QaQMkr9WH4{FtseRhv@f|};MhM{uNx%lt02VtshUC`3HA6)( zh%K9-<4N?iJtYuRJx?=ful~|2D^O~*hdxmvk<@M5rC{v5B%2waxPmZSn!xV#uWO9* zJ5}6Pqvx+qixUM0pyNZ{+_)xDCZNxy4^h1+#xDzYV6l-stCuSb&3C%|1vCYR#~%hA zH!oK&*~!*bwWzp(#&1d{9bk6ep26t~+udX04c8^7y%$yrEnfy;{+z}wzS{rso!s!O zcBH_i=V08Z1@!=#CEugd7He1r>#di9wpr0jW?9k1rLitn6SL^cSDUi8=#FdJgB-_V z=f8P@*{Nx9jU8-diFhlWnygeCb#?XexCZAsQ9>OUmzRGgE;E;eDde`|QvNUYTFRo+ z%v4JbF~Vgp?X(GIys8bMzc#;bVyKvRnTpy^WP}9p7%AFjrBFCZ%8U)y?d_XyE{faY zZwL=;5l^K*q^4Oy5be`EK|n=t1jm&H3=WRA7DULi~^>%6Ie>LN(I`N1296lS4 zpdZeWEQBsc-NL=h$XGniFo4u^bC@*R?gNPwWCv?=R;3jI!4j&FM~-(OKIhG>T)3Y$ z0ef8Q+(a&K3uy`yhYP#PQPd98alzW54rmHim-Y0_Fj~z>ewg4DX_;evADw9S7|jc- zI(5f(1KX0{|5xXave&>qtJRDmWx}P{y#kfR)Y%116A|m|PS5(o2H>uqG6V@LA^nq$ z8rooLU<$VYnRd40N@s6ERlwt@g|X@0q$hw%G9#Vpj$K_Pb`~zl^jQZL3tn7258cPn zme;~WC)Euae)Qr?=XWThrR_2OHgx)G+cw*yMoCN>RWtboYc^GFKAffR>yxK)|H14>Mjwy%NbhBJ{$Hj%aND$lTCQ`#`ABvWtxu zW7oomCbOSJDoxSGFgXK~dmJO=te95Yf`PQX08O(c!k9TTq;!In2A3oMT#&GM6Oo$@ zQ6M$qf%a0qiT{@SW+nrIYAXlAw~phfu8W}1n#S>CW@#-?Q|4m=&llIQH9pjglYHsf zP>0+d^nHjFh)pJ^et9#Pr7_|%%usEgs4N zTI~0cZBKQm5EUTDg8fPQhaIJW^>tVyoOG<+CwZlbE3X z}BL7TLD5hBM`Y|_*N&^ly;?H4zgWb#u`7CVL$nzrxBL|6(|C*`9b zOp}vWR-Nn3XT>ek20*c$buG=Rbb~h&eoPA{Hi9rKqc<0C;q2c&CkDH*qb-;)^EQ#= zj8z!MKS$ssb~Jpjr+w3`9T+hwoV|zH{HHv+>mpckRYSa(-sfytVBFIjS1Vwcdu1MS zE_%TX``bVd+urY|-~81MA(F#rYQJIIaX3Y?6QSmuHGF>gR!y12FQ!#~yefOxWJq8o zSR^OKl31?8T8CIrmGe)gqX`3oV}0Lin(;G;Qrk0RqLH44N1@_rIKb8^ zh#r5ElmuIBssVitVp35V;FCc?QAVR-#QtoNZIK*qrbB*c8l~e2mTkNaOFP?8eE6d3 zKx(Aoi0VDI*xO{bsU`6#pu+}bbU8cr?aiGIUP{g#7+sImeWvwn$?NiV&W`>M zL}HM!>i%8UUn?jrXV+$^M~qP5egO*!9VwMgG@*Ktax=?yJk1qAVp-51fZn3?CrpR{ zrCR0v15MKJ8oRHa0V-JUi}3ORRQPs#mv`6a(1Y6e?myw-{rFGqoba%D@={Wcj2RYUdBI!7D)5cp zT&Bis443x-O+87wd&J8-V}lKxstqRM37069qBl($tR#EBTE{f&|7FS$&a8r)tRa-FsQYiC zzUKf;2a1#_2e>TUlvz(C<}zekgg@!|=nmRzAf2-2MUy5W&BAfKzW$x-;$x)@Q zBSK>>_|SEx0PeCcERf}~VvPZ7SL+V?Y+>8f%y`A=0AtMK+AVTflzh(L0vg zp8DUBOROpS=pgI&Y+&bi`$etNd*Q(kxah$M(Udm8e;9sJ8ND#GK>DV>Zgr4s2JkNt zJ|R!Z1J-aftcZ#t0d5*&Jz#-3n0fnU28uLbOlE9JC8O~;{3F?Kf#9n$Es5H}$U zI9Nod&Jn7srwM~3<)+S~#vj&AAS*kJ2S`Qs%74xOCJ8A3G^{+oIJK2h5UYp zXSEbC+t7giL-y6rP39?9%p!TsNir<6(9ixWnGG)oj&VA zu*ASq=wnV@YmQp~&9sAp>#$IN2)G&@tXDNI*kS!?2IPc?z|8grbWo3B}6BTBiTk+a#kE_S8dns>H{!rM-^a zxIZ{f;fUtRbdx^wwEi-!_;REO!65!qa5ygbH$KYVQ>+*= z#L^orIQ>N#=m|;fLB+sSluI`ORISl)a-k@VaK<*L9u>p35ybl4IIfMM;(_ONECnt< zrVEhcCX`#ZkdNFV7?_-Z7fp0f_tc)GtQN9Ig%4iE*EL2PTD!}VIARZWi=UYI&p~Ag z^?4d4D2(BlaV?_s4%dK{p+liKNWT$sb2hlpPO&;Bb?YC1EmdWKd{r{ zNm3Y>74qD?!6>vM4T{rz zvoP}KkiL1{moLX^@MVZ9kY$Edy8$L92kYzN*c`vn0Qxj(SwfdpwHkvhMblU;WeT|= zR_G<~)*ydz*Fgnr&$H4MRaN8Q-|q`9s#5;6XUd~ilfe>1FV! zye`O3)iX%_H)7>93~`S*YEt`jw1zz&8itgRxraf3-WL&_Y$FbDv6ZAd3`jm&hmeZp zzrY`oIgnX-P3Rame7ATu+GX zD*Kj~!^zf8G;WT0083ae%x#3Kfaw$YW{?GpAGOzG3;qV9XX9@YK#sQ`&r}136#FYc{7QyQOi1aHoI&Q!cq*Wg?tSOayPN#TsVCzLvr!tjcoRR8 z&CSZjO6RJk!h6Sz8eA#-`ZN z+b4uTofqPFvJrp51o0!Png!^Ep2~eNz|*z*p)1V3UkI>`n6oc2TKZ=p65dV@qE0=h zg}Q>U=RURcyqeI4`U-j#hA|W?TI1Ogr4*d6XZnyV^zt4%m@4}S>pBW8O_ax+80&^4 zB&Ow8rC$XNa5vzW)AOr3)Ic`#Vf!IT3L(UFUK%5?zLMZqez{CMOgcs&{V(h%lLV4} zLPrg4ByEa!lL>l)R#zQ7lNNP-#&oK3h>Ute_?00;XEz|Wc!A|GneA2O~M!swM=-On7T=(5@TZW@FeSgF{t zYmZhWABcvf1d=!BExKnwo^+S8SrfB^ZgbF1br*x}xpxFtrr+pu4ckXfhdYsDz#eWr zM1{%(cumF*>@lWgC}PTjNTY=g5yqdWsU_toZ9Yh`tA(P$61fuYpt|s1AZSDIK;efx z_8uHx)zsgAYzBED?ZcIRib_{%3YJ|_cX~eBL+Sjp5hGXk{fCLeD0{!f%4uX|32=vbf*P$A1dNd>0w8fi? z50e4m$nbuJ`x3h@N-DUkKtqCyjZSL{Va_du!v9lLl6+*mQt`L;7YKi?V`Lqf$hRLR zAeidMW+n&|PNm=Ius{h&*qeVsnw`z!IHH2P1)wgXPG`v2Z)>yyJeoHn z8i!d9S%=&4Ep@_P!Pi+d`m7@0Gs)^}Cmh{~X22WvQk4GB+{E2Tc=_s(spSyBT2GBX zgq;f2t~i^nu!MTzr&#x~{{&Id$6zIq^2t)!E#i+^oBM3F0jZpWEQ$q8G`^zfH9b?2o7rhY{y1r zd-?cx`C0y|z%J)$?IDXxxRc_jmvd$wefl%`CU=TRMrq1V?1?}v8!!hr3`n`#TID-H zENcI`)Q>QxFlALU=;OLz8a<(?=quV#H8SkqEhC(zC2fp5VRjS`LCO?Anf76F_FlMk z_1XCp*N+excsy^ImJ{!<`=QjowGir5BNc^(ifEtbr!MaV0-jaN){&Od_-F~&i;?`F zb%z=#yMj`}1w>c?)hse&cqR z9;nBO#X|1hm-x(DribQDSp`gFZRkHOwXjXTq$R_UGPA+IC!rCpNV7J48clk%tRQ^^8)pRyk>A?N>B}Rj}Py5G(Tj zh~<3au!%*CALZGZKB-g9(c5;hC{FatI}xuK^m1zd{PM`g8jA2It5{2OBp!p#SHV%*zqeK>aWoP1BX|k=Smt3940=C>I7(-Vh&Vjr~bD zY<4Ys=P^6;A*&JpLo0WSy}$63+d}djP_jUDK!6Y(o?zC8pR&P!DaHn&H=RSiAtkcI zH?9;V{)K#>Lg;Q_7F)i=;(;PHDCLO0ZPip+G>HGLX9?cW>{4gdF|YS(nK<14-O1%h zoE7K^llr5P{YfHQ(5dDf)Ac!+%G*#Ct3M}`l3&8<%^^WU*#Bry@TyUk%5V>YE=LC- zG1xfr<0G$B@K1*3J4!+Q=BgOxC`TzFl->U<{^FLbGGKWE!ESV+(Eh5+u^INUlF?&7 zze*+^8xsSSi~FU)$~0r7=SKJAUD}v@kvsaUE9bbc z!e)JS^RmX5zB4RxX5;N{R`)w<0V)j1AKB%%R_Wk=A^X-jYb@Wc_y@(KhT%V7glSDM zsG~Q5?`cVlf}N1|MimE-ON={yogUpMA#o9g z{vH3zKVrDND!b$A(9A}rO&LVEZ)_p8%2NM1thHp=`8$ho&rsOJ{Mu_{zt&!6>^C@I zM>f?c44>2ls^aR30kFK!u||0;0uZlJ_a1A__NK9-e-v>=sNi-;pvPF1S-BZ;Dl|`y zDPN*aDmwtFjgtZ8EG%MDvY>hNj$?hS^m6h1f9bA0^z*wU6uV{EjJOArzw5vGgN{goWh% zw(YB&PI)4Z>*>XcFm@zjYKHV1C-&DRcW325@(z=3%ToZ~tng#B(Z0#W3@p$19=8{2 zH?#5*0~6dUBpKm77S`3vqzXo+j3b(Jw-B@P6Qo;?3cuY|$^UXWVE6RcscVWW%Z_@o z7${s*JSM$ntl1e0QG=KFe>pBXo*!RPe4=`=xi2_|`Vlji8gFALUDneP|B!OoylT;S zPLxLqWi)$l!r)~e=1+HUblv@KD#4$)IvBqX9)@5P4_HfAa8cV1flm{wHfT5j6+r<@Gmr7{9q)s(;75FJKh+cj zzEA-mc92Wx=@K8E6PIV5(>N3b1kPASB8b6+>#o>{?Fjjcp)Z~sn9c_U^5E7Hh6{e@ zOhtmJgTydXhbY(Zf4_IMhjv2r4`d8zXL~KDQ5jvoStWTAH6&<-af2v$z+I|*Q!}y# zv_phMdjNHgLUTH#^jFsJX`-svUtQACo|u3U4<5+-`bsXOu%7J+IG0tzC+0W7>*DYi zOzNRE58=9zRVShZ;?mQ4|A|!)MLPK1gSPaaKYTr`>Vxn&F#0Z=;rGo{NAWO5L+Mcy z9iAUOR|QMiXuVwc#|A97R`JU<=Eh=2pVkgKFB2+9By>I=wVisfbhD&FZv(6XG*|%W zFvcmG^sz!@g_`)N#sJ3L{6>qLlW-3jd|)Pd6eK(@Eaq~7T|sCvlXS4LLxqSY;~m8( z4r*g+Zvb6H<(AW#2-buxH(|ptanu}fi0}^CUHXR$cCZ8~reUz_|M3vj&H7pS{ifopTxv zt-EhN>2QCL^%j~KNCY!Z70kGP#%tPuQ~Y!|3h8EjJaGXWoq;cK_=_YEm_cdDn;$$j>m zBq+py9aYllI%Dp>3t(_MMH*Lz2#0}(w9knpOC~+DWVbg2 zmLoyShPtno!LV0N=U|_De+j2}PCUBDsWl(2xCrxMc3t(8%=voXH<+gM za3#;5oP{GURCf3=5dm?YUp1G3T4|jfhxa$LFa>%SVW9`Xa8g_Ruzje%t8q~*Fiq|F z_Oq$G96I?7o?9W^FaIr#3sNFTH8&8@7)d-^xM`VSh7xdG$@#%#1O z$F5QLd7RUy{zPzh9#l9Nu+im>T zT3={xps&!rAN;rz1@tFMf2PdnrwIhi2+^i&nOb$yN>e=+YB^FATlx$1hwLPOA^nB+ z|LnnE(sixI86Y`4!P1ibqJ)jjO$lT6*s_#G<+i>%s@|6@&% zNN6!9ry+3Do%1TuDMKakB)J2ECZGXx&vVk^juJL@wsKk&N8^T#nd6#qr>WO>;6$O? zeLc&`GTJEu_2W%hGkPS@X6*AAuEmp`-b@`i| zpTPHueD$ae00>!s5CGPV1hDjCN2Kh_ue$317Yo(Qye)fQ#)Whd8qE<&3!%CW3T>Ij z>QOuymP(a29_X44Z?R;u$sk{o>YEw>3)LrcUPRD%YIIE_f4pMQCw0U~4P*}H7T#&B zQZ~nakX=lDPIBRG>d%!aG%7b#pAnj_?s_^1?_(NkSg~F2K=-*n&X%{tg*uBZuuu`m zM~CBl#=*+cSsomooD0!+(YReraDrs;X27)|?p)W8FfeDPQGd!50`DeVmEumVjS!7Q zV1E-~56YKqe=$^lVxB4YdERN@37BPB*S;u z(rlVpkG0s>I5nb_+HU9OzS?{0XbtkO00Pg1>WONkmjY%1*8z=}+GYVQ66$-Ad+3d~ zFy1Q$(nl{_KVM^)8D{~u6OLBT?`cFKvcR7gC^5x9K_}|#x8i33GXa0E8?l$qzI^XE zUOzVW%TLL)2FjgZcaY@!Lvt-1uAl9fpFARWEma%P9>v`Y_$5DM6b`m^HI5^;c+c@f zvk=dNo+zptw$tNPrZL>Cs~hV2Txk5|2w(Mp(iI7AR3KLoV(^Oann%$A>L&RzpFApXmjk_*^&*!| z*%Wormk+p=S$;9*e@qsKn;j5VFJ=)ER@4Guq3)7j3@q(^n2UJliZBd+bW?HzO9E9V zvuih1-?yEbygl}_L!BJKuh0?dZE>j`-HBWBrit25@Hv51{;2xQ`p1*#=hy|Bs}8gN zF)9cb)!;PJ2{M1s87He~&jRAaDck0Uq1aUeqE;4Wwl<@yh zZE;0X{GNZ1`$UAs5QMQDL8gevc~h|pGG115ZhBwg?-{Qwj}Df^yts%Y`0kqO%dTly zVJB5KQz@s`H>{%XP~}YZWj;-;tjq_>koV3~LiDT}8a|630R!a!NWOgT)X>=Tp_%4-aToyV_ElaLCYxb2GBN)(>ZcyAQ` zn!bN$s{7@*ziEeVzM~*pmqq#?`ctNs{!nhdM-FM6HT`u}m?*>LZr48Il1m$uR_(>( z!wfq*R->508cA3ry(7>dEj8O}#-_nomFffSbgCik+~yCDFy$;J&MOu(NWW{@7zzlf<12lh4@>4QEQ^!rw2!|)bmBF;*OW&mSI2?`x zzQu2<`|_a@qWHJY{E`$5VE}qR>@6teF~I=_fr@ z4v_FXU>~DgtVFe2+m^NP)X-R#+PLkMTv{&5VzTrQqDfD){nApfkj&epAh6IV2z!6C z{u00+38FYxbdpZl^mTzP5!yG~hP065CwrO>cnj?<$a@KhD~)&szj@hJs4?aUpCGM^ zp`(rAWj_(kfM-yU1BQ{Rys+E4KkUkeb)Mu7avb-JEc5>qf?l#MmT;tD3B-7Nk^9s za6ZN9+H3iW`0*!NJ5mn*g`M zMTpRBtF63r0uebDW0WYFtiVp<(iNY5Un;)d?4?#|hP2}?;s4=RDIE3-0g zYoe1XB;hg@OUrbjnDihvfcSqErp+oaf;>|RKToF;Msz2pew5Utbd8CyzOJ?>G797G zQmeN>we@Pi#lFwD=h}aKr_VHMQa(Uofmj^7tecBog1jye;p1@^xUG|3(`m__^q$-_ zPkK8su&jSIuc zcgZ1oxO1N2K65J2(CGZc)&0$;q8L{lu4dmRvg(XA7#K}UW2{09Ax(WAeedq!o`X)G z+f?-F^E!W4BYb9QvCisvbC~5f>zH+RYn-zf6R+>7DfjgzJ3GkD$qj`Q&I~dtce^LG z;(B``F+ix5-P@T67N36=RDGj8-leVAl2j-^QEKkue2V1d>oYid#O1ZaN_iXqZZjM) z*^kU701pAIkGFyE6aenH!&UJ-HY)`dz;}1oU3E7-1IkMd%ig;?K`tL0f1Y5tudu4T zJ?>Or=t;*7Tck1qh9C^pEqbzX$wCCIq(gb^^?L5C5=@RXu&aL@FK1XhrF~P%2fDs% zs;!PJH?6;m5~J9N$OyGzrbiltU%7t_RaX@WbF%@)t`ege*{5#w5t* z-UCDtmc^v0hFEpYiy#c_FlvnT3^pc&#)fG;COoF?Q9<2j8s-6jPh-F_zX_q)%NKLi zIFVZ)%6g}QXsRd0gv}(|fHH%+M$2h1R}BsI6+NF58BTvl*QpE(UJ!UJJ*A`Hq zqI(Lrp$R|4>rNH+Q_R|zBRm})lzp_ThiVHOjTicZm+buE91T>HMw{!Oc~BJ_t-Xyb zMx21Fvjf^&wFL2eg2R&S%40(Vzqq41CpE^E_HC2vdj^juhW)?FDJPlWr^r+~-%pWP zK4(W%Rw{p;y;aKZa*D+AsSWDn0-;Cbr|=B;m{;wEr-VY(5&4Ox!mltG)cG8FtOI5y zpzBV-Fe%DjxaWTU0P`58-%dd{DPEuHw$IR5(xg87m@cu$t|;8ecle>8;mRR2>*4ab z)9v6d9DjF;{bG#GC@~$}M&1Ez!x`U~T)O0f~~ zW)2?G(p3lN#GoFgNSpBUJlA6|u+9Vwyy;fcN1i04tA`ylvZ*bbKTZ!RM^z7dcMw51 z2u6R?nj;7*qWXbC)R;#!OA%E&20>6UHHtWbpdz)k5x2AHtr+w?Wyw+-Cvgv*-u6K- zR-2b9B=D)~Up6h|@BWZi#Gha@c`KBsk@2q*@MjI^XATS>Fk~i~<3RxhNsm|A-5vMX zIZ?gf4&3XxNDjbyGe*F*l>9=41Gr|Uyb2b~+^J6ynDb6PU%O(TIF_-)kqUtjk zdIilrw_ODX2^0_I?kFD$oVm>^>f|rTpANDyMg5~6n^6L%sutn}bL)=K|jCm!jFSLp+ss;5a zkS&92tZ=??2TXdYp+Q0Q6nFut0a9m7vTRRvwcF+~p^IU`Zvh6ZPtsp#x(ZS+FJQPZ z2os97gJaP#glYgri%m)h+btQZLjZ z4s+#2xse6pn#N+Up+$ph!M=D^yq2z)z{k*zdeq5h_d`3#l`m^tv5QBf3l8*KH z^5g35yPw}glVOIM3}~uSGsoRx`L1`+B5-$M$IP#QgW)A7y`T zV*GQcuxA+tKOdlfAzNYXEp^G#QwRvcBEU$PLRkB-JzAhftts54Ii!y+C5wR?mLSYI ze?mb(ZTpVUUu$%7^~lk)W4eFfc><_6)Emiwth6LU6b)0Q* zb8GIB!x_}m6))vcb_?kA>+sr_x8Tezd@%^qB{0hgv{#BVK!ky*+x9CIDfoPvGG{aj z+cy#rN-umK2~8vR={9pWXj?&;`#}9MQ#o=M+Wm|J^(lbMPqI&1%PxO%Ah5xV8vTUv zJ0HRL$Z+TKX-PG%CYi6NU_RE93V?f);Ucpd%jM8v-%d-M4)!)m-+KnqM^9&3VR)d^ z6es{F;v*4j9@wkncr&zzdXvL!T-N%N4}GXM_b`XNiwtAWIE9Uu+ z`ra9n(duHeZp?vLdeJ>{HoIE>bR8Q@m`Wfwq20zP9xDA#PUX<{>Td+~gnZPE2gmhn zhUTG_Pe7YYgvRin2MjvgC*BC?y-#k&94$b5LbjO!19BUq1gL*-_$P~nJdCdg`-CJo zF7IN}ckNx>BqNhG{_nxtw@q-ec8aL&)n5-PO~WLEDs%edfeem~O##{QF$e6}(RX@d@= zkC+%dxKZ&di)DYNh_)U#dKcHq2_%0O%RTP<}m5{pB&CycNU$76msBcc*5X20CNKP-}KFs2*5*FkM|=0 zo*)^Q;20DfvqY_wKJ4q8$+QG?Ja7u7TL57I@WiS29{7K`8hLU1OWEADKlH_+>h^Vy zk=7%<6-SNaCV*a8f8BBU&=hBQ5o0#a@aJ;$qdAUVP1%(oMpp&npw*aJ=70?bdagsh zF6(XflZRg82k$R4AeT&4%lA^#uId)!uU^IrGJ8vAqnDg^9h(FwZL9wo?koNp|Wh>KxkgF%>F*}oi?+9+fH>grZk2x#rf0K?M)I8Mpc*dWDrdywInzM} z3J4zQ;F56~V?o46I<)bJd5mz4=kC^!wXl8jwoQ@68W~^pag#n@RK7^N)I9C|8Cak;=rBAPE zpJrr|X`wo;Q*VZtqbyFkALbAX*V~+4aT&iKC$YLt2^@btR=Z%hz8Qh>__O-pgYMgX z6>o>n@WIWtzSk~@m+2_K!6xS%8tbz*AANrWc;>xrY~R;a2eaN!>2%PRbDHxO;mQL& zlG1iVxf8UV9roZX=$C?a$>XjZuM+ZI;#PUERK;WpS&(6|#EtRr%Sb`j4lTac?EWVE zo1fg6Os2OS-?KTMhk4&_kFa31guUJ;u)F@Qf(stkqXIrgDxC?h^|;iZ0@(Pm_*#EG zV@mJ~nFm*ayIrbBp*_!BIAzY!-q&#UT(PanooSiTwW8{}P-yXy280m`h1!6GA{5G7 z;yH792%$Jf3r?J#?bJ(E@@|0gHk-|j_d5?PCxHS5s2tIo`;+J?Jb=oDaaezV^$3om zRfOd*lo(4$c0bF8v_uB{M;a8nhJl{0f-$|K7*RkS?7Ek?_MtB@e%Q;%Gzh1RAmETS zgizagv?`v!uc*)A?n94-nOsmSz)4RUdTn;LNLN(=^ah(TAjb@q(A}=RDR{@2}UZkMAz8))t%Rh&rt$ zcoxW5iR(wFe_TwFSU#pZQAIkQW8ztNLKuKci>+>ncIBmv26=O3jK+VAt%MO~ke)V; zn7w6c3zW{lG!+Je_OPifRvP1Dh=J9lKBzf>)V!E_t;gR(OqmotpQZI(Q||B#*^)M3 zm4%+hfLBUE27W5?H>b)Hh$w{u!8eysAj>cbtII@VP`@N9F##X6+j0uTv1M^+JV(`8)aC z{7#>waWX$Z!2_v}?HB`nzQ;Y(gQoH8lU-&tZK88t|B|vf{>r+KZi4>V-5$U6!utfp zPAZ$RYX|1^u@Qf6r$Ppl*nPH=(uov;e2k%2ZV^@0_MM~Vq znK+ASw%j|IViW^1nckNGoT+tPk^&3PG~+z2D{>ZI&`aV|27#+~ZHd$B_ig(%BL^K< zL9QRBU_REr9;@z2SLLqeWO9vw?+h2=&mL%>l>V_ioKkk*8P?4+c+PFL{+ z9S>W2xTKb7Vc9DsjK+0x}nom^kRJdLWeeN{Pge7(tQc; zqjsKdJ3u?xVk~C_{0Z?^(#^5n*@Y(1S;5~^)o6EW!$41n++WRL(TUdpC#c+2Xf@OW ztvbzCLLh%A0YUWkF9KPGC_JhrJ$rd2Q_*DPz(CIi4Gc7|{Y^0zSZQtG!vqOK^BMI@lL+OiXYX7m%q!BtRt4G zh3=={lyJMYmJCq=WXiJX)6cP|_iV}IDsBQU~QS;LC zpF8I{vjx`!-cek1vkX(0(Nrq(w@W>>|L1=xuqula8EV?X9t*81gLr~_X9B|>2d%0Z z<-X)$c@1>Fy7^8+%(pw)7fMt?=c^k48o@>YI&J;)9GX{RH6$`y2XkSHTn`mAkaY|V z=q(>2?+WlStzsRP1Nz_SC>z6iCyxg6aN7Pk6y+>d+vkTet$F8w9J6Zo%12F>1ayDZ z%WlhEXm|fegKGC82=a?D$SO>drVE%(m4m)>6>qOD-UrBON?QGh9(|Son)Fuwg8Wxr z=ztIk6LHsOu~Q5R>E!e~-plVH9_*Ij5v03gcaukl9UeU96nz!z)fh5BF2CYU!E+|5 zWgR=|nbVDMTV?ck9FsMnTFwTP%oG4sM zqDxPb1YDJ(J>EF(9Q?lB*0)c()u|h1S$qZp%b{+KX^0D!;Im&59xxO>fP6%c#}twM zC*#Tk} z(_J1i`K?gja=09j0u2gf;A3)oL3rg}RJN4tjoKK24a)3m7~y(ug5?>J~z3t1=AnqwFr$bE2hl-KP&8 z=s(rXP{Ei;{ZRQML;9sr*e!npF%1yOqFX&TWdo}p7V58u_7z>#jZ!jIKQdTtJEUSM z(^vF&j^)hs$e&UmotYi*Sd9SY1oa^mxIQ4@yGtHuSKsCdRSrt$d)IxA-oRTZ5g2R{ z^JnEWhwG2~Jw!g0FVXS_W*>3h(R=)-zXf#QZgwjsTLNxoxBj?$-I#}|u^p?% zPT1}0advFgB81+t4pjn;r`Uj70S%A$@*Q3GHV6KgF9I;&*d&_^pB1Wc`lF*l&ri4; ze(02`$ks2dL<7t={TP3g(IST>haJ&l=3t&9heNj0Fqg?<%nmRd7kQ2%jYLB)F4CWU z91(4}mJarF(V>^Qf^eZ8xZ_EhSa>a(rBz^v=0PA&l>5mEQnbR* zT6u;RN{^wX8>Luj*UwVzWX-PLe8m-_FkguQ?dW@f-+jq5UNDPkgW9=J#cB-YaN=Oe zqHOva2TqQimj^9XB_qv+Hedd{ey4qBzk0dRjye_wXhc3@+ndErS68>YC+N{&TU3P@RbhvGdG+DLD>Z{h?xIyk ztcZ#Gt1$dni~JYk0~7gW?58{bcJ!OR6=1Ea%LuR@1F!?|^i4<%T^XBkffcZZzq1o!+}P5APuo09E+vhP_}hj8#qvUn2+HA=TPmMYKT!Nt1JA&0{lP4 z-F|aO!x3nDr5)c~tS&v6`+l2>iKYhgVtqEj^soJ&0#4Tan}zPmu5WJ#j5KaXLLjh^ z?>4Q$9D=M(20h5f40S*>qMjphmzKh>TtI(xp2}TNYCPR#q-*sfM+@~^-|miqaf=BZ z)Ro5LgLGf3FC4rqjj|5kt5^|v>C(O`nw$2$96^TC2A_&_KI4d>7%-1Reag?Wr%|5$ zYs+RDj=fh61zxuS#?|V^sxX&4oG?}|&b84vxVQ$f_$H?K9N#Mmrxs3;F~*@;g>!$N z4#R%bjiB>%ATS7?EV(Uio+3k9fNCRuC_{d}(vzP|J$`?3C?T$r%rIzf=>5LmBYAr81_|I6LF>j4EQ9>n$uVtj zIFH3Hk$QeIOamQ&&C)H~P#^K-%hqE?P$APnBNXTt4wZSVil(Zz-y;!v;0o$(q!AQo zxP~Zhl|Y(Rf|l$A!cCPQYFOZ-Z+%UhhD|wse)^zf5sN8cP~af7hUI@lT**nPyREx^ z_&=REBnhW2tmCAl^}})dBq96iJ0$}F1pVRa0GVWFk(86?9w`MINDfOsJr&Ae<@#*yKUvY`8>j?+5{M(P?mG# zG&wYF4+mi$Vc4WP^rwF+A|!!Gf{>P$V2uQ8_&Gt?j+PWu#oe)%ooLyeI+WkASz%3K ztnjgJw(a9-k~N1w4(QQI4s7Q*_Od6XIhJ!#m#nDI6R=N64S%s%@)U7x zn_X2l1(XRoEb*i~Mi2qTL4&NOuqjGpbB)3Usl;^Ep*>BGM52HALCOq~RxCkWnEDQ0 zYMnK#Jg-j5DfJ@=6Cg2)NYclh%4ZGx-Fi-p!W1an zbpp9fg4w0CubK^GzxX2S`0LF*yeq#HmwAi<`yEfPyri}dn_1u4eknSB7~y#7bXn-J zaSg#$cGb6+k&OYV0qeIrjsX(_0eqKFkO5i&7MH4!0Um$1r@v*tdbH2K{OiBH8NXRn z$6Bu-glB$0|Q%}&0)hjFq|0- zE0~19BuEd_h_askT0P14={8#$?ly(qwpoD)(=LAsRT$K(B=SfCk{0&)l_sv@+dehr zzTOBusvvvMcCa2YQT}l7mwDx_2O(sCdopSdIi?_9xv&@bTUdu$6ranj-PAJqFo*gL ziWQDR?aM*@y1{^T`+ew<@ku~$VZ2`>*h+m36DO<_^3o=( z5#oO+C+mYCzqWOM;0_mv2$-x0f}tOcG+74(BSB|$DJ%|*v26nHMqK=zsR@Jt0KR+? z0IGvG3KBclVFh-N{0W88?urLzy8(Vw0DIUf7k=i8va3p8+SlYCed+~)ykfC~a_q8~ zTn(wy&CDi*q`Z;DnrhKKZx;*+!_Irw1BP(wI zXt3%Xjm}}erzkkeZ)w0T&5v`+n_av4DjUIkfMbSBIjFG4uUz*zx;}ttSHVn63cPP15G?`@^*YD&uKhdb3kQEK`%>NUFo@)bV(Rj4{5{0cu<@pX9OUwD{C&;= z1v~x0gBO#szA%nFXtHF$Bx8X5*)LN~;Uq#T>kF(^yV01r14_|Iar;f4V(Vwciz^G} zNe67Lc$AIH`P}a~T_&5AG z2bG-}oZHw!?Bith(hDX@9H&nT=gj;x=Xz{AoZ7&_Ce!svpi_=Cn5DZs#b*v~&Ke#v z9`Sfbilsg8{7 zQ;g%?WQhPE)uoYri!sov1h$Y!+z};zDP%^<#?e!rGTd|}e-_&Nl@B+jfypCyAfUV< zOt!3fUg1**MG^sDC9p%O1>=x-8kBG7*d6HiZR;*iEsg#Yg3t)BLimgx`_!i8m8}4J z+OI^PeaP?$8(kUbj?aH;jKQ+lUm&WM-sqTo^GA?Ft9MG$&0bB=)t*U+6UB+q`{DX0 zSsK12(d*51%H@27z)?JuI{{rVIY1=jZ<=bFP~cs-$q zIU;3xWx@$hp{jq)eN%7BT^gFPzS5r<%wxCfU+OdOXqp!S794ivCM|aWKv)2bvn0FQ z1n>#aKl12|7}*WJk?n$gfiVwL*tG{mN&JiJ&*S5cUVVl=_V%iSd@M@;2mnKgvB(t& z_5NItzeHFVVUK0k_y%dF{Mz<2{T-o=U+`YE`MZ2{IRJk-+;{Eq4%bJ>E+_1=kUjOj z9@_3HhfXLQSdM`>!ogW35(Z>qb53_BvxH$Y(Ri+Apt{EyBR`bG=Ds?CTRYCFFX_sd zdD}Lzva2I_YQr=AX^ey+U63fT6Q$c2y8|g7yS+7VXWm}YqCe>1l^A%_H=g6r84n7z z2_EYi$lrglVL)W3?7%SyY>d&ud+1lszDZG zbvj5agUC-9KVkgd_z*|D*fr)BYR{Ok$E_?ctk(#QP7O%DyJYU%-SxzO41O=${hQ+u zMKyM7{b_{b#`p{)xt3S<^9W6r@m)QiFPmXmyHEO)!EtBP7ZA{*mJJEn_=Zu(c3(Z- z%VvMfA9;Lt?p>es+K5_!zo-Xc{EL;ueaGPPDs)BWUnAgGzyX>*`Dn2KOASLp%@0HI zwP_!VALZjiUmv0KCp-7s_9xl0d4h?=yRO{tq5c&z$9_5X)~Gu+^34t7DSw};8U~J< zK>(|e&p3VoI2di%wz9SLBpgba#Xx8*B%yz7Q{c)17*vArzvC3(58*Vt^QOUi5VE5d<)TBL;uugw0(aVuZRj4KP+PwB_XCjI>gBVHNXoa3ONZ!`v@yx21rkO z){`G{@6#PgCzGscD*7}WADRbKwf3X1+Kxju7&Gulf5Ek4f#*F1X64=(5e=qbI2+@g7nB`7=mB zI>u#;knDIGg~5Q2f`!I8TyqcAD4gV+kqzF+aVbNdMWZnIZ1_f&Kv{YiG!8=nffujY z0FEq=YwjT%1$JZ@*6Q zT)xnjESEL*a5-o}uB34|zgLu&j) z@;pvh*g27W(aJa8H5USw;~JUsbY!9!UDO43TWsr8dm1t%u0QX=aFgagtdk zYwV$N(B@ohq-2gq8S)$&WsXmAj<0Fk)wL&9GRNm}@V8ma5$#a>R#7GH9|9` zsM1HytVH64AHKAyq@oUXL+=#hsFev zp0lXH%h!LifXy6_W6U$TVVoH*nWfiU;AED|8hf~4jjcjsxKe3C41Vycy5=G@^9;t= zM`PnQGhCh+%`BC%^)Oki5Yda_=9(6j<}hlf7_}H~Xnku`L-p5VeaO{-PAM7)J*J_a zAG#9PfKDkI2tB4@U*6^43v^1+KK?-^$2_gKs z4DaC&9J^!8le%bgF5mGF9F?`@nH;P+5gW~mV^M}Yg+}q>XN(3hMnH zM#HP0=Zl>uYn#ykqPisDXtOz>FbEUm=*BYFiou<4C?ki+;!wwk1D!4nMf1orX>ETP z#Oc$=giLd>@bVajJSGVEe`GFjV#uHhi^AbY=VfQ6K92c(YqT}SHoNBSD{U4nP7^~G zmnl@nEmE$=b{_O;>C#TgnGwnqCUa8WpT74c`+jtcq1B%Ti5^05gO+PSTlOJjdoqUhv2I}JadaMxzhM{Huq;xdnzaf>`+V>=J} z^bxa84a7={R%yJwk8FfFC#Ap1oFj9da*XI>>{Ge=5DS-$L)m{#PLE^E^SEdXSH1aK zrQflUxrc9r=rBg6^tg$;+4P(;l0B;H&91IO+cjsV9JG*^g+iLK$kty|;qZUw^<(|F zvfD<DAesp!%) zzyS4Wh~+x*Eim(laC+Yq3h1sY57k56RH@9yAw+CZeY|zINoAC#Aud4jvFtaSx7HJw{0VF@mE}dl;X7S(3{&0y%mmDG-Q1m(jJi^)9%w zcWTMg85}>wi|uj0f9j4+lTyQTUSVqC;-|^DR>$@Br|B{7>B59z3@F@J`@^msGDInl zhz^Y#pw{xP_w~2XR)>gVM2I#P#1hbhYh3?&th&0&xk;{DL<@f|lGO|mCAkt(xWlCN zz8bnRp>xgn#K;ZyOh97KC(zyT^>OG=G%^=w9pIVA;4%QIL?MbWcxt0Hp`99Qn)dZw zQzrD=l^xHaFlOLzpg?#L^~8{cHz+gwhjLeMVPj5Qzcpn!9HbeGeB&jSUSr8}SR9u^ z)p5~Ck5kJjg{pu4=8+zgwhVeV2lCqhUGs9Fxc8~>*51n`988`x9{q{4_7gIZphf_Z z!L7M%fNDC-fml#;iF< zGew*-!lIV4ZmKw$wd8mloEZfj*bsw9D;Apkr?6Y7K5BniQT;87?U-@|F4B}me%sc; z9hGA{4&PwR!Ef7cABP4j9vJ=Su;Hc1t`!eESzv4&+OA4~l~x{D@Snrt;Zt#3G~EiG zYu?@__d~t;x~nh%OpM7f<#=4ADT_LjCPF|~9JcbG!eSS=tLTir=v^6Gb2Qjbws>>8 zZ^Q4wEzYD2c@m8>#ZPJ!`I<(a29oJVL?&}NYmR?qf;Xe9x|?g+68YtL#~dKW5Kin_ zN@*ip%oynl{kh7fH=Zd%gyo4!k`2J7JvM!|BJG$Y$go89Bvr<|SCW!xU!&@pDS%wjO-$q!PzDp-0MDd&#)os0D~bH=Y>!NTyMat=p|E zWy60V7-57l_VHLWjw`$ne{APtm@LJ&PSG{UGgBYMd>yiNjjm6enfh4fYZM*V$cWI? z(#tU&5wecqv4F9i4}LNZV4dJ7*%WZF^MNA<3m$&6P7J;9lQ%579qI_~p=R(7^&AIw zlnlXPfQccCD>TX+UpAWeHIBX}a5%<1kBfgc=jz(fonY=lLOtWDVYs?Q4PQdt)7L|lf@_RD48o#uTo5O+3hsaQ zo!k1D3>HVE4l;qp<@~sBo^Rsfqg7@?BXjKgdMi7_k7bvXr`FoX>ELm62^EQB=p*4O zlY})LBeOX+w|-;n5`R3#wgC?Ak+IGR)z`#0M8#EQFyR$_kdzUN%{(~T9L9nBG-NdO z;tN9JSrUrU$kfl`DNg8`bjyvUpM!tD-RPKhv#qJ0BygjZYg#{#_lfZO`h8=t&3)N4 z)hf++-jAHy$7q>;70=|X{uObGckuD=?sje8m)(EULZ1qF zJ@$E{t`oOD3{d@by{T&~#e@NjSz$lAFnZi3jH0ay^U1+b&wCI-*%a#U*qa{In7=xK z(0p<+C<;RuK^+vO{*Ju6D&i`eQShJRwEd-Q?%JRmnH2QLam5LVpeIdP;Qx-_T^%kg z@_HfvjXmy9iWo z@X8<3h(RGlLqm^eqmy;ypQl0?E*g5ka@n(DEb_qdYP;X3F0N=O*$a4pBs zpFY0tv-Dts>IOgan+LMBp%IM!-&b~bz%oo3*G%z)Ws7tucRPP(x;afIqKFa7s~K=y z44tP|{|%CK=<0_WVsV|6Zw``hkX9@~T$oA*xIM~t2fT7mQDtESzzBeOH;0bv!Ieqm zB5yiO{Po3c*X|3|^gl(M#v~KOgn7li4tr2s_(;#mATAsBwg3P%zvgo&X+jl>a8N$Z zfRz|?YGx_+)#iWRgu7gn-CjR9aDmhD%Hyk^Oa#EE5doGK@Iro%@tafJOXAlT@`d;) zidPOE@(;y-5!TyNBn)h0P+^({hFYFHCitA*c2`42<;55>0H)%$vOoGmF_ z5yI=`pY7XN!B8~>H%Yc1EXa~0`t8^MHMGC|`oAq1s}Owf*i~rO=#2}y3gHLwyfX1{ zQ#`^I<AtP7btGz6iaJ<)3aXf6Ph+>rO$NQ?0-IHBgZfE-* zJ%U{{q0xUZX14$|VbPY!#B}5x$^t>piBDJ@W-guIQFy1RKFe3s# z7V={fsc|gmQXwzRK^u53ASViEEL47D*H-gP2ErLmg+`Nx_}N2o{%{4?=b8>39&3ho z$BgLUTW{Y!z^}6DBRgpFnJrk|F~tET|fBgj-NHYDvD1TU>mMsyKhRa8+;# zQR&tXJs)e?Cs<{*u3C)qM<485fjVwPr|Hz&_EZ+v*EF!o^ zCZGsF5rCq1ON#m+G|JjT^zKp<&Baj#(%#~DY&Dw-*Zl0YCG=J{`}}!0}&3 zxwl8^I4sH=2#EmqC|s40+nI7xEdcFnYm(&*ErDDMxptDW1EE(QBkP{nCHA@Qgs?-qcoB-)T@I#dnaWV8BE z%Bs>95d?ag?|F$SCs33u8}$fk-yxU?0=-HXFiC^#N9_;8qAcixtlZ@-LTlM}>YfVr z9E-8+OY~HamI4%jLkbbcG-H+#B3_>M*1l+o$w4(wx*F%o|D< zUT|KF%px@;k(X}eC-lvbZHzIHp=&$&dpT6S?u=rS#Q7Z>AUMtpI~I9{}J;?d;} z5VUx3bP9o%32dB5+0^FF=UVBg(0kU%4z*frRHmwxOird&025Mk*ftD5NXVHuY;i+Mv zdgx4noCC0jWyjYAA%TX$3?s_23=BAba|#Rs z8032fW#R0G5p`}wz1N~%gQ)i)YFPl;%a0!}B8gNe@@Gs&fj?&_gatPe0UTTkbO{T> z>gTrH*Sosxis9ZjR~eFnwUEXT3Il7P*Bbch-kFhfrRgLI_wtN7 zAx1r_(mCqXBKSwcv@{-+U08!1bH1tn*`RfCU+$?mMLe3=5)atUzmJ$;7t-f7!@YV-(1X8q^9Yxf5zhm&X*U- z50Q5OFpZ7eKRTm+QO15KJL+K^pYf*AC<0J_)(&K<4Co?Y_hw)A@Uj7;)8#;)1p8Hl zhL$+L^9Cp`EJcnyTPGIxb=ASx=F{^eT0~(HuRK)AQtOIooy(ei^yA60>uTOkhZlaVRyLLz*d$mKRDx+ZnV+sM5YD7gaKPd`EsPnXBk|! z-$|^73(B2wdIg)PpP}{39(6OcLK_xWRPxWs8II{Je-qlj|*%_thLRiyfA3l6XF9 zZLT1g#Z{SQ0I!mGm25n&yMK}|vAz2s-*k0#TXfYPHdM1W5_V#VH91b7Tl5yjdpUs% zQL8}HrQQ>jM@` z3@mO~EXaKNUSMVHs^JHj4OLatvRBu3U-L9bcZii+iCXp-!TWtR{PydAju1oiaPQzz zna6gFF+(wcrw%j4e&zQRzq3u zPJHm;g+&1N(Z8C5#x&d>rC?P6v-!bUp(3{f7UQKr8mA|nPOlxMd<+>B&=&Rn(6tX0 zO#Ai4t*k?iU9O5&C=i%r?1cuo;=#2Z_+QA29aNNyZB-p)YyN>>Hh}+six0|JPY4;0 zGxL!Lzb*fo42!m}mw)y^;nyFM(a^jn1E>gi(0zMDlg70KRdHWFRH0&kkOI`S+Ijv22Dc=HDA;biGt~ zpB=ma^M6~&_YZDIQ}*`EJS6AtA%&aeej59vjs`j`VAx7$w zhw8rG?9!`IWB(WRfro`~P`XoNQ<%u%I1B6inS)g9`?5LWPRLE$+}3x;&g|w~=-wyp z*rdy$!RQN(v~rME;Owq{P&-8l&I~@U{8VwB`cmOsQcx$z^b-}@wQyVubWIRRv7UCG z1%pvlu$oA@Us$LRI4_hd*rbXz)R%pK_v24rx7W1+#Q}f69&1<~c>0}30DI^EJi?38 z_toz9g-pmP%-}1?SEI!FhORywJfU%7e8zXJKSlX)Sf=c%`Az%d2?}rssO+kFv7r$u zo+vJ|?Y^3zNqXDga~?$nNVE5PccG&-$d@U1=zKeWvP3GF&kVK_q{n7J+3-&OHe1#efYSx3+7lu;K+^~w#ulQGJVTkPJT)XdkO-;j&40C2Z{hcJt%qZOuf@s^ z^e}jKCZq~gcogG8<6SBekXgKBp%u+QvfX*D+#|celJpz01uyu;D zqcFPOUAw(++hsiGp{u$YL)SFz;1A)h& zR;ceMDo`l;N7#Aiq9!WQqj{&Run2Z+FpXWG*-{QA1cZEMekgE_X7Yt>i?az!lEPb& z{^)R;tp97#hMtuPFD+ZZ#T;Gr*vePxix)3W)IdukaM_5$dNV`+?brV=O_ywg9Hqs44@_vKq3^0a7f-{X-Y~a{C$G%ADs;Z4YK3m z)Z}O|fnY*|{h8(9<>}GoU47HZewbYs;e_C7Z{^3suI=>8Oc^Jr)*E)-EBNv92^+Ty zf`J+ie5GoRWn4#Q%Jc`o0~9?*|GiSB@gYr+l8KPw!-W5Q%%7Q>M_igz_eFm_{PEe+ z5ez1z>Y@1T0P~ulO|z{#t3?kEyi5@CMmdiKm_Z2xl}PR0)F-{#7#m&E>|{Cat$fle zk+HD{s2?~^+`V^JcZs^`Q1sI?OdrlpFnOe~Hsra?xWJ@v0rNEM+PnVQ8UUnl0TVTt zRVvjpG&mrI3z(?kvAQ{(TRMNk!9dAe(Bpds8+IcJglF7UCB0Fdj98R<{Zrc%)Qx{g zdV#;!U{@AQ?*t-52u@@XmmE)yPJJfgGsRh$rTLg4Bd_7?*OAqH=9TE~5A~wecA)fW zhk!QS(V{N&1bG$WeXjoNA_;rO_oQXu*#mw(0Z^J&2)?X8{n zwKJ8@BFLOM!V3jBp4c_Bmd?UUJ6C8XF;@&{p6cC@rn-U;40 zV{*l*SfN>BlITPNJewk8dY{)%halj|7fwKWgTD&S@_Ur&vl8^`wdZNm2Q+B33yvdE zpE>I2+4*M9J({0)l$mE8#HHC(ZjnrGGyAk5qFV~hX;B`oM6Kz|ICy1A>o{htPwi2@ z2`YSK?%N%0W9ffo&vN_sCo7Sd0x)rXki?|b{eTJ6vOYRqunKjn4{#mK8HAa=vr8Y& z30*Y5COv?8U+s2n^6YU$n;vjPP&I?BM=IZ1qFk-!*aFx(iA$;B5DQv=|4hZ^a07(K z1^*RR-u9G(DQT|ydVgp;dnh4Jf+HxzH9hXC?@%TT1s#8ph%@3yAvDFin279DshH8v z*RFun-&`H4--eOb2MGK7!(CS%?(0qe!}GPN{u+j42XLXWbqCGT{`TvC=!?Jo`k&dU zz#!gulIh{;JLooWLc(3R;JM1EkUYXMP4W>Ka3MF{FkhJPJgHPn0UsW|0aurk2jYL2 z(_dQp?8JYV-X1PTIW`+#woBNYS_-Sh`%%y2Yci-G87(o@Tw4SrIE(y`KNl zCCgXb_q0UJ+5MuE|6Qab{&?$+#lH;F=O#vTOqk2PDrZKEVFhKk9yZ4w3fZo-i* z5-NS?Zly1UiAm+J6(3l>Y}xvC`F}*ZpI2AmtM8D6^bTK4Z&KGUpagasK>(4qxP#@M zG(3NyF8=X5=mUH>t3&|28WGVM3fq||ei_Tor-gQ%Im-@BXGWo7(2rU^yj8imS8eim zI@Si(U5jXXGisDrV++8hH;nDq`1uo4vWKNi^lR4Jo!1U%YRjJUF2CS767?y!o2R1O z)n(ckFt1I?x_J^BX+6cx*QDopzlSP=Wp#gww+FiM@rG7z4GQp=ZnTof?@b31O_9tMV?tLsH!4!g2u0-+-XUeMH~E)?#552N}om`R5xKBgs}LL^8cqK zp{f>#iKWMSx1;Hv(L!M000W>Yai07cvk@~t=P%jHOI?6200lJkV2ce@oji3xU9z$=0SXV5 zI8J91-%rdG49`cJx*TYXq9d$*i^Aie5n#LKJ(VWI> zFk!6fGHhM{94(y1HD}j`9}SGN#?K%UX>lLJCS1k=m!bU}077VpGX#IUps`nft;F-Fn|I9-@yNv+{v{O29JZd+KaGLi0Rz=c5aBs5oT{*p-%pO z8@2<%Lrer^BFhy^?yIdk@RbU-$%0 zVQyw97$?DNP`-a5b1q7#p=at5h6@a827|vx3m(b>=ipGozV6nKC z?188O!i{Y{tSnCdQr+i!GQTb*Xyq}&&o)6L`@ijF1qXls34A0!VCFyF+`zCe#Yj-=WV4YNpH}^sfX|fIx=vK~ zCw@OiSYiGo=dZ@60x{w|+D{}{{ zf-Zbl<_|J^jb~?ANcF6gMVyp!JxA-T%!RNDzC03#M|jv4cMxWjq(uuqvxSe@vBkbm z)@zx;Jvx}MVNpU=pdC~~0@-{$dtDF*xa|jYX}NzCXU451yqE6Vb_My$u;?wrv|0lf zNJXhexm0c?ZxTT-#^FZwg-?j9jl*LpxBE0ML7Vb~(N@wbCqu_H*(J4xP=zhxy98Wy z&Q`hL+{scEnyS9GuP?7coN$~Gn5tl^0;rO;CQ}t{s?-RrDtYr2s$^1IX?%pn`+W61 z@|Ay1uyyd~u3m$aZwlEA5t}io1iPp-|4i4X=sE&G&ecA;nz4rQrWnu@a6n@>xkOKZ zdvXdt4bi7DsRTnVqz7iqmL9fAPth006n#=Vz_h=?a5_5v`MnyqP+GJBDfstpuT}(* z6gCWTR26asI4^nX z6U0maF>-l@S0;}w@bACK$vHadnm=uD701NPtO~&o^2BcCp-uw|b94Q+ zuP{@qkZw-ENq?c5FijqCb+{)Fs(gPhWRvctN-$%E(M=APDnP2RQu&SwOV!mghUnDF zz=*OjUf^M`T|z36`R)no{I4+V#?bAd_p?@=n&dUS&vN_()JUu|#Tff~#(D#S=qLg- zgAIbvvw$GXGDuLcir#j-EEmMjc?6f+^u=8qxhd8jJ-o-V1 zU`ggo2_nL@8B#>gW2*09e^FyI#Wlh^IhBmTAak~Q$FTN_9M&9cC5Rk!VLRzzN~A`< z(&8ujLL?cB(q$rMMpb`&nLiztd35zV8b%!2;Lfb0!upmkOMMG{;#+^Uc2$4QQL&DS z)QEL7Zu*Lr>f9((E6}=V{{GuPIm_?A{R^n72bfX)oLVQ`M80!Vm>wSHs|N04-V<7o z#HAl3G^wDO`pnCGU*TGn)>HaMojVh$mF`x8v#46FSE{fwBbdYIHUXgF*Ge1JN0 zpQQC%m5Rp7Cfo-qRso*k)pv*q>H#F8*tOcwLy8S+ zRKUDe)~b5vQ6?uF(pT_TgjcIsNg9&^6^CpjM0G@j;B<%7M__*s%!J^iCU$f~$Cht= z{Z@8aiu&EPtX5@$fhO4y*;zY5i@FK!z{{7)3HSDSR+*uKE4vKG`gA0+@wBr{gd({K z?!XzD$_YLOkWzFxa}lT1FM31rB zoXu3Zc%c`#KsA3e7riu8^~xh64tB^zB?B%xhKoQhP^1gB zPZ2`xH;32`8guq=;86#Teoyf58aGmCwNvFK?u_DOM)Q9IJe$UoYTN~)kp~EZ-ASB8 zONS1gOCQoXyL>&hl=^tY8B>cKTpaCDzVpF={h%6cGntY$^f8IG&oLQitiih5r>Rr~ z#9bbj>p6`y^cj&enE+97Koq?UGEv;QDWcka8W1JzT#Kl#<*!^FQ(H-&)Kc5qT@sm% z$eE2{Xo`Qw&S*DqT2!XuRGNgGTY=OI0gl$*{IFa2Gr`o{eGubXqaIa zSI{;y)`nFFAQ|X=nhd)7M!hAIfd@#2GB6okUo#YIe2oU%s1H_0h{1Xf6BDG`1j5@% z_+1;PBSxjHiWm-#P+NtO ztdc6vX0Knv3C2+3Bn%~ilqh1OU`C{s!$@2}s9C|@5?;4U_;a&_x6Kkxt7D_Fp{-wC zN>qOwJm6rj4TT)TfADrAzZ4Lz3l4tNWTLh_W&Wtrg4>dW-2cl=?$D;J%F~9)ph}}P z-!mQbW2+eT6zzwh6c{&*CPp$fa#T{_$j24}=3OoXI%1(R2rh%*B53PLmBJ|jHRC`f zlBLojs1o0JDskDW#5c`KoYwFOGp^&!Cc1x5WC@-mo*IhX*O2H@ee-D=8~=PDxpFqN zJPy#!^c-TIJPWX*^=8&Z6pWoGUfIKHIh?*nDkegO?tof#hhYSwn!JB{2 zy-dm|i^;YL4b{xk;{K^hR%*)@7ll;0XF3|k>cLLetRv)vUV%Wm$YQePLL)u%RC5xR z6IJ1yg&e463WcY>ghbKaCfO;RN7Q7@H`3Y~Bk76rTwIDb0L3QCfF}&zSp$A7xrydP zerD6Gi4Hh{#XChORNr|L;lm%GLB@ZrG5j2>{6HXdo=i;vj?~MB)UgFH3pxpB*z$PN zX1U3Lw@m?K`I)63eik^RRx?zsS-s)sOR#nk=E|BxIH?F@m)FT7_5BUb1?*0Awjv}I zmB0!@H#sN>tQ0FVnGNt6U(9BwpQS)e862I{cJU694KF#*Pp#`Q23R;L5Pb93pKtYdSitin4;^d?B;sg#u>KZ3|nzD7= zQ?=evB~rVPKb_ieBzdNfc?05*zBoA(OAXF0-Q2jSf+dJQnOGX2@#5oVC17#LWZ`2n zwPept$yf)*3-#Fw_S|?(BTauE<1Y?*EG!SRVF)i)_;lGrJ$Rb*aaiZsceNUI9^pPH zOj#LhSnH50L7kKoW-S0x>?;_TGNB>Q(U96NFO;!~tEXRt#)|6XYl7&tMA@KuEm0$> z+AlAu(I3gNOwE@j81TvpS~!CIJdLf3bpwK`MOGr7j`^N0`>|TK>O+5@$RM+ZhH@@; zt^yUD*jN$MSUQ2i;W5WUnTxIysvO@j`h^vGV}(vDfcswio57N>t@KPK8K4ne_S2YF zHi$wD_PH!0$u?zN)#ZLw@5|ZRh=pi7;g*mOeH5mZ>MQg!w{s2lsK)x}#oz+(#j^mG zjrG!tpatHG!3ExnXa0Wzz)f?!aza8!7mB@%AS4jX$#8)R?jEK+M(0Y9J8WM1=bd%*S9JUoWJf(G4OT+Pc{!3u(1xI!i~9sR9_F>QRQL7(R^ zQ`pVp#8t{&Tt3WMu?Aac?8Sk&$;9#a09}EiuO<9e{zwi8;P-r`U_oFR0lt^;v$b*- z4i9j{1@dRpb7KEe-GT`!>?Ug#d5(8q9yT5j>r>g;)$0#k7!?a^Y~W z?E`O*XdSc#`xZ{~zXjv%&t`I7<)xhQ3nEt>V6y;H%oIyf-T{fyma(LzCU_Hdh8dhDAskK9lK#st>Y zQDb(cRy%(%7Rb5|3Jw#@l7NK)UXq|C|DMXXX2qBhAycsOQ ztCO=XRPENT<8^e_C3Gx%F6bQIz3K+`|@&WElH43!g52{7@OyAvJ zy`NNb=o__6=ivlEz~o&*$XWCTQ9tx35L!gEn+LiDU*=hjec`)`VjoYTWgJrAeSLt$ zwyrS9GOWU_z#mcIwR(#oJ#STlv7FOa~CQ6j-?VbmHw+t=}tf1P3>!?2K+-ki$_A z3o~<{SrE8T)tazdBJ5Xbv!Q>`HZ{D#1vkhgMS`i|c9vX6SzgP2K7eL(8q+|`E-3q1 z18qRGsTAaIo{#3xfp2RBucMjgZC3SXDRJP#GcLFn&mE(S5zi>9Q&HxG!`42F7!@5GOJ~&gUX~be$=BC858+mPRl!dCa*~Cq8Hmk{bPRjOl*?ppQsuLD}9p7@dOBoV40&uwv%(m(KIf4ylYG z07LMB3t_zPLht0mS`OP!&|oN>3u`QF55)XeKGaSQW}MJZM#w)vv%`Q+$a41?cxSEo z*m9Mp5JEBDsv#h&5}(A6jSLIS0Ks*2oJ*DK?5E{r5Ip{-fWL6V#VkW72z7t3Vd&9V zKqbQT7y%f>@S1aoAS3(`AyfD+zo>6?_x#m=jwh(s!AKNF00VWQr65s|^1u9Qh+pG{ zTa%;Nb%}@?*_>J&qBgyvOwLvI|a*N!h^)0zRai;bb7tJ6Q| z3FZ%-n_O7k84bCxr(3NF%5HyYp?;lBMz`#>tm7n|Dw%SV+;jXpOlqPU?aNf5n3-f= z!kvY(DcCcAjpLVJ%V&jKk77KK(nF?ds4#l;GPBk~`4*1F7d zT+wLd6@ynu5+JlB*nKtcAvKEXP+Xi{FW#Lgiu^|(#i63JK4_P(!9{<-v=0T1z#u#8 zey;FWpyYjdgj~$bQa|3j50wesd%94{%~F4XAEU$y)lPEtP~=HgpB_g-SfmCYC1YV_ zgt0^P$#gKY12iO)hPjC{d5px&4$zQHOkc}g0WlsYG(YMQZGKcF-s+!2!f}Y5SY8^Q zF|UOg7KmYLVbD0T$60?Qx4&Jw_#=9o!wc?E7sXM8;2OAsxNLx)6~!2ZFdwamA=3TA@hLlz75dU~*pbA48%biX&X_$?xizJbop$d;tG*a4aX) zpizT1aTjg#eCxL{>}Lc5#GeG=(-jTC$5lMxgGO^F7=OupK4^bFOO^i59zJg|eNge9 zpGJ*-4fcN7CfV*wttD8?b+U>yyP z=Z0rc6}&i&co~J;cUnBvIc}xdMg5e*z7V`*LUjQxl(X+2IDJ zf4k`tgr$;4!`~sRMe`Teg!LPomQmt5Ux7Sly4MG2=lN<6H!7%Xlwh|uiifrPx=G%G zb)+5;v4e3@jcoPdH9`lvnd%Car~Hec%pv4gqI$Y>Wln$MnIsv;@`gq=f&NT4Sov%?R~eFCg53(4y zj=YP0d75FKr#-Uq?JfNO8?`#MqoGM$JPG}RM#X1zhHW^O=aye4rCuQ&oit(ftZ^)}XglhFP_ngpo z3XFg8+!rsvtL(yNKkLBtlfYlR5)GB?B1DuRq6B?1?(14rCfP;mm9J+O8xjjJg3T?P zFwErL?d`R;zg)NpyyRASVR}Zgc_Q1X`@E_HSwVi?>r{TS#lrjx5ArYXJ}hs&JY@FQ z{3%c-rM-av`?2&%kzB!4p%zwEzIp)1K@)$f-54n$m@r_i%D)Jb>7}bJRLG72!)U41 zadjF4E zpk|vB8VDl(8p9-VULIWp=e=RX8$zUfUfH#pnsD&_<8hr(;qU<8)&FkaFZ(4iztw+z zo>#2Bs{WSpNP>o?yC?OaMNe&Hz2~mPbfLk{GO_&my`WLY+LIz;lPGMU&FQNWdiA6- z9tzc`umhwY!AaQ~9T0=%k)pq^z;x{UQtn_9poGuHb0=V7fdv8!!es)g08HT868K02 zZioP(KI<=sehm6UfY4U@<4F6#Bb|RGI?E!cYRb}2NH>sEuYISYrJFu61;%$k-%Am5Sr)qQaVk%ul zP9t1e(B;qgD2RmC&m9y7zvq)3xEEUAP2{H)hX*xEgM|ja9H4^Z#>o|=K7W7HUn&~c zPNIpto4jbeI*EcLspoDFOcV5(zAp-J@k4Y$;A&x52n{acN@#HB^5!M6xg|C~eYhTC(^E1~ zMa5;l2h%#ZxWjdgl>Cd@&SE%FcuR=I5mfZ4R}eGQQxAFdMOB}gSu(KqG_vQrSoop4x#*b|ZG1gSh<+M}fMzB|D_*Um=n#KS0VF$a1NKX% ztoFX&6+xN%ew{KiwFE5ocWJW1GLI5!^9suQQwvOs{Zh+pjd6@|5~0(CEpel3EYjcH zI^(62QENsqx6rxYGTM@U_exf?*#3(?{2D12^J+NIdnqJN6(F-#pT}J)D>XdV9jcW< z*=-EsaNB&^%Vig@CYFC*F@oK>C<6XQ*)n9W~gA$!=X*504fG ztJZ$3$01C*1(1z>;gl~ziXt3(H0)ktxTtT)b&UV+Coc02c&MkXJ& zYP-74qwL@g*Pv+fSF1L}+gxDwPa5xS9{mItw0ecB0X6?zP5ghdIJfz_J~3Lz7p5g2 zSMi!b8$~nmH^jD#3;CF2=zqjm516Mu4sZ2KGj|({1)Fc-pqUH@GRMfVX}j@w{)DjZ z=HU+!+BDof(Z9oj7z6^$8xVm840liXub!4c%v--0W_BNwmWkC@ddghMvQ9Q=o8kSW z-<@4!Hdke(C(M6F-nSk=zvv!Q5l$IOq{m=IBVBe2V?;kmz6WCN0)TFwRIQ(@D*C>y z3$C7F^sFdLRx*83-?^%zd%vQ`R}j86q8C*t42z_M9jK=(3{x9Bs^ZR6AQcb7}3w29S&8xtOXI*dkqy%$pSVGaWBN#SpvKY-B-#BqFJGkcs zK{$AGqxUT8(eYddrQ;1TNBV`8KDHcsuEU#ijLrw>J|Bal%AvJycxjJb2tIh<=>y{d z>A~gTrG|ejsv`&kh#(MHYM?Qj9*dnJQ}I_Fxy(Un5UYX^dqOne^f6i?x|Ax^*YCd4e z+#@+`uacCj#)P7Nd*$3L4yOx9>rNFak%Kyf1n-+UoCU7>IlQzrP|l)OW$awes`TE4 zY@VgK3Wgu2t2E!Q|H~)t10};BTC-^%Yfet=kIJi{+r zFkVqr8i=kEsy9-jrqEz5fiWrOtG}SOQq8~Vnn!q% zZnnb;=^T;l-FSi%8crCvGb?MMWi9ySAW^=5ZTcvk^zIHErv=gE8_(vWpo4!^1Y2~< z8Kk(DMVddk%rJ6X$0gMuq6F#iqZo1)@_ayM0BQ0T1z`CGC)Z!;RirZg+NbCnYN1ZrLuLYp%uBDCqnu8^D2yh4iF zP);P-^hW8F(pFl4l=I-G$jq#Z<;2;Rai@-KTAr);LzQz5zTtH#P2;Jy-w=54(wyh+-pthDH0gc*nQ?_Vs@R>J$ccBNBmu z5dlvS9EX10M3*Kq;wO;y`)~hze|CGZy#4*Re`!qsoWdk^DfY~bP65>*9l9t2!s0ya!sE~MZ3~fTm~>97}0>Cud?E> z769`uL|B_4#3rXUPV;R*Q$c#_D471wjqGi3{l_q@NvR(nLe;QTjiZg)wtw!hxM*Y6 zu=0(C$+B#Nw56!JgKGd_cu~TF6ApAcHxx~2Dl1s*>a4gbaW2T-VjsAe^A+1(M_uyaP_85PKv&{Yb}rQgadPsy7v(yU zM*=&zov^&IhvEhzvu*%$EZzJD-$`-mD!SHk6YtYH3XsYWKdJ=QU%0tUPdK8<<<`+^ zowKA4eqiU%?y`RyJ6k^$m0CO3KG@*8n_EBr79*3hacH0b%%crT-#P$(5w1;C^zV^g z7X=D)a|@mK(hJ!u9?fa?RSiyTSgBZz)U4jS%eQayvkm7`~LKt(8>U6h&{xYfH2MF}D9g4OD7=%dorsV-#mtac6W**@(Ng5k= z;L!Y&2GM_#kQFp7Uuw0tC~=L43)zjCJBl)2$*S_7%wuuH60qnhZ0q)<1_UjNxdLba z&wO$(+HyN-vn#8<6~3Py`=v5#`UXy?IJJwHTfA)2dD7M)&*r29w;!8Gof01s8hyV< zGyD@UYtOUv>DdU;3?aynAI#bTA^NjMMpOQiD~*5LNu`u`-S!F{vTdFl{Z|iukMD<0 ze4Xc}<>A4HUzy7v;rKewjsB|>zq)4|MLb9im!b2aQ}Sr(qIApRp)W7kwZ#~DZ8RQ{ zAR$*{zuW<%nLe?u#f*vP(lnXz3a$4Q-vDj9xEYeEa`H`6m2=rd>X!JF)$x}|mSwIM zL2F4`ZKiO~VnDap#RKsK;R(VMfY(qXE<>b#Q|Bw!&zJg1PG@yRK bU9L|XznY{!y05gOZ#Q)#!8iX8c)78m$sQs| delta 113317 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

    9=PyNXe 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

  • Attributes +
  • +
  • In-memory Attributes (NAttributes)
  • Batch Code Processor