summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gay <david@davidgay.org>2021-05-28 11:26:44 -0400
committerDavid Gay <david@davidgay.org>2021-05-28 11:26:54 -0400
commit5ae89950fb330fd623634b98a77de259ab174b53 (patch)
tree3ec11fae10758379761f5b824586b1c22bc57c12
parentc522bc8efa0378e0fcbcfdd137d6cd2ae4010d5b (diff)
Lockbox unlocking, and with it items that start activities when used
-rw-r--r--app/controllers/activities_controller.rb10
-rw-r--r--app/controllers/application_controller.rb13
-rw-r--r--app/controllers/characters/items_controller.rb2
-rw-r--r--app/controllers/game_controller.rb5
-rw-r--r--app/models/activity.rb28
-rw-r--r--app/models/character.rb15
-rw-r--r--app/models/concerns/has_costs_and_requirements.rb33
-rw-r--r--app/views/characters/items/index.html.erb4
-rw-r--r--data/activities.yml47
-rw-r--r--data/items.yml57
10 files changed, 173 insertions, 41 deletions
diff --git a/app/controllers/activities_controller.rb b/app/controllers/activities_controller.rb
index c115abb..8e18ec9 100644
--- a/app/controllers/activities_controller.rb
+++ b/app/controllers/activities_controller.rb
@@ -5,14 +5,6 @@ class ActivitiesController < ApplicationController
def start
@activity = Activity.find(params[:id])
- if current_char.start_activity(@activity, queued_actions: params[:queued_actions])
- redirect_to look_path
- else
- message = "You can't do that."
- message += " (requires #{@activity.requirements&.join(", ")})" if @activity.requirements.any?
- message += " (costs #{@activity.costs&.join(", ")})" if @activity.costs.any?
- flash[:alert] = message
- redirect_back(fallback_location: character_path(current_char))
- end
+ start_activity(@activity)
end
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 94859d1..0fc78a8 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -14,4 +14,17 @@ class ApplicationController < ActionController::Base
def roll(sides)
rand(sides) + 1
end
+
+ private
+ def start_activity(activity)
+ if current_char.start_activity(activity, queued_actions: params[:queued_actions])
+ redirect_to look_path
+ else
+ message = "You can't do that."
+ message += " (requires #{activity.requirements&.join(", ")})" if activity.requirements.any?
+ message += " (costs #{activity.costs&.join(", ")})" if activity.costs.any?
+ flash[:alert] = message
+ redirect_back(fallback_location: character_path(current_char))
+ end
+ end
end
diff --git a/app/controllers/characters/items_controller.rb b/app/controllers/characters/items_controller.rb
index e1dfd5c..93dc683 100644
--- a/app/controllers/characters/items_controller.rb
+++ b/app/controllers/characters/items_controller.rb
@@ -45,6 +45,8 @@ class Characters::ItemsController < ApplicationController
heal_or_gain = wounds_change.positive? ? "gain" : "heal"
flash[:notice] += " You #{heal_or_gain} #{wounds_change.abs} wound(s)."
end
+ when "activity"
+ start_activity(Activity.find_by_gid(effect[:gid])) and return
else
raise "Invalid use effect type string (#{effect[:type]})"
end
diff --git a/app/controllers/game_controller.rb b/app/controllers/game_controller.rb
index 8b92222..bf45973 100644
--- a/app/controllers/game_controller.rb
+++ b/app/controllers/game_controller.rb
@@ -24,6 +24,11 @@ class GameController < ApplicationController
activity.whatnot[:results].each do |result|
type = result[:type]
case type
+ when "xp"
+ skill = Skill.find_by_gid(result[:gid])
+ amount = result[:base]
+ current_char.add_skill_xp(skill, amount)
+ @results.push({ type: "xp", skill: skill, xp: amount })
when "monster"
raise TooManyWoundsError unless current_char.can_fight?
next if rand > (result[:chance] || 1)
diff --git a/app/models/activity.rb b/app/models/activity.rb
index c557752..4a169b4 100644
--- a/app/models/activity.rb
+++ b/app/models/activity.rb
@@ -1,34 +1,8 @@
class Activity < ApplicationRecord
- include HasWhatnot
+ include HasWhatnot, HasCostsAndRequirements
belongs_to :location, optional: true
validates :gid, :name, :description, presence: true
attribute :innate, :boolean, default: false
-
- def costs
- costs = []
- self.whatnot[:cost]&.each do |cost|
- case cost[:type]
- when "item"
- costs.push "#{cost[:quantity]} #{Item.find_by_gid(cost[:gid]).name}"
- end
- end
- costs
- end
-
- def requirements
- requirements = []
- self.whatnot[:requirements]&.each do |req|
- case req[:type]
- when "skill"
- requirements.push "level #{req[:level]} #{Skill.find_by_gid(req[:gid]).name}"
- when "hearth_amenity"
- requirements.push "level #{req[:level]} #{HearthAmenity.find_by_gid(req[:gid]).name}"
- else
- raise "Invalid requirement type string (#{req[:type]})"
- end
- end
- requirements
- end
end
diff --git a/app/models/character.rb b/app/models/character.rb
index 42f5f10..fda6868 100644
--- a/app/models/character.rb
+++ b/app/models/character.rb
@@ -60,7 +60,7 @@ class Character < ApplicationRecord
activity.whatnot[:cost]&.each do |cost|
case cost[:type]
when "item"
- self.shift_item(cost[:gid], -cost[:quantity])
+ self.shift_item(cost[:gid], -(cost[:quantity] || 1))
end
end
end
@@ -72,6 +72,11 @@ class Character < ApplicationRecord
ci && ci.quantity >= quantity
end
+ def equipment_with_gid(item)
+ item = Item.find_by_gid(item) if item.is_a? String
+ self.equipment.find_by(item: item)
+ end
+
def open_slots_for(item)
full_slots = self.equipment.map { |e| e.slot }
item.equip_slots.reject { |slot| full_slots.include?(slot) }
@@ -134,17 +139,23 @@ class Character < ApplicationRecord
activity.whatnot[:cost]&.each do |cost|
case cost[:type]
when "item"
- return false unless self.has_item?(cost[:gid], cost[:quantity])
+ return false unless self.has_item?(cost[:gid], cost[:quantity] || 1)
+ else
+ raise "Invalid cost type string (#{cost[:type]})"
end
end
end
unless ignore_requirements
activity.whatnot[:requirements]&.each do |requirement|
case requirement[:type]
+ when "equipment"
+ return false unless self.equipment_with_gid(requirement[:gid])
when "skill"
return false unless self.skill_level(requirement[:gid]) >= requirement[:level]
when "hearth_amenity"
return false unless self.hearth.has_amenity?(requirement[:gid], requirement[:level])
+ else
+ raise "Invalid requirement type string (#{requirement[:type]})"
end
end
end
diff --git a/app/models/concerns/has_costs_and_requirements.rb b/app/models/concerns/has_costs_and_requirements.rb
new file mode 100644
index 0000000..34ff0f3
--- /dev/null
+++ b/app/models/concerns/has_costs_and_requirements.rb
@@ -0,0 +1,33 @@
+module HasCostsAndRequirements
+ extend ActiveSupport::Concern
+
+ included do
+ def costs
+ costs = []
+ self.whatnot[:cost]&.each do |cost|
+ case cost[:type]
+ when "item"
+ costs.push "#{cost[:quantity]} #{Item.find_by_gid(cost[:gid]).name}"
+ end
+ end
+ costs
+ end
+
+ def requirements
+ requirements = []
+ self.whatnot[:requirements]&.each do |req|
+ case req[:type]
+ when "skill"
+ requirements.push "level #{req[:level]} #{Skill.find_by_gid(req[:gid]).name}"
+ when "equipment"
+ requirements.push "equipped #{Item.find_by_gid(req[:gid]).name}"
+ when "hearth_amenity"
+ requirements.push "level #{req[:level]} #{HearthAmenity.find_by_gid(req[:gid]).name}"
+ else
+ raise "Invalid requirement type string (#{req[:type]})"
+ end
+ end
+ requirements
+ end
+ end
+end
diff --git a/app/views/characters/items/index.html.erb b/app/views/characters/items/index.html.erb
index 14d4b13..f40e666 100644
--- a/app/views/characters/items/index.html.erb
+++ b/app/views/characters/items/index.html.erb
@@ -13,7 +13,7 @@
<tbody>
<% @character.equipment.order(:slot).each do |eq| %>
<tr>
- <td class="table-cell-padded"><%= eq.slot.to_s %></td>
+ <td class="table-cell-padded"><%= eq.slot.to_s.humanize %></td>
<td class="table-cell-padded"><%= eq.item.name %></td>
<td class="table-cell-padded">
<%= button_to "Unequip", character_item_unequip_path(slot: eq.slot ) %>
@@ -23,8 +23,6 @@
</tbody>
</table>
-
-
<h2 class="text-xl mb-4">Inventory</h2>
<table class="table-auto mb-8">
diff --git a/data/activities.yml b/data/activities.yml
index 59689e8..df93c62 100644
--- a/data/activities.yml
+++ b/data/activities.yml
@@ -525,3 +525,50 @@ manatrawl_sor_well_depths:
xp:
- gid: "manatrawl"
value: 50
+synthsever_rusted_lockbox:
+ name: "Unlock Rusted Lockbox"
+ description: "Unseal the lock on a rusted lockbox."
+ innate: true
+ whatnot:
+ duration:
+ base: 180
+ minimum: 35
+ scaling:
+ - type: "skill"
+ gid: "synthsever"
+ scale_value: 1
+ requirements:
+ - type: "equipment"
+ gid: "iron_lockpicks"
+ cost:
+ - type: "item"
+ gid: "rusted_lockbox"
+ results:
+ - type: "item"
+ chance: 1
+ table:
+ - gid: "vestige"
+ score: 0
+ min_quantity: 20
+ max_quantity: 100
+ - gid: "red_beryl"
+ score: 0.30
+ - gid: "tourmaline"
+ score: 0.45
+ - gid: "yellow_beryl"
+ score: 0.60
+ titles:
+ - gid: "beryly"
+ - gid: "paraiba_tourmaline"
+ score: 0.70
+ - gid: "slate_ring"
+ score: 0.80
+ - gid: "iron_ring"
+ score: 0.85
+ - gid: "quartz_ring"
+ score: 0.90
+ - gid: "granite_ring"
+ score: 0.95
+ - type: "xp"
+ gid: "synthsever"
+ base: 25
diff --git a/data/items.yml b/data/items.yml
index c153b57..1e48293 100644
--- a/data/items.yml
+++ b/data/items.yml
@@ -138,6 +138,10 @@ waning_light:
rusted_lockbox:
name: "rusted lockbox"
description: "A small, rusty, metal box with a lock on it."
+ whatnot:
+ use_effects:
+ - type: "activity"
+ gid: "synthsever_rusted_lockbox"
warm_diadem:
name: "warm diadem"
description: "A thin, blood-colored circlet giving off a faint warmth."
@@ -163,3 +167,56 @@ grinpad_trophy:
lesser_trodgeathomp_trophy:
name: "lesser trodgeathomp trophy"
description: "A trophy from a lesser trodgeathomp."
+slate_ring:
+ name: "slate ring"
+ description: "A brittle ring made of slate. It's flat, inside and out."
+ whatnot:
+ equip_slots:
+ - "left_ring"
+ - "right_ring"
+ equip_effects:
+ - type: "stat_change"
+ gid: "accuracy"
+ modifier: 1
+iron_ring:
+ name: "iron ring"
+ description: "A strong, iron ring."
+ whatnot:
+ equip_slots:
+ - "left_ring"
+ - "right_ring"
+ equip_effects:
+ - type: "stat_change"
+ gid: "power"
+ modifier: 1
+quartz_ring:
+ name: "quartz ring"
+ description: "A small ring, strangely made entirely of quartz."
+ whatnot:
+ equip_slots:
+ - "left_ring"
+ - "right_ring"
+ equip_effects:
+ - type: "stat_change"
+ gid: "evasion"
+ modifier: 1
+granite_ring:
+ name: "granite ring"
+ description: "A heavy ring made of granite."
+ whatnot:
+ equip_slots:
+ - "left_ring"
+ - "right_ring"
+ equip_effects:
+ - type: "stat_change"
+ gid: "block"
+ modifier: 1
+enzon_seed:
+ name: "enzon seed"
+ description: "The seed of an enzon plant."
+iron_lockpicks:
+ name: "iron lockpicks"
+ description: "Tools for getting into places other people -- or things -- don't want you to be."
+ whatnot:
+ equip_slots:
+ - "mainhand"