From e78a3513632954cb53fc8c806158c1fc98357173 Mon Sep 17 00:00:00 2001 From: David Gay Date: Sun, 13 Jun 2021 21:29:52 -0400 Subject: ItemInfixes --- app/models/character.rb | 6 ++++++ app/models/item_infix.rb | 13 +++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 app/models/item_infix.rb (limited to 'app/models') diff --git a/app/models/character.rb b/app/models/character.rb index d386002..03bd510 100644 --- a/app/models/character.rb +++ b/app/models/character.rb @@ -9,6 +9,7 @@ class Character < ApplicationRecord has_many :character_items has_many :learned_activities has_many :items, through: :character_items + has_many :item_infixes has_many :character_skills has_many :conditions, through: :states has_many :states @@ -182,6 +183,11 @@ class Character < ApplicationRecord end end + def max_infixes(skill) + skill = Skill.find_by_gid(skill) if skill.is_a? String + 1 + (skill_level(skill) / 20).floor + 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_infix.rb b/app/models/item_infix.rb new file mode 100644 index 0000000..cc99ee7 --- /dev/null +++ b/app/models/item_infix.rb @@ -0,0 +1,13 @@ +class ItemInfix < ApplicationRecord + belongs_to :character + belongs_to :item + belongs_to :skill + + before_create :check_max_infixes + + private + def check_max_infixes + current_infixes = character.item_infixes.where(skill: skill) + raise :abort if current_infixes.count >= character.max_infixes(skill) + end +end -- cgit v1.2.3 From d349eaa9ce4700f5c71f7266dbbaaceade9dd7c1 Mon Sep 17 00:00:00 2001 From: David Gay Date: Sun, 13 Jun 2021 22:18:43 -0400 Subject: Move skills to their own page, with a new interface and XP bars --- CHANGELOG.md | 3 + app/models/character_skill.rb | 16 ++- app/views/application/_navbar.html.erb | 3 + app/views/characters/show.html.erb | 25 ---- app/views/characters/skills/index.html.erb | 190 +++-------------------------- config/routes.rb | 1 + 6 files changed, 37 insertions(+), 201 deletions(-) (limited to 'app/models') diff --git a/CHANGELOG.md b/CHANGELOG.md index c49e520..0e8872f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,9 @@ All notable changes to this project will be documented in this file. ### Hearth - New amenity: binding array (level 1, level 2) +### UI +- Character skills were moved to their own view, which features a new interface with XP bars. + ## [0.1.10.2] - 2021-06-10 ### Activities diff --git a/app/models/character_skill.rb b/app/models/character_skill.rb index 368cc28..406cade 100644 --- a/app/models/character_skill.rb +++ b/app/models/character_skill.rb @@ -39,6 +39,10 @@ class CharacterSkill < ApplicationRecord end end + def self.xp_required_for_level(level) + level <= 120 ? XP_TOTALS_PER_LEVEL[level - 1] : nil + end + def level XP_TOTALS_PER_LEVEL.each_with_index do |total, index| return index if total > self.xp @@ -46,7 +50,7 @@ class CharacterSkill < ApplicationRecord end def total_xp_for_next_level - xp_required_for_level(level + 1) + CharacterSkill.xp_required_for_level(level + 1) end def xp_to_next_level @@ -57,11 +61,13 @@ class CharacterSkill < ApplicationRecord CharacterSkill.top_xp_for(self.skill, limit: nil).map(&:character).map(&:id).index(self.character.id) + 1 end - private - def xp_required_for_level(level) - level <= 120 ? XP_TOTALS_PER_LEVEL[level - 1] : nil - end + def percentage_of_skill_level_completed + xp_gained_this_level = xp - CharacterSkill.xp_required_for_level(level) + total_xp_gain_neeeded_for_entire_level = total_xp_for_next_level - CharacterSkill.xp_required_for_level(level) + (xp_gained_this_level.to_f / total_xp_gain_neeeded_for_entire_level) * 100 + end + private def send_chat_message_if_leveled_up if CharacterSkill.level_for_xp(self.xp_was) < CharacterSkill.level_for_xp(self.xp) chat_message = ChatMessage.new(body: "reached #{self.skill.name} level #{self.level}!", diff --git a/app/views/application/_navbar.html.erb b/app/views/application/_navbar.html.erb index be2d9f2..3436619 100644 --- a/app/views/application/_navbar.html.erb +++ b/app/views/application/_navbar.html.erb @@ -6,6 +6,9 @@
  • <%= link_to "Character", character_path(current_char) %>
  • +
  • + <%= link_to "Skills", character_skills_path(current_char) %> +
  • <%= link_to "Inventory", character_items_path(current_char) %>
  • diff --git a/app/views/characters/show.html.erb b/app/views/characters/show.html.erb index a7b7c0e..02f2f55 100644 --- a/app/views/characters/show.html.erb +++ b/app/views/characters/show.html.erb @@ -149,31 +149,6 @@ -
    -

    Skills

    - - - - - - - - - - - - <% @character.character_skills.ordered_by_skill_name.each do |cs| %> - - - - - - - <% end %> - -
    SkillLevelXPTNLTotal XP
    <%= cs.skill.name %><%= cs.level %><%= cs.xp_to_next_level %><%= cs.xp %>
    -
    - <% if @character == current_char %> <%= link_to "Manage account", edit_user_registration_path, class: "text-sm" %> <% end %> diff --git a/app/views/characters/skills/index.html.erb b/app/views/characters/skills/index.html.erb index f13e611..fd53870 100644 --- a/app/views/characters/skills/index.html.erb +++ b/app/views/characters/skills/index.html.erb @@ -1,176 +1,24 @@ -

    Skills

    -
    -
      -
    • <%= link_to "Rankings", character_rankings_path(@character) %>
    • -
    • <%= link_to "Titles", character_titles_path(@character) %>
    • -
    -
    - -

    First entered the planes - <%= pluralize((Date.current - @character.created_at.to_date).to_i, "day") %> ago.

    - -

    Learned <%= @character.learned_activities.count %> recipe(s) or technique(s).

    - -
    -
    -

    Boons & Banes

    - <% if @character.active_states.any? %> -
      - <% @character.active_states.each do |state| %> -
        <%= state.condition.name %> (expires in <%= distance_of_time_in_words_to_now(state.expires_at)%>)
      - <% end %> -
    - <% else %> -

    No boons or banes affect you.

    - <% end %> -
    -
    - <% if @character == current_char %> -

    Combat Styles

    - <%= form_with url: character_combat_styles_path(character_id: @character) do |f| %> - <%= f.label :offensive_style, "Offensive" %> - <%= f.select :offensive_style, Character.offensive_styles.keys.to_a, selected: @character.offensive_style %> - - <%= f.label :defensive_style, "Defensive" %> - <%= f.select :defensive_style, Character.defensive_styles.keys.to_a, selected: @character.defensive_style %> - - <%= f.submit "Set" %> - <% end %> - <% end %> -
    -
    - - -
    -
    -
    -

    Combat Statistics

    - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Wounds<%= @character.wounds %> / <%= @character.max_wounds %>
    Max HP<%= @character.max_hp %>
    Speed<%= @character.speed %>
    Accuracy<%= @character.accuracy(with_combat_style: true) %>
    Power<%= @character.power(with_combat_style: true) %>
    Evasion<%= @character.evasion(with_combat_style: true) %>
    -
    -
    -

    Resistances

    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Slash<%= @character.resistance("slash")%>
    Pierce<%= @character.resistance("pierce") %>
    Bash<%= @character.resistance("bash") %>
    Arcane<%= @character.resistance("arcane") %>
    Fire<%= @character.resistance("fire") %>
    Frost<%= @character.resistance("frost") %>
    Lightning<%= @character.resistance("lightning") %>
    +

    Skills

    +
    + <% @character.character_skills.ordered_by_skill_name.each do |cs| %> +
    +
    +
    +
    + <%= cs.skill.name %> +
    +
    + XP<%= cs.xp %> +
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Acid<%= @character.resistance("acid") %>
    Thunder<%= @character.resistance("thunder")%>
    Radiant<%= @character.resistance("radiant") %>
    Necrotic<%= @character.resistance("necrotic") %>
    Poison<%= @character.resistance("poison") %>
    Bleed<%= @character.resistance("bleed") %>
    +
    + <%= cs.level %> +
    +
    +
    +
    -
    -
    - -
    -

    Skills

    - - - - - - - - - - - - <% @character.character_skills.ordered_by_skill_name.each do |cs| %> - - - - - - - <% end %> - -
    SkillLevelXPTNLTotal XP
    <%= cs.skill.name %><%= cs.level %><%= cs.xp_to_next_level %><%= cs.xp %>
    + <% end %>
    - -<% if @character == current_char %> - <%= link_to "Manage account", edit_user_registration_path, class: "text-sm" %> -<% end %> diff --git a/config/routes.rb b/config/routes.rb index fa6d748..22b8299 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -32,6 +32,7 @@ Rails.application.routes.draw do post "/equip", to: "items#equip" post "/use", to: "items#use" end + resources :skills, only: [:index] resources :titles, only: [:index] do post "/activate", to: "titles#activate" end -- cgit v1.2.3 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 (limited to 'app/models') 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 From d2a31e04d19796a600a932a3491e056fe2c89af2 Mon Sep 17 00:00:00 2001 From: David Gay Date: Tue, 15 Jun 2021 19:54:29 -0400 Subject: Basic spellcasting --- app/controllers/characters/spells_controller.rb | 5 ++++ app/lib/activity_processor.rb | 7 ++++++ app/models/character.rb | 6 ++++- app/models/concerns/has_costs_and_requirements.rb | 2 ++ app/models/item_infix.rb | 4 ++++ app/views/application/_navbar.html.erb | 3 +++ app/views/application/_results.html.erb | 2 ++ app/views/characters/skills/index.html.erb | 2 +- app/views/characters/spells/index.html.erb | 10 ++++++++ config/routes.rb | 1 + data/activities.yml | 29 +++++++++++++++++++++++ 11 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 app/controllers/characters/spells_controller.rb create mode 100644 app/views/characters/spells/index.html.erb (limited to 'app/models') diff --git a/app/controllers/characters/spells_controller.rb b/app/controllers/characters/spells_controller.rb new file mode 100644 index 0000000..9694856 --- /dev/null +++ b/app/controllers/characters/spells_controller.rb @@ -0,0 +1,5 @@ +class Characters::SpellsController < ApplicationController + def index + @spell_activities = Activity.where("gid like ?", "havencast_%").order(:name) + end +end diff --git a/app/lib/activity_processor.rb b/app/lib/activity_processor.rb index 4a06a98..9b03f55 100644 --- a/app/lib/activity_processor.rb +++ b/app/lib/activity_processor.rb @@ -90,6 +90,13 @@ class ActivityProcessor item = Item.find_by_gid(result[:gid]) hp = @character.hearth.hearth_plantings.create(item: item) @results.push({ type: type, hearth_planting: hp }) + when "condition" + Character.transaction do + condition = Condition.find_by_gid(result[:gid]) + @character.states.create!(condition: condition, expires_at: Time.now + result[:duration]) + @results.push({ type: "message", body: result[:message] }) + @results.push({ type: type, condition: condition }) + end when "activity" next if rand > (result[:chance] || 1) table_roll = rand diff --git a/app/models/character.rb b/app/models/character.rb index 4ee1f71..5ff067c 100644 --- a/app/models/character.rb +++ b/app/models/character.rb @@ -273,6 +273,9 @@ class Character < ApplicationRecord case requirement[:type] when "equipment" return false unless self.equipment_with_gid(requirement[:gid]) + when "stat" + # TODO: HACK: This won't work with built-in stats! Need to change this to work with power and whatnot. + return false unless self.total_stat_change(requirement[:gid]) >= requirement[:value] when "skill" return false unless self.skill_level(requirement[:gid]) >= requirement[:level] when "hearth_amenity" @@ -331,7 +334,8 @@ class Character < ApplicationRecord hearth_amenity_effects = self.hearth.built_hearth_amenities.filter_map { |a| a.effects if a.effects } equipment_effects = self.equipment.filter_map { |a| a.effects if a.effects } state_effects = self.states.filter_map { |a| a.effects if a.effects && !a.expired? } - (hearth_amenity_effects + equipment_effects + state_effects).flatten + item_infix_effects = self.item_infixes.filter_map { |a| a.effects if a.effects } + (hearth_amenity_effects + equipment_effects + state_effects + item_infix_effects).flatten end def total_stat_change(gid) diff --git a/app/models/concerns/has_costs_and_requirements.rb b/app/models/concerns/has_costs_and_requirements.rb index 34ff0f3..9f859f5 100644 --- a/app/models/concerns/has_costs_and_requirements.rb +++ b/app/models/concerns/has_costs_and_requirements.rb @@ -19,6 +19,8 @@ module HasCostsAndRequirements case req[:type] when "skill" requirements.push "level #{req[:level]} #{Skill.find_by_gid(req[:gid]).name}" + when "stat" + requirements.push "#{req[:value]} #{req[:gid]}" when "equipment" requirements.push "equipped #{Item.find_by_gid(req[:gid]).name}" when "hearth_amenity" diff --git a/app/models/item_infix.rb b/app/models/item_infix.rb index cc99ee7..3167320 100644 --- a/app/models/item_infix.rb +++ b/app/models/item_infix.rb @@ -5,6 +5,10 @@ class ItemInfix < ApplicationRecord before_create :check_max_infixes + def effects + self.item.whatnot[:infix_effects] + end + private def check_max_infixes current_infixes = character.item_infixes.where(skill: skill) diff --git a/app/views/application/_navbar.html.erb b/app/views/application/_navbar.html.erb index 3436619..aaec030 100644 --- a/app/views/application/_navbar.html.erb +++ b/app/views/application/_navbar.html.erb @@ -12,6 +12,9 @@
  • <%= link_to "Inventory", character_items_path(current_char) %>
  • +
  • + <%= link_to "Spells", character_spells_path(current_char) %> +
  • <%= link_to "Hearth", character_hearth_path(current_char) %>
  • diff --git a/app/views/application/_results.html.erb b/app/views/application/_results.html.erb index ec62991..691f1d5 100644 --- a/app/views/application/_results.html.erb +++ b/app/views/application/_results.html.erb @@ -24,6 +24,8 @@

    You gained <%= result[:xp] %> <%= result[:skill].name %> XP.

    <% when "title" %>

    You earned the title <%= render "application/components/text/title", title: result[:title] %>!

    + <% when "condition" %> +

    You gained the <%= result[:condition].name %> condition.

    <% when "message" %>

    <%= result[:body] %>

    <% when "warning" %> diff --git a/app/views/characters/skills/index.html.erb b/app/views/characters/skills/index.html.erb index f79b06e..d804384 100644 --- a/app/views/characters/skills/index.html.erb +++ b/app/views/characters/skills/index.html.erb @@ -47,7 +47,7 @@
    <% end %> <% else %> -
    No items to infix.
    +
    No omens to infix.
    <% end %> <% end %> <% end %> diff --git a/app/views/characters/spells/index.html.erb b/app/views/characters/spells/index.html.erb new file mode 100644 index 0000000..5f415a3 --- /dev/null +++ b/app/views/characters/spells/index.html.erb @@ -0,0 +1,10 @@ +

    Spells

    +
    + <%= form_with url: start_activity_path, method: :post do |f| %> + <%= f.select :id, @spell_activities.map { |a| [a.name, a.id] }, {}, + { data: { activity_select_target: "select", action: "activity-select#load" } } %> + <%= f.number_field :actions, value: 1, size: 5, min: 1, max: 2_000_000_000 %> + <%= f.submit "Cast" %> + <% end %> +
    +
    diff --git a/config/routes.rb b/config/routes.rb index 51d9e6c..af608e5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -34,6 +34,7 @@ Rails.application.routes.draw do post "/use", to: "items#use" end resources :skills, only: [:index] + resources :spells, only: [:index] resources :titles, only: [:index] do post "/activate", to: "titles#activate" end diff --git a/data/activities.yml b/data/activities.yml index a508781..ec82b38 100644 --- a/data/activities.yml +++ b/data/activities.yml @@ -2741,3 +2741,32 @@ craft_faint_mana: xp: - gid: "omenbind" value: 6 +havencast_light: + name: "Cast Light" + description: "Risk a little light." + whatnot: + tags: + - "spell" + - "cantrip" + duration: + base: 30 + minimum: 10 + scaling: + - type: "skill" + gid: "havencast" + scale_value: 1 + requirements: + - type: "skill" + gid: "havencast" + level: 1 + - type: "stat" + gid: "mana" + value: 1 + results: + - type: "condition" + gid: "light" + duration: 3600 # 1 Hour + message: "A ball of light glows before you." + - type: "xp" + gid: "havencast" + base: 3 -- cgit v1.2.3 From f637f622af2d9b891271344ef23402c41419b3fe Mon Sep 17 00:00:00 2001 From: David Gay Date: Tue, 15 Jun 2021 21:11:10 -0400 Subject: Add breakage to all equipment items that give a skill speed increase, and to omens --- CHANGELOG.md | 10 +++- app/lib/activity_processor.rb | 28 +++++++--- app/models/character.rb | 24 +++++++++ app/models/item_infix.rb | 4 ++ data/activities.yml | 117 +++++++++++++++++++++++++++++++++++------- 5 files changed, 155 insertions(+), 28 deletions(-) (limited to 'app/models') diff --git a/CHANGELOG.md b/CHANGELOG.md index c08461d..acc3268 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,16 @@ All notable changes to this project will be documented in this file. ## [Unreleased] -### Skills +### General +- Any items equipped which provide a speed increase to a skill now have a chance to break when performing that skill. + The break chance is based on the equip slot of the item, and uses the same numbers as the combat equipment break + chance. The combat equipment break check process is unchanged. - Omenbind has been implemented. Omens can be bound once a character has constructed a binding array in their hearth. Omens are tradable items that can be infixed to a particular skill via the new skills UI (see the UI section of this - changelog). Omens can be removed and re-infixed at will. + changelog). Omens can be removed and re-infixed at will. All omens infixed in a skill have a chance to fade away and + be permanently lost when performing that skill (like equipment breakage). The chance of an infixed omen fading away + is 1/1000. You do not need to actively be getting a bonus from an infixed omen for it to have a chance to fade away. + When performing a skill, all omens infixed in that skill have the same chance to fade away. - Havencast has been implemented. Spells can be cast from a new "Spells" view, accessible with the navigation. Spells typically require that a certain amount of mana is available. Mana can be made available by infixing certain omens. diff --git a/app/lib/activity_processor.rb b/app/lib/activity_processor.rb index 9b03f55..e211db4 100644 --- a/app/lib/activity_processor.rb +++ b/app/lib/activity_processor.rb @@ -115,6 +115,24 @@ class ActivityProcessor end end + # Note: This will result in equipment being checked for breakage twice (after combat, and now) if it provides the + # `beastslay_speed` stat. At the time of this writing, that stat doesn't exist. + # But just something to keep in mind. + # Note: This will result in equipment being checked twice if it provides two speed stats. + # Fine for now since no equipment gives two skill speed stats, but may want to refine in the future. + if @activity.whatnot[:requirements].any? + required_skill_gids = @activity.whatnot[:requirements].select { |r| r[:type] == "skill" }.map { |r| r[:gid] }.uniq + required_skill_gids.each do |required_skill_gid| + skill = Skill.find_by_gid(required_skill_gid) + @character.do_skill_based_equipment_break_checks(skill).each do |broken_item| + @results.push({ type: "warning", message: "Your #{broken_item.name} was damaged beyond repair!" }) + end + @character.do_skill_based_item_infix_break_checks(skill).each do |broken_item| + @results.push({ type: "warning", message: "Your #{broken_item.name} omen faded away." }) + end + end + end + if @character.activity && @character.queued_actions if @character.queued_actions > 0 @character.queued_actions -= 1 @@ -282,7 +300,9 @@ class ActivityProcessor end if char_hp < 1 || mon_hp < 1 - break_check + @character.do_equipment_break_checks.each do |broken_item| + @results.push({ type: "warning", message: "Your #{broken_item.name} was damaged beyond repair!" }) + end if monster_spawn hp_lost = monster_spawn.remaining_hp - mon_hp @@ -325,10 +345,4 @@ class ActivityProcessor end end end - - def break_check - @character.do_equipment_break_checks.each do |broken_item| - @results.push({ type: "warning", message: "Your #{broken_item.name} was damaged beyond repair!" }) - end - end end diff --git a/app/models/character.rb b/app/models/character.rb index 5ff067c..0f2c5b3 100644 --- a/app/models/character.rb +++ b/app/models/character.rb @@ -116,6 +116,30 @@ class Character < ApplicationRecord end end + def do_skill_based_equipment_break_checks(skill) + skill = Skill.find_by_gid(skill) if skill.is_a? String + broken_items = [] + # TODO: HACK: Should check other stats besides speed stat in the future. + # TODO: HACK: May not want a chance to break if speed is _reduced_. Though no equipment does this yet. + equipment.all.select { |eq| eq.effects.select { |ef| ef[:gid] == "#{skill.gid}_speed" }.any? }.each do |equipment| + if equipment.break_check + broken_items.push(equipment.item) + end + end + broken_items + end + + def do_skill_based_item_infix_break_checks(skill) + skill = Skill.find_by_gid(skill) if skill.is_a? String + broken_items = [] + item_infixes.where(skill: skill).each do |ii| + if ii.break_check + broken_items.push(ii.item) + end + end + broken_items + end + def do_equipment_break_checks(exclude_slots: []) broken_items = [] equipment.where.not(slot: exclude_slots).each do |equipment| diff --git a/app/models/item_infix.rb b/app/models/item_infix.rb index 3167320..47b6aa4 100644 --- a/app/models/item_infix.rb +++ b/app/models/item_infix.rb @@ -9,6 +9,10 @@ class ItemInfix < ApplicationRecord self.item.whatnot[:infix_effects] end + def break_check + rand > 0.999 ? destroy : false + end + private def check_max_infixes current_infixes = character.item_infixes.where(skill: skill) diff --git a/data/activities.yml b/data/activities.yml index ec82b38..2940973 100644 --- a/data/activities.yml +++ b/data/activities.yml @@ -322,6 +322,9 @@ plant_mudtub_seed: - type: "hearth_amenity" gid: "loamspire" level: 1 + - type: "skill" + gid: "magiculture" + level: 1 duration: base: 120 scaling: @@ -345,6 +348,9 @@ harvest_mudtub: - type: "hearth_amenity" gid: "loamspire" level: 1 + - type: "skill" + gid: "magiculture" + level: 1 duration: base: 120 scaling: @@ -536,6 +542,9 @@ craft_crude_iron_ingot: - type: "hearth_amenity" gid: "forge" level: 1 + - type: "skill" + gid: "otherforge" + level: 1 duration: base: 50 minimum: 35 @@ -564,6 +573,9 @@ craft_iron_ingot: - type: "hearth_amenity" gid: "forge" level: 1 + - type: "skill" + gid: "otherforge" + level: 1 duration: base: 60 minimum: 35 @@ -716,6 +728,9 @@ craft_iron_lockpicks: - type: "hearth_amenity" gid: "forge" level: 1 + - type: "skill" + gid: "otherforge" + level: 1 duration: base: 50 minimum: 35 @@ -744,6 +759,9 @@ craft_iron_dagger: - type: "hearth_amenity" gid: "forge" level: 1 + - type: "skill" + gid: "otherforge" + level: 1 duration: base: 50 minimum: 35 @@ -834,6 +852,9 @@ craft_iron_buckler: - type: "hearth_amenity" gid: "forge" level: 1 + - type: "skill" + gid: "otherforge" + level: 1 duration: base: 100 minimum: 35 @@ -1392,6 +1413,9 @@ craft_iron_pickaxe: - type: "hearth_amenity" gid: "forge" level: 1 + - type: "skill" + gid: "otherforge" + level: 1 duration: base: 75 minimum: 35 @@ -1423,6 +1447,9 @@ craft_iron_axe: - type: "hearth_amenity" gid: "forge" level: 1 + - type: "skill" + gid: "otherforge" + level: 1 duration: base: 75 minimum: 35 @@ -1454,6 +1481,9 @@ craft_iron_spade: - type: "hearth_amenity" gid: "forge" level: 1 + - type: "skill" + gid: "otherforge" + level: 1 duration: base: 75 minimum: 35 @@ -1630,6 +1660,9 @@ craft_mending_salve: - type: "hearth_amenity" gid: "laboratory" level: 1 + - type: "skill" + gid: "fluxseethe" + level: 1 duration: base: 90 minimum: 35 @@ -1942,6 +1975,10 @@ planequarry_floret_mines: description: "Planequarry at the Floret Mines." location: "floret_region" whatnot: + requirements: + - type: "skill" + gid: "planequarry" + level: 1 duration: base: 130 minimum: 35 @@ -2079,6 +2116,10 @@ planequarry_brine_trench: description: "Planequarry in the south Floret brine trench." location: "floret_region" whatnot: + requirements: + - type: "skill" + gid: "planequarry" + level: 1 duration: base: 60 minimum: 25 @@ -2108,6 +2149,10 @@ beastslay_killing_fields: description: "Hunt monsters in the Killing Fields." location: "floret_region" whatnot: + requirements: + - type: "skill" + gid: "beastslay" + level: 1 duration: base: 60 minimum: 35 @@ -2132,6 +2177,10 @@ beastslay_hopegraves: description: "Hunt monsters in the Hopegraves." location: "floret_region" whatnot: + requirements: + - type: "skill" + gid: "beastslay" + level: 1 duration: base: 70 minimum: 35 @@ -2154,6 +2203,10 @@ wealdreap_twil_woods: description: "Wealdreap within Twil Woods." location: "floret_region" whatnot: + requirements: + - type: "skill" + gid: "wealdreap" + level: 1 duration: base: 120 minimum: 35 @@ -2289,6 +2342,12 @@ manatrawl_sor_well: description: "Manatrawl within Sor Well." location: "floret_region" whatnot: + requirements: + - type: "skill" + gid: "manatrawl" + level: 1 + - type: "equipment" + gid: "aethermesh" duration: base: 60 minimum: 35 @@ -2299,9 +2358,6 @@ manatrawl_sor_well: - type: "stat" gid: "manatrawl_speed" scale_value: 1 - requirements: - - type: "equipment" - gid: "aethermesh" results: - type: "item" chance: 1 @@ -2330,6 +2386,12 @@ manatrawl_sor_well_depths: description: "Manatrawl deep within Sor Well." location: "floret_region" whatnot: + requirements: + - type: "skill" + gid: "manatrawl" + level: 7 + - type: "equipment" + gid: "aethermesh" duration: base: 70 minimum: 35 @@ -2340,12 +2402,6 @@ manatrawl_sor_well_depths: - type: "stat" gid: "manatrawl_speed" scale_value: 1 - requirements: - - type: "skill" - gid: "manatrawl" - level: 7 - - type: "equipment" - gid: "aethermesh" results: - type: "item" chance: 1 @@ -2374,6 +2430,12 @@ synthsever_rusted_lockbox: name: "Unlock Rusted Lockbox" description: "Unseal the lock on a rusted lockbox." whatnot: + requirements: + - type: "equipment" + gid: "iron_lockpicks" + - type: "skill" + gid: "synthsever" + level: 1 duration: base: 180 minimum: 35 @@ -2381,9 +2443,6 @@ synthsever_rusted_lockbox: - type: "skill" gid: "synthsever" scale_value: 1 - requirements: - - type: "equipment" - gid: "iron_lockpicks" cost: - type: "item" gid: "rusted_lockbox" @@ -2433,6 +2492,10 @@ wildscour_crumbling_ruins: description: "Wildscour within the crumbling ruins." location: "floret_region" whatnot: + requirements: + - type: "skill" + gid: "wildscour" + level: 1 duration: base: 60 minimum: 35 @@ -2483,6 +2546,9 @@ craft_gem_dust_from_red_beryl: - type: "hearth_amenity" gid: "laboratory" level: 1 + - type: "skill" + gid: "fluxseethe" + level: 1 duration: base: 60 minimum: 15 @@ -2511,6 +2577,9 @@ craft_gem_dust_from_tourmaline: - type: "hearth_amenity" gid: "laboratory" level: 1 + - type: "skill" + gid: "fluxseethe" + level: 1 duration: base: 60 minimum: 15 @@ -2573,6 +2642,9 @@ craft_mudtub_mash: - type: "hearth_amenity" gid: "spicebench" level: 1 + - type: "skill" + gid: "spicework" + level: 1 duration: base: 60 minimum: 35 @@ -2696,6 +2768,10 @@ beastslay_leviathan_floret_region: name: "Hunt a Leviathan in the Floret Region" description: "You are hunting down a leviathan ravaging the Floret Region." whatnot: + requirements: + - type: "skill" + gid: "beastslay" + level: 1 duration: base: 80 minimum: 40 @@ -2718,6 +2794,9 @@ craft_faint_mana: - type: "hearth_amenity" gid: "binding_array" level: 1 + - type: "skill" + gid: "omenbind" + level: 1 duration: base: 60 minimum: 35 @@ -2748,13 +2827,6 @@ havencast_light: tags: - "spell" - "cantrip" - duration: - base: 30 - minimum: 10 - scaling: - - type: "skill" - gid: "havencast" - scale_value: 1 requirements: - type: "skill" gid: "havencast" @@ -2762,6 +2834,13 @@ havencast_light: - type: "stat" gid: "mana" value: 1 + duration: + base: 30 + minimum: 10 + scaling: + - type: "skill" + gid: "havencast" + scale_value: 1 results: - type: "condition" gid: "light" -- cgit v1.2.3 From 637adf2963f174c3e3e3d6cf9efbff314e306f3e Mon Sep 17 00:00:00 2001 From: David Gay Date: Tue, 15 Jun 2021 21:52:49 -0400 Subject: MonsterKills and bestiary view --- CHANGELOG.md | 5 ++++- app/controllers/characters/bestiary_controller.rb | 12 ++++++++++++ app/lib/activity_processor.rb | 5 +++++ app/models/character.rb | 1 + app/models/monster_kill.rb | 7 +++++++ app/views/characters/bestiary/index.html.erb | 22 ++++++++++++++++++++++ app/views/characters/show.html.erb | 1 + config/routes.rb | 1 + db/migrate/20210616014044_create_monster_kills.rb | 11 +++++++++++ db/schema.rb | 14 +++++++++++++- test/fixtures/monster_kills.yml | 11 +++++++++++ test/models/monster_kill_test.rb | 7 +++++++ 12 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 app/controllers/characters/bestiary_controller.rb create mode 100644 app/models/monster_kill.rb create mode 100644 app/views/characters/bestiary/index.html.erb create mode 100644 db/migrate/20210616014044_create_monster_kills.rb create mode 100644 test/fixtures/monster_kills.yml create mode 100644 test/models/monster_kill_test.rb (limited to 'app/models') diff --git a/CHANGELOG.md b/CHANGELOG.md index acc3268..22ebaf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ All notable changes to this project will be documented in this file. When performing a skill, all omens infixed in that skill have the same chance to fade away. - Havencast has been implemented. Spells can be cast from a new "Spells" view, accessible with the navigation. Spells typically require that a certain amount of mana is available. Mana can be made available by infixing certain omens. +- Characters now each have a bestiary where monster kills are recorded. For leviathans, only the character who actually + slays the leviathan by dealing the final damage gets credit for the kill in their bestiary. The bestiary can be viewed + via a link on the Character view. (Hopefully) obviously, kills before this release were not counted. ### Activities - Planequarry XP award changes @@ -34,7 +37,7 @@ All notable changes to this project will be documented in this file. - New amenity: binding array (level 1, level 2) ### UI -- Character skills were moved to their own view, which features a new interface with XP bars. +- Character skills were moved from the Character view to their own view, which features a new interface with XP bars. ## [0.1.10.3] - 2021-06-14 diff --git a/app/controllers/characters/bestiary_controller.rb b/app/controllers/characters/bestiary_controller.rb new file mode 100644 index 0000000..7e37d9c --- /dev/null +++ b/app/controllers/characters/bestiary_controller.rb @@ -0,0 +1,12 @@ +class Characters::BestiaryController < ApplicationController + before_action :set_character + + def index + @monster_kills = @character.monster_kills.all + end + + private + def set_character + @character = Character.find(params[:character_id]) + end +end diff --git a/app/lib/activity_processor.rb b/app/lib/activity_processor.rb index e211db4..79c8f3e 100644 --- a/app/lib/activity_processor.rb +++ b/app/lib/activity_processor.rb @@ -323,6 +323,11 @@ class ActivityProcessor end else @results.push({ type: "message", body: "You slew the #{mon.name}." }) + + monster_kills = character.monster_kills.find_or_initialize_by(monster: mon) + monster_kills.quantity ? monster_kills.quantity += 1 : monster_kills.quantity = 1 + monster_kills.save + if monster_spawn char.stop_activity return diff --git a/app/models/character.rb b/app/models/character.rb index 0f2c5b3..7f26ad4 100644 --- a/app/models/character.rb +++ b/app/models/character.rb @@ -14,6 +14,7 @@ class Character < ApplicationRecord has_many :conditions, through: :states has_many :states has_many :chat_messages + has_many :monster_kills 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. diff --git a/app/models/monster_kill.rb b/app/models/monster_kill.rb new file mode 100644 index 0000000..4096e8e --- /dev/null +++ b/app/models/monster_kill.rb @@ -0,0 +1,7 @@ +class MonsterKill < ApplicationRecord + belongs_to :monster + belongs_to :character + + validates :quantity, numericality: { greater_than_or_equal_to: 0, only_integer: true } + scope :ordered_by_monster_name, -> { includes(:monster).order("monsters.name") } +end diff --git a/app/views/characters/bestiary/index.html.erb b/app/views/characters/bestiary/index.html.erb new file mode 100644 index 0000000..f7376e9 --- /dev/null +++ b/app/views/characters/bestiary/index.html.erb @@ -0,0 +1,22 @@ +

    Bestiary

    + +<% if @monster_kills.any? %> + + + + + + + + + <% @monster_kills.ordered_by_monster_name.each do |mk| %> + + + + + <% end %> + +
    MonsterKills
    <%= mk.monster.name %><%= mk.quantity %>
    +<% else %> +

    You haven't killed any monsters yet.

    +<% end %> diff --git a/app/views/characters/show.html.erb b/app/views/characters/show.html.erb index 02f2f55..96a87f8 100644 --- a/app/views/characters/show.html.erb +++ b/app/views/characters/show.html.erb @@ -5,6 +5,7 @@
    • <%= link_to "Titles", character_titles_path(@character) %>
    • +
    • <%= link_to "Bestiary", character_bestiary_path(@character) %>
    • <%= link_to "Rankings", character_rankings_path(@character) %>
    diff --git a/config/routes.rb b/config/routes.rb index af608e5..fefd12f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -27,6 +27,7 @@ Rails.application.routes.draw do post "/combat_styles", to: "characters#set_combat_styles" scope module: :characters do get "/rankings", to: "rankings#index" + get :bestiary, to: "bestiary#index" post "/items/unequip/:slot", to: "items#unequip", as: :item_unequip resources :item_infixes, only: [:create, :destroy] resources :items, only: [:index] do diff --git a/db/migrate/20210616014044_create_monster_kills.rb b/db/migrate/20210616014044_create_monster_kills.rb new file mode 100644 index 0000000..b61908d --- /dev/null +++ b/db/migrate/20210616014044_create_monster_kills.rb @@ -0,0 +1,11 @@ +class CreateMonsterKills < ActiveRecord::Migration[6.1] + def change + create_table :monster_kills do |t| + t.references :monster, null: false, foreign_key: true + t.references :character, null: false, foreign_key: true + t.bigint :quantity + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index f3992ee..6c503fd 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_06_14_004827) do +ActiveRecord::Schema.define(version: 2021_06_16_014044) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -207,6 +207,16 @@ ActiveRecord::Schema.define(version: 2021_06_14_004827) do t.index ["sender_id"], name: "index_messages_on_sender_id" end + create_table "monster_kills", force: :cascade do |t| + t.bigint "monster_id", null: false + t.bigint "character_id", null: false + t.bigint "quantity" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["character_id"], name: "index_monster_kills_on_character_id" + t.index ["monster_id"], name: "index_monster_kills_on_monster_id" + end + create_table "monster_spawn_combats", force: :cascade do |t| t.bigint "monster_spawn_id", null: false t.bigint "character_id", null: false @@ -326,6 +336,8 @@ ActiveRecord::Schema.define(version: 2021_06_14_004827) do add_foreign_key "learned_activities", "characters" add_foreign_key "messages", "characters", column: "recipient_id" add_foreign_key "messages", "characters", column: "sender_id" + add_foreign_key "monster_kills", "characters" + add_foreign_key "monster_kills", "monsters" add_foreign_key "monster_spawn_combats", "characters" add_foreign_key "monster_spawn_combats", "monster_spawns" add_foreign_key "monster_spawns", "locations" diff --git a/test/fixtures/monster_kills.yml b/test/fixtures/monster_kills.yml new file mode 100644 index 0000000..776b079 --- /dev/null +++ b/test/fixtures/monster_kills.yml @@ -0,0 +1,11 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + monster: one + character: one + quantity: + +two: + monster: two + character: two + quantity: diff --git a/test/models/monster_kill_test.rb b/test/models/monster_kill_test.rb new file mode 100644 index 0000000..aef80ac --- /dev/null +++ b/test/models/monster_kill_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class MonsterKillTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end -- cgit v1.2.3 From 23d07f8badb2b2ce8139ee421157a96fb61455dc Mon Sep 17 00:00:00 2001 From: David Gay Date: Tue, 15 Jun 2021 22:30:47 -0400 Subject: Add 7 new titles, awarded for MonsterKill quantity --- CHANGELOG.md | 10 ++++++++++ app/models/monster_kill.rb | 15 +++++++++++++++ app/views/application/components/text/_title.html.erb | 14 ++++++++++++++ data/titles.yml | 14 ++++++++++++++ 4 files changed, 53 insertions(+) (limited to 'app/models') diff --git a/CHANGELOG.md b/CHANGELOG.md index 22ebaf8..e584534 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,16 @@ All notable changes to this project will be documented in this file. ### Hearth - New amenity: binding array (level 1, level 2) +### Titles +- 7 new titles + - Slayer: Kill 1,000 monsters + - Butcher: Kill 10,000 monsters + - Slaughterer: Kill 100,000 monsters + - Massacrer: Kill 1,000,000 monsters + - Spiteful: Kill 1,000 of one particular monster + - Hateful: Kill 10,000 of one particular monster + - Vicious: Kill 100,000 of one particular monster + ### UI - Character skills were moved from the Character view to their own view, which features a new interface with XP bars. diff --git a/app/models/monster_kill.rb b/app/models/monster_kill.rb index 4096e8e..24519b1 100644 --- a/app/models/monster_kill.rb +++ b/app/models/monster_kill.rb @@ -4,4 +4,19 @@ class MonsterKill < ApplicationRecord validates :quantity, numericality: { greater_than_or_equal_to: 0, only_integer: true } scope :ordered_by_monster_name, -> { includes(:monster).order("monsters.name") } + + after_save :award_titles + + private + def award_titles + character.award_title("spiteful") if quantity >= 1000 + character.award_title("hateful") if quantity >= 10_000 + character.award_title("vicious") if quantity >= 100_000 + + all_kills_quantity = character.monster_kills.sum(:quantity) + character.award_title("slayer") if all_kills_quantity >= 1_000 + character.award_title("butcher") if all_kills_quantity >= 10_000 + character.award_title("slaughterer") if all_kills_quantity >= 100_000 + character.award_title("massacrer") if all_kills_quantity >= 1_000_000 + end end diff --git a/app/views/application/components/text/_title.html.erb b/app/views/application/components/text/_title.html.erb index a7c2a7e..5e1d5a2 100644 --- a/app/views/application/components/text/_title.html.erb +++ b/app/views/application/components/text/_title.html.erb @@ -10,6 +10,20 @@ Aspirant <% when "sentinel" %> Sentinel + <% when "spiteful" %> + Spiteful + <% when "hateful" %> + Hateful + <% when "vicious" %> + Vicious + <% when "slayer" %> + Slayer + <% when "butcher" %> + Butcher + <% when "slaughterer" %> + Slaughterer + <% when "massacrer" %> + Massacrer <% else %> <%= title.name %> <% end %> diff --git a/data/titles.yml b/data/titles.yml index a8c228a..23ff009 100644 --- a/data/titles.yml +++ b/data/titles.yml @@ -8,3 +8,17 @@ aspirant: name: "Aspirant" sentinel: name: "Sentinel" +spiteful: + name: "Spiteful" +hateful: + name: "Hateful" +vicious: + name: "Vicious" +slayer: + name: "Slayer" +butcher: + name: "Butcher" +slaughterer: + name: "Slaughterer" +massacrer: + name: "Massacrer" -- cgit v1.2.3 From ecf1d03813e75b2929dce4cfc68352ad5b1a1377 Mon Sep 17 00:00:00 2001 From: David Gay Date: Wed, 16 Jun 2021 17:44:38 -0400 Subject: [data] New activity: havencast_dazzle --- CHANGELOG.md | 1 + app/lib/activity_processor.rb | 5 +++++ app/models/character.rb | 4 ++++ data/activities.yml | 28 ++++++++++++++++++++++++++++ 4 files changed, 38 insertions(+) (limited to 'app/models') diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bcdd0b..b6fd397 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ All notable changes to this project will be documented in this file. - Purify iron ingot 115 -> 70 - Level requirements changes - Arcanite longsword 15 -> 17 (setting it to 15 was a programming error) +- The first havencast spells: Light, Dazzle ### Items - New item: faint mana diff --git a/app/lib/activity_processor.rb b/app/lib/activity_processor.rb index 79c8f3e..248ed9d 100644 --- a/app/lib/activity_processor.rb +++ b/app/lib/activity_processor.rb @@ -256,8 +256,13 @@ class ActivityProcessor turn_order = [[char, mon], [mon, char]].shuffle end turn_order.cycle do |actor, target| + base_accuracy_roll = roll(20) accuracy_roll = base_accuracy_roll + actor.accuracy(with_combat_style: true) + if actor == mon + accuracy_roll += char.total_enemy_stat_change("accuracy") + end + evasion_roll = roll(20) + target.evasion(with_combat_style: true) if accuracy_roll >= evasion_roll || base_accuracy_roll == 20 diff --git a/app/models/character.rb b/app/models/character.rb index 7f26ad4..9db3f8c 100644 --- a/app/models/character.rb +++ b/app/models/character.rb @@ -367,6 +367,10 @@ class Character < ApplicationRecord effects.filter_map { |e| e[:modifier] if e[:type] == "stat_change" && e[:gid] == gid }.sum end + def total_enemy_stat_change(gid) + effects.filter_map { |e| e[:modifier] if e[:type] == "enemy_stat_change" && e[:gid] == gid }.sum + end + def damage_ranges effects.filter_map { |e| { gid: e[:gid], min: e[:min], max: e[:max] } if e[:type] == "damage" } end diff --git a/data/activities.yml b/data/activities.yml index 2940973..c9ea218 100644 --- a/data/activities.yml +++ b/data/activities.yml @@ -2849,3 +2849,31 @@ havencast_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 + - type: "stat" + gid: "mana" + value: 1 + results: + - type: "condition" + gid: "dazzle" + duration: 600 # 10 minutes + message: "Sparkling lights distract your enemies." + - type: "xp" + gid: "havencast" + base: 6 -- cgit v1.2.3 From b5234514e2c8d8a1e798726991892bf80eec90ae Mon Sep 17 00:00:00 2001 From: David Gay Date: Wed, 16 Jun 2021 18:16:57 -0400 Subject: Activity equipment item tag requirements, and apply to / adjust all relevant activities --- CHANGELOG.md | 6 +++ app/models/character.rb | 10 +++- app/models/concerns/has_costs_and_requirements.rb | 6 ++- data/activities.yml | 60 +++++++++++++++++------ data/items.yml | 33 +++++++++---- 5 files changed, 88 insertions(+), 27 deletions(-) (limited to 'app/models') diff --git a/CHANGELOG.md b/CHANGELOG.md index aeb3184..53201bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,10 @@ All notable changes to this project will be documented in this file. via a link on the Character view. (Hopefully) obviously, kills before this release were not counted. ### Activities +- Planequarry activities now require a pickaxe, wealdreap activities now require an axe, magiculture activities now + require a spade, and base timers and item speed bonuses have been adjusted appropriately +- Planequarry at the Brine Trench base duration changed from 60 to 50 (should have been like, 120 before but it was + mistakenly set to 60, and now it's being adjusted for the tool/timer changes in this release) - Planequarry XP award changes - Pure iron ore 25 -> 18 - Gaian ore 50 -> 25 @@ -44,6 +48,8 @@ All notable changes to this project will be documented in this file. ### Items - New item: faint mana +- Iron lockpicks now increase synthsever speed by 10 seconds +- Axes, pickaxes, and spades skill speed increase numbers all adjusted to compensate for base timer reductions ### Hearth - New amenity: binding array (level 1, level 2) diff --git a/app/models/character.rb b/app/models/character.rb index 9db3f8c..a26fb93 100644 --- a/app/models/character.rb +++ b/app/models/character.rb @@ -162,6 +162,10 @@ class Character < ApplicationRecord self.equipment.find_by(item: item) end + def equipment_with_tag(tag) + self.equipment.all.find { |e| e.item.has_tag?(tag) } + end + def open_slots_for(item) full_slots = self.equipment.map { |e| e.slot } item.equip_slots.reject { |slot| full_slots.include?(slot) } @@ -297,7 +301,11 @@ class Character < ApplicationRecord activity.whatnot[:requirements]&.each do |requirement| case requirement[:type] when "equipment" - return false unless self.equipment_with_gid(requirement[:gid]) + if requirement[:tag] + return false unless self.equipment_with_tag(requirement[:tag]) + else + return false unless self.equipment_with_gid(requirement[:gid]) + end when "stat" # TODO: HACK: This won't work with built-in stats! Need to change this to work with power and whatnot. return false unless self.total_stat_change(requirement[:gid]) >= requirement[:value] diff --git a/app/models/concerns/has_costs_and_requirements.rb b/app/models/concerns/has_costs_and_requirements.rb index 9f859f5..9c4abf8 100644 --- a/app/models/concerns/has_costs_and_requirements.rb +++ b/app/models/concerns/has_costs_and_requirements.rb @@ -22,7 +22,11 @@ module HasCostsAndRequirements when "stat" requirements.push "#{req[:value]} #{req[:gid]}" when "equipment" - requirements.push "equipped #{Item.find_by_gid(req[:gid]).name}" + if req[:tag] + requirements.push "equipped #{req[:tag]}" + else + requirements.push "equipped #{Item.find_by_gid(req[:gid]).name}" + end when "hearth_amenity" requirements.push "level #{req[:level]} #{HearthAmenity.find_by_gid(req[:gid]).name}" else diff --git a/data/activities.yml b/data/activities.yml index ebad3e1..a5364a6 100644 --- a/data/activities.yml +++ b/data/activities.yml @@ -325,8 +325,10 @@ plant_mudtub_seed: - type: "skill" gid: "magiculture" level: 1 + - type: "equipment" + tag: "spade" duration: - base: 120 + base: 60 scaling: - type: "skill" gid: "magiculture" @@ -351,8 +353,10 @@ harvest_mudtub: - type: "skill" gid: "magiculture" level: 1 + - type: "equipment" + tag: "spade" duration: - base: 120 + base: 60 scaling: - type: "skill" gid: "magiculture" @@ -380,8 +384,10 @@ plant_midoras_seed: - type: "skill" gid: "magiculture" level: 2 + - type: "equipment" + tag: "spade" duration: - base: 130 + base: 70 scaling: - type: "skill" gid: "magiculture" @@ -406,8 +412,10 @@ harvest_midoras: - type: "skill" gid: "magiculture" level: 2 + - type: "equipment" + tag: "spade" duration: - base: 130 + base: 70 scaling: - type: "skill" gid: "magiculture" @@ -435,8 +443,10 @@ plant_templis_seed: - type: "skill" gid: "magiculture" level: 4 + - type: "equipment" + tag: "spade" duration: - base: 140 + base: 80 scaling: - type: "skill" gid: "magiculture" @@ -461,8 +471,10 @@ harvest_templis: - type: "skill" gid: "magiculture" level: 4 + - type: "equipment" + tag: "spade" duration: - base: 140 + base: 80 scaling: - type: "skill" gid: "magiculture" @@ -490,8 +502,10 @@ plant_enzon_seed: - type: "skill" gid: "magiculture" level: 7 + - type: "equipment" + tag: "spade" duration: - base: 150 + base: 90 scaling: - type: "skill" gid: "magiculture" @@ -516,8 +530,10 @@ harvest_enzon: - type: "skill" gid: "magiculture" level: 7 + - type: "equipment" + tag: "spade" duration: - base: 150 + base: 90 scaling: - type: "skill" gid: "magiculture" @@ -1979,8 +1995,10 @@ planequarry_floret_mines: - type: "skill" gid: "planequarry" level: 1 + - type: "equipment" + tag: "pickaxe" duration: - base: 130 + base: 70 minimum: 35 scaling: - type: "skill" @@ -2047,8 +2065,10 @@ planequarry_deepshaft: - type: "skill" gid: "planequarry" level: 10 + - type: "equipment" + tag: "pickaxe" duration: - base: 160 + base: 80 minimum: 35 scaling: - type: "skill" @@ -2120,8 +2140,10 @@ planequarry_brine_trench: - type: "skill" gid: "planequarry" level: 1 + - type: "equipment" + tag: "pickaxe" duration: - base: 60 + base: 50 minimum: 25 scaling: - type: "skill" @@ -2207,8 +2229,10 @@ wealdreap_twil_woods: - type: "skill" gid: "wealdreap" level: 1 + - type: "equipment" + tag: "axe" duration: - base: 120 + base: 60 minimum: 35 scaling: - type: "skill" @@ -2276,8 +2300,10 @@ wealdreap_twil_grove: - type: "skill" gid: "wealdreap" level: 10 + - type: "equipment" + tag: "axe" duration: - base: 150 + base: 90 minimum: 35 scaling: - type: "skill" @@ -2347,7 +2373,7 @@ manatrawl_sor_well: gid: "manatrawl" level: 1 - type: "equipment" - gid: "aethermesh" + tag: "aethermesh" duration: base: 60 minimum: 35 @@ -2391,7 +2417,7 @@ manatrawl_sor_well_depths: gid: "manatrawl" level: 7 - type: "equipment" - gid: "aethermesh" + tag: "aethermesh" duration: base: 70 minimum: 35 @@ -2432,7 +2458,7 @@ synthsever_rusted_lockbox: whatnot: requirements: - type: "equipment" - gid: "iron_lockpicks" + gid: "lockpicks" - type: "skill" gid: "synthsever" level: 1 @@ -2929,6 +2955,8 @@ havencast_stinging_rays: - type: "stat" gid: "mana" value: 1 + - type: "equipment" + tag: "focus" results: - type: "condition" gid: "stinging_rays" diff --git a/data/items.yml b/data/items.yml index 428a8a5..ef0a103 100644 --- a/data/items.yml +++ b/data/items.yml @@ -720,6 +720,11 @@ iron_lockpicks: whatnot: tags: - "tool" + - "lockpicks" + equip_effects: + - type: "stat_change" + gid: "synthsever_speed" + modifier: 10 equip_slots: - "mainhand" stone_pickaxe: @@ -728,12 +733,13 @@ stone_pickaxe: whatnot: tags: - "tool" + - "pickaxe" equip_slots: - "mainhand" equip_effects: - type: "stat_change" gid: "planequarry_speed" - modifier: 60 + modifier: 2 - type: "stat_change" gid: "accuracy" modifier: 0 @@ -746,12 +752,13 @@ stone_axe: whatnot: tags: - "tool" + - "axe" equip_slots: - "mainhand" equip_effects: - type: "stat_change" gid: "wealdreap_speed" - modifier: 60 + modifier: 2 - type: "stat_change" gid: "accuracy" modifier: 0 @@ -764,12 +771,13 @@ stone_spade: whatnot: tags: - "tool" + - "spade" equip_slots: - "mainhand" equip_effects: - type: "stat_change" gid: "magiculture_speed" - modifier: 60 + modifier: 2 - type: "stat_change" gid: "accuracy" modifier: 0 @@ -782,12 +790,13 @@ iron_pickaxe: whatnot: tags: - "tool" + - "pickaxe" equip_slots: - "mainhand" equip_effects: - type: "stat_change" gid: "planequarry_speed" - modifier: 80 + modifier: 10 - type: "stat_change" gid: "accuracy" modifier: 1 @@ -800,12 +809,13 @@ iron_axe: whatnot: tags: - "tool" + - "axe" equip_slots: - "mainhand" equip_effects: - type: "stat_change" gid: "wealdreap_speed" - modifier: 80 + modifier: 10 - type: "stat_change" gid: "accuracy" modifier: 1 @@ -818,12 +828,13 @@ iron_spade: whatnot: tags: - "tool" + - "spade" equip_slots: - "mainhand" equip_effects: - type: "stat_change" gid: "magiculture_speed" - modifier: 80 + modifier: 10 - type: "stat_change" gid: "accuracy" modifier: 1 @@ -836,6 +847,7 @@ arcanite_pickaxe: whatnot: tags: - "tool" + - "pickaxe" equip_slots: - "mainhand" equip_requirements: @@ -845,7 +857,7 @@ arcanite_pickaxe: equip_effects: - type: "stat_change" gid: "planequarry_speed" - modifier: 90 + modifier: 20 - type: "stat_change" gid: "accuracy" modifier: 2 @@ -858,6 +870,7 @@ arcanite_axe: whatnot: tags: - "tool" + - "axe" equip_slots: - "mainhand" equip_requirements: @@ -867,7 +880,7 @@ arcanite_axe: equip_effects: - type: "stat_change" gid: "wealdreap_speed" - modifier: 90 + modifier: 20 - type: "stat_change" gid: "accuracy" modifier: 2 @@ -880,6 +893,7 @@ arcanite_spade: whatnot: tags: - "tool" + - "spade" equip_slots: - "mainhand" equip_requirements: @@ -889,7 +903,7 @@ arcanite_spade: equip_effects: - type: "stat_change" gid: "magiculture_speed" - modifier: 90 + modifier: 20 - type: "stat_change" gid: "accuracy" modifier: 2 @@ -902,6 +916,7 @@ aethermesh: whatnot: tags: - "tool" + - "aethermesh" equip_slots: - "mainhand" quarrying_draught: -- cgit v1.2.3 From 8b9191b20faf7473e42b08f5cbf73783f4353b4a Mon Sep 17 00:00:00 2001 From: David Gay Date: Wed, 16 Jun 2021 19:45:34 -0400 Subject: Stinging Rays spell as the first DoT --- app/lib/activity_processor.rb | 11 +++++++++++ app/models/character.rb | 4 ++++ data/activities.yml | 2 +- data/conditions.yml | 5 +++-- 4 files changed, 19 insertions(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/lib/activity_processor.rb b/app/lib/activity_processor.rb index 18fdece..6509b44 100644 --- a/app/lib/activity_processor.rb +++ b/app/lib/activity_processor.rb @@ -305,6 +305,17 @@ class ActivityProcessor combat_message.call("#{target.name} evaded #{actor.name}'s attack.") end + # HACK: DoT is char-only, and one-damage-type-only for now. + if actor == char + actor.dots.each do |data| + damage_roll = rand(data[:min]..data[:max]) + effective_resistance = [target.resistance(data[:gid]), damage_roll].min + resolved_damage = damage_roll - (effective_resistance * rand(0.5..1)).round + mon_hp -= resolved_damage + combat_message.call("#{data[:message]} (#{resolved_damage} #{data[:gid]})") + end + end + if char_hp < 1 || mon_hp < 1 @character.do_equipment_break_checks.each do |broken_item| @results.push({ type: "warning", message: "Your #{broken_item.name} was damaged beyond repair!" }) diff --git a/app/models/character.rb b/app/models/character.rb index a26fb93..b7649c3 100644 --- a/app/models/character.rb +++ b/app/models/character.rb @@ -383,6 +383,10 @@ class Character < ApplicationRecord effects.filter_map { |e| { gid: e[:gid], min: e[:min], max: e[:max] } if e[:type] == "damage" } end + def dots + effects.filter_map { |e| { gid: e[:gid], min: e[:min], max: e[:max], message: e[:message] } if e[:type] == "dot" } + end + def planting_spots [total_stat_change("planting_spots"), 0].max end diff --git a/data/activities.yml b/data/activities.yml index 3202e7f..316b3de 100644 --- a/data/activities.yml +++ b/data/activities.yml @@ -3001,7 +3001,7 @@ havencast_stinging_rays: results: - type: "condition" gid: "stinging_rays" - duration: 300 # 10 minutes + duration: 600 # 10 minutes message: "Beams of arcane energy shoot at your enemies from the air around you." - type: "xp" gid: "havencast" diff --git a/data/conditions.yml b/data/conditions.yml index c72cf36..95d2bda 100644 --- a/data/conditions.yml +++ b/data/conditions.yml @@ -115,11 +115,12 @@ dazzle: gid: "accuracy" modifier: -1 stinging_rays: - name: "stinging_rays" + name: "stinging rays" description: "Adds arcane damage to your attacks." whatnot: effects: - - type: "damage" + - type: "dot" gid: "arcane" min: 1 max: 3 + message: "Stinging rays spring from the air around you and hit your enemy." -- cgit v1.2.3 From 212c104c2020faddcb2949bc8f11e15c8284fb52 Mon Sep 17 00:00:00 2001 From: David Gay Date: Wed, 16 Jun 2021 20:12:18 -0400 Subject: Change item infix break chance to 1/500 --- CHANGELOG.md | 6 +++--- app/models/item_infix.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'app/models') diff --git a/CHANGELOG.md b/CHANGELOG.md index fa5e676..203a738 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ All notable changes to this project will be documented in this file. thereafter, another infix slot becomes available. - Omens can be removed and re-infixed at will. - All omens infixed in a skill have a chance to fade away and be permanently lost when performing that skill - (like equipment breakage). The chance of an infixed omen fading away is 1/1000. You do not need to actively be + (like equipment breakage). The chance of an infixed omen fading away is 1/500. You do not need to actively be getting a bonus from an infixed omen for it to have a chance to fade away. When performing a skill, all omens infixed in that skill have the same chance to fade away. - Duplicate omens can be infixed, and their effects will stack if possible. @@ -43,11 +43,11 @@ All notable changes to this project will be documented in this file. - Level requirements changes - Arcanite longsword 15 -> 17 (setting it to 15 was a programming error) - Havencast - - New cantrips: Light, Dazzle, Decipher Magicscript, Enchant Apprentice Wand + - New cantrips: Light, Dazzle, Decipher Simple Magicscript, Enchant Apprentice Wand - New spells: Stinging Rays, Flame Whirl ### Items -- New items: apprentice wand, faint mana, minor mana +- New items: apprentice wand, faint mana, minor mana, simple spellpage - Iron lockpicks now increase synthsever speed by 10 seconds - Axes, pickaxes, and spades skill speed increase numbers all adjusted to compensate for base timer reductions diff --git a/app/models/item_infix.rb b/app/models/item_infix.rb index 47b6aa4..b59ccdb 100644 --- a/app/models/item_infix.rb +++ b/app/models/item_infix.rb @@ -10,7 +10,7 @@ class ItemInfix < ApplicationRecord end def break_check - rand > 0.999 ? destroy : false + rand > 0.998 ? destroy : false end private -- cgit v1.2.3