b1760e6e by Barry

Finished the first round of feral skills.

1 parent 93d98e04
No preview for this file type
......@@ -1282,7 +1282,7 @@ def check_arena():
winner = 1
while fighting:
actions = battle_arena.step()
time.sleep(4)
time.sleep(3)
out_str = ""
for action in actions:
# TODO: Decide if I should merge magicresistaction with miss action
......@@ -1306,7 +1306,7 @@ def check_arena():
# give a small amount to the loser
if result:
out_str += xp_msg
result, xp_msg = monster2.add_xp(5)
result, xp_msg = monster2.add_xp(action.losing_xp)
if result:
out_str += xp_msg
winner = 1
......@@ -1318,7 +1318,7 @@ def check_arena():
# give a small amount to the loser
if result:
out_str += xp_msg
result, xp_msg = monster.add_xp(5)
result, xp_msg = monster.add_xp(action.losing_xp)
if result:
out_str += xp_msg
winner = 2
......
......@@ -12,6 +12,7 @@ def log(message):
except:
pass
ATTACK_EFFECT_PERCENTAGE = 25
FIND_PERCENTAGE = 100
SKILL_PERCENT = 80
......@@ -148,7 +149,80 @@ FeralSkills = {
'Accuracy +30%': {'fp_cost': 30, 'effect': 'acc', 'amount': 30, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
'Accuracy Bonus': {'fp_cost': 30, 'effect': 'acc', 'amount': 15, 'is_percent': True, 'expires_seconds': 0, 'levels': True},
'AGI +25': {'fp_cost': 17, 'effect': 'agi', 'amount': 25, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'AGI +50': {'fp_cost': 23, 'effect': 'agi', 'amount': 50, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'AGI Bonus': {'fp_cost': 23, 'effect': 'agi', 'amount': 15, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
'Amnesia Attack': {'fp_cost': 47, 'effect': 'amnesia', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Amorph Killer': {'fp_cost': 8, 'effect': 'amorph_killer', 'amount': 5, 'is_percent': True, 'expires_seconds': 0, 'levels': True},
'Attack +15%': {'fp_cost': 23, 'effect': 'attack', 'amount': 15, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
'Attack Bonus': {'fp_cost': 30, 'effect': 'attack', 'amount': 10, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'Auto Refresh': {'fp_cost': 38, 'effect': 'auto_refresh', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'Auto Refresh +5': {'fp_cost': 30, 'effect': 'auto_refresh', 'amount': 5, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Auto Regain': {'fp_cost': 70, 'effect': 'auto_regain', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'Auto Regain +3': {'fp_cost': 58, 'effect': 'auto_regain', 'amount': 3, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Auto Regen': {'fp_cost': 47, 'effect': 'auto_regen', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'Auto Regen +5': {'fp_cost': 38, 'effect': 'auto_regen', 'amount': 5, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Aquan Killer': {'fp_cost': 8, 'effect': 'aquan_killer', 'amount': 5, 'is_percent': True, 'expires_seconds': 0, 'levels': True},
'Bird Killer': {'fp_cost': 8, 'effect': 'bird_killer', 'amount': 5, 'is_percent': True, 'expires_seconds': 0, 'levels': True},
'Blinding Attack': {'fp_cost': 23, 'effect': 'blind', 'amount': -20, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
'CHR +25': {'fp_cost': 17, 'effect': 'cha', 'amount': 25, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'CHR Bonus': {'fp_cost': 23, 'effect': 'cha', 'amount': 15, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
'Curse Attack': {'fp_cost': 23, 'effect': 'curse', 'amount': -20, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
'Damage Resistance +15%': {'fp_cost': 30, 'effect': 'damage_resist', 'amount': 15, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
'Damage Resistance Bonus': {'fp_cost': 38, 'effect': 'damage_resist', 'amount': 10, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'Dark Resistance +2': {'fp_cost': 8, 'effect': 'dark_resist', 'amount': 2, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Dark Resistance Bonus': {'fp_cost': 12, 'effect': 'dark_resist', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'Defense +15%': {'fp_cost': 23, 'effect': 'def', 'amount': 15, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
'Defense Bonus': {'fp_cost': 30, 'effect': 'def', 'amount': 10, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'Defense +30%': {'fp_cost': 30, 'effect': 'def', 'amount': 30, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
'DEX +25': {'fp_cost': 17, 'effect': 'dex', 'amount': 25, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'DEX +50': {'fp_cost': 23, 'effect': 'dex', 'amount': 50, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'DEX Bonus': {'fp_cost': 23, 'effect': 'dex', 'amount': 15, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'Demon Killer': {'fp_cost': 8, 'effect': 'demon_killer', 'amount': 5, 'is_percent': True, 'expires_seconds': 0, 'levels': True},
'Dragon Killer': {'fp_cost': 8, 'effect': 'dragon_killer', 'amount': 5, 'is_percent': True, 'expires_seconds': 0, 'levels': True},
'Earth Resistance +2': {'fp_cost': 8, 'effect': 'earth_resist', 'amount': 2, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Earth Resistance Bonus': {'fp_cost': 12, 'effect': 'earth_resist', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'Evasion +15%': {'fp_cost': 23, 'effect': 'eva', 'amount': 15, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
'Evasion Bonus': {'fp_cost': 30, 'effect': 'eva', 'amount': 5, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'Fire Resistance +2': {'fp_cost': 8, 'effect': 'fire_resist', 'amount': 2, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Fire Resistance Bonus': {'fp_cost': 12, 'effect': 'fire_resist', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'HP Max Bonus': {'fp_cost': 12, 'effect': 'hp', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'HP Max +15%': {'fp_cost': 23, 'effect': 'hp', 'amount': 15, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
'HP Max +30%': {'fp_cost': 30, 'effect': 'hp', 'amount': 30, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
'HP Max +50': {'fp_cost': 8, 'effect': 'hp', 'amount': 50, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Ice Resistance +2': {'fp_cost': 8, 'effect': 'ice_resist', 'amount': 2, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Ice Resistance Bonus': {'fp_cost': 12, 'effect': 'ice_resist', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'INT Bonus': {'fp_cost': 23, 'effect': 'int', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'INT +25': {'fp_cost': 17, 'effect': 'int', 'amount': 25, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'INT +50': {'fp_cost': 23, 'effect': 'int', 'amount': 50, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Light Resistance +2': {'fp_cost': 8, 'effect': 'light_resist', 'amount': 2, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Lightning Resistance +2': {'fp_cost': 8, 'effect': 'lightning_resist', 'amount': 2, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Lizard Killer': {'fp_cost': 8, 'effect': 'lizard_killer', 'amount': 5, 'is_percent': True, 'expires_seconds': 0, 'levels': True},
'MP Max Bonus': {'fp_cost': 17, 'effect': 'mp', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'MP Max +15%': {'fp_cost': 12, 'effect': 'mp', 'amount': 15, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
'MP Max +50': {'fp_cost': 5, 'effect': 'mp', 'amount': 50, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Magic Accuracy Bonus': {'fp_cost': 30, 'effect': 'magic_acc', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'Magic Accuracy 15%': {'fp_cost': 23, 'effect': 'magic_acc', 'amount': 15, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
'Magic Attack Bonus': {'fp_cost': 30, 'effect': 'magic_attack', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'Magic Attack +15%': {'fp_cost': 23, 'effect': 'magic_attack', 'amount': 15, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
'MND Bonus': {'fp_cost': 23, 'effect': 'mnd', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'MND +25': {'fp_cost': 17, 'effect': 'mnd', 'amount': 25, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'MND +50': {'fp_cost': 23, 'effect': 'mnd', 'amount': 50, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Poisoning Attack': {'fp_cost': 17, 'effect': 'poison', 'amount': -4, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Plantoid Killer': {'fp_cost': 8, 'effect': 'plantoid_killer', 'amount': 5, 'is_percent': True, 'expires_seconds': 0, 'levels': True},
'Silencing Attack': {'fp_cost': 30, 'effect': 'silence', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Store TP +10%': {'fp_cost': 38, 'effect': 'store_tp', 'amount': 10, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
'STR Bonus': {'fp_cost': 23, 'effect': 'str', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'STR +25': {'fp_cost': 17, 'effect': 'str', 'amount': 25, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'STR +50': {'fp_cost': 23, 'effect': 'str', 'amount': 50, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Undead Killer': {'fp_cost': 8, 'effect': 'undead_killer', 'amount': 5, 'is_percent': True, 'expires_seconds': 0, 'levels': True},
'Vermin Killer': {'fp_cost': 8, 'effect': 'vermin_killer', 'amount': 5, 'is_percent': True, 'expires_seconds': 0, 'levels': True},
'VIT Bonus': {'fp_cost': 23, 'effect': 'vit', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'VIT +25': {'fp_cost': 17, 'effect': 'vit', 'amount': 25, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'VIT +50': {'fp_cost': 23, 'effect': 'vit', 'amount': 50, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Water Resistance +2': {'fp_cost': 8, 'effect': 'water_resist', 'amount': 2, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Water Resistance Bonus': {'fp_cost': 12, 'effect': 'water_resist', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
'Wind Resistance +2': {'fp_cost': 8, 'effect': 'wind_resist', 'amount': 2, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
'Wind Resistance Bonus': {'fp_cost': 12, 'effect': 'wind_resist', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': True},
}
class Spells:
......@@ -199,9 +273,10 @@ class Spells:
'Banish III': {'mp_cost': 96, 'casting_time': 3, 'recast_time': 45, 'magic_acc_stat': 'mnd', 'spell_type': 't3', 'damage_type': 'light', 'jobs': {Jobs.WHM: 65} },
}
def get_spell_list(self, mp, level, job = None, support_job = None):
@staticmethod
def get_spell_list(mp, level, job = None, support_job = None):
available_spells = []
for spell_name, spell in self.SpellList.iteritems():
for spell_name, spell in Spells.SpellList.iteritems():
if job and job in spell['jobs'] and spell['jobs'][job] <= level:
if spell_name not in available_spells:
if spell['mp_cost'] < mp:
......@@ -212,9 +287,10 @@ class Spells:
available_spells.append(spell_name)
return sorted(available_spells)
def get_spell_data(self, spell):
spell = self.SpellList[spell]
type_data = self.SpellTypes[spell['spell_type']]
@staticmethod
def get_spell_data(spell):
spell = Spells.SpellList[spell]
type_data = Spells.SpellTypes[spell['spell_type']]
spell_data = {
'type': type_data,
'magic_acc_stat': spell['magic_acc_stat'],
......@@ -527,15 +603,16 @@ class Pankration:
return ""
class AttackResponse:
def __init__(self, is_a_hit, damage, is_a_crit, spell, resisted):
def __init__(self, is_a_hit, damage, is_a_crit, spell, resisted, intimidated):
self.spell = spell
self.is_a_crit = is_a_crit
self.is_a_hit = is_a_hit
self.resisted = resisted
self.intimidated = intimidated
self.damage = damage
def __str__(self):
return "Spell: {} Resisted: {} Is a Hit: {} Is a Crit: {} Damage: {}".format(self.spell, self.resisted, self.is_a_hit, self.is_a_crit, self.damage)
return "Spell: {} Resisted: {} Is a Hit: {} Is a Crit: {} Damage: {} intimidated: {}".format(self.spell, self.resisted, self.is_a_hit, self.is_a_crit, self.damage, self.intimidated)
class Monster:
def __init__(self, monster_type, family_name, family, base_hp, base_mp, level, weapon_base_damage, main_job,
......@@ -553,6 +630,14 @@ class Monster:
self.support_job = support_job
self.innate_feral_skills = innate_feral_skills
self.equipped_feral_skills = equipped_feral_skills
effects = self.get_status_effect_list()
for feral_skill in innate_feral_skills + equipped_feral_skills:
effect = effects[FeralSkills[feral_skill]['effect']]
# Should init = true
if effect:
self.apply_feral_skill(feral_skill)
self.discipline_level = dicipline_level
self.temperament_posture = family['temperament_posture']['initial_value']
self.temperament_attitude = family['temperament_attitude']['initial_value']
......@@ -615,7 +700,9 @@ class Monster:
def get_hp(self):
#this is a bit dumb but it's close enough.
return self.get_status_effect('hp', int((self.level * 20) + self.base_hp))
return self.get_status_effect('curse',
self.get_status_effect('hp',
int((self.level * 20) + self.base_hp)))
def get_mp(self):
#this is a bit dumb but it's close enough.
......@@ -625,7 +712,8 @@ class Monster:
main_mp = int((self.level * (self.base_mp + main_add_amount)) + self.base_mp)
sub_mp = int((self.level/2) * sub_add_amount)
return self.get_status_effect('mp', main_mp + sub_mp)
return self.get_status_effect('curse',
self.get_status_effect('mp', main_mp + sub_mp))
def get_fp(self):
......@@ -711,6 +799,7 @@ class Monster:
def get_hit_rate(self, enemy_eva, level_difference):
rate = 75 + math.floor(((self.get_accuracy() - enemy_eva)/2)) - (2*level_difference)
rate = self.get_status_effect('blind', rate)
if rate < 20:
rate = 20
elif rate > 95:
......@@ -719,7 +808,7 @@ class Monster:
def get_magic_hit_rate(self, spell, enemy):
# Calculate the magic accuracy
spell_data = Spells().get_spell_data(spell)
spell_data = Spells.get_spell_data(spell)
# Get the stat for the spell and base magic accuracy for that spells MA
magic_acc_stat = spell_data['magic_acc_stat']
if magic_acc_stat == 'int':
......@@ -736,6 +825,7 @@ class Monster:
dSTAT = self.get_agility() - enemy.get_agility()
magic_hit_rate = 50 - 0.5 * (enemy.get_magic_evasion(spell_data['damage_type']) - dSTAT)
magic_hit_rate = self.get_status_effect('magic_acc', magic_hit_rate)
if magic_hit_rate < 5:
magic_hit_rate = 5
......@@ -848,7 +938,7 @@ class Monster:
else:
dINT = self.get_intelligence() - enemy.get_intelligence()
spell_data = Spells().get_spell_data(spell)
spell_data = Spells.get_spell_data(spell)
base_damage = 0
if dINT < 0:
......@@ -876,6 +966,14 @@ class Monster:
return base_damage
def apply_feral_skill(self, feral_skill):
# 'Amnesia Attack': {'fp_cost': 47, 'effect': 'amnesia', 'amount': 1, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
fs = FeralSkills[feral_skill]
self.set_status_effect(fs['effect'], fs['amount'], fs['is_percent'], fs['expires_seconds'])
if feral_skill == 'Curse Attack':
self.hp = min(self.hp, self.get_hp())
self.mp = min(self.mp, self.get_mp())
# it is up to the rest of the system to understand how to read this data and act on it.
# Example Call: ('acc', '10', False, 30)
def set_status_effect(self, effect, amount, is_percent, expires_seconds):
......@@ -892,30 +990,52 @@ class Monster:
else:
return base_amount
# This is a list of all status effects that are available.
# This is a list of all status effects that are available and if they should be auto intialized.
def get_status_effect_list(self):
return [
'acc',
'agi',
'cha',
'def',
'dex',
'eva',
'hp',
'int',
'mnd',
'mp',
'str',
'vit',
'fire_resist',
'water_resist',
'ice_resist',
'wind_resist',
'earth_resist',
'thunder_resist',
'light_resist',
'dark_resist'
]
return {
'acc': True,
'agi': True,
'cha': True,
'def': True,
'dex': True,
'eva': True,
'hp': True,
'int': True,
'mnd': True,
'mp': True,
'str': True,
'vit': True,
'store_tp': True,
'fire_resist': True,
'water_resist': True,
'ice_resist': True,
'wind_resist': True,
'earth_resist': True,
'thunder_resist': True,
'light_resist': True,
'dark_resist': True,
'damage_resist': True,
'auto_refresh': True,
'auto_regain': True,
'auto_regen': True,
'amnesia': False,
'amorph_killer': False,
'aquan_killer': False,
'bird_killer': False,
'demon_killer': False,
'dragon_killer': False,
'lizard_killer': False,
'plantoid_killer': False,
'undead_killer': False,
'vermin_killer': False,
'attack': False,
'blind': False,
'curse': False,
'poison': False,
'silence': False,
'magic_acc': True,
'magic_attack': True,
}
# Calculate the base damage against the provided defense
# attack_type can be 'ranged' or 'melee'
......@@ -942,9 +1062,9 @@ class Monster:
# Step 2: Do i have a memory of this monster from past battles? Does it have any elemental weakness?
spell_list = Spells().get_spell_list(self.mp, self.level, job=self.main_job, support_job=self.support_job)
spell_list = Spells.get_spell_list(self.mp, self.level, job=self.main_job, support_job=self.support_job)
best_spell_name = None
if spell_list:
if spell_list and 'silence' not in self.status_effects:
if monster.family_name in self.battle_memory:
battles = self.battle_memory[monster.family_name]
# this assumes spells are: 'spells':{'Fire': 100, 'Stone II': 500}
......@@ -1001,8 +1121,12 @@ class Monster:
is_a_hit = False
spell = None
resisted = False
intimidated = False
damage = 0
if self.unable_to_move(monster):
return AttackResponse(is_a_hit, damage, is_a_crit, spell, resisted, True)
# intialize the monster memory for this family name if it isn't already set.
if monster.family_name not in self.battle_memory:
self.battle_memory[monster.family_name] = {'spells': {}}
......@@ -1015,9 +1139,10 @@ class Monster:
damage = self.get_magic_base_damage(spell, monster)
if damage == 0:
resisted = True
damage = self.get_status_effect('magic_attack', damage)
log("MAGIC DAMAGE: {}".format(damage))
is_a_hit = True
spell_data = Spells().get_spell_data(spell)
spell_data = Spells.get_spell_data(spell)
self.mp -= spell_data['mp_cost']
if self.mp < 0:
self.mp = 0
......@@ -1026,22 +1151,45 @@ class Monster:
self.battle_memory[monster.family_name]['spells'][spell] = damage + (self.battle_memory[monster.family_name]['spells'][spell]) / 2
else:
self.battle_memory[monster.family_name]['spells'][spell] = damage
return AttackResponse(is_a_hit, damage, is_a_crit, spell, resisted)
return AttackResponse(is_a_hit, damage, is_a_crit, spell, resisted, intimidated)
else:
if self.is_a_hit(monster):
# TODO: Make this follow the behavior in temprament and select the right behavior.
if self.tp >= 1000:
if random.randint(1, 100) < ATTACK_EFFECT_PERCENTAGE: # 50% chance of applying the effects "XXX Attack"
if 'Amnesia Attack' in self.equipped_feral_skills:
monster.apply_feral_skill('Amnesia Attack')
if 'Blinding Attack' in self.equipped_feral_skills:
monster.apply_feral_skill('Blinding Attack')
if 'Curse Attack' in self.equipped_feral_skills:
monster.apply_feral_skill('Curse Attack')
if 'Poisoning Attack' in self.equipped_feral_skills:
monster.apply_feral_skill('Poisoning Attack')
if 'Silencing Attack' in self.equipped_feral_skills:
monster.apply_feral_skill('Silencing Attack')
# TODO: Make this follow the behavior in temperament and select the right behavior.
if self.tp >= 1000 and not self.get_status_effect('amnesia', 0):
damage = self.get_physical_ws_damage(monster.get_base_defense(), 'melee', [1.0, 1.5, 4.0], [], monster.level - self.level, monster.get_vitality())
log("WS DAMAGE: {}".format(damage))
self.tp = 0
else:
damage = self.get_physical_base_damage(monster.get_base_defense(), 'melee', monster.level - self.level, monster.get_vitality())
print("STD DAMAGE: {}".format(damage))
self.tp += 64
self.tp += self.get_status_effect('store_tp', 64)
damage = self.get_status_effect('damage_resist', damage)
is_a_hit = True
# Returns the amount of damage and if it is a crit
return AttackResponse(is_a_hit, damage, is_a_crit, spell, resisted)
return AttackResponse(is_a_hit, damage, is_a_crit, spell, resisted, intimidated)
# This determines if a monster is paralized or intimidated and unable to act.
def unable_to_move(self, monster):
killer_type = "{}_{}".format(monster.family['type'], "killer").lower()
if killer_type in self.status_effects:
if random.randint(1, 100) < self.status_effects[killer_type]['amount']:
return True
return False
#if
#monster.family['type'] == killer
def is_a_magic_hit(self, spell, monster):
hit_rate = self.get_magic_hit_rate(spell, monster)
......@@ -1058,6 +1206,15 @@ class Monster:
else:
self.tp += 30
def apply_per_tick_adjustment(self):
# apply all healing first
self.mp = self.get_status_effect('auto_refresh', self.mp)
self.tp = self.get_status_effect('auto_regain', self.tp)
self.hp = self.get_status_effect('auto_regen', self.hp)
# apply DOTs
self.hp = self.get_status_effect('poison', self.hp)
# This should ONLY be executed at the start of battle.
def set_strategy(self, temperament_posture, temperament_attitude):
distance_from_nature = abs(self.temperament_posture - temperament_posture)
......@@ -1114,6 +1271,14 @@ class MagicResistAction(Action):
self.spell = spell
self.message = random.choice(MagicResistAction.MESSAGES)
class IntimidatedAction(Action):
MESSAGES = ['was unable to act']
def __init__(self, attacker):
self.attacker = attacker
self.message = random.choice(IntimidatedAction.MESSAGES)
class MissAction(Action):
MAGIC_MESSAGES = ['fizzled the spell against']
MESSAGES = ['missed', 'was unable to hit', 'attack went wide of', 'fumbled the hit on']
......@@ -1130,11 +1295,12 @@ class MissAction(Action):
class DefeatAction(Action):
MESSAGES = ['was defeated', 'was smited', 'was conquered', 'was routed', 'was thwarted',
'was vanquished', 'was bested']
def __init__(self, attacker, target, xp):
def __init__(self, attacker, target, xp, losing_xp):
self.attacker = attacker
self.target = target
self.message = random.choice(DefeatAction.MESSAGES)
self.xp = xp
self.losing_xp = xp
class Arena:
......@@ -1167,12 +1333,16 @@ class Arena:
#if primary.is_a_magic_hit(spell, secondary)
result1 = primary.attack(secondary)
if result1.resisted:
if result1.intimidated:
actions.append(IntimidatedAction(primary))
elif result1.resisted:
actions.append(MagicResistAction(primary, secondary, result1.spell))
elif result1.is_a_hit:
secondary.apply_damage(result1.damage)
actions.append(AttackAction(primary, secondary, result1.damage, result1.is_a_crit,
result1.spell))
# apply healing then dots to make sure secondary survived.
secondary.apply_per_tick_adjustment()
if secondary.hp <= 0:
level_difference = secondary.level - primary.level
if level_difference in exp_table:
......@@ -1181,18 +1351,26 @@ class Arena:
xp = exp_table[15]
else:
xp = 0
actions.append(DefeatAction(primary, secondary, xp))
losing_xp = max(5, 11*level_difference)
if losing_xp > 75:
losing_xp = 75
actions.append(DefeatAction(primary, secondary, xp, losing_xp))
return actions
else:
actions.append(MissAction(primary, secondary, result1.spell))
result2 = secondary.attack(primary)
if result2.resisted:
if result2.intimidated:
actions.append(IntimidatedAction(secondary))
elif result2.resisted:
actions.append(MagicResistAction(secondary, primary, result2.spell))
elif result2.is_a_hit:
primary.apply_damage(result2.damage)
actions.append(AttackAction(secondary, primary, result2.damage, result2.is_a_crit,
result2.spell))
tick_result = primary.apply_per_tick_adjustment()
if primary.hp <= 0:
level_difference = primary.level - secondary.level
if level_difference in exp_table:
......@@ -1201,7 +1379,10 @@ class Arena:
xp = exp_table[15]
else:
xp = 0
actions.append(DefeatAction(secondary, primary, xp))
losing_xp = max(5, 11*level_difference)
if losing_xp > 75:
losing_xp = 75
actions.append(DefeatAction(secondary, primary, xp, losing_xp))
return actions
else:
actions.append(MissAction(secondary, primary, result2.spell))
......@@ -1211,7 +1392,7 @@ class Arena:
if __name__ == "__main__":
#print Families
print("Spell List: \n{}\n".format(Spells().get_spell_list(100, 10, job=Jobs.RDM, support_job=Jobs.WAR)))
print("Spell List: \n{}\n".format(Spells.get_spell_list(100, 10, job=Jobs.RDM, support_job=Jobs.WAR)))
hunt_response = None
p = Pankration()
print("Zones: \n\n{}".format('\n'.join(p.list_zones())))
......@@ -1226,7 +1407,8 @@ if __name__ == "__main__":
print(hunt_response.message)
monster = hunt_response.monster
monster.set_monster_name('Kickass 1')
monster.set_status_effect('demon_killer', 50, False, None)
print("The Soul Plate Shows: \n\n{}".format(monster))
# print(monster.set_strategy(4, 3))
# print(monster.set_strategy(1, 1))
......@@ -1253,9 +1435,11 @@ if __name__ == "__main__":
print("2 The Soul Plate Shows: \n\n{}".format(monster2))
print("MP m1: {}\nMP m2: {}".format(monster.get_mp(), monster2.get_mp()))
#print(monster2.add_xp(16900))
#monster2.set_status_effect('int', 100, False, None)
monster2.set_status_effect('demon_killer', 50, False, None)
phy_damage = monster2.attack(monster)
print("Phys Attack: {}".format(phy_damage))
phy_damage = monster.attack(monster2)
print("Phys Attack2: {}".format(phy_damage))
print("Acc: {}".format(monster.get_accuracy()))
......@@ -1268,8 +1452,10 @@ if __name__ == "__main__":
fighting = True
while fighting:
actions = battle_arena.step()
time.sleep(2)
time.sleep(3)
for action in actions:
if isinstance(action, IntimidatedAction):
print("{} {}.".format(action.attacker.get_monster_name(), action.message))
if isinstance(action, MagicResistAction):
print("{} {} {} while casting {}.".format(action.attacker.get_monster_name(), action.message, action.target.get_monster_name(), action.spell))
if isinstance(action, MissAction):
......