class MonsterSpawnCombat < ApplicationRecord belongs_to :monster_spawn belongs_to :character validates :hp_lost, numericality: { greater_than_or_equal_to: 0, only_integer: true } after_create :check_hp private def check_hp return if monster_spawn.alive? monster = monster_spawn.monster message_body_parts = {} # TODO: HACK (should allow multiple xp awards, eventually) xp_award_data = monster.whatnot[:awards].find { |a| a[:type] == "xp" } involved_character_ids = MonsterSpawnCombat.where(monster_spawn: monster_spawn).pluck(:character_id).uniq involved_characters = Character.where(id: involved_character_ids) involved_characters.each do |character| total_xp = xp_award_data[:base] * MonsterSpawnCombat.where(monster_spawn: monster_spawn, character: character).count character.add_skill_xp(xp_award_data[:gid], total_xp) message_body_parts[character.id] ||= [] message_body_parts[character.id].push("You got #{total_xp} #{Skill.find_by_gid(xp_award_data[:gid]).name} XP.") end monster.whatnot[:awards]&.each do |data| case data[:type] when "item" return if rand > (data[:chance] || 1) if data[:table] table_roll = rand data[:table].sort_by { |t| -t[:score] }.each do |table_entry| min_quantity = table_entry[:min_quantity] || table_entry[:quantity] || 1 max_quantity = table_entry[:max_quantity] || table_entry[:quantity] || 1 quantity = rand(min_quantity..max_quantity) score = table_entry[:score] if table_roll >= score winning_character = involved_characters.sample item = Item.find_by_gid(data[:gid]) winning_character.shift_item(item, quantity) message_body_parts[winning_character.id] ||= [] message_body_parts[winning_character.id].push("You got #{quantity} #{item.name}.k") break end end else min_quantity = data[:min_quantity] || data[:quantity] || 1 max_quantity = data[:max_quantity] || data[:quantity] || 1 quantity = rand(min_quantity..max_quantity) winning_character = involved_characters.sample item = Item.find_by_gid(data[:gid]) winning_character.shift_item(item, quantity) message_body_parts[winning_character.id] ||= [] message_body_parts[winning_character.id].push("You got #{quantity} #{item.name}.") break end end end message_body_parts.each do |character_id, body_parts| if body_parts.any? Message.create(recipient_id: character_id, subject: "#{monster.name} slain", body: body_parts.join(", ")) end end chat_message = ChatMessage.new(body: "The #{monster.name} in #{monster_spawn.location.name} has been slain!", chat_room: ChatRoom.find_by_gid("news")) if chat_message.save ChatRoomChannel.broadcast_chat_message(chat_message) end end end