summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/controllers/characters/spells_controller.rb4
-rw-r--r--app/errors/too_many_monster_spawn_combats_error.rb2
-rw-r--r--app/lib/activity_processor.rb26
-rw-r--r--app/models/character.rb6
-rw-r--r--app/models/hearth.rb1
-rw-r--r--app/models/location.rb1
-rw-r--r--app/models/monster_spawn.rb8
-rw-r--r--app/views/application/_results.html.erb8
-rw-r--r--app/views/look/look.html.erb4
9 files changed, 54 insertions, 6 deletions
diff --git a/app/controllers/characters/spells_controller.rb b/app/controllers/characters/spells_controller.rb
index a0e6913..b98c1c3 100644
--- a/app/controllers/characters/spells_controller.rb
+++ b/app/controllers/characters/spells_controller.rb
@@ -1,6 +1,8 @@
class Characters::SpellsController < ApplicationController
def index
- @spell_activities = Activity.where("gid like ?", "havencast_%").where(innate: true).order(:name)
+ @spell_activities = Activity.where("gid like ?", "havencast_%")
+ .or(Activity.where("gid like ?", "worldcall_%"))
+ .where(innate: true).order(:name)
# TODO: Don't load into memory
@spell_activities = @spell_activities.to_a + current_char.learned_activities
.map { |la| la.activity }
diff --git a/app/errors/too_many_monster_spawn_combats_error.rb b/app/errors/too_many_monster_spawn_combats_error.rb
new file mode 100644
index 0000000..51153c8
--- /dev/null
+++ b/app/errors/too_many_monster_spawn_combats_error.rb
@@ -0,0 +1,2 @@
+class TooManyMonsterSpawnCombatsError < StandardError
+end
diff --git a/app/lib/activity_processor.rb b/app/lib/activity_processor.rb
index 72aa85d..d14282e 100644
--- a/app/lib/activity_processor.rb
+++ b/app/lib/activity_processor.rb
@@ -40,14 +40,17 @@ class ActivityProcessor
puts "Result: #{result}"
handle_xp_result(result)
when "monster_spawn"
+ monster_spawn = MonsterSpawn.where(location: Location.find_by_gid(result[:location])).select(&:alive?).first
+ raise MonsterSpawnError unless monster_spawn
+
raise TooManyWoundsError unless @character.can_fight?
+ unless @character.monster_spawns_attacked_in_past_24_hours.count < 2 || @character.monster_spawns_attacked_in_past_24_hours.include?(monster_spawn)
+ raise TooManyMonsterSpawnCombatsError
+ end
next if rand > (result[:chance] || 1)
@results.push({ type: "br" })
- monster_spawn = MonsterSpawn.where(location: Location.find_by_gid(result[:location])).select(&:alive?).first
- raise MonsterSpawnError unless monster_spawn
-
@results.push({ type: type, monster_spawn: monster_spawn })
resolve_combat_with(monster_spawn)
break
@@ -111,6 +114,19 @@ class ActivityProcessor
end
end
end
+ when "hearth_location"
+ location = @character.hearth&.location || Location.find_by_gid("floret")
+ @character.update(location: location)
+ @results.push({ type: type, location: location })
+ when "create_monster_spawn"
+ next if rand > (result[:chance] || 1)
+ monster = Monster.find_by_gid(result[:gid])
+ monster_spawn = MonsterSpawn.new(monster: monster, location: @character.location)
+ if monster_spawn.save
+ @results.push({ type: type, monster: monster })
+ else
+ @results.push({ type: "message", body: "A leviathan did not appear since there is already a leviathan at #{@character.location.name}." })
+ end
else
raise "Invalid result type (#{type})" # TODO: Improve this.
end
@@ -173,6 +189,10 @@ class ActivityProcessor
@character.stop_activity
@results.replace([{ type: "error",
message: "There are no living leviathans here." }])
+ rescue TooManyMonsterSpawnCombatsError
+ @character.stop_activity
+ @results.replace([{ type: "error",
+ message: "You're too worn out to hunt any more leviathans right now. You can only hunt two different leviathans in a 24 hour period." }])
end
private
diff --git a/app/models/character.rb b/app/models/character.rb
index f6ddb92..b3d8c25 100644
--- a/app/models/character.rb
+++ b/app/models/character.rb
@@ -16,6 +16,7 @@ class Character < ApplicationRecord
has_many :states
has_many :chat_messages
has_many :monster_kills
+ has_many :monster_spawn_combats
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.
@@ -459,6 +460,11 @@ class Character < ApplicationRecord
base
end
+ def monster_spawns_attacked_in_past_24_hours
+ # TODO: Don't load into memory
+ monster_spawn_combats.where(created_at: 24.hours.ago..).map { |msc| msc.monster_spawn }.uniq
+ end
+
private
def create_skills
Skill.all.each { |skill| self.character_skills.create(skill: skill, xp: 0) }
diff --git a/app/models/hearth.rb b/app/models/hearth.rb
index ee00c0c..cbd98dc 100644
--- a/app/models/hearth.rb
+++ b/app/models/hearth.rb
@@ -1,5 +1,6 @@
class Hearth < ApplicationRecord
belongs_to :character
+ belongs_to :location
has_many :built_hearth_amenities
has_many :hearth_amenities, through: :built_hearth_amenities
has_many :hearth_plantings
diff --git a/app/models/location.rb b/app/models/location.rb
index 7bd1386..e0aaf9b 100644
--- a/app/models/location.rb
+++ b/app/models/location.rb
@@ -3,6 +3,7 @@ class Location < ApplicationRecord
has_many :activities
has_many :characters
+ has_many :hearths
has_many :monster_spawns
validates :gid, :name, presence: true
end
diff --git a/app/models/monster_spawn.rb b/app/models/monster_spawn.rb
index 5162cc6..42db98a 100644
--- a/app/models/monster_spawn.rb
+++ b/app/models/monster_spawn.rb
@@ -7,6 +7,7 @@ class MonsterSpawn < ApplicationRecord
after_create :send_chat_message
validates :starting_hp, presence: true, numericality: { greater_than_or_equal_to: 1, only_integer: true }
+ validate :one_living_leviathan_per_location, on: :create
def alive?
self.remaining_hp > 0
@@ -28,4 +29,11 @@ class MonsterSpawn < ApplicationRecord
ChatRoomChannel.broadcast_chat_message(chat_message)
end
end
+
+ def one_living_leviathan_per_location
+ # TODO: Don't load into memory
+ if location.monster_spawns.find { |ms| ms.alive? && ms != self }
+ errors.add(:chat, "A location can only have one monster spawn at a time.")
+ end
+ end
end
diff --git a/app/views/application/_results.html.erb b/app/views/application/_results.html.erb
index a7dc002..71d6992 100644
--- a/app/views/application/_results.html.erb
+++ b/app/views/application/_results.html.erb
@@ -12,6 +12,12 @@
<% when "hearth_planting" %>
<p>You planted <%= link_to result[:hearth_planting].item.name,
item_path(result[:hearth_planting].item) %> in the loam.</p>
+ <% when "hearth_location" %>
+ <% if current_char.hearth&.location %>
+ <p>You appear in <%= result[:location].name %>.</p>
+ <% else %>
+ <p>Lacking a hearth to return to, you appear in an empty patch of land in <%= result[:location].name %>.</p>
+ <% end %>
<% when "activity" %>
<p>You learned how to <%= result[:activity].name %>!</p>
<% when "monster" %>
@@ -20,6 +26,8 @@
<% when "monster_spawn" %>
<p>You found the <%= result[:monster_spawn].monster.name %>!</p>
<p class="text-xs italic"><%= result[:monster_spawn].monster.description %></p>
+ <% when "create_monster_spawn" %>
+ <p>You've called a <%= result[:monster].name %>!</p>
<% when "xp" %>
<p class="text-xs">You gained <%= result[:xp] %> <%= result[:skill].name %> XP.</p>
<% when "title" %>
diff --git a/app/views/look/look.html.erb b/app/views/look/look.html.erb
index 2f1074a..ef0f6c4 100644
--- a/app/views/look/look.html.erb
+++ b/app/views/look/look.html.erb
@@ -3,10 +3,10 @@
<p class="italic"><%= @location.description %></p>
</div>
+<%# TODO: Don't load into memory %>
<% @location.monster_spawns.select(&:alive?).each do |ms| %>
<p class="text-yellow-400">A <%= ms.monster.name %> is ravaging this location! (<%= ms.remaining_hp %> HP)</p>
- <%# TODO: HACK %>
- <% activity = Activity.find_by_gid("beastslay_leviathan_floret") %>
+ <% activity = Activity.find_by_gid("beastslay_leviathan_#{@location.gid}") %>
<%= form_with url: start_activity_path(activity) do |f| %>
<%= f.hidden_field :id, value: activity.id %>
<%= f.submit "Hunt" %>