def resolve_opposed_initiative(a: Creature, b: Creature) -> Optional[Creature]: a_initiative = a.get_initiative_modifier() b_initiative = b.get_initiative_modifier() a_roll = dice(1, 10).get_roll_result() b_roll = dice(1, 10).get_roll_result() a_total = a_roll + a_initiative b_total = b_roll + b_initiative a_crit = 1 if a_roll >= 10 else (-1 if a_roll <= 1 else 0) b_crit = 1 if b_roll >= 10 else (-1 if b_roll <= 1 else 0) winner = None if a_crit != b_crit: winner = a if a_crit > b_crit else b elif a_total != b_total: winner = a if a_total > b_total else b elif round(a_initiative) != round(b_initiative): winner = a if a_initiative > b_initiative else b success_text = f'{winner} takes initiative!' if winner is not None else 'Tie!' print( f'[Initiative] {a} vs {b} RESULT: {a_roll}{a_initiative:+.0f}={a_total:.0f} vs ' f'{b_roll}{b_initiative:+.0f}={b_total:.0f} {success_text}') return winner
from core.combat.criticals import KnockdownCritical from core.contest import CombatSkillClass from core.dice import dice from core.constants import * ## Blades WEAPON_BROADSWORD = Weapon( name='Broadsword', size=SizeCategory.Medium, skill_class=CombatSkillClass.Blade, encumbrance=2, cost=200, melee_attacks=[ MeleeAttackTemplate('Slash', (REACH_MEDIUM, REACH_SHORT), FORCE_MEDIUM, DamageType.Slashing, dice(1, 8)), MeleeAttackTemplate('Thrust', (REACH_LONG, REACH_MEDIUM), FORCE_SMALL, DamageType.Puncture, dice(1, 6)), MeleeAttackTemplate('Pommel Strike', (REACH_SHORT, REACH_CLOSE), FORCE_SMALL, DamageType.Bludgeon, dice(1, 3), dice(0), criticals=[KnockdownCritical]), ], ) WEAPON_LONGSWORD = Weapon( name='Longsword', size=SizeCategory.Medium, skill_class=CombatSkillClass.Blade,
from core.constants import MeleeRange, SizeCategory, FORCE_MEDIUM from core.combat.damage import DamageType from core.contest import CombatSkillClass if TYPE_CHECKING: from core.creature.template import CreatureTemplate from core.combat.criticals import CriticalEffect def _create_table( table_data: Mapping[float, Any]) -> Sequence[Tuple[float, Any]]: return [(k, v) for k, v in sorted(table_data.items())] _DAMAGE_TABLE = _create_table({ 0: dice(0), 1: dice(1), 2: dice(1, 2), 4: dice(1, 3), 8: dice(1, 4), # medium size 16: dice(1, 6), 24: dice(1, 8), 32: dice(1, 10), 40: dice(1, 12), 48: dice(1, 10) + dice(1, 3), 56: dice(1, 12) + dice(1, 3), 64: dice(1, 8) + dice(2, 4), 72: dice(1, 10) + dice(2, 4), 80: dice(1, 12) + dice(2, 4), 88: dice(1, 10) + dice(2, 6), 96: dice(1, 12) + dice(2, 6),
def armpen(self) -> DicePool: if self.template.armpen is not None: return self.template.armpen + self.str_modifier return dice(0)
def reroll(self) -> None: contest_dice = dice(Contest.BASE_DICE + self.skill_level.bonus_dice, Contest.BASE_SIDES) self.base_result = sorted(contest_dice.get_roll(), reverse=True)[:Contest.BASE_DICE] self.base_total = sum(self.base_result)
def apply(self) -> None: self.combat.damage = dice(self.combat.damage.max())
SHIELD_BUCKLER = Weapon(name='Buckler', size=SizeCategory.Tiny, skill_class=CombatSkillClass.Shield, encumbrance=1, cost=50, shield=ShieldTemplate(min_reach=REACH_CLOSE, block_force=FORCE_MEDIUM, block_bonus=-1, block_ranged=15), melee_attacks=[ MeleeAttackTemplate('Bash', (REACH_SHORT, REACH_CLOSE), FORCE_TINY, DamageType.Bludgeon, dice(1, 3), -dice(1, 3), traits=[CannotDefendTrait()], criticals=[KnockdownCritical]), ]) SHIELD_SMALL = Weapon(name='Small Shield', size=SizeCategory.Small, skill_class=CombatSkillClass.Shield, encumbrance=2, cost=150, shield=ShieldTemplate(min_reach=REACH_SHORT, block_force=FORCE_LARGE, block_bonus=0, block_ranged=30), melee_attacks=[