From 0fb7d13d63f675b3c2c28f355a7387c405b3464d Mon Sep 17 00:00:00 2001 From: Griatch Date: Mon, 17 Apr 2017 08:43:01 +0200 Subject: [PATCH] Correct for PEP8 compliance. Add contrib entry to README. --- evennia/contrib/README.md | 2 + evennia/contrib/clothing.py | 220 +++++++++++++++++++----------------- 2 files changed, 116 insertions(+), 106 deletions(-) diff --git a/evennia/contrib/README.md b/evennia/contrib/README.md index 0901e81540..510d9762bb 100644 --- a/evennia/contrib/README.md +++ b/evennia/contrib/README.md @@ -19,6 +19,8 @@ things you want from here into your game folder and change them there. for any game. Allows safe trading of any godds (including coin) * CharGen (Griatch 2011) - A simple Character creator for OOC mode. Meant as a starting point for a more fleshed-out system. +* Clothing (BattleJenkins 2017) - A layered clothing system with + slots for different types of garments auto-showing in description. * Custom gametime (Griatch, vlgeoff 2017) - Implements Evennia's gametime module but for custom game world-specific calendars. * Dice (Griatch 2012) - A fully featured dice rolling system. diff --git a/evennia/contrib/clothing.py b/evennia/contrib/clothing.py index 2096211680..0608dac03a 100644 --- a/evennia/contrib/clothing.py +++ b/evennia/contrib/clothing.py @@ -8,7 +8,7 @@ Clothing items, when worn, are added to the character's description in a list. For example, if wearing the following clothing items: a thin and delicate necklace - a pair of regular ol' shoes + a pair of regular ol' shoes one nice hat a very pretty dress @@ -16,17 +16,17 @@ A character's description may look like this: Superuser(#1) This is User #1. - - Superuser is wearing one nice hat, a thin and delicate necklace, + + Superuser is wearing one nice hat, a thin and delicate necklace, a very pretty dress and a pair of regular ol' shoes. - + Characters can also specify the style of wear for their clothing - I.E. to wear a scarf 'tied into a tight knot around the neck' or 'draped loosely across the shoulders' - to add an easy avenue of customization. For example, after entering: wear scarf draped loosely across the shoulders - + The garment appears like so in the description: Superuser(#1) @@ -50,69 +50,67 @@ inherit from ClothedCharacter in your game's characters.py file: from evennia.contrib.clothing import ClothedCharacter class Character(ClothedCharacter): - + And do the same with the ClothedCharacterCmdSet in your game's default_cmdsets.py: from evennia.contrib.clothing import ClothedCharacterCmdSet class CharacterCmdSet(default_cmds.CharacterCmdSet): - + From here, you can use the default builder commands to create clothes with which to test the system: - + @create a pretty shirt : evennia.contrib.clothing.Clothing @set shirt/clothing_type = 'top' + """ from evennia import DefaultObject from evennia import DefaultCharacter from evennia import default_cmds from evennia.commands.default.muxcommand import MuxCommand -from evennia.utils import search from evennia.utils import list_to_string from evennia.utils import evtable # Options start here. # Maximum character length of 'wear style' strings, or None for unlimited. -WEARSTYLE_MAXLENGTH = 50 +WEARSTYLE_MAXLENGTH = 50 # The order in which clothing types appear on the description. Untyped clothing goes last. -CLOTHING_TYPE_ORDER = ['hat','jewelry','top','undershirt','gloves','fullbody','bottom','underpants','socks','shoes','accessory'] +CLOTHING_TYPE_ORDER = ['hat', 'jewelry', 'top', 'undershirt', 'gloves', 'fullbody', 'bottom', + 'underpants', 'socks', 'shoes', 'accessory'] # The maximum number of each type of clothes that can be worn. Unlimited if untyped or not specified. CLOTHING_TYPE_LIMIT = { - 'hat':1, - 'gloves':1, - 'socks':1, - 'shoes':1 + 'hat': 1, + 'gloves': 1, + 'socks': 1, + 'shoes': 1 } # The maximum number of clothing items that can be worn, or None for unlimited. -CLOTHING_OVERALL_LIMIT = 20 +CLOTHING_OVERALL_LIMIT = 20 # What types of clothes will automatically cover what other types of clothes when worn. # Note that clothing only gets auto-covered if it's already worn when you put something # on that auto-covers it - for example, it's perfectly possible to have your underpants # showing if you put them on after your pants! CLOTHING_TYPE_AUTOCOVER = { - 'top':['undershirt'], - 'bottom':['underpants'], - 'fullbody':['undershirt','underpants'], - 'shoes':['socks'] + 'top': ['undershirt'], + 'bottom': ['underpants'], + 'fullbody': ['undershirt', 'underpants'], + 'shoes': ['socks'] } # Types of clothes that can't be used to cover other clothes. CLOTHING_TYPE_CANT_COVER_WITH = ['jewelry'] -""" ----------------------------------------------------------------------------- -HELPER FUNCTIONS START HERE ----------------------------------------------------------------------------- -""" + +# HELPER FUNCTIONS START HERE def order_clothes_list(clothes_list): """ Orders a given clothes list by the order specified in CLOTHING_TYPE_ORDER. - + Args: clothes_list (list): List of clothing items to put in order - + Returns: ordered_clothes_list (list): The same list as passed, but re-ordered according to the hierarchy of clothing types @@ -133,17 +131,18 @@ def order_clothes_list(clothes_list): ordered_clothes_list.insert(0, clothes) return ordered_clothes_list + def get_worn_clothes(character, exclude_covered=False): """ Get a list of clothes worn by a given character. - + Args: character (obj): The character to get a list of worn clothes from. - + Kwargs: exclude_covered (bool): If True, excludes clothes covered by other clothing from the returned list. - + Returns: ordered_clothes_list (list): A list of clothing items worn by the given character, ordered according to @@ -153,24 +152,25 @@ def get_worn_clothes(character, exclude_covered=False): clothes_list = [] for thing in character.contents: # If uncovered or not excluding covered items - if not thing.db.covered_by or exclude_covered == False: + if not thing.db.covered_by or exclude_covered is False: # If 'worn' is True, add to the list if thing.db.worn: clothes_list.append(thing) # Might as well put them in order here too. ordered_clothes_list = order_clothes_list(clothes_list) return ordered_clothes_list - + + def clothing_type_count(clothes_list): """ Returns a dictionary of the number of each clothing type in a given list of clothing objects. - + Args: clothes_list (list): A list of clothing items from which to count the number of clothing types represented among them. - + Returns: types_count (dict): A dictionary of clothing types represented in the given list and the number of each @@ -185,15 +185,16 @@ def clothing_type_count(clothes_list): else: types_count[type] += 1 return types_count - + + def single_type_count(clothes_list, type): """ Returns an integer value of the number of a given type of clothing in a list. - + Args: clothes_list (list): List of clothing objects to count from type (str): Clothing type to count - + Returns: type_count (int): Number of garments of the specified type in the given list of clothing objects @@ -205,19 +206,20 @@ def single_type_count(clothes_list, type): type_count += 1 return type_count + class Clothing(DefaultObject): - + def wear(self, wearer, wearstyle, quiet=False): """ - Sets clothes to 'worn' and optionally echoes to the room. - + Sets clothes to 'worn' and optionally echoes to the room. + Args: wearer (obj): character object wearing this clothing object wearstyle (True or str): string describing the style of wear or True for none - + Kwargs: quiet (bool): If false, does not message the room - + Notes: Optionally sets db.worn with a 'wearstyle' that appends a short passage to the end of the name of the clothing to describe how it's worn that shows @@ -230,7 +232,8 @@ class Clothing(DefaultObject): to_cover = [] if self.db.clothing_type and self.db.clothing_type in CLOTHING_TYPE_AUTOCOVER: for garment in get_worn_clothes(wearer): - if garment.db.clothing_type and garment.db.clothing_type in CLOTHING_TYPE_AUTOCOVER[self.db.clothing_type]: + if garment.db.clothing_type and garment.db.clothing_type \ + in CLOTHING_TYPE_AUTOCOVER[self.db.clothing_type]: to_cover.append(garment) garment.db.covered_by = self # Return if quiet @@ -238,29 +241,29 @@ class Clothing(DefaultObject): return # Echo a message to the room message = "%s puts on %s" % (wearer, self.name) - if not wearstyle == True: + if wearstyle is not True: message = "%s wears %s %s" % (wearer, self.name, wearstyle) if to_cover: message = message + ", covering %s" % list_to_string(to_cover) wearer.location.msg_contents(message + ".") - + def remove(self, wearer, quiet=False): """ Removes worn clothes and optionally echoes to the room. - + Args: wearer (obj): character object wearing this clothing object - + Kwargs: quiet (bool): If false, does not message the room """ self.db.worn = False remove_message = "%s removes %s." % (wearer, self.name) uncovered_list = [] - + # Check to see if any other clothes are covered by this object. for thing in wearer.contents: - # If anything is covered by + # If anything is covered by if thing.db.covered_by == self: thing.db.covered_by = False uncovered_list.append(thing.name) @@ -269,7 +272,7 @@ class Clothing(DefaultObject): # Echo a message to the room if not quiet: wearer.location.msg_contents(remove_message) - + def at_get(self, getter): """ Makes absolutely sure clothes aren't already set as 'worn' @@ -277,7 +280,8 @@ class Clothing(DefaultObject): location changed without getting removed. """ self.db.worn = False - + + class ClothedCharacter(DefaultCharacter): """ Character that displays worn clothing when looked at. You can also @@ -291,7 +295,7 @@ class ClothedCharacter(DefaultCharacter): Args: looker (Object): Object doing the looking. - + Notes: The name of every clothing item carried and worn by the character is appended to their description. If the clothing's db.worn value @@ -309,7 +313,7 @@ class ClothedCharacter(DefaultCharacter): # Append worn, uncovered clothing to the description for garment in clothes_list: # If 'worn' is True, just append the name - if garment.db.worn == True: + if garment.db.worn is True: worn_string_list.append(garment.name) # Otherwise, append the name and the string value of 'worn' elif garment.db.worn: @@ -323,37 +327,9 @@ class ClothedCharacter(DefaultCharacter): string += "|/|/%s is not wearing anything." % self return string -""" ----------------------------------------------------------------------------- -COMMANDS START HERE ----------------------------------------------------------------------------- -""" - -class ClothedCharacterCmdSet(default_cmds.CharacterCmdSet): - """ - Command set for clothing, including new versions of 'give' and 'drop' - that take worn and covered clothing into account, as well as a new - version of 'inventory' that differentiates between carried and worn - items. - """ - key = "DefaultCharacter" - def at_cmdset_creation(self): - """ - Populates the cmdset - """ - super(ClothedCharacterCmdSet, self).at_cmdset_creation() - # - # any commands you add below will overload the default ones. - # - self.add(CmdWear()) - self.add(CmdRemove()) - self.add(CmdCover()) - self.add(CmdUncover()) - self.add(CmdGive()) - self.add(CmdDrop()) - self.add(CmdInventory()) - +# COMMANDS START HERE + class CmdWear(MuxCommand): """ Puts on an item of clothing you are holding. @@ -364,10 +340,10 @@ class CmdWear(MuxCommand): Examples: wear shirt wear scarf wrapped loosely about the shoulders - + All the clothes you are wearing are appended to your description. If you provide a 'wear style' after the command, the message you - provide will be displayed after the clothing's name. + provide will be displayed after the clothing's name. """ key = "wear" @@ -387,12 +363,12 @@ class CmdWear(MuxCommand): if not clothing.is_typeclass("evennia.contrib.clothing.Clothing"): self.caller.msg("That's not clothes!") return - + # Enforce overall clothing limit. if CLOTHING_OVERALL_LIMIT and len(get_worn_clothes(self.caller)) >= CLOTHING_OVERALL_LIMIT: self.caller.msg("You can't wear any more clothes.") return - + # Apply individual clothing type limits. if clothing.db.clothing_type and not clothing.db.worn: type_count = single_type_count(get_worn_clothes(self.caller), clothing.db.clothing_type) @@ -400,7 +376,7 @@ class CmdWear(MuxCommand): if type_count >= CLOTHING_TYPE_LIMIT[clothing.db.clothing_type]: self.caller.msg("You can't wear any more clothes of the type '%s'." % clothing.db.clothing_type) return - + if clothing.db.worn and len(self.arglist) == 1: self.caller.msg("You're already wearing %s!" % clothing.name) return @@ -413,14 +389,15 @@ class CmdWear(MuxCommand): else: wearstyle = wearstring clothing.wear(self.caller, wearstyle) - + + class CmdRemove(MuxCommand): """ Takes off an item of clothing. - + Usage: remove - + Removes an item of clothing you are wearing. You can't remove clothes that are covered up by something else - you must take off the covering item first. @@ -444,13 +421,14 @@ class CmdRemove(MuxCommand): return clothing.remove(self.caller) + class CmdCover(MuxCommand): """ Covers a worn item of clothing with another you're holding or wearing. - + Usage: cover [with] - + When you cover a clothing item, it is hidden and no longer appears in your description until it's uncovered or the item covering it is removed. You can't remove an item of clothing if it's covered. @@ -463,7 +441,7 @@ class CmdCover(MuxCommand): """ This performs the actual command. """ - + if len(self.arglist) < 2: self.caller.msg("Usage: cover [with] ") return @@ -497,17 +475,18 @@ class CmdCover(MuxCommand): self.caller.msg("%s is already covered by %s." % (cover_with.name, to_cover.db.covered_by.name)) return if not cover_with.db.worn: - cover_with.wear(self.caller, True) #Put on the item to cover with if it's not on already + cover_with.wear(self.caller, True) # Put on the item to cover with if it's not on already self.caller.location.msg_contents("%s covers %s with %s." % (self.caller, to_cover.name, cover_with.name)) to_cover.db.covered_by = cover_with - + + class CmdUncover(MuxCommand): """ Reveals a worn item of clothing that's currently covered up. - + Usage: uncover - + When you uncover an item of clothing, you allow it to appear in your description without having to take off the garment that's currently covering it. You can't uncover an item of clothing if the item covering @@ -521,7 +500,7 @@ class CmdUncover(MuxCommand): """ This performs the actual command. """ - + if not self.args: self.caller.msg("Usage: uncover ") return @@ -541,7 +520,8 @@ class CmdUncover(MuxCommand): return self.caller.location.msg_contents("%s uncovers %s." % (self.caller, to_uncover.name)) to_uncover.db.covered_by = None - + + class CmdDrop(MuxCommand): """ drop something @@ -572,7 +552,7 @@ class CmdDrop(MuxCommand): multimatch_string="You carry more than one %s:" % self.args) if not obj: return - + # This part is new! # You can't drop clothing items that are covered. if obj.db.covered_by: @@ -589,7 +569,8 @@ class CmdDrop(MuxCommand): exclude=caller) # Call the object script's at_drop() method. obj.at_drop(caller) - + + class CmdGive(MuxCommand): """ give away something to someone @@ -623,7 +604,7 @@ class CmdGive(MuxCommand): if not to_give.location == caller: caller.msg("You are not holding %s." % to_give.key) return - # This is new! Can't give away something that's worn. + # This is new! Can't give away something that's worn. if to_give.db.covered_by: caller.msg("You can't give that away because it's covered by %s." % to_give.db.covered_by) return @@ -637,7 +618,8 @@ class CmdGive(MuxCommand): target.msg("%s gives you %s." % (caller.key, to_give.key)) # Call the object script's at_give() method. to_give.at_give(caller, target) - + + class CmdInventory(MuxCommand): """ view inventory @@ -650,7 +632,7 @@ class CmdInventory(MuxCommand): """ # Alternate version of the inventory command which separates # worn and carried items. - + key = "inventory" aliases = ["inv", "i"] locks = "cmd:all()" @@ -661,7 +643,7 @@ class CmdInventory(MuxCommand): if not self.caller.contents: self.caller.msg("You are not carrying or wearing anything.") return - + items = self.caller.contents carry_table = evtable.EvTable(border="header") @@ -679,3 +661,29 @@ class CmdInventory(MuxCommand): wear_table.add_row("|CNothing.|n", "") string += "|/|wYou are wearing:\n%s" % wear_table self.caller.msg(string) + + +class ClothedCharacterCmdSet(default_cmds.CharacterCmdSet): + """ + Command set for clothing, including new versions of 'give' and 'drop' + that take worn and covered clothing into account, as well as a new + version of 'inventory' that differentiates between carried and worn + items. + """ + key = "DefaultCharacter" + + def at_cmdset_creation(self): + """ + Populates the cmdset + """ + super(ClothedCharacterCmdSet, self).at_cmdset_creation() + # + # any commands you add below will overload the default ones. + # + self.add(CmdWear()) + self.add(CmdRemove()) + self.add(CmdCover()) + self.add(CmdUncover()) + self.add(CmdGive()) + self.add(CmdDrop()) + self.add(CmdInventory())