def poison_breath(self, caster, *targets): if "rechargable" in caster.placeholder.keys(): pass else: caster.placeholder["rechargable"] = 0 if caster.placeholder["rechargable"] > 0: print( "{} probably tried to use Poison Breath, but it failed to do so..." ) else: damage_roll = dnd_mechanics.roll(6, 12) for target in targets: damage_taken = 0 message = "" target_saving_throw = dnd_mechanics.roll( 20, 1) + target.abilities["con"] damage_score = { "immunity": { "score": 0, "message": "{} seems to be immune to poison breath and takes no damage!" .format(target.name) }, "resistance": { "score": damage_roll / 4 if target_saving_throw >= 14 else damage_roll / 2, "message": "{} only takes {} damage from poison breath".format( target.name, str(damage_roll / 2)) }, "vulnerability": { "score": damage_roll if target_saving_throw >= 14 else damage_roll * 2, "message": "For {}, the posion breath was devastating, taking {} damage" .format(target.name, str(damage_roll * 2)) }, "normal": { "score": damage_roll / 2 if target_saving_throw >= 14 else damage_roll, "message": "{} takes {} damage from poison breath!".format( target.name, str(damage_roll)) } } for k, v in damage_score.items(): if "{}.damage.poison".format(k) in target.special: damage_taken = v["score"] message = v["message"] else: damage_taken = damage_score["normal"]["score"] message = damage_score["normal"]["message"] target.hp -= damage_taken print(message) caster.placeholder["rechargable"] = 5
def wounding_ray(self, caster, target): target_saving_throw = dnd_mechanics.roll(20, 1) + target.abilities["con"] hit_roll = dnd_mechanics.roll(10, 3) print("{} has used Wounding Ray on {}!".format(caster.name, target.name)) damage = (hit_roll // 2) if target_saving_throw >= 13 else hit_roll print("It dealt {} of damage!".format(str(damage)))
def slam(self, caster, target): hit_roll = min([(dnd_mechanics.roll(20, 1) + 3), (dnd_mechanics.roll(20, 1) + 3)]) \ if "resistance.damage.bludgeoning" in target.special else (dnd_mechanics.roll(20, 1) + 3) damage_roll = dnd_mechanics.roll(6, 1) + 1 if hit_roll >= target.ac: target.hp -= damage_roll print("{} mindlessly slammed on {}, dealing {} damage!".format( caster.name, target.name, str(damage_roll))) else: print("{} mindlessly tried to slam on {}, but missed".format( caster.name, target.name))
def rotting_gaze(self, caster, target): target_saving_throw = dnd_mechanics.roll(20, 1) + target.abilities["con"] caster_damage_throw = dnd_mechanics.roll(6, 3) if target_saving_throw >= 12: print("{} Just had a bizzare feeling of being observed...".format( target.name)) else: print( "{} Looks at it's hands... There are black spots on the skin, also the smell...\n" "They smell like a dead rat! Now everything starts to get itchy! Then this feeling of dizzyness...\n" "{} pukes on the ground, taking {} damage!".format( target.name, target.name, caster_damage_throw)) target.hp -= caster_damage_throw target.checkOnMe()
def surprise_attack(self, caster, target): if target in dnd_combat_gui.game_on.surprise_list: current_weapon = caster.weaponUsedNow() caster.attack(current_weapon, target) if caster.placeholder["attack_successful"] is True: damage = dnd_mechanics.roll(6, 2) target.hp -= damage print( "Due to a surprise attack, {} takes {} additional damage!". format(target.name, str(damage))) else: pass
def blood_drain(self, caster, target): if caster.physical_state != "latched": caster.physical_state = "latched" print("A Strige just latched to {}!".format(target.name)) else: pass damage = (dnd_mechanics.roll(4, 1) + 3) target.hp -= damage print("A Strige just drained blood from {} dealing {} damage!".format( target.name, str(damage))) target.checkOnMe() if target.hp <= 0: caster.physical_state = "normal"
def search(self): if self.hp >= 0: score = dnd_mechanics.roll(20, 1) total = self.skills["perception"] + score if total >= 10: print("Success, you've found it!") else: print( "After a while of searching, you didn't manage to find it..." ) else: print("...{} can't search anything right now, {} is dying".format( self.name, self.name))
def search(self, obj, target): if self.hp >= 0: print("You're looking for {} in {}".format(target, obj)) score = dnd_mechanics.roll(20, 1) total = self.skills["perception"] + score if total >= 10: print("Success, you've found {}!".format(target)) else: print( "After a while of searching, you didn't manage to find {}". format(target)) else: print("...{} can't search anything right now, {} is dying".format( self.name, self.name))
def web(self, caster, target): if "rechargable" in caster.placeholder.keys(): pass else: caster.placeholder["rechargable"] = 0 if caster.placeholder["rechargable"] > 0: print("{} probably tried to use Web, but it failed to do so...") else: hit_roll = dnd_mechanics.roll(20, 1) + 5 target_saving_throw = dnd_mechanics.roll( 20, 1) + target.abilities["str"] if hit_roll > target.ac: print("{} shot a web, restraining {} in the process!".format( caster.name, target.name)) if target_saving_throw >= 12: print( "Using all the might and determination {} managed to escape the web!" .format(target)) else: target.physical_state = "restrained" else: print("{} shot a web missle to {} but missed!".format( caster.name, target.name)) caster.placeholder["rechargable"] = 5
def paralyzing_ray(self, caster, *targets): for target in targets: roll = dnd_mechanics.roll(20, 1) target_constitution_check = roll + target.abilities["con"] print("{} DC roll: {}\n".format(target.name, roll)) print("{} modifier: {}\n".format(target.name, target.abilities["con"])) print("{} overall score: {}\n".format(target.name, target_constitution_check)) if target_constitution_check >= 13: print( "{} tried to use Paralyzing Ray on {}, but failed".format( caster.name, target.name)) else: reason = "{} succesfully used Paralyzing Ray on {}...".format( caster.name, target.name) target.skip_turn(1, reason)
def sort(self): for char in self.charpool: score = dnd_mechanics.roll(20, 1) + char.initiative() self.initiative_scores[str(char.name)] = score while len(self.initiative_scores) > 0: max_value = max(self.initiative_scores.values()) character = [ name for name, score in self.initiative_scores.items() if score == max_value ][0] self.turn_list.append( [c for c in self.charpool if c.name == character][0]) del self.initiative_scores[character] for i in self.turn_list: if i in self.surprise_list: self.turn_list.append(self.turn_list.pop(i))
def second_wind(self, caster, *targets): for target in targets: roll = dnd_mechanics.roll(10, 1) recover = roll + target.level if target.hp != target.max_hp and recover <= (target.max_hp - target.hp): target.hp += recover print( "{} used second wind as a bonus action, in result {} healed for {} points and now has {} hp!" .format(target.name, target.name, recover, target.hp)) elif target.hp != target.max_hp and recover > (target.max_hp - target.hp): target.hp = target.max_hp print( "{} used second wind as a bonus action, in result {} healed for {} points and now has {} hp!" .format(target.name, target.name, recover, target.hp)) else: print("{} tried to use second wind, but something went wrong". format(target.name))
def deathSavingThrow(self): if self.physical_state != "dead": if self.hp <= 0: roll = dnd_mechanics.roll(20, 1) if roll == 20: self.hp = 1 self.resetDeathSavingThrows() print("Gods blessing! {} wakes up and regains 1 Hit Point". format(self.name)) elif roll == 1: self.death_saves["failure"] += 2 print( "{} feels the cold hand of death on the shoulder\nDeath Save Failures: {}\nDeath Save Successes: {}" .format(self.name, self.death_saves["failure"], self.death_saves["success"])) elif roll >= 10: self.death_saves["success"] += 1 print( "{} doesn't give up on life!\nDeath Save Failures: {}\nDeath Save Successes: {}" .format(self.name, self.death_saves["failure"], self.death_saves["success"])) else: self.death_saves["failure"] += 1 print( "{} is slowly drifting into the abyss...\nDeath Save Failures: {}\nDeath Save Successes: {}" .format(self.name, self.death_saves["failure"], self.death_saves["success"])) if self.death_saves["failure"] >= 3: self.physical_state = "dead" print("{} is dead".format(self.name)) self.resetDeathSavingThrows() elif self.death_saves["success"] >= 3: self.physical_state = "normal" self.hp = 1 print("{} is back on feet!".format(self.name)) self.resetDeathSavingThrows() else: print("{} is fine!".format(self.name)) else: print("{} is dead, there's nothing you can do...".format( self.name))
def stabilize(self, target): if self.hp >= 0: if target.physical_state != "dead": roll = dnd_mechanics.roll(20, 1) score = roll + self.skills["medicine"] if self.skills[ "medicine"] == 1 else roll + self.skills[ "medicine"] + self.proficiency_bonus if score >= 10: target.resetDeathSavingThrows() target.hp = 0 print("{} managed to stabilize {}".format( self.name, target.name)) else: print("{} didn't manage to stabilize {}!".format( self.name, target.name)) pass else: print("{} is dead, there's nothing {} could do...".format( target.name, self.name)) else: print("{} can't stabilize {}, {} is dying".format( self.name, target.name, self.name))
def life_drain(self, caster, target): target_roll = dnd_mechanics.roll(20, 1) target_constitution_check = target_roll + target.abilities["con"] if "resistance.damage.necrotic" in target.special: hit_roll = min( [dnd_mechanics.roll(20, 1), dnd_mechanics.roll(20, 1)]) print("The dice rolls...\n\nResult: {}".format(str(hit_roll))) if hit_roll > target.AC: print("{} rolled a higher score than {}'s Armor Class - {}...". format(caster.name, target.name, str(target.ac))) damage_roll = dnd_mechanics.roll(8, 3) + 5 target.hp -= damage_roll print( "{} drained life forces from {}...\nDespite the resistance, " "the attack was successful and took {} of hp.".format( caster.name, target.name, str(damage_roll))) if target_constitution_check >= 13: pass else: target.max_hp -= damage_roll print( "Horribly, it also lowered {}'s maximum hp by the same amount!" .format(target.name)) else: print("{} rolled a lower score than {}'s Armor Class - {}...". format(caster.name, target.name, str(target.ac))) print("{}'s attack failed...".format(caster.name)) elif "immunity.damage.necrotic" in target.special: print( "{} tried to drain life from {}\nFortunately {} " "is completely immune to necrotic damage, therefore took no damage" .format(caster.name, target.name, target.name)) elif "vulnerability.damage.necrotic" in target.special: hit_roll = max( [dnd_mechanics.roll(20, 1), dnd_mechanics.roll(20, 1)]) print("The dice rolls...\n\nResult: {}".format(str(hit_roll))) if hit_roll > target.AC: print("{} rolled a higher score than {}'s Armor Class - {}...". format(caster.name, target.name, str(target.ac))) damage_roll = dnd_mechanics.roll(8, 3) + 5 target.hp -= damage_roll print( "{} drained life forces from {}...\nDue to the vulnerability, " "the attack was successful and took {} of hp.".format( caster.name, target.name, str(damage_roll))) if target_constitution_check >= 13: pass else: target.max_hp -= damage_roll print( "Horribly, it also lowered {}'s maximum hp by the same amount!" .format(target.name)) else: print("{} rolled a lower score than {}'s Armor Class - {}...". format(caster.name, target.name, str(target.ac))) print("{}'s attack failed...".format(caster.name)) else: hit_roll = dnd_mechanics.roll(20, 1) print("The dice rolls...\n\nResult: {}".format(str(hit_roll))) if hit_roll > target.AC: print("{} rolled a higher score than {}'s Armor Class - {}...". format(caster.name, target.name, str(target.ac))) damage_roll = dnd_mechanics.roll(8, 3) + 5 target.hp -= damage_roll print( "{} drained life forces from {}...\nThe attack was successful and took {} of hp." .format(caster.name, target.name, str(damage_roll))) if target_constitution_check >= 13: pass else: target.max_hp -= damage_roll print( "Horribly, it also lowered {}'s maximum hp by the same amount!" .format(target.name)) else: print("{} rolled a lower score than {}'s Armor Class - {}...". format(caster.name, target.name, str(target.ac))) print("{}'s attack failed...".format(caster.name))
def attack( self, weapon="current", *targets ): #TODO: If character has more dexterity than strength, he can choose to use it as a modifier if a weapon is light enough:/ self.placeholder["attack_successful"] = False wpn = self.weaponUsedNow() if weapon == "current" else dnd_data.items[ weapon] #TODO: Sneak attack grants a modifier to dexterity based attacks(check the class sheet) hit_roll = 0 damage_score = 0 total_ac = 0 for i in targets: # ============ # # dodge_mechanics if i.trigger_dodge != 0: self.adv = -1 # ============ # if int(self.hp) >= 0 and i.physical_state != "dead": # ====== HIT_ROLL ====== # if self.adv == 0: hit_roll = dnd_mechanics.roll(20, 1) print("{} rolls {} on a hit roll".format( self.name, hit_roll)) elif self.adv == 1: hit_roll = max(dnd_mechanics.roll(20, 1), dnd_mechanics.roll(20, 1)) print("{} has an advantage and rolls {} on a hit roll". format(self.name, hit_roll)) else: hit_roll = min(dnd_mechanics.roll(20, 1), dnd_mechanics.roll(20, 1)) print("{} has a disadvantage and rolls {} on a hit roll". format(self.name, hit_roll)) dmg_type = self.abilities["dex"] if "RANGED" in wpn[ "type"] else self.abilities["str"] modifier = round((dmg_type - 10) / 2) hit_score = hit_roll + modifier + self.proficiency_bonus print( "... Adding hit roll ({}), modifier ({}) and proficiency bonus ({}), sum is: {}" .format(hit_roll, modifier, self.proficiency_bonus, hit_score)) if "parry" in i.perks: total_ac += dnd_mechanics.roll(6, 1) else: total_ac = i.ac if hit_roll == 20: damage_roll = dnd_mechanics.roll(self.hit_dice[0], self.hit_dice[1] * 2) elif hit_roll != 20 and hit_score >= total_ac: damage_roll = dnd_mechanics.roll(self.hit_dice[0], self.hit_dice[1]) else: # ===== MISS ====== # print( "{} missed, hit score({}) is lesser that {} armor class ({})" .format(self.name, hit_score, i.name, total_ac)) break damage_score = damage_roll + modifier damage_type = wpn["damage"][2] if "immunity.{}".format(damage_type) in i.special: print( "{0} hit with {1}, it seems to have no effect!".format( i.name, wpn['name'])) self.checkOnEnemy(i) self.placeholder["attack_successful"] = False elif "vulnerability.{}".format(damage_type) in i.special: i.hp -= damage_score * 2 print("{0} hit with {1}, caused damage is {2}".format( i.name, wpn['name'], damage_score * 2)) self.checkOnEnemy(i) self.placeholder["attack_successful"] = True elif "resistance.{}".format(damage_type) in i.special: i.hp -= damage_score / 2 print("{0} hit with {1}, caused damage is {2}".format( i.name, wpn['name'], damage_score / 2)) self.checkOnEnemy(i) self.placeholder["attack_successful"] = True else: i.hp -= damage_score print("{0} hit with {1}, caused damage is {2}".format( i.name, wpn['name'], damage_score)) self.checkOnEnemy(i) self.placeholder["attack_successful"] = True elif i.hp <= 0 and i.physical_state != "dead": if damage_score >= i.max_hp: i.physical_state = "dead" elif hit_roll == 20 and damage_score << i.max_hp: i.death_saves["failure"] += 2 elif hit_roll << 20 and damage_score << i.max_hp: i.death_saves["failure"] += 1 else: pass elif int(self.hp) <= 0: print("{} can't fight with 0 or less hp".format(self.name)) print("{} Current physical state is: {}\n".format( self.name, self.physical_state)) elif i.physical_state == "dead": print("Chop, chop, {} attacks dead body of {}".format( self.name, i.name)) if self.watchlist["attack"] == 1: dnd_IC.readyTriggerFlag.change_state() else: pass