diff options
Diffstat (limited to 'app/models/character.rb')
-rw-r--r-- | app/models/character.rb | 81 |
1 files changed, 72 insertions, 9 deletions
diff --git a/app/models/character.rb b/app/models/character.rb index d386002..2669626 100644 --- a/app/models/character.rb +++ b/app/models/character.rb @@ -9,10 +9,12 @@ class Character < ApplicationRecord has_many :character_items has_many :learned_activities has_many :items, through: :character_items + has_many :item_infixes has_many :character_skills has_many :conditions, through: :states has_many :states has_many :chat_messages + has_many :monster_kills has_many :bazaar_orders validates :name, presence: true # TODO: Make defaults better. This has to allow nil so the `attribute` default works, and I don't like that. @@ -115,14 +117,30 @@ class Character < ApplicationRecord end end - def do_equipment_break_checks(exclude_slots: []) - broken_items = [] - equipment.where.not(slot: exclude_slots).each do |equipment| - if equipment.break_check - broken_items.push(equipment.item) - end + def do_equipment_break_check(skill: nil) + skill = Skill.find_by_gid(skill) if skill&.is_a? String + # TODO: HACK: Should check other stats besides speed stat in the future. + # TODO: HACK: May not want a chance to break if speed is _reduced_. Though no equipment does this yet. + if skill + threatened_equipment = equipment.all.select { |eq| eq.effects&.select { |ef| ef[:gid] == "#{skill.gid}_speed" }&.any? } + else + threatened_equipment = equipment.all end - broken_items + break_slot = Equipment.random_break_slot + return nil unless break_slot + broken_equipment = threatened_equipment.find { |eq| eq.slot == break_slot } + return nil unless broken_equipment + broken_equipment.destroy + broken_equipment.item + end + + def do_item_infix_break_check(skill:) + skill = Skill.find_by_gid(skill) if skill.is_a? String + return nil unless ItemInfix.break_check + broken_ii = item_infixes.where(skill: skill).sample + return nil unless broken_ii + broken_ii.destroy + broken_ii.item end def has_item?(item, quantity = 1) @@ -136,6 +154,10 @@ class Character < ApplicationRecord self.equipment.find_by(item: item) end + def equipment_with_tag(tag) + self.equipment.all.find { |e| e.item.has_tag?(tag) } + end + def open_slots_for(item) full_slots = self.equipment.map { |e| e.slot } item.equip_slots.reject { |slot| full_slots.include?(slot) } @@ -182,6 +204,30 @@ class Character < ApplicationRecord end end + def max_infixes(skill) + skill = Skill.find_by_gid(skill) if skill.is_a? String + 1 + (skill_level(skill) / 20).floor + end + + def available_infixes(skill) + skill = Skill.find_by_gid(skill) if skill.is_a? String + max_infixes(skill) - item_infixes.where(skill: skill).count + end + + def infix(item, skill) + Character.transaction do + shift_item(item, -1) + item_infixes.create(item: item, skill: skill) + end + end + + def remove_infix(item_infix) + Character.transaction do + shift_item(item_infix.item, 1) + item_infix.destroy + end + end + def add_skill_xp(skill, amount) skill = Skill.find_by_gid(skill) if skill.is_a? String Character.transaction do @@ -247,7 +293,14 @@ class Character < ApplicationRecord activity.whatnot[:requirements]&.each do |requirement| case requirement[:type] when "equipment" - return false unless self.equipment_with_gid(requirement[:gid]) + if requirement[:tag] + return false unless self.equipment_with_tag(requirement[:tag]) + else + return false unless self.equipment_with_gid(requirement[:gid]) + end + when "stat" + # TODO: HACK: This won't work with built-in stats! Need to change this to work with power and whatnot. + return false unless self.total_stat_change(requirement[:gid]) >= requirement[:value] when "skill" return false unless self.skill_level(requirement[:gid]) >= requirement[:level] when "hearth_amenity" @@ -278,6 +331,7 @@ class Character < ApplicationRecord def start_resting return false if self.started_resting_at + stop_activity self.update(started_resting_at: Time.now) end @@ -306,17 +360,26 @@ class Character < ApplicationRecord hearth_amenity_effects = self.hearth.built_hearth_amenities.filter_map { |a| a.effects if a.effects } equipment_effects = self.equipment.filter_map { |a| a.effects if a.effects } state_effects = self.states.filter_map { |a| a.effects if a.effects && !a.expired? } - (hearth_amenity_effects + equipment_effects + state_effects).flatten + item_infix_effects = self.item_infixes.filter_map { |a| a.effects if a.effects } + (hearth_amenity_effects + equipment_effects + state_effects + item_infix_effects).flatten end def total_stat_change(gid) effects.filter_map { |e| e[:modifier] if e[:type] == "stat_change" && e[:gid] == gid }.sum end + def total_enemy_stat_change(gid) + effects.filter_map { |e| e[:modifier] if e[:type] == "enemy_stat_change" && e[:gid] == gid }.sum + end + def damage_ranges effects.filter_map { |e| { gid: e[:gid], min: e[:min], max: e[:max] } if e[:type] == "damage" } end + def dots + effects.filter_map { |e| { gid: e[:gid], min: e[:min], max: e[:max], message: e[:message] } if e[:type] == "dot" } + end + def planting_spots [total_stat_change("planting_spots"), 0].max end |