mirror of
https://github.com/evennia/evennia.git
synced 2026-03-27 02:06:32 +01:00
Made TraitHandler classes replaceable and generic
This commit is contained in:
parent
fb8403e729
commit
7c31e8bd5a
1 changed files with 260 additions and 207 deletions
|
|
@ -1,7 +1,7 @@
|
|||
"""
|
||||
Traits
|
||||
|
||||
Whitenoise 2014, Ainneve contributors,
|
||||
Whitenoise 2014, Ainneve contributors,
|
||||
Griatch 2020
|
||||
|
||||
|
||||
|
|
@ -40,21 +40,21 @@ Here's an example for adding the TraitHandler to the base Object class:
|
|||
```
|
||||
|
||||
### Trait Configuration
|
||||
|
||||
|
||||
A single Trait can be one of three basic types:
|
||||
|
||||
- `Static` - this means a base value and an optional modifier. A typical example would be
|
||||
something like a Strength stat or Skill value. That is, something that varies slowly or
|
||||
not at all.
|
||||
- `Counter` - a Trait of this type has a base value and a current value that
|
||||
can vary inside a specified range. This could be used for skills that can only incrase
|
||||
to a max value.
|
||||
- `Static` - this means a base value and an optional modifier. A typical example would be
|
||||
something like a Strength stat or Skill value. That is, something that varies slowly or
|
||||
not at all.
|
||||
- `Counter` - a Trait of this type has a base value and a current value that
|
||||
can vary inside a specified range. This could be used for skills that can only incrase
|
||||
to a max value.
|
||||
- `Gauge` - Modified counter type modeling a refillable "gauge" that varies between "empty"
|
||||
and "full". The classic example is a Health stat.
|
||||
|
||||
|
||||
```python
|
||||
obj.traits.add("hp", name="Health", type="static",
|
||||
obj.traits.add("hp", name="Health", type="static",
|
||||
base=0, mod=0, min=None, max=None, extra={})
|
||||
```
|
||||
|
||||
|
|
@ -177,7 +177,7 @@ Examples:
|
|||
A "gauge" type `Trait` is a modified counter trait used to model a
|
||||
gauge that can be emptied and refilled. The `base` property of a
|
||||
gauge trait represents its "full" value. The `mod` property increases
|
||||
or decreases that "full" value, rather than the `current`.
|
||||
or decreases that "full" value, rather than the `current`.
|
||||
|
||||
Gauge type traits are best used to represent traits such as health
|
||||
points, stamina points, or magic points.
|
||||
|
|
@ -392,43 +392,28 @@ class TraitHandler:
|
|||
trait_cls = _TRAIT_CLASSES[trait_type]
|
||||
except KeyError:
|
||||
raise TraitException("Trait class for {trait_type} could not be found.")
|
||||
trait = self._cache[key] = trait_cls(self.trait_data[key])
|
||||
trait = self._cache[key] = trait_cls(_GA(self, "trait_data")[key])
|
||||
return trait
|
||||
|
||||
def add(
|
||||
self,
|
||||
key,
|
||||
name=None,
|
||||
trait_type=DEFAULT_TRAIT_TYPE,
|
||||
base=0,
|
||||
modifier=0,
|
||||
min_value=None,
|
||||
max_value=None,
|
||||
force=False,
|
||||
**extra_properties,
|
||||
):
|
||||
def add(self, key, name=None, trait_type=DEFAULT_TRAIT_TYPE, force=True, **trait_properties):
|
||||
"""
|
||||
Create a new Trait and add it to the handler.
|
||||
|
||||
Args:
|
||||
key (str): This is the name of the property that will be made
|
||||
available on this handler (example 'hp').
|
||||
name (str, optional): This is a longer name used in Trait
|
||||
string representation (example 'Health'). If not given, this
|
||||
will be set the same as `key`, starting with a capital letter.
|
||||
name (str, optional): Name of the Trait, like "Health". If
|
||||
not given, will use `key` starting with a capital letter.
|
||||
trait_type (str, optional): One of 'static', 'counter' or 'gauge'.
|
||||
base (int or float, optional): The base value, or 'full' value in the case
|
||||
of a gauge.
|
||||
modifier (int, optional): A modifier affecting the current or base value.
|
||||
min_value (int or float, optional): The minimum allowed value.
|
||||
max_value (int or float, optional): The maximum allowed value.
|
||||
force (bool, optional): Always add, replacing any existing trait.
|
||||
**extra_properties (any): All other kwargs will be made available as key:value
|
||||
properties on the handler. These must all be possible to store
|
||||
in an Attribute.
|
||||
force_add (bool): If set, create a new Trait even if a Trait with
|
||||
the same `key` already exists.
|
||||
trait_properties (dict): These will all be use to initialize
|
||||
the new trait. See the `properties` class variable on each
|
||||
Trait class to see which are required.
|
||||
|
||||
Raises:
|
||||
TraitException: If specifying invalid values or an existing trait
|
||||
TraitException: If specifying invalid values for the given Trait,
|
||||
the `trait_type` is not recognized, or an existing trait
|
||||
already exists (and `force` is unset).
|
||||
|
||||
"""
|
||||
|
|
@ -440,25 +425,24 @@ class TraitHandler:
|
|||
else:
|
||||
raise TraitException(f"Trait '{key}' already exists.")
|
||||
|
||||
if trait_type not in _TRAIT_CLASSES:
|
||||
trait_class = _TRAIT_CLASSES.get(trait_type)
|
||||
if not trait_class:
|
||||
raise TraitException("Trait-type '{trait_type} is invalid.")
|
||||
|
||||
trait_kwargs = dict(
|
||||
name=name if name is not None else key.title(),
|
||||
trait_type=trait_type,
|
||||
base=base,
|
||||
modifier=modifier,
|
||||
min_value=min_value,
|
||||
max_value=max_value,
|
||||
extra_properties=extra_properties,
|
||||
)
|
||||
trait_properties["name"] = key.title() if not name else name
|
||||
trait_properties["trait_type"] = trait_type
|
||||
|
||||
self.trait_data[key] = trait_kwargs
|
||||
# this will raise exception if input is insufficient
|
||||
trait_properties = trait_class.validate_input(trait_properties)
|
||||
|
||||
print("trait_properties", trait_properties)
|
||||
|
||||
self.trait_data[key] = trait_properties
|
||||
|
||||
def remove(self, key):
|
||||
"""
|
||||
Remove a Trait from the handler's parent object.
|
||||
|
||||
|
||||
Args:
|
||||
key (str): The name of the trait to remove.
|
||||
|
||||
|
|
@ -481,39 +465,49 @@ class TraitHandler:
|
|||
# Parent Trait class
|
||||
|
||||
|
||||
@total_ordering
|
||||
class Trait:
|
||||
"""Represents an object or Character trait.
|
||||
|
||||
Note:
|
||||
See module docstring for configuration details.
|
||||
"""
|
||||
|
||||
_keys = (
|
||||
"name",
|
||||
"trait_type",
|
||||
"base",
|
||||
"modifier",
|
||||
"current",
|
||||
"min_value",
|
||||
"max_value",
|
||||
"extra_properties",
|
||||
)
|
||||
"""
|
||||
# this is the name used to refer to this trait when adding
|
||||
# a new trait in the TraitHandler
|
||||
trait_type = "trait"
|
||||
|
||||
# These keywords form the internal data store of the Trait.
|
||||
# Unless a default value is also given, each must be given
|
||||
# supplied with an explicit value when creating this Trait.
|
||||
# This list should at minimum contain "name" and "trait_type".
|
||||
data_keys = ("name", "trait_type")
|
||||
# If a dat key has a default, we will use this if it's not supplied at
|
||||
# creation.
|
||||
data_default = {}
|
||||
|
||||
# enable to set/retrieve other arbitrary properties on the Trait
|
||||
# and have them treated like data to store.
|
||||
allow_extra_properties = True
|
||||
|
||||
def __init__(self, trait_data):
|
||||
"""
|
||||
Initialize a Trait with stored data.
|
||||
This both initializes and validates the Trait on creation. It must
|
||||
raise exception if validation fails. The TraitHandler will call this
|
||||
when the trait is furst added, to make sure it validates before
|
||||
storing.
|
||||
|
||||
Args:
|
||||
trait_data (_SaverDict or dict): This will be a _SaverDict if
|
||||
passed from the TraitHandler, which means this will automatically
|
||||
save itself the database when updating
|
||||
trait_data (any): Any pickle-able values to store with this trait.
|
||||
This must contain any cls.data_keys that do not have a default
|
||||
value in cls.data_default_values. Any extra kwargs will be made
|
||||
available as extra properties on the Trait, assuming the class
|
||||
variable `allow_extra_properties` is set.
|
||||
|
||||
Raises:
|
||||
TraitException: If input-validation failed.
|
||||
|
||||
"""
|
||||
|
||||
self._type = trait_data["trait_type"]
|
||||
self._data = trait_data
|
||||
self._locked = True
|
||||
self._data = self.__class__.validate_input(trait_data)
|
||||
|
||||
if not isinstance(trait_data, _SaverDict):
|
||||
logger.log_warn(
|
||||
|
|
@ -521,20 +515,34 @@ class Trait:
|
|||
f"loaded for {type(self).__name__}."
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
"""Debug-friendly representation of this Trait."""
|
||||
return "{}({{{}}})".format(
|
||||
type(self).__name__,
|
||||
", ".join(
|
||||
["'{}': {!r}".format(k, self._data[k]) for k in self._keys if k in self._data]
|
||||
),
|
||||
)
|
||||
@classmethod
|
||||
def validate_input(cls, trait_data):
|
||||
"""
|
||||
Validate input
|
||||
|
||||
def __str__(self):
|
||||
status = "{actual:11}".format(actual=self.actual)
|
||||
return "{name:12} {status} ({mod:+3})".format(name=self.name, status=status, mod=self.mod)
|
||||
"""
|
||||
inp, req = set(trait_data.keys()), set(cls.data_keys)
|
||||
unset = req.difference(inp.intersection(req))
|
||||
if unset:
|
||||
# try to add defaults to those we have not set
|
||||
no_defaults = unset.difference(set(cls.data_default))
|
||||
print(f"inp: {inp}, req: {req}, unset: {unset}, no_defaults: {no_defaults}")
|
||||
if no_defaults:
|
||||
raise TraitException(
|
||||
"Trait {} could not be created - misses required keys {}".format(
|
||||
cls.trait_type, ", ".join(no_defaults)
|
||||
)
|
||||
)
|
||||
trait_data.update({key: cls.data_default[key] for key in unset})
|
||||
|
||||
# Extra Properties - allow access to properties on Trait
|
||||
if not cls.allow_extra_properties:
|
||||
# don't allow any extra properties - remove the extra data
|
||||
for key in inp.difference(req):
|
||||
del trait_data[key]
|
||||
|
||||
return trait_data
|
||||
|
||||
# Grant access to properties on this Trait.
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""Access extra parameters as dict keys."""
|
||||
|
|
@ -553,11 +561,17 @@ class Trait:
|
|||
|
||||
def __getattr__(self, key):
|
||||
"""Access extra parameters as attributes."""
|
||||
if key in ("data_keys", "data_default", "trait_type", "allow_extra_properties"):
|
||||
return _GA(self, key)
|
||||
try:
|
||||
return self._data["extra_properties"][key]
|
||||
return self._data[key]
|
||||
except KeyError:
|
||||
raise AttributeError(
|
||||
"{} '{}' has no attribute {!r}".format(type(self).__name__, self.name, key)
|
||||
"{!r} {} ({}) has no attribute {!r}.".format(
|
||||
self._data['name'],
|
||||
type(self).__name__,
|
||||
self.trait_type,
|
||||
key)
|
||||
)
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
|
|
@ -568,36 +582,71 @@ class Trait:
|
|||
|
||||
This behavior is enabled by setting the instance
|
||||
variable `_locked` to True.
|
||||
|
||||
"""
|
||||
propobj = getattr(self.__class__, key, None)
|
||||
if isinstance(propobj, property):
|
||||
if propobj.fset is None:
|
||||
raise AttributeError(f"Can't set attribute {key}.")
|
||||
propobj.fset(self, value)
|
||||
# we have a custom property named as this key, find and use its setter
|
||||
if propobj.fset:
|
||||
propobj.fset(self, value)
|
||||
return
|
||||
else:
|
||||
if self.__dict__.get("_locked", False) and key not in ("_keys",):
|
||||
_GA(self, "_data")["extra_properties"][key] = value
|
||||
else:
|
||||
# this is some other value
|
||||
if key in ("_data", ):
|
||||
_SA(self, key, value)
|
||||
return
|
||||
if _GA(self, "allow_extra_properties"):
|
||||
_GA(self, "_data")[key] = value
|
||||
return
|
||||
raise AttributeError(f"Can't set attribute {key} on "
|
||||
f"{self.trait_type} Trait.")
|
||||
|
||||
def __delattr__(self, key):
|
||||
"""Delete extra parameters as attributes."""
|
||||
if key in self._data["extra_properties"]:
|
||||
del self._data["extra_properties"][key]
|
||||
if key not in _GA(self, properties) and key in self._data:
|
||||
del self._data[key]
|
||||
|
||||
# Limiting the value to set
|
||||
def __repr__(self):
|
||||
"""Debug-friendly representation of this Trait."""
|
||||
return "{}({{{}}})".format(
|
||||
type(self).__name__,
|
||||
", ".join(
|
||||
["'{}': {!r}".format(k, self._data[k]) for k in self._keys if k in self._data]
|
||||
),
|
||||
)
|
||||
|
||||
def _enforce_bounds(self, value):
|
||||
"""Ensures that incoming value falls within trait's range."""
|
||||
return value
|
||||
def __str__(self):
|
||||
return f"<Trait {self.name}>"
|
||||
|
||||
def _mod_base(self):
|
||||
"""Calculate adding base and modifications"""
|
||||
return self._enforce_bounds(self.mod + self.base)
|
||||
# access properties
|
||||
|
||||
def _mod_current(self):
|
||||
"""Calculate the current value"""
|
||||
return self._enforce_bounds(self.mod + self.current)
|
||||
@property
|
||||
def name(self):
|
||||
"""Display name for the trait."""
|
||||
return self._data["name"]
|
||||
|
||||
key = name
|
||||
|
||||
|
||||
|
||||
@total_ordering
|
||||
class NumericTrait(Trait):
|
||||
"""
|
||||
Base trait for all Traits based on numbers. This implements
|
||||
number-comparisons, limits etc. It also features a "modifier"
|
||||
to the value, since this is a common use.
|
||||
|
||||
"""
|
||||
|
||||
trait_type = "numeric"
|
||||
|
||||
data_keys = (
|
||||
"name",
|
||||
"base",
|
||||
)
|
||||
data_default = {
|
||||
"base": 0
|
||||
}
|
||||
|
||||
# Numeric operations
|
||||
|
||||
|
|
@ -689,17 +738,10 @@ class Trait:
|
|||
|
||||
# Public members
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Display name for the trait."""
|
||||
return self._data["name"]
|
||||
|
||||
key = name
|
||||
|
||||
@property
|
||||
def actual(self):
|
||||
"The actual value of the trait"
|
||||
return self._mod_base()
|
||||
return self.base_mod_base()
|
||||
|
||||
@property
|
||||
def base(self):
|
||||
|
|
@ -711,115 +753,94 @@ class Trait:
|
|||
"""
|
||||
return self._data["base"]
|
||||
|
||||
@base.setter
|
||||
def base(self, amount):
|
||||
if self._data.get("max", None) == "base":
|
||||
self._data["base"] = amount
|
||||
if type(amount) in (int, float):
|
||||
self._data["base"] = self._enforce_bounds(amount)
|
||||
|
||||
@property
|
||||
def mod(self):
|
||||
"""The trait's modifier."""
|
||||
return self._data["modifier"]
|
||||
|
||||
@mod.setter
|
||||
def mod(self, amount):
|
||||
if type(amount) in (int, float):
|
||||
self._data["modifier"] = amount
|
||||
|
||||
@property
|
||||
def min(self):
|
||||
return self._data["min_value"]
|
||||
|
||||
@min.setter
|
||||
def min(self, value):
|
||||
self._data["min_value"] = value
|
||||
|
||||
@property
|
||||
def max(self):
|
||||
return self._data["max_value"]
|
||||
|
||||
@max.setter
|
||||
def max(self, value):
|
||||
self._data["max_value"] = value
|
||||
|
||||
@property
|
||||
def current(self):
|
||||
"""The `current` value of the `Trait`."""
|
||||
return self._data.get("current", self.base)
|
||||
|
||||
@current.setter
|
||||
def current(self, value):
|
||||
self._data["current"] = value
|
||||
|
||||
@property
|
||||
def extra(self):
|
||||
"""Returns a list containing available extra data keys."""
|
||||
return self._data["extra"].keys()
|
||||
|
||||
def reset_mod(self):
|
||||
"""Clears any mod value to 0."""
|
||||
self.mod = 0
|
||||
|
||||
def reset(self):
|
||||
"""Resets `current` property equal to `base` value."""
|
||||
self.current = self.base
|
||||
|
||||
def percent(self):
|
||||
"""Returns the value formatted as a percentage."""
|
||||
return "100.0%"
|
||||
|
||||
|
||||
# Implementation of the respective Trait types
|
||||
|
||||
|
||||
class StaticTrait(Trait):
|
||||
class StaticTrait(NumericTrait):
|
||||
"""
|
||||
Static Trait.
|
||||
Static Trait. This has a modification value.
|
||||
|
||||
"""
|
||||
|
||||
trait_type = "static"
|
||||
|
||||
@property
|
||||
def min(self):
|
||||
raise TraitException(f"Static Trait {self.key} has no minimum value.")
|
||||
data_keys = (
|
||||
"name",
|
||||
"base",
|
||||
"mod",
|
||||
)
|
||||
data_default = {
|
||||
"base": 0,
|
||||
"mod": 0
|
||||
}
|
||||
|
||||
|
||||
def __str__(self):
|
||||
status = "{actual:11}".format(actual=self.actual)
|
||||
return "{name:12} {status} ({mod:+3})".format(name=self.name, status=status, mod=self.mod)
|
||||
|
||||
# Helpers
|
||||
|
||||
@min.setter
|
||||
def min(self):
|
||||
raise TraitException(f"Cannot set minimum value for static Trait {self.key}.")
|
||||
|
||||
@property
|
||||
def max(self):
|
||||
raise TraitException("Static Trait {self.key} has no maximum value.")
|
||||
def mod(self):
|
||||
"""The trait's modifier."""
|
||||
return self._data["mod"]
|
||||
|
||||
@max.setter
|
||||
def max(self):
|
||||
raise TraitException("Cannot set maximum value for static Trait {self.key}.")
|
||||
@mod.setter
|
||||
def mod(self, amount):
|
||||
if type(amount) in (int, float):
|
||||
self._data["mod"] = amount
|
||||
|
||||
@property
|
||||
def current(self):
|
||||
"""The `current` value of the `Trait`. This is the same as base for a Static Trait."""
|
||||
return self.base
|
||||
|
||||
@current.setter
|
||||
def current(self, value):
|
||||
"""Current == base for Static Traits."""
|
||||
self.base = value
|
||||
|
||||
def reset(self):
|
||||
raise TraitException(f"Cannot reset static Trait {self.key}.")
|
||||
def actual(self):
|
||||
"The actual value of the Trait"
|
||||
return self.base + self.mod
|
||||
|
||||
|
||||
class CounterTrait(Trait):
|
||||
class CounterTrait(NumericTrait):
|
||||
"""
|
||||
Counter Trait.
|
||||
|
||||
This includes modifications and min/max limits as well as the notion of a
|
||||
current value. The value can also be reset to the base value.
|
||||
|
||||
"""
|
||||
|
||||
trait_type = "counter"
|
||||
|
||||
data_keys = (
|
||||
"name",
|
||||
"base",
|
||||
"mod",
|
||||
"current",
|
||||
"min_value",
|
||||
"max_value"
|
||||
)
|
||||
data_default = {
|
||||
"base": 0,
|
||||
"mod": 0,
|
||||
"current": 0,
|
||||
"min_value": None,
|
||||
"max_value": None
|
||||
}
|
||||
|
||||
# Helpers
|
||||
|
||||
def _enforce_bounds(self, value):
|
||||
"""Ensures that incoming value falls within trait's range."""
|
||||
return value
|
||||
|
||||
def _mod_base(self):
|
||||
"""Calculate adding base and modifications"""
|
||||
return self._enforce_bounds(self.mod + self.base)
|
||||
|
||||
def _mod_current(self):
|
||||
"""Calculate the current value"""
|
||||
return self._enforce_bounds(self.mod + self.current)
|
||||
|
||||
def _enforce_bounds(self, value):
|
||||
"""Ensures that incoming value falls within trait's range."""
|
||||
if self.min is not None and value <= self.min:
|
||||
|
|
@ -830,15 +851,27 @@ class CounterTrait(Trait):
|
|||
return self.max
|
||||
return value
|
||||
|
||||
# properties
|
||||
|
||||
@property
|
||||
def actual(self):
|
||||
"The actual value of the Trait"
|
||||
return self._mod_current()
|
||||
|
||||
@property
|
||||
def base(self):
|
||||
return self._data["base"]
|
||||
|
||||
@base.setter
|
||||
def base(self, amount):
|
||||
if self._data.get("max", None) == "base":
|
||||
self._data["base"] = amount
|
||||
if type(amount) in (int, float):
|
||||
self._data["base"] = self._enforce_bounds(amount)
|
||||
|
||||
@property
|
||||
def min(self):
|
||||
"""The lower bound of the range."""
|
||||
return super().min
|
||||
return self._data["min_value"]
|
||||
|
||||
@min.setter
|
||||
def min(self, amount):
|
||||
|
|
@ -851,7 +884,7 @@ class CounterTrait(Trait):
|
|||
def max(self):
|
||||
if self._data["max_value"] == "base":
|
||||
return self._mod_base()
|
||||
return super().max
|
||||
return self._data["max_value"]
|
||||
|
||||
@max.setter
|
||||
def max(self):
|
||||
|
|
@ -862,12 +895,6 @@ class CounterTrait(Trait):
|
|||
When set this way, the property returns the value of the
|
||||
`mod`+`base` properties.
|
||||
"""
|
||||
if self._data["max_value"] == "base":
|
||||
return self._mod_base()
|
||||
return super().max
|
||||
|
||||
@max.setter
|
||||
def max(self, value):
|
||||
if value == "base" or value is None:
|
||||
self._data["max_value"] = value
|
||||
elif type(value) in (int, float):
|
||||
|
|
@ -876,14 +903,20 @@ class CounterTrait(Trait):
|
|||
@property
|
||||
def current(self):
|
||||
"""The `current` value of the `Trait`."""
|
||||
return super().current
|
||||
return self._data.get("current", self.base)
|
||||
|
||||
@current.setter
|
||||
def current(self, value):
|
||||
if type(value) in (int, float):
|
||||
self._data["current"] = self._enforce_bounds(value)
|
||||
else:
|
||||
raise AttributeError("'current' property is read-only on static 'Trait'.")
|
||||
|
||||
def reset_mod(self):
|
||||
"""Clears any mod value to 0."""
|
||||
self.mod = 0
|
||||
|
||||
def reset(self):
|
||||
"""Resets `current` property equal to `base` value."""
|
||||
self.current = self.base
|
||||
|
||||
def percent(self):
|
||||
"""Returns the value formatted as a percentage."""
|
||||
|
|
@ -899,10 +932,29 @@ class GaugeTrait(CounterTrait):
|
|||
"""
|
||||
Gauge Trait.
|
||||
|
||||
This emulates a gauge-meter that can be reset.
|
||||
|
||||
"""
|
||||
|
||||
trait_type = "gauge"
|
||||
|
||||
# same as Counter, here for easy reference
|
||||
data_keys = (
|
||||
"name",
|
||||
"base",
|
||||
"mod",
|
||||
"current",
|
||||
"min_value",
|
||||
"max_value"
|
||||
)
|
||||
data_default = {
|
||||
"base": 0,
|
||||
"mod": 0,
|
||||
"current": 0,
|
||||
"min_value": None,
|
||||
"max_value": None
|
||||
}
|
||||
|
||||
def __str__(self):
|
||||
status = "{actual:4} / {base:4}".format(actual=self.actual, base=self.base)
|
||||
return "{name:12} {status} ({mod:+3})".format(name=self.name, status=status, mod=self.mod)
|
||||
|
|
@ -915,13 +967,13 @@ class GaugeTrait(CounterTrait):
|
|||
@property
|
||||
def mod(self):
|
||||
"""The trait's modifier."""
|
||||
return super().mod
|
||||
return self._data["mod"]
|
||||
|
||||
@mod.setter
|
||||
def mod(self, amount):
|
||||
if type(amount) in (int, float):
|
||||
self._data["modifier"] = amount
|
||||
delta = amount - self._data["modifier"]
|
||||
self._data["mod"] = amount
|
||||
delta = amount - self._data["mod"]
|
||||
if delta >= 0:
|
||||
# apply increases to current
|
||||
self.current = self._enforce_bounds(self.current + delta)
|
||||
|
|
@ -936,7 +988,8 @@ class GaugeTrait(CounterTrait):
|
|||
|
||||
@current.setter
|
||||
def current(self, value):
|
||||
super().current = value
|
||||
if type(value) in (int, float):
|
||||
self._data["current"] = self._enforce_bounds(value)
|
||||
|
||||
def fill_gauge(self):
|
||||
"""Adds the `mod`+`base` to the `current` value.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue