def loadCombat(self): filename = tkfd.askopenfilename(title="Select file", defaultextension='.rmc', filetypes=(("Rolemaster Combat files", "*.rmc"), ("all files", "*.*"))) load_file = open(filename, 'rb') self.combat = pickle.load(load_file) load_file.close() v.p( verbose_msg, "Combat loaded. Combatants: " + str([ self.combat.combatants[guy].name for guy in self.combat.combatants ])) for combatant in self.combat.combatants: new_frame = combatantframe.CombatantFrame( self, self.combat, self.combat.combatants[combatant]) if self.combat.num_of_combatants == 1: new_frame.grid(row=1, column=0, columnspan=7) else: new_frame.grid(column=0, columnspan=7) self.combatant_frames.append(new_frame) new_frame.update_targets() self.combat_log_msg.grid(rowspan=len(self.combatant_frames) + 1) for i in self.combat.log: self.combat_log_msg.insert(tk.END, i) self.update_combatants_list()
def initialize(self): v.p(verbose_msg, "Creating the combatant frame for " + self.combatant.name) r = 0 self.hits_and_PP_label = ttk.Label(self, textvariable=self.hits_PP) self.hits_and_PP_label.grid(row=r, column=0, sticky="w") r += 1 self.status_label = ttk.Label(self, textvariable=self.status) self.status_label.grid(row=r, column=0, sticky="w") r += 1 self.AT_and_DB_label = ttk.Label(self, textvariable=self.AT_DB) self.AT_and_DB_label.grid(row=r, column=0, sticky="w") r += 1 self.exh_label = ttk.Label(self, textvariable=self.exh) self.exh_label.grid(row=r, column=0, sticky="w") r += 1 self.init_bonus_label = ttk.Label(self, textvariable=self.init_bonus) self.init_bonus_label.grid(row=r, column=0, sticky="w") r += 1 self.edit_combatant_btn = ttk.Button(self, text="Edit", command=self.edit) self.edit_combatant_btn.grid(row=r, column=0) self.choose_actions_ntbk = chooseactionsnotebook.ChooseActionNtbk( self, self.combat, self.combatant) self.choose_actions_ntbk.grid(row=0, column=1, rowspan=r + 1, sticky=tk.N + tk.S + tk.E + tk.W) self.update_info()
def __init__(self, parent, combat, guy): tk.Frame.__init__(self, parent) v.p(verbose_msg, "Init Targeted Action Frame") self.parent = parent self.combat = combat self.combatant = guy self.targets_list = [] self.target = tk.StringVar() self.choose_target_optmenu = ttk.OptionMenu(self, self.target, *['None'])
def resolve_recurring_trigger(self, rtrigger): if rtrigger.name == "Bleeding": rtrigger.target.hits += -rtrigger.parameters['damage'] self.add_to_log(rtrigger.target.name + " bled " + str(rtrigger.parameters['damage']) + " hits.") else: v.p( verbose_msg, "Not actually doing anything with recurring trigger: " + rtrigger.name) rtrigger.target.update_status()
def update_attacks_list(self): self.attacks_list = [] for item in self.combatant.attacks_list: self.attacks_list.append(str(item)) v.p(verbose_msg, " Updating attacks list for " + self.combatant.name + " to " + str(self.attacks_list)) self.choose_attack_optmenu['menu'].delete(0, tk.END) if not self.attacks_list: self.attack.set("None") self.choose_attack_optmenu['menu'].add_command(label="None", command=tk._setit(self.attack, "None")) else: for item in self.attacks_list: self.choose_attack_optmenu['menu'].add_command(label=item, command=tk._setit(self.attack, item)) self.attack.set(self.attacks_list[0])
def submit(self): if self.name.get() in self.combat.get_combatant_names() and \ self.combatant != self.combat.get_combatant(self.name.get()): self.duplicate_mb = tkmb.showwarning( "Duplicate Name", "A combatant with that name already exists. Please change the name." ) else: if self.frame is None: self.combatant.update_info(self.name.get(), self.max_hits.get(), self.hits.get(), self.combatant.status, self.max_PP.get(), self.PP.get(), self.AT.get(), self.DB_melee.get(), self.DB_ranged.get(), self.max_exhpts.get(), self.exhpts.get(), self.initiative_bonus.get()) self.combatant.update_status() self.combat.add_combatant(self.combatant) self.frame = combatantframe.CombatantFrame( self.parent, self.combat, self.combatant) if self.combat.num_of_combatants == 1: self.frame.grid(row=1, column=0, columnspan=2) else: self.frame.grid(column=0, columnspan=2) self.parent.combatant_frames.append(self.frame) self.parent.combat_log_msg.grid( rowspan=len(self.parent.combatant_frames) + 1) else: self.combat.update_combatant(self.combatant, self.name.get(), self.max_hits.get(), self.hits.get(), self.combatant.status, self.max_PP.get(), self.PP.get(), self.AT.get(), self.DB_melee.get(), self.DB_ranged.get(), self.max_exhpts.get(), self.exhpts.get(), self.initiative_bonus.get()) self.combatant.update_status() v.p(verbose_msg, "Updating combatant: " + self.name.get()) self.frame.update_info() self.parent.update_combatants_list() self.parent.update_target_lists() self.destroy()
def resolve_trigger(self, trig): v.p(verbose_msg, "Resolving trigger: " + trig.name + " for " + trig.target.name) print(self.trigger_list) if trig.name == "Stun No Parry": if trig.target.stun_ends_at > self.time: new_trig = trigger.Trigger("Stun", trig.target, trig.target.stun_ends_at) self.add_trigger(new_trig) else: v.p(verbose_msg, "Not actually doing anything with this trigger: " + trig.name) trig.target.update_status()
def act(self): triggers_to_resolve = self.trigger_list.get(self.time) recurring_triggers_to_resolve = self.recurring_trigger_list.get( self.time) actions_to_resolve = self.action_list.get(self.time) v.p(verbose_msg, "Actions to resolve: " + str(actions_to_resolve)) while not actions_to_resolve and not triggers_to_resolve and not recurring_triggers_to_resolve: self.time += 0.5 triggers_to_resolve = self.trigger_list.get(self.time) recurring_triggers_to_resolve = self.recurring_trigger_list.get( self.time) actions_to_resolve = self.action_list.get(self.time) v.p(verbose_msg, "Time is " + str(self.time)) self.add_to_log(" Time is " + str(self.time)) if recurring_triggers_to_resolve: v.p( verbose_msg, "---Resolving recurring triggers at " + str(self.time) + " seconds") for rtrigger in recurring_triggers_to_resolve: self.resolve_recurring_trigger(rtrigger) rtrigger.end_time += 10 self.add_recurring_trigger(rtrigger) self.recurring_trigger_list[self.time] = [] if actions_to_resolve: v.p(verbose_msg, "---Resolving actions at " + str(self.time) + " seconds") if len(actions_to_resolve) > 1: actions_to_resolve = self.roll_initiative(actions_to_resolve) for action in actions_to_resolve: self.resolve_action(action) self.action_list[self.time] = [] if triggers_to_resolve: v.p(verbose_msg, "---Resolving triggers at " + str(self.time) + " seconds") for item in triggers_to_resolve: self.resolve_trigger(item) self.trigger_list[self.time] = []
def __init__(self, filename): with open(filename) as attack_table_file: v.p(verbose_msg, "Reading attack table: " + filename) readCSV = csv.reader(attack_table_file, delimiter=',') self.name = next(readCSV)[1] self.critical_type = next(readCSV)[1] line = next(readCSV) self.hands = line[1] line = next(readCSV) self.min_length = float(line[1]) self.max_length = float(line[2]) line = next(readCSV) self.min_weight = float(line[1]) self.max_weight = float(line[2]) line = next(readCSV) self.fumble = int(line[2]) line = next(readCSV) self.breakage_num = int(line[2]) line = next(readCSV) self.min_strength = int(line[1]) self.max_strength = int(line[2]) if len(line) == 4: self.strength_type = line[3] else: self.strength_type = None line = next(readCSV) self.ranges = [] ranges = int(line[1]) if ranges > 0: for i in range(0, ranges): line = next(readCSV) self.ranges.append( [int(line[1]), int(line[2]), int(line[3])]) line = next(readCSV) self.results = [] for i in readCSV: #readCSV.line_num - 9 - ranges): self.results.append(i)
def loadCombatant(self): filename = tkfd.askopenfilename( title="Select file", defaultextension='.cbt', filetypes=(("Rolemaster Combatant files", "*.cbt"), ("all files", "*.*"))) load_file = open(filename, 'rb') combatant = pickle.load(load_file) load_file.close() proceed = True if combatant.name in self.combat.get_combatant_names(): proceed = tkmb.askokcancel( "Overwrite Combatant?", combatant.name + " already exists in this combat. Continuing will overwrite the current combatant." ) if proceed: for frame in self.combatant_frames: if frame.combatant.name == combatant.name: self.combatant_frames.remove(frame) self.combat.combatants.pop(combatant.name) if proceed: self.combat.add_combatant(combatant) new_frame = combatantframe.CombatantFrame( self, self.combat, self.combat.combatants[combatant.name]) if self.combat.num_of_combatants == 1: new_frame.grid(row=1, column=0, columnspan=4) else: new_frame.grid(column=0, columnspan=4) self.combatant_frames.append(new_frame) self.update_target_lists() v.p(verbose_msg, "Combatant loaded: " + combatant.name) self.combat_log_msg.grid(rowspan=len(self.combatant_frames) + 1)
def update_targets(self): v.p(verbose_msg, " Updating Targets in " + self.combatant.name + "'s frame.") self.choose_actions_ntbk.attack_frame.update_targets_list() self.choose_actions_ntbk.cast_spell_frame.update_targets_list()
def begin_combat(self): for item in self.combatant_frames: action_num = item.choose_actions_ntbk.index( item.choose_actions_ntbk.select()) action_desc = self.action_dict[action_num] parameters = {} # if action is an attack if action_num == 0: target = item.choose_actions_ntbk.attack_frame.target.get() parameters['target'] = self.combat.get_combatant(target) parameters['attack'] = item.combatant.get_attack( item.choose_actions_ntbk.attack_frame.attack.get()) parameters[ 'parry_percentage'] = item.choose_actions_ntbk.attack_frame.parry_percentage.get( ) target_text = " " + target + " with a " + item.choose_actions_ntbk.attack_frame.attack.get( ) log_message = item.combatant.name + " " + action_desc + target_text action = attackaction.AttackAction(self.combat, item.combatant, self.combat.time, action_num, parameters, log_message) # if action is a spell cast elif action_num == 1: target = item.choose_actions_ntbk.cast_spell_frame.target.get() if target and target != "None": parameters['target'] = self.combat.get_combatant(target) else: parameters['target'] = None spell_to_cast = spell.Spell( item.choose_actions_ntbk.cast_spell_frame.spell_list.get(), item.choose_actions_ntbk.cast_spell_frame.spell_level.get( )) parameters['spell'] = spell_to_cast target_text = " at " + target log_message = item.combatant.name + " " + action_desc + target_text action = castspellaction.CastSpellAction( self.combat, item.combatant, self.combat.time, action_num, parameters, log_message) elif action_num == 2: parameters[ 'pace'] = item.choose_actions_ntbk.move_frame.pace.get() log_message = item.combatant.name + " " + action_desc action = moveaction.MoveAction(self.combat, item.combatant, self.combat.time, action_num, parameters, log_message) elif action_num == 3: parameters = [] log_message = item.combatant.name + " " + action_desc action = performskillaction.PerformSkillAction( self.combat, item.combatant, self.combat.time, action_num, parameters, log_message) else: raise (NotImplementedError, "This action type is not implemented yet.") self.combat.add_action(action) item.combatant.current_action = action v.p( verbose_msg, "Action put in list: " + action.log_message + " at time " + str(action.end_time)) prior_log_length = len(self.combat.log) # Call the routine to carry out the actions self.combat.act() for item in self.combatant_frames: item.update_info() for i in range(prior_log_length, len(self.combat.log)): self.combat_log_msg.insert(tk.END, self.combat.log[i])
def resolve_attack(self, action): roll = dice.oehighroll() table = self.attack_tables[action.attack_table] if roll <= table.fumble: v.p(verbose_msg, "Attack roll is fumbled: " + str(roll)) self.add_to_log(action.combatant.name + " fumbled the attack.") else: penalties = self.calc_penalties(action.combatant.hits, action.combatant.max_hits, action.combatant.exhpts, action.combatant.max_exhpts) if action.target.current_action.action_type == 0 and \ action.target.current_action.target == action.combatant: target_parry = action.target.current_action.parry_DB else: target_parry = 0 if action.attack_ranged: # need to deal with parrying ranged attacks adjusted_roll = roll + action.attack_OB + penalties[ 0] - action.target.DB_ranged else: adjusted_roll = roll + action.attack_OB + penalties[ 0] - action.target.DB_melee - target_parry v.p( verbose_msg, "Roll: " + str(roll) + "OB: " + str(action.attack_OB) + " Pen: " + str(penalties[0]) + " DBs: " + str(action.target.DB_melee) + "/" + str(action.target.DB_ranged) + " Parried by: " + str(target_parry) + " Final: " + str(adjusted_roll)) for item in table.results: if adjusted_roll < int(item[0]): pass else: result = item[22 - action.target.AT] v.p(verbose_msg, "Attack result: " + result) if result == "-": self.add_to_log(action.combatant.name + " missed " + action.target.name) else: if result[len(result) - 1].isdigit(): damage = int(result) self.add_to_log(action.combatant.name + " did " + str(damage) + " hits to " + action.target.name) else: i = 0 while result[i].isdigit(): i += 1 damage = int(result[0:i]) critical_level = result[i:] self.add_to_log(action.combatant.name + " did " + str(damage) + " hits and a " + critical_level + " critical to " + action.target.name) critical_table = self.critical_tables[ self.attack_tables[ action.attack_table].critical_type] critical_column = critical_table.columns[ critical_level] i = 0 critical_roll = dice.Dice.d100() while critical_column[i][2] < critical_roll: i += 1 crit = critical_column[i] log_message = "Crit: " + str( critical_roll) + " " + crit[3] + "\n " #Next four lines are for testing purposes: crit[8] = "1~0" crit[7] = "2~0" crit[6] = "1~0" if crit[4] != 0: damage += crit[4] log_message = log_message + " Hits: " + str( crit[4]) if crit[5] != 0: rtrigger = trigger.Trigger( "Bleeding", action.target, self.time + 10, {"damage": crit[5]}) self.add_recurring_trigger(rtrigger) log_message = log_message + " Bleeding: " + str( crit[5]) if crit[8] != "0~0": snp = crit[8].split("~") num_of_rounds = int(snp[0]) penalty = int(snp[1]) stun_duration = 0 if action.target.stun_no_parry_ends_at > self.time: end_time = action.target.stun_no_parry_ends_at + 10 * num_of_rounds for i in self.trigger_list[ action.target. stun_no_parry_ends_at]: if i.name == "Stun No Parry" and i.target == action.target: self.trigger_list[ action.target. stun_no_parry_ends_at].remove( i) if action.target.stun_ends_at > action.target.stun_no_parry_ends_at: stun_duration = action.target.stun_ends_at - action.target.stun_no_parry_ends_at for i in self.trigger_list[ action.target.stun_ends_at]: if i.name == "Stun" and i.target == action.target: self.trigger_list[ action.target. stun_ends_at].remove(i) else: end_time = self.time + 10 * num_of_rounds if action.target.stun_ends_at > self.time: stun_duration = action.target.stun_ends_at - self.time action.target.stun_no_parry_ends_at = end_time action.target.stun_ends_at = end_time + stun_duration trig = trigger.Trigger("Stun No Parry", action.target, end_time) self.add_trigger(trig) log_message = log_message + " Stun No Parry: " + snp[ 0] if crit[7] != "0~0": snp = crit[7].split("~") num_of_rounds = int(snp[0]) penalty = int(snp[1]) must_parry_duration = 0 if action.target.stun_ends_at > self.time: end_time = action.target.stun_ends_at + 10 * num_of_rounds for i in self.trigger_list[ action.target.stun_ends_at]: if i.name == "Stun" and i.target == action.target: self.trigger_list[ action.target. stun_ends_at].remove(i) if action.target.must_parry_ends_at > action.target.stun_ends_at: must_parry_duration = action.target.must_parry_ends_at - action.target.stun_ends_at for i in self.trigger_list[ action.target. must_parry_ends_at]: if i.name == "Must Parry" and i.target == action.target: self.trigger_list[ action.target. must_parry_ends_at].remove( i) else: end_time = self.time + 10 * num_of_rounds if action.target.must_parry_ends_at > self.time: must_parry_duration = action.target.must_parry_ends_at - self.time action.target.stun_ends_at = end_time action.target.must_parry_ends_at = end_time + must_parry_duration trig = trigger.Trigger("Stun", action.target, end_time) self.add_trigger(trig) log_message = log_message + " Stunned: " + snp[ 0] if crit[6] != "0~0": snp = crit[6].split("~") num_of_rounds = int(snp[0]) penalty = int(snp[1]) initiative_loss_duration = 0 if action.target.must_parry_ends_at > self.time: end_time = action.target.must_parry_ends_at + 10 * num_of_rounds for i in self.trigger_list[ action.target.must_parry_ends_at]: if i.name == "Must Parry" and i.target == action.target: self.trigger_list[ action.target. must_parry_ends_at].remove(i) if action.target.initiative_loss_ends_at > action.target.must_parry_ends_at: initiative_loss_duration = action.target.initiative_loss_ends_at - action.target.must_parry_ends_at for i in self.trigger_list[ action.target. initiative_loss_ends_at]: if i.name == "Initiative Loss" and i.target == action.target: self.trigger_list[ action.target. initiative_loss_ends_at].remove( i) else: end_time = self.time + 10 * num_of_rounds if action.target.initiative_loss_ends_at > self.time: initiative_loss_duration = action.target.initiative_loss_ends_at - self.time action.target.must_parry_ends_at = end_time action.target.initiative_loss_ends_at = end_time + initiative_loss_duration trig = trigger.Trigger("Must Parry", action.target, end_time) self.add_trigger(trig) log_message = log_message + " Must Parry: " + snp[ 0] self.add_to_log(log_message) action.target.hits += -damage action.target.update_status() break
def add_combatant(self, guy): if guy.name not in self.combatants: self.combatants[guy.name] = guy else: raise NameError('Another combatant already has this name.') v.p(verbose_msg, "Added combatant: " + guy.name)