summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/characters/hearth_controller.rb3
-rw-r--r--app/controllers/characters/item_infixes_controller.rb27
-rw-r--r--app/errors/item_infix_error.rb2
-rw-r--r--app/models/character.rb19
-rw-r--r--app/models/item.rb7
-rw-r--r--app/views/characters/items/index.html.erb4
-rw-r--r--app/views/characters/skills/_infix_slot.html.erb3
-rw-r--r--app/views/characters/skills/index.html.erb59
-rw-r--r--config/routes.rb1
-rw-r--r--data/activities.yml166
-rw-r--r--data/conditions.yml1
-rw-r--r--data/items.yml30
12 files changed, 127 insertions, 195 deletions
diff --git a/app/controllers/characters/hearth_controller.rb b/app/controllers/characters/hearth_controller.rb
index 82f72d6..c525add 100644
--- a/app/controllers/characters/hearth_controller.rb
+++ b/app/controllers/characters/hearth_controller.rb
@@ -7,6 +7,7 @@ class Characters::HearthController < ApplicationController
forge: [],
laboratory: [],
spicebench: [],
+ binding_array: [],
}
Activity.where("gid like ?", "craft_%").each do |activity|
@@ -20,6 +21,8 @@ class Characters::HearthController < ApplicationController
@amenity_activities[:laboratory].push(activity) && next
when "spicebench"
@amenity_activities[:spicebench].push(activity) && next
+ when "binding_array"
+ @amenity_activities[:binding_array].push(activity) && next
else
raise "Invalid amenity gid (#{requirement_data[:gid]}"
end
diff --git a/app/controllers/characters/item_infixes_controller.rb b/app/controllers/characters/item_infixes_controller.rb
new file mode 100644
index 0000000..0b5f1c5
--- /dev/null
+++ b/app/controllers/characters/item_infixes_controller.rb
@@ -0,0 +1,27 @@
+class Characters::ItemInfixesController < ApplicationController
+ def create
+ # TODO: Can this find-by-id happen automagically?
+ @item_infix = current_char.infix(Item.find(params[:item_id]), Skill.find(params[:skill_id]))
+ if @item_infix
+ flash[:notice] = "Infixed #{@item_infix.item.name}."
+ else
+ flash[:alert] = "Failed to infix item."
+ end
+ redirect_to character_skills_path(current_char)
+ end
+
+ def destroy
+ @item_infix = ItemInfix.find(params[:id])
+ if current_char.remove_infix(@item_infix)
+ flash[:notice] = "Removed #{@item_infix.item.name}."
+ else
+ flash[:alert] = "Failed to remove #{@item_infix.item.name}."
+ end
+ redirect_to character_skills_path(current_char)
+ end
+
+ private
+ def item_infix_params
+ params.require(:item_infix).permit(:item_id, :skill_id)
+ end
+end
diff --git a/app/errors/item_infix_error.rb b/app/errors/item_infix_error.rb
new file mode 100644
index 0000000..bc6b251
--- /dev/null
+++ b/app/errors/item_infix_error.rb
@@ -0,0 +1,2 @@
+class ItemInfixError < StandardError
+end
diff --git a/app/models/character.rb b/app/models/character.rb
index 03bd510..4ee1f71 100644
--- a/app/models/character.rb
+++ b/app/models/character.rb
@@ -188,6 +188,25 @@ class Character < ApplicationRecord
1 + (skill_level(skill) / 20).floor
end
+ def available_infixes(skill)
+ skill = Skill.find_by_gid(skill) if skill.is_a? String
+ max_infixes(skill) - item_infixes.where(skill: skill).count
+ end
+
+ def infix(item, skill)
+ Character.transaction do
+ shift_item(item, -1)
+ item_infixes.create(item: item, skill: skill)
+ end
+ end
+
+ def remove_infix(item_infix)
+ Character.transaction do
+ shift_item(item_infix.item, 1)
+ item_infix.destroy
+ end
+ end
+
def add_skill_xp(skill, amount)
skill = Skill.find_by_gid(skill) if skill.is_a? String
Character.transaction do
diff --git a/app/models/item.rb b/app/models/item.rb
index 8b80788..0e25b2f 100644
--- a/app/models/item.rb
+++ b/app/models/item.rb
@@ -13,6 +13,13 @@ class Item < ApplicationRecord
self.whatnot && self.whatnot[:use_effects]&.any?
end
+ def infixable?(skill = nil)
+ skill = Skill.find_by_gid(skill) if skill.is_a? String
+ return false unless self.whatnot && self.whatnot[:infix_skills]&.any?
+ return true unless skill
+ self.whatnot[:infix_skills].select { |data| data[:gid] == skill.gid }.any?
+ end
+
def equip_slots
return [] unless self.equipment?
self.whatnot[:equip_slots].map { |data| data.to_sym }
diff --git a/app/views/characters/items/index.html.erb b/app/views/characters/items/index.html.erb
index 671e68f..57e8531 100644
--- a/app/views/characters/items/index.html.erb
+++ b/app/views/characters/items/index.html.erb
@@ -35,6 +35,10 @@
character_items: @character.character_items.ordered_by_item_name.select { |ci|
ci.item.has_tag?("currency") } %>
+<%= render "characters/items/inventory_section", heading: "Omens",
+ character_items: @character.character_items.ordered_by_item_name.select { |ci|
+ ci.item.has_tag?("omen") } %>
+
<%= render "characters/items/inventory_section", heading: "Seeds",
character_items: @character.character_items.ordered_by_item_name.select { |ci|
ci.item.has_tag?("seed") } %>
diff --git a/app/views/characters/skills/_infix_slot.html.erb b/app/views/characters/skills/_infix_slot.html.erb
new file mode 100644
index 0000000..0113596
--- /dev/null
+++ b/app/views/characters/skills/_infix_slot.html.erb
@@ -0,0 +1,3 @@
+<div class="flex justify-between items-center border-t border-gray-700 p-2">
+ <%= yield %>
+</div>
diff --git a/app/views/characters/skills/index.html.erb b/app/views/characters/skills/index.html.erb
index fd53870..f79b06e 100644
--- a/app/views/characters/skills/index.html.erb
+++ b/app/views/characters/skills/index.html.erb
@@ -1,23 +1,56 @@
<h2 class="text-3xl mb-2">Skills</h2>
<div class="grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
<% @character.character_skills.ordered_by_skill_name.each do |cs| %>
- <div class="rounded border border-gray-700">
- <div class="flex p-1">
- <div class="flex-grow">
- <div class="text-xl text-display mb-1">
- <%= cs.skill.name %>
+ <div>
+ <div class="rounded border border-gray-700">
+ <div class="flex p-1">
+ <div class="flex-grow">
+ <div class="text-xl text-display mb-1">
+ <%= cs.skill.name %>
+ </div>
+ <div class="flex items-center text-xs">
+ <span class="bg-gray-700 px-1 py-0.5 rounded mr-1">XP</span><%= cs.xp %>
+ </div>
</div>
- <div class="flex items-center text-xs">
- <span class="bg-gray-700 px-1 py-0.5 rounded mr-1">XP</span><%= cs.xp %>
+ <div class="text-xl m-2 text-display">
+ <%= cs.level %>
</div>
</div>
- <div class="text-xl m-2 text-display">
- <%= cs.level %>
- </div>
- </div>
- <div class="border border-gray-800 h-2 my-1">
- <div class="bg-gray-600 h-full" style="width: <%= cs.percentage_of_skill_level_completed %>%">
+ <div class="border border-gray-700 h-2 mt-1 -mb-px -mx-px">
+ <div class="bg-gray-600 h-full" style="width: <%= cs.percentage_of_skill_level_completed %>%">
+ </div>
</div>
+ <% @character.item_infixes.where(skill: cs.skill).each do |ii| %>
+ <%= render "characters/skills/infix_slot" do %>
+ <div>
+ <%= ii.item.name %>
+ </div>
+ <div>
+ <%= button_to "Remove", character_item_infix_path(id: ii.id), method: :delete %>
+ </div>
+ <% end %>
+ <% end %>
+ <% @character.available_infixes(cs.skill).times do %>
+ <%= render "characters/skills/infix_slot" do %>
+ <%# TODO: Don't load all into memory %>
+ <% infixable_items = @character.items.select {|i| i.infixable?(cs.skill)} %>
+ <% if infixable_items.any? %>
+ <%= form_with url: character_item_infixes_path, class: "w-full" do |f| %>
+ <div class="flex space-x-1">
+ <div class="flex-grow">
+ <%= f.select :item_id, infixable_items.map { |i| [i.name, i.id]}, {}, class: "w-full" %>
+ <%= f.hidden_field :skill_id, value: cs.skill.id %>
+ </div>
+ <div>
+ <%= f.submit "Infix" %>
+ </div>
+ </div>
+ <% end %>
+ <% else %>
+ <div class="text-gray-500">No items to infix.</div>
+ <% end %>
+ <% end %>
+ <% end %>
</div>
</div>
<% end %>
diff --git a/config/routes.rb b/config/routes.rb
index 22b8299..51d9e6c 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -28,6 +28,7 @@ Rails.application.routes.draw do
scope module: :characters do
get "/rankings", to: "rankings#index"
post "/items/unequip/:slot", to: "items#unequip", as: :item_unequip
+ resources :item_infixes, only: [:create, :destroy]
resources :items, only: [:index] do
post "/equip", to: "items#equip"
post "/use", to: "items#use"
diff --git a/data/activities.yml b/data/activities.yml
index 525905a..a508781 100644
--- a/data/activities.yml
+++ b/data/activities.yml
@@ -305,7 +305,7 @@ construct_binding_array_level2:
gid: "tourmaline"
quantity: 2
- type: "item"
- gid: "paraiba tourmaline"
+ gid: "paraiba_tourmaline"
quantity: 1
- type: "item"
gid: "yellow_beryl"
@@ -2710,9 +2710,9 @@ beastslay_leviathan_floret_region:
- type: "monster_spawn"
location: "floret_region"
chance: 1
-craft_faint_hope:
- name: "Bind faint hope"
- description: "Bind an omen of faint hope."
+craft_faint_mana:
+ name: "Bind faint mana"
+ description: "Bind an omen of faint mana."
whatnot:
requirements:
- type: "hearth_amenity"
@@ -2737,163 +2737,7 @@ craft_faint_hope:
quantity: 10
results:
- type: "item"
- gid: "faint_hope"
+ gid: "faint_mana"
xp:
- gid: "omenbind"
value: 6
-craft_fleeting_glimpse:
- name: "Bind fleeting glimpse"
- description: "Bind a fleeting glimpse omen."
- whatnot:
- requirements:
- - type: "hearth_amenity"
- gid: "binding_array"
- level: 1
- - type: "skill"
- gid: "omenbind"
- level: 3
- duration:
- base: 65
- minimum: 35
- scaling:
- - type: "skill"
- gid: "omenbind"
- scale_value: 1
- - type: "stat"
- gid: "omenbind_speed"
- scale_value: 1
- cost:
- - type: "item"
- gid: "vestige"
- quantity: 8
- - type: "item"
- gid: "shimmering_essence"
- quantity: 1
- results:
- - type: "item"
- gid: "fleeting_glimpse"
- xp:
- - gid: "omenbind"
- value: 12
-craft_bright_token:
- name: "Bind bright token"
- description: "Bind a bright token omen."
- whatnot:
- requirements:
- - type: "hearth_amenity"
- gid: "binding_array"
- level: 1
- - type: "skill"
- gid: "omenbind"
- level: 6
- duration:
- base: 70
- minimum: 35
- scaling:
- - type: "skill"
- gid: "omenbind"
- scale_value: 1
- - type: "stat"
- gid: "omenbind_speed"
- scale_value: 1
- cost:
- - type: "item"
- gid: "vestige"
- quantity: 12
- - type: "item"
- gid: "gem_dust"
- quantity: 1
- results:
- - type: "item"
- gid: "bright_token"
- xp:
- - gid: "omenbind"
- value: 16
-craft_sign_of_solace:
- name: "Bind sign of solace"
- description: "Bind a sign of solace."
- whatnot:
- requirements:
- - type: "hearth_amenity"
- gid: "binding_array"
- level: 2
- - type: "skill"
- gid: "omenbind"
- level: 10
- duration:
- base: 80
- minimum: 35
- scaling:
- - type: "skill"
- gid: "omenbind"
- scale_value: 1
- - type: "stat"
- gid: "omenbind_speed"
- scale_value: 1
- cost:
- - type: "item"
- gid: "vestige"
- quantity: 25
- - type: "item"
- gid: "claritas_flower"
- quantity: 1
- results:
- - type: "item"
- gid: "sign_of_solace"
- xp:
- - gid: "omenbind"
- value: 22
-havencast_light:
- name: "Cast Light"
- description: "Cast the Light cantrip."
- whatnot:
- tags:
- - "cantrip"
- duration:
- base: 30
- minimum: 10
- scaling:
- - type: "skill"
- gid: "havencast"
- scale_value: 1
- requirements:
- - type: "skill"
- gid: "havencast"
- level: 1
- cost:
- - type: "mana"
- gid: "clear"
- quantity: 1
- results:
- - type: "condition"
- gid: "light"
- - type: "xp"
- gid: "havencast"
- base: 3
-havencast_dazzle:
- name: "Cast Dazzle"
- description: "Cast the Dazzle cantrip."
- whatnot:
- tags:
- - "cantrip"
- duration:
- base: 32
- minimum: 10
- scaling:
- - type: "skill"
- gid: "havencast"
- scale_value: 1
- requirements:
- - type: "skill"
- gid: "havencast"
- level: 2
- cost:
- - type: "mana"
- gid: "clear"
- quantity: 2
- results:
- - type: "condition"
- gid: "dazzle"
- - type: "xp"
- gid: "havencast"
- base: 6
diff --git a/data/conditions.yml b/data/conditions.yml
index 11dcede..3badf5b 100644
--- a/data/conditions.yml
+++ b/data/conditions.yml
@@ -106,6 +106,7 @@ light:
dazzle:
name: "dazzle"
description: "Reduces enemies' accuracy."
+ whatnot:
effects:
- type: "enemy_stat_change"
gid: "accuracy"
diff --git a/data/items.yml b/data/items.yml
index 1f0be2c..224aac6 100644
--- a/data/items.yml
+++ b/data/items.yml
@@ -1094,27 +1094,15 @@ balgoloth_claw:
gid: "pierce"
min: 1
max: 6
-faint_hope:
- name: "faint hope"
- description: "A weak omen made from compressed arcane energy."
- whatnot:
- tags:
- - "omen"
-fleeting_glimpse:
- name: "fleeting glimpse"
- description: "A weak omen that shows vague images in its ethereal surface."
- whatnot:
- tags:
- - "omen"
-bright_token:
- name: "bright token"
- description: "An omen with promising magical potential."
- whatnot:
- tags:
- - "omen"
-sign_of_solace:
- name: "sign of solace"
- description: "A sign that shines radiantly from a pinpoint at its center."
+faint_mana:
+ name: "faint mana"
+ description: "A weak omen that provides a very small amount of magical energy."
whatnot:
tags:
- "omen"
+ infix_skills:
+ - gid: "havencast"
+ infix_effects:
+ - type: "stat_change"
+ gid: "mana"
+ modifier: 1