226fb773 by Barry

Added the start of weapon skills calc and lots of little fixes.

1 parent 5f1e010c
......@@ -339,6 +339,14 @@ def db_remove_soul_plate(member_id, idx):
conn.commit()
return True
def db_update_pankration_record(member_id, column_name, value):
conn = sqlite3.connect('db.sqlite3')
c = conn.cursor()
c.execute("""UPDATE pankration SET """ + column_name + """ = ?
WHERE member_id = ?;""", (value, member_id))
conn.commit()
conn.close()
def db_add_reflector(member_id, reflector):
pan_record = db_get_pankration_record(member_id)
log("{}".format(member_id))
......@@ -394,15 +402,22 @@ def db_convert_soul_plate_to_reflector(member_id, soul_plate, idx):
return True
def db_register_battle(member_id, reflector, idx, target_member=None):
def db_register_battle(member_id, reflector, idx, target_member_id=None):
pan_record = db_get_pankration_record(member_id)
conn = sqlite3.connect('db.sqlite3')
c = conn.cursor()
db_state = c.execute("SELECT battle_id, reflector_primary member_id FROM pankration_arena WHERE battle_status = 'waiting';").fetchall()
if target_member_id:
db_state = c.execute("SELECT battle_id, reflector_primary FROM pankration_arena WHERE battle_status = 'waiting' AND direct_challenge = ?;", (member_id,)).fetchall()
else:
db_state = c.execute("SELECT battle_id, reflector_primary FROM pankration_arena WHERE battle_status = 'waiting' AND direct_challenge = 0;").fetchall()
if not db_state:
log("No battles available: {}".format(idx,))
c.execute("""INSERT INTO pankration_arena(primary_member_id, reflector_primary)
VALUES(?, ?);""", (member_id, pickle.dumps(reflector)))
if target_member_id:
c.execute("""INSERT INTO pankration_arena(primary_member_id, reflector_primary, direct_challenge)
VALUES(?, ?, ?);""", (member_id, pickle.dumps(reflector), target_member_id))
else:
c.execute("""INSERT INTO pankration_arena(primary_member_id, reflector_primary)
VALUES(?, ?);""", (member_id, pickle.dumps(reflector)))
conn.commit()
conn.close()
db_remove_reflector(member_id, idx)
......@@ -440,16 +455,17 @@ def db_complete_battle(battle_id, primary_member_id, primary_reflector, secondar
else:
c.execute("""UPDATE pankration SET reflectors = ?, losses = losses + 1
WHERE member_id = ?;""", (pickle.dumps(reflectors), primary_member_id))
conn.commit()
reflectors = pickle.loads(str(db_get_pankration_record(secondary_member_id)['reflectors']))
reflectors.append(secondary_reflector)
reflectors2 = pickle.loads(str(db_get_pankration_record(secondary_member_id)['reflectors']))
reflectors2.append(secondary_reflector)
log('Completing battle - secondary')
if winner == 2:
c.execute("""UPDATE pankration SET reflectors = ?, wins = wins + 1
WHERE member_id = ?;""", (pickle.dumps(reflectors), secondary_member_id))
WHERE member_id = ?;""", (pickle.dumps(reflectors2), secondary_member_id))
else:
c.execute("""UPDATE pankration SET reflectors = ?, losses = losses + 1
WHERE member_id = ?;""", (pickle.dumps(reflectors), secondary_member_id))
WHERE member_id = ?;""", (pickle.dumps(reflectors2), secondary_member_id))
conn.commit()
conn.close()
log('Completing battle - done')
......
No preview for this file type
......@@ -93,6 +93,7 @@ registered_commands = {'!help': 'do_help', '!commands': 'do_help',
'!convertplate': 'do_convert_plate', '!convertsoulplate': 'do_convert_plate',
'!assignskill': 'do_assign_skill',
'!registerbattle': 'do_register_battle',
'!setreflectorname': 'do_set_reflector_name',
'!pankration': 'do_pankration',
}
......@@ -1041,6 +1042,7 @@ def do_pankration(client, message_parts, message):
Ex: **!convertplate 1 reflector**
**!convertplate 4 skill**
**!assignskill <reflector number> <skill num>** - Assigns a skill to a reflector. Each skill is worth a certain amount of feral points, each monster has a maximum of feral points available.
**!setreflectorname <reflector number> <name>** - This will rename a monster in your collection to a custom name.
*Arena Battle:*
**!registerbattle <reflector number>** - Adds your reflector to the queue in the arena. When the arena is available your monster will be paired with either another players monster or a similarly matched arena monster.
......@@ -1048,6 +1050,28 @@ def do_pankration(client, message_parts, message):
""".format(message.author.mention()))
def do_set_reflector_name(client, message_parts, message):
member = data.db_get_member(message.author.id)
if len(message_parts) < 2:
send_message(client, message.channel, 'You must provide the reflector number and the new name.')
return
reflector_num = message_parts[0]
new_name = ' '.join(message_parts[1:])
pankration_data = data.db_get_pankration_record(member['member_id'])
if pankration_data and pankration_data['reflectors']:
reflectors = pickle.loads(str(pankration_data['reflectors']))
if not reflector_num.isdigit() or int(reflector_num) < 1 or int(reflector_num) > len(reflectors):
send_message(client, message.channel, 'The requested reflector is invalid. Please provide the number from !listreflectors')
return
reflector_num = int(reflector_num) - 1
reflectors[reflector_num].set_monster_name(new_name)
data.db_update_pankration_record(member['member_id'], 'reflectors', pickle.dumps(reflectors))
send_message(client, message.channel, 'The reflector (monster) name has been updated.')
else:
send_message(client, message.channel, 'Unable to find the reflector data.')
def do_register_battle(client, message_parts, message):
member = data.db_get_member(message.author.id)
......@@ -1067,13 +1091,17 @@ def do_register_battle(client, message_parts, message):
reflector_num = int(reflector_num) - 1
if len(message_parts) > 1:
user = ' '.join(message_parts[1:])
username = ' '.join(message_parts[1:])
data.db_register_battle(member['member_id'], reflectors[reflector_num], reflector_num, user)
send_message(client, message.channel, "Your *{} level {}* has been registered for battle with {}. The battle will begin when the arena is availble with the next challenger".format(reflectors[reflector_num].monster_type, reflectors[reflector_num].level, user))
target_member = data.db_get_member(username=username)
if target_member and 'member_id' in target_member:
data.db_register_battle(member['member_id'], reflectors[reflector_num], reflector_num, target_member['member_id'])
send_message(client, message.channel, "Your *{} level {}* has been registered for battle with {}. The battle will begin when the arena is availble with the next challenger".format(reflectors[reflector_num].get_monster_name(), reflectors[reflector_num].level, username))
else:
send_message(client, message.channel, "There was a problem looking up that user.")
else:
data.db_register_battle(member['member_id'], reflectors[reflector_num], reflector_num)
send_message(client, message.channel, "Your *{} level {}* has been registered for battle. The battle will begin when the arena is availble with the next challenger".format(reflectors[reflector_num].monster_type, reflectors[reflector_num].level))
send_message(client, message.channel, "Your *{} level {}* has been registered for battle. The battle will begin when the arena is availble with the next challenger".format(reflectors[reflector_num].get_monster_name(), reflectors[reflector_num].level))
else:
send_message(client, message.channel, 'You have no available reflectors. You can get reflectors by converting soul plates with !convertplate')
return
......@@ -1221,15 +1249,15 @@ def check_arena():
send_message(client, arena_channel, "Ladies and gentlemen!\nFor our next match...")
time.sleep(5)
send_message(client, arena_channel, "In the red corner we have...\n **{}**!".format(monster.monster_type))
send_message(client, arena_channel, "In the red corner we have...\n **{}**!".format(monster.get_monster_name()))
time.sleep(5)
send_message(client, arena_channel, "Hmmm... This monster seems {} and {}.".format(monster.get_current_posture()["name"], monster.get_current_attitude()["name"]))
time.sleep(5)
send_message(client, arena_channel, "And in the blue corner is...\n **{}**!".format(monster2.monster_type))
send_message(client, arena_channel, "And in the blue corner is...\n **{}**!".format(monster2.get_monster_name()))
time.sleep(5)
send_message(client, arena_channel, "Hmmm... This monster seems {} and {}.".format(monster2.get_current_posture()["name"], monster2.get_current_attitude()["name"]))
time.sleep(5)
send_message(client, arena_channel, "Alright, Pankration fans, the match is about to begin!\n *Chaaaaaarge!*".format(monster2.monster_type))
send_message(client, arena_channel, "Alright, Pankration fans, the match is about to begin!\n *Chaaaaaarge!*".format(monster2.get_monster_name()))
time.sleep(5)
data.db_start_battle(battle['battle_id'])
......@@ -1244,12 +1272,12 @@ def check_arena():
out_str = ""
for action in actions:
if isinstance(action, MissAction):
out_str += "{} {} {}.\n".format(action.attacker.monster_type, action.message, action.target.monster_type)
out_str += "{} {} {}.\n".format(action.attacker.get_monster_name(), action.message, action.target.get_monster_name())
if isinstance(action, AttackAction):
out_str += "{} {} {} for {}.\n".format(action.attacker.monster_type, action.message, action.target.monster_type, int(action.damage))
out_str += "{} {} {} for {}.\n".format(action.attacker.get_monster_name(), action.message, action.target.get_monster_name(), int(action.damage))
if isinstance(action, DefeatAction):
out_str += "\n\n**{}** {}. {} gains {} xp.\n\n".format(action.target.monster_type, action.message, action.attacker.monster_type, action.xp)
out_str += "\n\n**{}** {}. {} gains {} xp.\n\n".format(action.target.get_monster_name(), action.message, action.attacker.get_monster_name(), action.xp)
fighting = False
if action.attacker == monster:
result, xp_msg = monster.add_xp(action.xp)
......@@ -1266,7 +1294,7 @@ def check_arena():
monster2.wins += 1
monster.losses += 1
break
out_str += "\n{} {}% - {} {}%\n".format(monster.monster_type, monster.get_hp_percent(), monster2.monster_type, monster2.get_hp_percent())
out_str += "\n{} {}% - {} {}%\n".format(monster.get_monster_name(), monster.get_hp_percent(), monster2.get_monster_name(), monster2.get_hp_percent())
log(out_str)
send_message(client, arena_channel, byteify(out_str))
# Heal the monsters before they are returned to the player inventory
......
......@@ -164,6 +164,10 @@ Families = {
'agi_per_level': 0.76,
'base_dex': 10,
'dex_per_level': 0.76,
'base_mnd': 8,
'mnd_per_level': 0.76,
'base_int': 8,
'int_per_level': 0.76,
'temperament_attitude': {
'initial_value': 4,
'actions': {
......@@ -203,6 +207,10 @@ Families = {
'agi_per_level': 0.88,
'base_dex': 10,
'dex_per_level': 0.714,
'base_mnd': 9,
'mnd_per_level': 0.9066,
'base_int': 9,
'int_per_level': 0.9066,
'temperament_attitude': {
'initial_value': 4,
'actions': {
......@@ -235,29 +243,97 @@ Monsters = {
'family': 'ahriman',
'zone': ['ranguemont pass'],
'hp': 15,
'weapon_base_damage': 15
'weapon_base_damage': 15,
'image_url': 'http://vignette1.wikia.nocookie.net/ffxi/images/9/94/Floating_Eye.JPG/revision/latest?cb=20070704142439'
},
'Bat Eye': {
'family': 'ahriman',
'zone': ['ranguemont pass', 'beaucedine glacier'],
'hp': 15,
'weapon_base_damage': 15
'weapon_base_damage': 15,
'image_url': 'http://vignette3.wikia.nocookie.net/ffxi/images/4/40/Bat_Eye.jpg/revision/latest?cb=20060909124134',
},
'Evil Eye': {
'family': 'ahriman',
'zone': ['castle zvahl baileys', 'castle zvahl keep', 'xarcabard'],
'hp': 15,
'weapon_base_damage': 15,
},
'Morbid Eye': {
'family': 'ahriman',
'zone': ['castle zvahl baileys', 'castle zvahl keep'],
'hp': 15,
'weapon_base_damage': 15
},
'Deadly Iris': {
'family': 'ahriman',
'zone': ['castle zvahl keep'],
'hp': 15,
'weapon_base_damage': 15
},
'Ahriman': {
'family': 'ahriman',
'zone': ['castle zvahl baileys'],
'hp': 15,
'weapon_base_damage': 15
},
'Fachan': {
'family': 'ahriman',
'zone': ['uleguerand range'],
'hp': 15,
'weapon_base_damage': 15
},
'Gawper': {
'family': 'ahriman',
'zone': ['beaucedine glacier (s)'],
'hp': 15,
'weapon_base_damage': 15
},
'Menacing Eye': {
'family': 'ahriman',
'zone': ['xarcabard (s)'],
'hp': 15,
'weapon_base_damage': 15
},
'Ogler': {
'family': 'ahriman',
'zone': ['castle zvahl keep (s)', 'castle zvahl baileys (s)'],
'hp': 15,
'weapon_base_damage': 15
},
'Smolenkos': {
'family': 'ahriman',
'zone': ['uleguerand range'],
'hp': 15,
'weapon_base_damage': 15
},
'Doom Lens': {
'family': 'ahriman',
'zone': ['castle zvahl keep (s)', 'castle zvahl baileys (s)'],
'hp': 15,
'weapon_base_damage': 15
},
'Scowlenkos': {
'family': 'ahriman',
'zone': ['uleguerand range'],
'hp': 15,
'weapon_base_damage': 15
}
}
UnsortedZones = {
'abyssea - uleguerand': {'cost': 10, 'find_percent': 50},
'beaucedine glacier': {'cost': 10, 'find_percent': 50},
'beaucedine glacier (s)': {'cost': 10, 'find_percent': 50},
'castle zvahl baileys': {'cost': 10, 'find_percent': 50},
'castle zvahl baileys (s)': {'cost': 10, 'find_percent': 50},
'castle zvahl keep': {'cost': 10, 'find_percent': 50},
'castle zvahl keep (s)': {'cost': 10, 'find_percent': 50},
'ranguemont pass': {'cost': 10, 'find_percent': 50},
'uleguerand range': {'cost': 10, 'find_percent': 50},
'xarcabard': {'cost': 10, 'find_percent': 50},
'xarcabard (s)': {'cost': 10, 'find_percent': 50},
}
Zones = collections.OrderedDict(sorted(UnsortedZones.items()))
......@@ -297,7 +373,7 @@ class Pankration:
monster_data = Monsters[monster_name]
hp = monster_data['hp']
weapon_base_damage = monster_data['weapon_base_damage']
print("Monster: {} Data: {}".format(monster_name, monster_data))
log("Monster: {} Data: {}".format(monster_name, monster_data))
family_name = monster_data['family']
family = Families[family_name]
level = 1
......@@ -317,7 +393,10 @@ class Pankration:
monster = Monster(monster_name, family_name, family, hp, level, weapon_base_damage, main_job, support_job, feral_skills,
[], dicipline_level)
return HuntResponse(HuntResponse.SUCCESS, "You captured a *{}*!".format(monster_name),
url = ''
if 'image_url' in monster_data:
url = monster_data['image_url']
return HuntResponse(HuntResponse.SUCCESS, "You captured a *{}*!\n\n{}".format(monster_name, url),
monster)
else:
return HuntResponse(HuntResponse.FAILURE, "You were unable to capture a monster's soul.",
......@@ -330,6 +409,7 @@ class Pankration:
class Monster:
def __init__(self, monster_type, family_name, family, base_hp, level, weapon_base_damage, main_job, support_job, innate_feral_skills,
equipped_feral_skills, dicipline_level):
self.custom_name = None
self.monster_type = monster_type
self.family_name = family_name
self.family = family
......@@ -355,17 +435,31 @@ class Monster:
self.agi_per_level = family['agi_per_level']
self.base_dex = family['base_dex']
self.dex_per_level = family['dex_per_level']
self.base_mnd = family['base_mnd']
self.mnd_per_level = family['mnd_per_level']
self.base_int = family['base_int']
self.int_per_level = family['int_per_level']
self.tp = 0
self.hp = self.get_hp()
self.wins = 0
self.losses = 0
def __str__(self):
try:
return "**{}**\n*Stats:*\nFamily: {}\nLevel: {}\nMain Job: {}\nSupport Job: {}\nInnate Feral Skills: {}\nEquipped Feral Skills: {}\nFeral Points: {}\n\nWins: {}\nLosses: {}".format(self.monster_type, self.family_name, self.level, Jobs().get_job_name(self.main_job), Jobs().get_job_name(self.support_job), ', '.join(self.innate_feral_skills), ', '.join(self.equipped_feral_skills), self.get_fp(), self.wins, self.losses)
return "**{}**\n*Stats:*\nFamily: {}\nLevel: {}\nMain Job: {}\nSupport Job: {}\nInnate Feral Skills: {}\nEquipped Feral Skills: {}\nFeral Points: {}\n\nWins: {}\nLosses: {}".format(self.get_monster_name(), self.family_name, self.level, Jobs().get_job_name(self.main_job), Jobs().get_job_name(self.support_job), ', '.join(self.innate_feral_skills), ', '.join(self.equipped_feral_skills), self.get_fp(), self.wins, self.losses)
except AttributeError:
return "Old Format monster, unable to display."
#return "Family: {}\nLevel: {}\nMain Job: {}\nSupport Job: {}\nInnate Feral Skills: {}\nEquipped Feral Skills: {}\nDicipline Level: {}\nTemperament...".format(self.family, self.level, self.main_job, self.support_job, self.innate_feral_skills, self.equipped_feral_skills, self.discipline_level)
def get_monster_name(self):
if self.custom_name:
return self.custom_name
else:
return self.monster_type
def set_monster_name(self, name):
self.custom_name = name
def get_soul_plate_description(self):
try:
return "*Family:*\n**{}**\nJob Trait: {}\nFeral Points: {}".format(self.family_name, Jobs().get_job_name(self.main_job), self.get_fp())
......@@ -375,7 +469,7 @@ class Monster:
def get_reflector_description(self):
try:
return "**{}**\n*Stats:*\nFamily: {}\nLevel: {}\nMain Job: {}\nSupport Job: {}\nInnate Feral Skills: {}\nEquipped Feral Skills: {}\nFeral Points: {}\n\nWins: {}\nLosses: {}".format(self.monster_type, self.family_name, self.level, Jobs().get_job_name(self.main_job), Jobs().get_job_name(self.support_job), ', '.join(self.innate_feral_skills), ', '.join(self.equipped_feral_skills), self.get_fp(), self.wins, self.losses)
return "**{}**\n*Stats:*\nFamily: {}\nLevel: {}\nMain Job: {}\nSupport Job: {}\nInnate Feral Skills: {}\nEquipped Feral Skills: {}\nFeral Points: {}\n\nWins: {}\nLosses: {}".format(self.get_monster_name(), self.family_name, self.level, Jobs().get_job_name(self.main_job), Jobs().get_job_name(self.support_job), ', '.join(self.innate_feral_skills), ', '.join(self.equipped_feral_skills), self.get_fp(), self.wins, self.losses)
except AttributeError:
return "Old Format monster, unable to display."
#return "Family: {}\nLevel: {}\nMain Job: {}\nSupport Job: {}\nInnate Feral Skills: {}\nEquipped Feral Skills: {}\nDicipline Level: {}\nTemperament...".format(self.family, self.level, self.main_job, self.support_job, self.innate_feral_skills, self.equipped_feral_skills, self.discipline_level)
......@@ -444,6 +538,12 @@ class Monster:
def get_agility(self):
return int(round(max(self.base_agi, self.level * self.agi_per_level)))
def get_mind(self):
return int(round(max(self.base_mnd, self.level * self.mnd_per_level)))
def get_intelligence(self):
return int(round(max(self.base_int, self.level * self.int_per_level)))
def get_base_defense(self):
return (math.floor(self.get_vitality()/2) + 8 + self.level)
......@@ -459,6 +559,41 @@ class Monster:
rate = 95
return rate
def get_physical_ws_damage(self, base_damage, modifiers):
level_range_alpha = 1.01 - (math.floor(float(self.level) / 5.0) / 100.0)
wsc = 0
for modifier in modifiers:
if modifier['stat'] == 'str':
wsc += (modifer['percent'] / 100) * self.get_strength()
elif modifiers['stat'] == 'vit':
wsc += (modifer['percent'] / 100) * self.get_vitality()
elif modifiers['stat'] == 'dex':
wsc += (modifer['percent'] / 100) * self.get_dexterity()
elif modifiers['stat'] == 'agi':
wsc += (modifer['percent'] / 100) * self.get_agility()
elif modifiers['stat'] == 'eva':
wsc += (modifer['percent'] / 100) * self.get_evasion()
elif modifiers['stat'] == 'int':
wsc += (modifer['percent'] / 100) * self.get_intelligence()
elif modifiers['stat'] == 'mnd':
wsc += (modifer['percent'] / 100) * self.get_mind()
wsc = (wsc * level_range_alpha)
bd = float(self.weapon_base_damage)
if attack_type == 'ranged':
bd += self.ammo_damage
fstr = ((self.get_strength() - enemy_vit)+4) / 4
final_damage = bd + fstr + wsc
return final_damage
#TODO: Add fTP calculation and PDIF
#final_damage = (bd )
#return final_damage
# Calculate the base damage against the provided defense
# attack_type can be 'ranged' or 'melee'
def get_physical_base_damage(self, defense, attack_type, level_difference, enemy_vit):
......@@ -520,15 +655,19 @@ class Monster:
def attack(self, monster):
phy_damage = self.get_physical_base_damage(monster.get_base_defense(), 'melee', monster.level - self.level, monster.get_vitality())
self.tp += 64
return (phy_damage, 'hits')
def is_a_hit(self, monster):
hit_rate = self.get_hit_rate(monster.get_evasion(), monster.level - self.level)
return random.randint(1, 100) < hit_rate
def apply_damage(self, damage):
def apply_damage(self, damage, is_spell=False):
self.hp -= damage
# Check life and return 'awesome', 'fucked up', 'dead' or something
if is_spell:
self.tp += 100
else:
self.tp += 30
# This should ONLY be executed at the start of battle.
def set_strategy(self, temperament_posture, temperament_attitude):
......@@ -633,18 +772,21 @@ class Arena:
if __name__ == "__main__":
#print Families
hunt_response = None
p = Pankration()
print("Zones: \n\n{}".format('\n'.join(p.list_zones())))
hunt_zone = p.list_zones()[0]
hunt_zone = p.list_zones().keys()[0]
print("Hunting for monster in zone: {}\n".format(hunt_zone))
hunt_response = p.hunt_monster(hunt_zone)
while not hunt_response or (hasattr(hunt_response, 'result') and hunt_response.result != HuntResponse.SUCCESS):
hunt_response = p.hunt_monster(hunt_zone)
print("hunt_response")
print(str(hunt_response.result))
time.sleep(0.5)
if hunt_response.result == HuntResponse.SUCCESS:
print(hunt_response.message)
monster = hunt_response.monster
# print("The Soul Plate Shows: \n\n{}".format(monster))
monster.set_monster_name('Kickass 1')
print("The Soul Plate Shows: \n\n{}".format(monster))
# print(monster.set_strategy(4, 3))
# print(monster.set_strategy(1, 1))
# print(monster.set_strategy(1, 2))
......@@ -659,11 +801,16 @@ if __name__ == "__main__":
else:
print(hunt_response.message)
hunt_response2 = None
hunt_zone = p.list_zones().keys()[1]
while not hunt_response2 or (hasattr(hunt_response2, 'result') and hunt_response2.result != HuntResponse.SUCCESS):
hunt_response2 = p.hunt_monster(hunt_zone)
if hunt_response2.result == HuntResponse.SUCCESS:
monster2 = hunt_response2.monster
monster2.set_monster_name('wreckbutt 2')
print("1 The Soul Plate Shows: \n\n{}".format(monster))
print("2 The Soul Plate Shows: \n\n{}".format(monster2))
hunt_zone = p.list_zones()[1]
hunt_response = p.hunt_monster(hunt_zone)
if hunt_response.result == HuntResponse.SUCCESS:
monster2 = hunt_response.monster
#monster2.add_xp(16900)
phy_damage = monster2.attack(monster)
print("Phys Attack: {}".format(phy_damage))
......@@ -682,17 +829,17 @@ if __name__ == "__main__":
time.sleep(2)
for action in actions:
if isinstance(action, MissAction):
print("{} {} {}.".format(action.attacker.monster_type, action.message, action.target.monster_type))
print("{} {} {}.".format(action.attacker.get_monster_name(), action.message, action.target.get_monster_name()))
if isinstance(action, AttackAction):
print("{} {} {} for {}.".format(action.attacker.monster_type, action.message, action.target.monster_type, action.damage))
print("{} {} {} for {}.".format(action.attacker.get_monster_name(), action.message, action.target.get_monster_name(), action.damage))
if isinstance(action, DefeatAction):
print("{} {}. {} gains {} xp.".format(action.target.monster_type, action.message, action.attacker.monster_type, action.xp))
print("{} {}. {} gains {} xp.".format(action.target.get_monster_name(), action.message, action.attacker.get_monster_name(), action.xp))
action.attacker.hp = 500
print("{} {}".format(action.target.hp, action.attacker.hp))
fighting = False
break
print("\n\nhp: {} {}\n\n".format(monster.hp, monster2.hp))
print("\n{} {}% - {} {}%\n".format(monster.monster_type, monster.get_hp_percent(), monster2.monster_type, monster2.get_hp_percent()))
print("\n{} {}% - {} {}%\n".format(monster.get_monster_name(), monster.get_hp_percent(), monster2.get_monster_name(), monster2.get_hp_percent()))
......