1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
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)
involved_character_ids = MonsterSpawnCombat.where(monster_spawn: monster_spawn).pluck(:character_id).uniq
involved_characters = Character.where(id: involved_character_ids)
monster.whatnot[:awards]&.each do |data|
case data[:type]
when "xp"
involved_characters.each do |character|
total_xp = data[:base] * MonsterSpawnCombat.where(monster_spawn: monster_spawn, character: character).count
character.add_skill_xp(data[:gid], total_xp)
message_body_parts[character.id] ||= []
message_body_parts[character.id].push("You got #{total_xp} #{Skill.find_by_gid(data[:gid]).name} XP")
end
when "item"
next 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
item = Item.find_by_gid(data[:gid])
character_quantities = {}
quantity.times do
id = involved_characters.sample.id
character_quantities[id] ||= 0
character_quantities[id] += 1
end
character_quantities.each do |character_id, character_quantity|
Character.find(character_id).shift_item(item, character_quantity)
message_body_parts[character_id] ||= []
message_body_parts[character_id].push("You got #{character_quantity} #{item.name}")
end
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)
item = Item.find_by_gid(data[:gid])
character_quantities = {}
quantity.times do
id = involved_characters.sample.id
character_quantities[id] ||= 0
character_quantities[id] += 1
end
character_quantities.each do |character_id, character_quantity|
Character.find(character_id).shift_item(item, character_quantity)
message_body_parts[character_id] ||= []
message_body_parts[character_id].push("You got #{character_quantity} #{item.name}")
end
end
else
raise "Invalid monster spawn reward gid string"
end
end
# TODO: HACK for title for now
character_damage = {}
involved_characters.each do |character|
character_damage[character] = MonsterSpawnCombat.where(monster_spawn: monster_spawn, character: character).sum(:hp_lost)
end
title_recipient = character_damage.max_by { |_, v| v }[0]
if title_recipient.award_title("sentinel")
message_body_parts[title_recipient.id].push("You earned the Sentinel title!")
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
|