Update rules

This commit is contained in:
Griatch 2022-04-12 20:02:22 +02:00
parent df5ae68a3c
commit 6e993feb88

View file

@ -23,9 +23,9 @@ This module presents several singletons to import
""" """
from random import randint from random import randint
from dataclasses import dataclass
from evennia.utils.evform import EvForm from evennia.utils.evform import EvForm
from evennia.utils.evtable import EvTable from evennia.utils.evtable import EvTable
from .enums import Ability
from .utils import roll from .utils import roll
from .random_tables import character_generation as chargen_table from .random_tables import character_generation as chargen_table
@ -39,8 +39,7 @@ class EvAdventureRollEngine:
""" """
@staticmethod def roll(self, roll_string, max_number=10):
def roll(roll_string, max_number=10):
""" """
NOTE: In evennia/contribs/rpg/dice/ is a more powerful dice roller with NOTE: In evennia/contribs/rpg/dice/ is a more powerful dice roller with
more features, such as modifiers, secret rolls etc. This is much simpler and only more features, such as modifiers, secret rolls etc. This is much simpler and only
@ -82,8 +81,7 @@ class EvAdventureRollEngine:
# At this point we know we have valid input - roll and all dice together # At this point we know we have valid input - roll and all dice together
return sum(randint(1, diesize) for _ in range(number)) return sum(randint(1, diesize) for _ in range(number))
@staticmethod def roll_with_advantage_or_disadvantage(self, advantage=False, disadvantage=False):
def roll_with_advantage_or_disadvantage(advantage=False, disadvantage=False):
""" """
Base roll of d20, or 2d20, based on dis/advantage given. Base roll of d20, or 2d20, based on dis/advantage given.
@ -104,8 +102,7 @@ class EvAdventureRollEngine:
else: else:
return min(roll("1d20"), roll("1d20")) return min(roll("1d20"), roll("1d20"))
@staticmethod def saving_throw(self, character, bonus_type=Ability.STR,
def saving_throw(character, bonus_type='strength',
advantage=False, disadvantage=False, modifier=0): advantage=False, disadvantage=False, modifier=0):
""" """
A saving throw without a clear enemy to beat. In _Knave_ all unopposed saving A saving throw without a clear enemy to beat. In _Knave_ all unopposed saving
@ -113,7 +110,8 @@ class EvAdventureRollEngine:
Args: Args:
character (Object): The one attempting to save themselves. character (Object): The one attempting to save themselves.
bonus (str): The ability bonus to apply, like strength or charisma. Minimum is 1. bonus_type (enum.Ability): The ability bonus to apply, like strength or
charisma.
advantage (bool): Roll 2d20 and use the bigger number. advantage (bool): Roll 2d20 and use the bigger number.
disadvantage (bool): Roll 2d20 and use the smaller number. disadvantage (bool): Roll 2d20 and use the smaller number.
modifier (int): An additional +/- modifier to the roll. modifier (int): An additional +/- modifier to the roll.
@ -130,7 +128,7 @@ class EvAdventureRollEngine:
""" """
bonus = getattr(character, bonus_type, 1) bonus = getattr(character, bonus_type, 1)
dice_roll = roll_with_advantage_or_disadvantage(advantage, disadvantage) dice_roll = self.roll_with_advantage_or_disadvantage(advantage, disadvantage)
if dice_roll == 1: if dice_roll == 1:
quality = "critical failure" quality = "critical failure"
elif dice_roll == 20: elif dice_roll == 20:
@ -139,9 +137,10 @@ class EvAdventureRollEngine:
quality = None quality = None
return (dice_roll + bonus + modifier) > 15, quality return (dice_roll + bonus + modifier) > 15, quality
@staticmethod def opposed_saving_throw(
def opposed_saving_throw(attacker, defender, attack_type='strength', defense_type='armor', self, attacker, defender,
advantage=False, disadvantage=False): attack_type=Ability.STR, defense_type=Ability.ARMOR,
advantage=False, disadvantage=False, modifier=0):
""" """
An saving throw that tries to beat an active opposing side. An saving throw that tries to beat an active opposing side.
@ -163,10 +162,10 @@ class EvAdventureRollEngine:
Advantage and disadvantage cancel each other out. Advantage and disadvantage cancel each other out.
""" """
attack_bonus = getattr(attacker, attack_type, 1) attack_bonus = getattr(attacker, attack_type.value, 1)
# defense is always bonus + 10 in Knave # defense is always bonus + 10 in Knave
defender_defense = getattr(defender, defense_type_type, 1) + 10 defender_defense = getattr(defender, defense_type.value, 1) + 10
dice_roll = roll_with_advantage_or_disadvantage(advantage, disadvantage) dice_roll = self.roll_with_advantage_or_disadvantage(advantage, disadvantage)
if dice_roll == 1: if dice_roll == 1:
quality = "critical failure" quality = "critical failure"
elif dice_roll == 20: elif dice_roll == 20:
@ -175,8 +174,7 @@ class EvAdventureRollEngine:
quality = None quality = None
return (dice_roll + attack_bonus + modifier) > defender_defense, quality return (dice_roll + attack_bonus + modifier) > defender_defense, quality
@staticmethod def roll_random_table(self, dieroll, table, table_choices):
def roll_random_table(dieroll, table, table_choices):
""" """
Make a roll on a random table. Make a roll on a random table.
@ -230,8 +228,7 @@ class EvAdventureRollEngine:
# specific rolls / actions # specific rolls / actions
@staticmethod def morale_check(self, defender):
def morale_check(defender):
""" """
A morale check is done for NPCs/monsters. It's done with a 2d6 against A morale check is done for NPCs/monsters. It's done with a 2d6 against
their morale. their morale.
@ -245,8 +242,19 @@ class EvAdventureRollEngine:
""" """
return roll('2d6') <= defender.morale return roll('2d6') <= defender.morale
@staticmethod def heal(self, character, amount):
def healing_from_rest(character): """
Heal specific amount, but not more than our max.
Args:
character (EvAdventureCharacter): The character to heal
amount (int): How many HP to heal.
"""
damage = character.hp_max - character.hp
character.hp += min(damage, amount)
def healing_from_rest(self, character):
""" """
A meal and a full night's rest allow for regaining 1d8 + Const bonus HP. A meal and a full night's rest allow for regaining 1d8 + Const bonus HP.
@ -257,10 +265,7 @@ class EvAdventureRollEngine:
int: How much HP was healed. This is never more than how damaged we are. int: How much HP was healed. This is never more than how damaged we are.
""" """
# we can't heal more than our damage self.heal(character, roll('1d8') + character.constitution)
damage = character.hp_max - character.hp
healed = roll('1d8') + character.constitution
return min(damage, healed)
death_map = { death_map = {
"weakened": "strength", "weakened": "strength",
@ -271,7 +276,7 @@ class EvAdventureRollEngine:
"disfigured": "charisma", "disfigured": "charisma",
} }
def roll_death(character): def roll_death(self, character):
""" """
Happens when hitting <= 0 hp. unless dead, Happens when hitting <= 0 hp. unless dead,
@ -282,12 +287,12 @@ class EvAdventureRollEngine:
character.handle_death() character.handle_death()
else: else:
# survives with degraded abilities (1d4 roll) # survives with degraded abilities (1d4 roll)
abi = death_map[result] abi = self.death_map[result]
current_abi = getattr(character, abi) current_abi = getattr(character, abi)
loss = self.roll("1d4") loss = self.roll("1d4")
current_abi =- loss current_abi -= loss
if current_abi < -10: if current_abi < -10:
# can't lose more - die # can't lose more - die
@ -312,7 +317,7 @@ class EvAdventureCharacterGeneration:
""" """
This collects all the rules for generating a new character. An instance of this class can be This collects all the rules for generating a new character. An instance of this class can be
used to track all the stats during generation and will be used to apply all the data to the used to track all the stats during generation and will be used to apply all the data to the
character at the end. This class instance can also be saved temporarily to make sure a user character at the end. This class instance can also be saved on the menu to make sure a user
is not losing their half-created character. is not losing their half-created character.
Note: Note:
@ -357,8 +362,6 @@ class EvAdventureCharacterGeneration:
self.wisdom = 2 self.wisdom = 2
self.charisma = 2 self.charisma = 2
self.armor_bonus = 1 # un-armored default
# physical attributes (only for rp purposes) # physical attributes (only for rp purposes)
self.physique = dice.roll_random_table('1d20', chargen_table['physique']) self.physique = dice.roll_random_table('1d20', chargen_table['physique'])
self.face = dice.roll_random_table('1d20', chargen_table['face']) self.face = dice.roll_random_table('1d20', chargen_table['face'])
@ -389,7 +392,7 @@ class EvAdventureCharacterGeneration:
self.weapon = dice.roll_random_table(chargen_table['1d20', "starting_weapon"]) self.weapon = dice.roll_random_table(chargen_table['1d20', "starting_weapon"])
self.equipment = [ self.backpack = [
"ration", "ration",
"ration", "ration",
dice.roll_random_table(chargen_table['1d20', "dungeoning gear"]), dice.roll_random_table(chargen_table['1d20', "dungeoning gear"]),
@ -416,7 +419,8 @@ class EvAdventureCharacterGeneration:
must not be lower than +1 and not above +6. must not be lower than +1 and not above +6.
Args: Args:
source_attribute (str): The name of the attribute to deduct bonus from, like 'strength' source_attribute (enum.Ability): The name of the attribute to deduct bonus from,
like 'strength'
target_attribute (str): The attribute to give the bonus to, like 'dexterity'. target_attribute (str): The attribute to give the bonus to, like 'dexterity'.
value (int): How much to change. This is always 1 for the current chargen. value (int): How much to change. This is always 1 for the current chargen.
@ -428,18 +432,18 @@ class EvAdventureCharacterGeneration:
much input validation here, we do make sure we don't overcharge ourselves though. much input validation here, we do make sure we don't overcharge ourselves though.
""" """
# we use getattr() to fetch the CharaAttribute of e.g. the .strength property etc # we use getattr() to fetch the Ability of e.g. the .strength property etc
source_current_bonus = getattr(self, source_attribute).bonus source_current_bonus = getattr(self, source_attribute.value, 1)
target_current_bonus = getattr(self, target_attribute).bonus target_current_bonus = getattr(self, target_attribute.value, 1)
if source_current_val - value < 1: if source_current_bonus - value < 1:
raise ValueError(f"You can't reduce the {source_attribute} bonus below +1.") raise ValueError(f"You can't reduce the {source_attribute} bonus below +1.")
if target_current_val + value > 6: if target_current_bonus + value > 6:
raise ValueError(f"You can't increase the {target_attribute} bonus above +6.") raise ValueError(f"You can't increase the {target_attribute} bonus above +6.")
# all is good, apply the change. # all is good, apply the change.
setattr(self, source_attribute, CharAttribute(bonus=source_current_val - value)) setattr(self, source_attribute, source_current_bonus - value)
setattr(self, target_attribute, CharAttribute(bonus=source_current_val + value)) setattr(self, target_attribute, source_current_bonus + value)
def apply(self, character): def apply(self, character):
""" """
@ -465,18 +469,20 @@ class EvAdventureCharacterGeneration:
character.db.desc = self.build_desc() character.db.desc = self.build_desc()
# TODO - spawn the actual equipment objects before adding them to equipment!
if self.weapon: if self.weapon:
character.equipment.add(self.weapon) character.equipment.use(self.weapon)
character.equipment.wield(self.weapon)
if self.shield: if self.shield:
character.equipment.add(self.shield) character.equipment.use(self.shield)
character.equipment.wield(self.shield)
if self.armor: if self.armor:
character.equipment.add(self.armor) character.equipment.use(self.armor)
character.equipment.wear(self.armor)
if self.helmet: if self.helmet:
character.equipment.add(self.helmet) character.equipment.use(self.helmet)
character.equipment.wear(self.helmet)
for item in self.backpack:
# TODO create here
character.equipment.store(item)
# character improvement # character improvement
@ -538,7 +544,8 @@ class EvAdventureImprovement:
except AttributeError: except AttributeError:
pass pass
new_hp_max = max(character.max_hpdice.roll(f"{character.level}d8")) character.hp_max = max(character.max_hp + 1,
EvAdventureRollEngine.roll(f"{character.level}d8"))
# character sheet visualization # character sheet visualization