Give objects weight

All in-game objets you can touch usually has some weight. What weight does varies from game to game. Commonly it limits how much you can carry. A heavy stone may also hurt you more than a ballon, if it falls on you. If you want to get fancy, a pressure plate may only trigger if the one stepping on it is heavy enough.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# inside your mygame/typeclasses/objects.py

from evennia import DefaultObject 
from evennia import AttributeProperty 

class ObjectParent: 

    weight = AttributeProperty(default=1, autocreate=False)

    @property 
    def total_weight(self):
        return self.weight + sum(obj.total_weight for obj in self.contents) 


class Object(ObjectParent, DefaultObject):
    # ...
  • Line 6: We use the ObjectParent mixin. Since this mixin is used for Characters, Exits and Rooms as well as for Object, it means all of those will automatically also have weight!

  • Line 8: We use an AttributeProperty to set up the ‘default’ weight of 1 (whatever that is). Setting autocreate=False means no actual Attribute will be created until the weight is actually changed from the default of 1. See the AttributeProperty documentation for caveats with this.

  • Line 10 and 11: Using the @property decorator on total_weight means that we will be able to call obj.total_weight instead of obj.total_weight() later.

  • Line 12: We sum up all weights from everything “in” this object, by looping over self.contents. Since all objects will have weight now, this should always work!

Let’s check out the weight of some trusty boxes

> create/drop box1
> py self.search("box1").weight
1 
> py self.search("box1").total_weight
1 

Let’s put another box into the first one.

> create/drop box2 
> py self.search("box2").total_weight
1 
> py self.search("box2").location = self.search("box1")
> py self.search(box1).total_weight 
2

Limit inventory by weight carried

To limit how much you can carry, you first need to know your own strength

# in mygame/typeclasses/characters.py 

from evennia import AttributeProperty

# ... 

class Character(ObjectParent, DefaultCharacter): 

    carrying_capacity = AttributeProperty(10, autocreate=False)

    @property
    def carried_weight(self):
        return self.total_weight - self.weight

Here we make sure to add another AttributeProperty telling us how much to carry. In a real game, this may be based on how strong the Character is. When we consider how much weight we already carry, we should not include our own weight, so we subtract that.

To honor this limit, we’ll need to override the default get command.

# in mygame/commands/command.py 

# ... 
from evennia import default_cmds 

# ... 

class WeightAwareCmdGet(default_cmds.CmdGet):

    def func(self):
        caller = self.caller 
        if not self.args: 
            caller.msg("Get what?")
            return 

        obj = caller.search(self.args)

        if (obj.weight + caller.carried_weight 
                > caller.carrying_capacity):
            caller.msg("You can't carry that much!")
            return 
        super().func()

Here we add an extra check for the weight of the thing we are trying to pick up, then we call the normal CmdGet with super().func().