Source code for pyzork.levels
from .utils import post_output
from .base import QM
from .enums import StatEnum
import math
[docs]class ExperienceLevels:
"""ExperienceLevels are handlers for an entity's epxerience and rank. You can pass a hardcoded list of
experience requirements and rewards or you can generate those automatically using certain parameters.
Parameters
-----------
requirements : Optional[List[int]]
A list of int meant to represent the amount of xp it takes to get from one rank to the next. The first
representing the amount it takes to go from level 0 to level 1. If this parameter is provided you won't
need to provide either of the `max_level`, `requirement` or `modifier` arguments.
requirement : Optional[int]
A single int, representing the xp it takes to get from level 0 to level 1. All further requirements will
be derived from this one and the modifier. If this argument is provided then `modifier` and `max_level`
must also be provided.
max_level : Optional[int]
A single int, meant to represent the maximum leve that can be reached, once that level is reached
experience can still be acumulated but no level up event will occur and no extra rewards will be granted.
modifier : Optional[float]
A float which defines by how much the next requirement is increased by. For example, with a starting
requirement of 100 and a modifier of 1.2, from level 0 to 1 you'll need a 100 exp, from 1 to 2 you'll
need 120, from 2 to 3 you'll need 144 and so on.
rXX : Optional[int]
An abstract keyword argument, there is not literal rXX argument, rather the XX can be replaced with
the level of the requirement you wish to change, this allows you automatically generate the requirements
but still have some control over the system.
rewards : Optional[List[Callable[[ExperienceLevels], None]]]
A list of functions to be called when a user levels up, with the first element being when the user
goes from level 0 to level 1. This allows you complete control over the rewards. If you provide this
parameter you do not have to provide `reward`.
reward : Optional[Callable[[ExperienceLevels], None]]
A single reward, which will be used as the default for every level up. If you provide this argument you
do not have to provide `rewards`. You can then further customise individual level up rewards using the
`lXX` keywords where XX is the level they need to reach to get the reward.
lXX : Optional[Callable[[ExperienceLevels], None]]
This is an abstract keyword argument, there is no literal lXX argument, rather you can replace XX with
the level of the reward you wish to change. This argument takes a standard reward callable.
experience_gain : Optional[float]
Multiplicative stat to define experience gain, 1 by default
Attributes
-----------
max_level : int
The max level the class (and by extension the attached entity) can reach.
experience : int
The current experience the entity has
requirement : int
How much experience the entity needs to have total to reach the next level
remaining : int
How much experience the entity still needs to reach the next level
level : int
The entity's current level (starts at 0)
experience_gain : float
The current multiplier for gained experienced
total : int
The total amount of experience that has been gained, the sum of all the past requirements and the
current amount of experience the entity has.
"""
def __init__(self, **kwargs):
if "requirements" in kwargs:
self.requirements = kwargs.pop("requirements")
self.max_level = len(self.requirements)
else:
modifier = kwargs.pop("modifier")
requirement = kwargs.pop("requirement")
self.max_level = kwargs.pop("max_level")
self.generate_levels(requirement, modifier)
self.level = kwargs.pop("level", 0)
self._experience = kwargs.pop("experience", 0)
self.entity = None
self.base_experience_gain = kwargs.get("experience_gain", 1)
self.standard_reward = kwargs.pop("reward", self.standard_reward)
self.rewards = kwargs.pop("rewards", [self.standard_reward for x in range(self.max_level)])
for kwarg in kwargs:
if kwarg.startswith(("l", "r")):
level = kwarg[1:]
if not level.isdigit() or 0 > int(level) > self.max_level:
return
index = int(level) - 1
if kwarg.startswith("l"):
self.rewards[index] = kwargs.pop(kwarg)
else:
self.requirements[index] = kwargs.pop(kwarg)
def __repr__(self):
return f"<ExperienceLevels exp={self.experience}/{self.requirement} level={self.level}>"
@property
def experience_gain(self):
return max(0, self.base_experience_gain + self.entity._big_calc(StatEnum.experience))
def generate_levels(self, requirement, modifier):
self.requirements = [requirement]
for _ in range(self.max_level - 1):
requirement = int(requirement * modifier)
self.requirements.append(requirement)
def set_entity(self, entity : "Entity"):
self.entity = entity
@property
def requirement(self):
if self.level == self.max_level:
return math.inf
return self.requirements[self.level]
@property
def total(self):
return sum(self.requirements[:self.level]) + self.experience
@property
def remaining(self):
return self.requirement - self.experience
@property
def experience(self):
return self._experience
@experience.setter
def experience(self, value):
if value < 0:
value = 0
while value >= self.requirement:
value -= self.requirement
self.level_up()
QM.progress_quests("on_level", self)
self._experience = value
def level_up(self):
self.level += 1
self.rewards[self.level - 1](self)
def standard_reward(self, levels):
post_output(f"You leveled up! You are now level {self.level}")
def __add__(self, value):
self.experience += value
return self