diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/characters/spells_controller.rb | 4 | ||||
-rw-r--r-- | app/errors/too_many_monster_spawn_combats_error.rb | 2 | ||||
-rw-r--r-- | app/lib/activity_processor.rb | 26 | ||||
-rw-r--r-- | app/models/character.rb | 6 | ||||
-rw-r--r-- | app/models/hearth.rb | 1 | ||||
-rw-r--r-- | app/models/location.rb | 1 | ||||
-rw-r--r-- | app/models/monster_spawn.rb | 8 | ||||
-rw-r--r-- | app/views/application/_results.html.erb | 8 | ||||
-rw-r--r-- | app/views/look/look.html.erb | 4 |
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" %> |