From 53c9df5feb8ad4ebef8f40840d29255a81edb6df Mon Sep 17 00:00:00 2001 From: David Gay Date: Tue, 15 Jun 2021 19:13:55 -0400 Subject: Reboot omens and allow infixing items (like omens) into skills --- app/controllers/characters/hearth_controller.rb | 3 + .../characters/item_infixes_controller.rb | 27 ++++ app/errors/item_infix_error.rb | 2 + app/models/character.rb | 19 +++ app/models/item.rb | 7 + app/views/characters/items/index.html.erb | 4 + app/views/characters/skills/_infix_slot.html.erb | 3 + app/views/characters/skills/index.html.erb | 59 ++++++-- config/routes.rb | 1 + data/activities.yml | 166 +-------------------- data/conditions.yml | 1 + data/items.yml | 30 ++-- 12 files changed, 127 insertions(+), 195 deletions(-) create mode 100644 app/controllers/characters/item_infixes_controller.rb create mode 100644 app/errors/item_infix_error.rb create mode 100644 app/views/characters/skills/_infix_slot.html.erb 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 @@ +
+ <%= yield %> +
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 @@

Skills

<% @character.character_skills.ordered_by_skill_name.each do |cs| %> -
-
-
-
- <%= cs.skill.name %> +
+
+
+
+
+ <%= cs.skill.name %> +
+
+ XP<%= cs.xp %> +
-
- XP<%= cs.xp %> +
+ <%= cs.level %>
-
- <%= cs.level %> -
-
-
-
+
+
+
+ <% @character.item_infixes.where(skill: cs.skill).each do |ii| %> + <%= render "characters/skills/infix_slot" do %> +
+ <%= ii.item.name %> +
+
+ <%= button_to "Remove", character_item_infix_path(id: ii.id), method: :delete %> +
+ <% 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| %> +
+
+ <%= f.select :item_id, infixable_items.map { |i| [i.name, i.id]}, {}, class: "w-full" %> + <%= f.hidden_field :skill_id, value: cs.skill.id %> +
+
+ <%= f.submit "Infix" %> +
+
+ <% end %> + <% else %> +
No items to infix.
+ <% end %> + <% end %> + <% end %>
<% 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 -- cgit v1.2.3