diff options
-rw-r--r-- | app/controllers/characters/items_controller.rb | 21 | ||||
-rw-r--r-- | app/errors/equipment_error.rb | 2 | ||||
-rw-r--r-- | app/models/character.rb | 25 | ||||
-rw-r--r-- | app/models/equipment.rb | 11 | ||||
-rw-r--r-- | app/models/item.rb | 9 | ||||
-rw-r--r-- | app/views/characters/items/index.html.erb | 42 | ||||
-rw-r--r-- | config/routes.rb | 5 | ||||
-rw-r--r-- | data/items.yml | 6 | ||||
-rw-r--r-- | data/skills.yml | 2 | ||||
-rw-r--r-- | db/migrate/20210522184444_create_equipment.rb | 13 | ||||
-rw-r--r-- | db/schema.rb | 15 | ||||
-rw-r--r-- | test/fixtures/equipment.yml | 11 | ||||
-rw-r--r-- | test/models/equipment_test.rb | 7 |
13 files changed, 152 insertions, 17 deletions
diff --git a/app/controllers/characters/items_controller.rb b/app/controllers/characters/items_controller.rb index e1a30f8..8df23c8 100644 --- a/app/controllers/characters/items_controller.rb +++ b/app/controllers/characters/items_controller.rb @@ -1,5 +1,24 @@ class Characters::ItemsController < ApplicationController def index - @character_items = Character.find(params[:character_id]).character_items + @character = Character.find(params[:character_id]) + end + + def equip + @item = Item.find(params[:item_id]) + current_char.equip(@item) + flash[:notice] = "Equipped #{@item.name}." + rescue EquipmentError + flash[:alert] = "Couldn't equip #{@item.name}." + ensure + redirect_to character_items_path(current_char) + end + + def unequip + current_char.unequip(params[:slot].to_sym) + flash[:notice] = "Unequipped item." + rescue EquipmentError + flash[:alert] = "Couldn't unequip item." + ensure + redirect_to character_items_path(current_char) end end diff --git a/app/errors/equipment_error.rb b/app/errors/equipment_error.rb new file mode 100644 index 0000000..0d24e8a --- /dev/null +++ b/app/errors/equipment_error.rb @@ -0,0 +1,2 @@ +class EquipmentError < StandardError +end diff --git a/app/models/character.rb b/app/models/character.rb index 73d2c4b..59ed5ae 100644 --- a/app/models/character.rb +++ b/app/models/character.rb @@ -5,6 +5,7 @@ class Character < ApplicationRecord has_many :titles, through: :title_awards belongs_to :active_title, class_name: "Title", optional: true has_one :hearth + has_many :equipment has_many :character_items has_many :learned_activities has_many :items, through: :character_items @@ -44,6 +45,30 @@ class Character < ApplicationRecord ci && ci.quantity >= quantity end + def open_slots_for(item) + full_slots = self.equipment.map { |e| e.slot } + item.equip_slots.reject { |slot| full_slots.include?(slot) } + end + + def equip(item) + Character.transaction do + open_slots = self.open_slots_for(item) + raise EquipmentError unless open_slots.any? + self.shift_item(item, -1) + self.equipment.create(item: item, slot: open_slots.first) + end + end + + def unequip(slot) + Character.transaction do + equipment = self.equipment.find_by(slot: slot) + raise EquipmentError unless equipment + item = equipment.item + equipment.destroy + self.shift_item(item, 1) + end + end + def add_skill_xp(skill, amount) CharacterSkill.find_by(skill: skill).increment!(:xp, amount) end diff --git a/app/models/equipment.rb b/app/models/equipment.rb new file mode 100644 index 0000000..11030fd --- /dev/null +++ b/app/models/equipment.rb @@ -0,0 +1,11 @@ +class Equipment < ApplicationRecord + belongs_to :character + belongs_to :item + enum slot: [:mainhand, :offhand, :head, :neck, :back, :torso, :grip, + :left_ring, :right_ring, :waist, :legs, :feet, :curio] + validates :slot, presence: true, uniqueness: { scope: :character } + + def slot + self[:slot].to_sym + end +end diff --git a/app/models/item.rb b/app/models/item.rb index d42460b..5e60f04 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -5,4 +5,13 @@ class Item < ApplicationRecord :left_ring, :right_ring, :waist, :legs, :feet, :curio] validates :gid, :name, :description, presence: true validates :usable, inclusion: { in: [true, false] } + + def equipment? + self.whatnot && self.whatnot[:equip_slots]&.any? + end + + def equip_slots + return [] unless self.equipment? + self.whatnot[:equip_slots].map { |data| data.to_sym } + end end diff --git a/app/views/characters/items/index.html.erb b/app/views/characters/items/index.html.erb index e313f7e..a7c932d 100644 --- a/app/views/characters/items/index.html.erb +++ b/app/views/characters/items/index.html.erb @@ -1,23 +1,49 @@ -<h1 class="text-xl">Inventory</h1> +<h1 class="text-3xl mb-4">Inventory</h1> -<table class="table-auto"> +<h2 class="text-xl mb-4">Equipment</h2> + +<table class="table-auto mb-8"> + <thead> + <tr> + <th class="table-header-padded">Slot</th> + <th class="table-header-padded">Item</th> + <th class="table-header-padded">Unequip</th> + </tr> + </thead> + <tbody> + <% @character.equipment.each do |eq| %> + <tr> + <td class="table-cell-padded"><%= eq.slot.to_s %></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 ) %> + </td> + </tr> + <% end %> + </tbody> +</table> + + + +<h2 class="text-xl mb-4">Inventory</h2> + +<table class="table-auto mb-8"> <thead> <tr> <th class="table-header-padded">Amount</th> <th class="table-header-padded">Item</th> <th class="table-header-padded">Equip</th> <th class="table-header-padded">Use</th> - <th class="table-header-padded">Destroy</th> </tr> </thead> <tbody> - <% @character_items.ordered_by_item_name.each do |ci| %> + <% @character.character_items.ordered_by_item_name.each do |ci| %> <tr> <td class="table-cell-padded text-right"><%= ci.quantity %></td> <td class="table-cell-padded"><%= ci.item.name %></td> <td class="table-cell-padded"> - <% if ci.item.equip_slot %> - <%= link_to "[Equip]", "#" %> + <% if ci.item.equipment? %> + <%= button_to "Equip", character_item_equip_path(item_id: ci.item.id) %> <% end %> </td> <td class="table-cell-padded"> @@ -25,10 +51,6 @@ <%= link_to "[Use]", "#" %> <% end %> </td> - <td class="table-cell-padded"> - <%= link_to "[Destroy]", "#" %> - <%= link_to "[Destroy All]", "#" %> - </td> </tr> <% end %> </tbody> diff --git a/config/routes.rb b/config/routes.rb index e29f9e9..f9c1f7b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -17,7 +17,10 @@ Rails.application.routes.draw do resources :characters, only: [:show, :new, :create] do scope module: :characters do - resources :items, only: [:index] + post "/items/unequip/:slot", to: "items#unequip", as: :item_unequip + resources :items, only: [:index] do + post "/equip", to: "items#equip" + end resources :titles, only: [:index] do post "/activate", to: "titles#activate" end diff --git a/data/items.yml b/data/items.yml index 5b5bc3b..ae1db0f 100644 --- a/data/items.yml +++ b/data/items.yml @@ -32,12 +32,14 @@ iron_short_sword: name: "Iron short sword" description: "A short sword made of iron." whatnot: - equip_slot: "mainhand" + equip_slots: + - "mainhand" iron_longsword: name: "Iron longsword" description: "A longsword made of iron." - equip_slot: "mainhand" whatnot: + equip_slots: + - "mainhand" equip_requirements: skills: beastslay: 3 diff --git a/data/skills.yml b/data/skills.yml index 7f3f5e9..68de599 100644 --- a/data/skills.yml +++ b/data/skills.yml @@ -59,7 +59,7 @@ otherforge: description: >- Materials of all kinds -- from all planes -- are combined in an arcane forge by otherforgers, who have the ability to craft weapons, armor, and materials from even the most bizarre and phenomenal resources. Masterful otherforgers - have the power to smelt and temper magical energy itself into physical equipments, with incredible and otherworldly + have the power to smelt and temper magical energy itself into physical equipment, with incredible and otherworldly results. planequarry: name: "Planequarry" diff --git a/db/migrate/20210522184444_create_equipment.rb b/db/migrate/20210522184444_create_equipment.rb new file mode 100644 index 0000000..4ac9543 --- /dev/null +++ b/db/migrate/20210522184444_create_equipment.rb @@ -0,0 +1,13 @@ +class CreateEquipment < ActiveRecord::Migration[6.1] + def change + create_table :equipment do |t| + t.references :character, null: false, foreign_key: true + t.references :item, null: false, foreign_key: true + t.integer :slot + + t.timestamps + end + + remove_column :items, :equip_slot + end +end diff --git a/db/schema.rb b/db/schema.rb index f2d776a..5649a54 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_05_20_230859) do +ActiveRecord::Schema.define(version: 2021_05_22_184444) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -92,6 +92,16 @@ ActiveRecord::Schema.define(version: 2021_05_20_230859) do t.datetime "updated_at", precision: 6, null: false end + create_table "equipment", force: :cascade do |t| + t.bigint "character_id", null: false + t.bigint "item_id", null: false + t.integer "slot" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["character_id"], name: "index_equipment_on_character_id" + t.index ["item_id"], name: "index_equipment_on_item_id" + end + create_table "hearth_amenities", force: :cascade do |t| t.string "gid" t.string "name" @@ -113,7 +123,6 @@ ActiveRecord::Schema.define(version: 2021_05_20_230859) do t.string "gid" t.string "name" t.text "description" - t.integer "equip_slot" t.boolean "usable" t.jsonb "whatnot" t.datetime "created_at", precision: 6, null: false @@ -206,6 +215,8 @@ ActiveRecord::Schema.define(version: 2021_05_20_230859) do add_foreign_key "chat_messages", "characters", column: "sender_id" add_foreign_key "chat_messages", "characters", column: "target_id" add_foreign_key "chat_messages", "chat_rooms" + add_foreign_key "equipment", "characters" + add_foreign_key "equipment", "items" add_foreign_key "hearths", "characters" add_foreign_key "learned_activities", "activities" add_foreign_key "learned_activities", "characters" diff --git a/test/fixtures/equipment.yml b/test/fixtures/equipment.yml new file mode 100644 index 0000000..a454920 --- /dev/null +++ b/test/fixtures/equipment.yml @@ -0,0 +1,11 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + character: one + item: one + slot: 1 + +two: + character: two + item: two + slot: 1 diff --git a/test/models/equipment_test.rb b/test/models/equipment_test.rb new file mode 100644 index 0000000..48c29d5 --- /dev/null +++ b/test/models/equipment_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class EquipmentTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end |