From 19cb44149e5c4d8be27afb948097b43b441adb0d Mon Sep 17 00:00:00 2001 From: David Gay Date: Sun, 6 Jun 2021 19:39:22 -0400 Subject: Awarding items and XP for leviathans --- app/models/monster_spawn.rb | 11 ------ app/models/monster_spawn_combat.rb | 70 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 11 deletions(-) (limited to 'app/models') diff --git a/app/models/monster_spawn.rb b/app/models/monster_spawn.rb index d34e390..4423557 100644 --- a/app/models/monster_spawn.rb +++ b/app/models/monster_spawn.rb @@ -3,7 +3,6 @@ class MonsterSpawn < ApplicationRecord belongs_to :location has_many :monster_spawn_combats - after_update :check_hp after_create :send_chat_message def alive? @@ -22,14 +21,4 @@ class MonsterSpawn < ApplicationRecord ChatRoomChannel.broadcast_chat_message(chat_message) end end - - def check_hp - if alive? - chat_message = ChatMessage.new(body: "The #{monster.name} in #{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 end diff --git a/app/models/monster_spawn_combat.rb b/app/models/monster_spawn_combat.rb index 50a565b..7ad06c8 100644 --- a/app/models/monster_spawn_combat.rb +++ b/app/models/monster_spawn_combat.rb @@ -3,4 +3,74 @@ class MonsterSpawnCombat < ApplicationRecord 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 -- cgit v1.2.3