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/lib/activity_processor.rb | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'app/lib/activity_processor.rb') 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 -- 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/lib/activity_processor.rb') 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/lib/activity_processor.rb') 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 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/lib/activity_processor.rb') 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 0f6b68f115d2d16c7ef73d80570b1b85a1368a43 Mon Sep 17 00:00:00 2001 From: David Gay Date: Wed, 16 Jun 2021 18:00:03 -0400 Subject: [data] New activities: havencast_dazzle, havencast_stinging_rays --- CHANGELOG.md | 4 ++- app/lib/activity_processor.rb | 4 +++ data/activities.yml | 62 ++++++++++++++++++++++++++++++++++++++++++- data/conditions.yml | 9 +++++++ data/items.yml | 6 +++++ 5 files changed, 83 insertions(+), 2 deletions(-) (limited to 'app/lib/activity_processor.rb') diff --git a/CHANGELOG.md b/CHANGELOG.md index b6fd397..aeb3184 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,7 +38,9 @@ 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 +- Havencast + - New cantrips: Light, Dazzle + - New spells: Stinging Rays ### Items - New item: faint mana diff --git a/app/lib/activity_processor.rb b/app/lib/activity_processor.rb index 248ed9d..fb0b13d 100644 --- a/app/lib/activity_processor.rb +++ b/app/lib/activity_processor.rb @@ -97,6 +97,10 @@ class ActivityProcessor @results.push({ type: "message", body: result[:message] }) @results.push({ type: type, condition: condition }) end + when "decipher_magicscript" + Character.transaction do + # TODO: Add functionality + end when "activity" next if rand > (result[:chance] || 1) table_roll = rand diff --git a/data/activities.yml b/data/activities.yml index c9ea218..ebad3e1 100644 --- a/data/activities.yml +++ b/data/activities.yml @@ -2854,6 +2854,7 @@ havencast_dazzle: description: "Cast the Dazzle cantrip." whatnot: tags: + - "spell" - "cantrip" duration: base: 32 @@ -2876,4 +2877,63 @@ havencast_dazzle: message: "Sparkling lights distract your enemies." - type: "xp" gid: "havencast" - base: 6 + base: 5 +havencast_decipher_magicscript: + name: "Cast Decipher Magicscript" + description: "Cast the Decipher Magicscript cantrip." + whatnot: + tags: + - "spell" + - "cantrip" + duration: + base: 34 + minimum: 10 + scaling: + - type: "skill" + gid: "havencast" + scale_value: 1 + requirements: + - type: "skill" + gid: "havencast" + level: 3 + - type: "stat" + gid: "mana" + value: 1 + cost: + - type: "item" + gid: "spellpage" + quantity: 1 + results: + - type: "xp" + gid: "havencast" + base: 7 + - type: "decipher_magicscript" +havencast_stinging_rays: + name: "Cast Stinging Rays" + description: "Cast the Stinging Rays spell." + innate: false + whatnot: + tags: + - "spell" + duration: + base: 38 + minimum: 10 + scaling: + - type: "skill" + gid: "havencast" + scale_value: 1 + requirements: + - type: "skill" + gid: "havencast" + level: 5 + - type: "stat" + gid: "mana" + value: 1 + results: + - type: "condition" + gid: "stinging_rays" + duration: 300 # 10 minutes + message: "Beams of arcane energy shoot at your enemies from the air around you." + - type: "xp" + gid: "havencast" + base: 11 diff --git a/data/conditions.yml b/data/conditions.yml index e1a5d2d..c72cf36 100644 --- a/data/conditions.yml +++ b/data/conditions.yml @@ -114,3 +114,12 @@ dazzle: - type: "enemy_stat_change" gid: "accuracy" modifier: -1 +stinging_rays: + name: "stinging_rays" + description: "Adds arcane damage to your attacks." + whatnot: + effects: + - type: "damage" + gid: "arcane" + min: 1 + max: 3 diff --git a/data/items.yml b/data/items.yml index 224aac6..428a8a5 100644 --- a/data/items.yml +++ b/data/items.yml @@ -1106,3 +1106,9 @@ faint_mana: - type: "stat_change" gid: "mana" modifier: 1 +spellpage: + name: "spellpage" + description: "A piece of parchment covered in magical script. Deciphering it can yield knowledge of a spell." + whatnot: + tags: + - "materials" -- cgit v1.2.3 From 361acfad2162e08a962c63c4443641fbbd812089 Mon Sep 17 00:00:00 2001 From: David Gay Date: Wed, 16 Jun 2021 19:20:17 -0400 Subject: Learn spells from spellpages --- app/controllers/characters/spells_controller.rb | 6 +++++- app/lib/activity_processor.rb | 5 +---- app/views/application/_results.html.erb | 2 +- data/activities.yml | 16 ++++++++++------ data/items.yml | 8 ++++---- 5 files changed, 21 insertions(+), 16 deletions(-) (limited to 'app/lib/activity_processor.rb') diff --git a/app/controllers/characters/spells_controller.rb b/app/controllers/characters/spells_controller.rb index 9694856..a0e6913 100644 --- a/app/controllers/characters/spells_controller.rb +++ b/app/controllers/characters/spells_controller.rb @@ -1,5 +1,9 @@ class Characters::SpellsController < ApplicationController def index - @spell_activities = Activity.where("gid like ?", "havencast_%").order(:name) + @spell_activities = Activity.where("gid like ?", "havencast_%").where(innate: true).order(:name) + # TODO: Don't load into memory + @spell_activities = @spell_activities.to_a + current_char.learned_activities + .map { |la| la.activity } + .select { |a| a.gid.start_with?("havencast_") } end end diff --git a/app/lib/activity_processor.rb b/app/lib/activity_processor.rb index fb0b13d..18fdece 100644 --- a/app/lib/activity_processor.rb +++ b/app/lib/activity_processor.rb @@ -97,10 +97,6 @@ class ActivityProcessor @results.push({ type: "message", body: result[:message] }) @results.push({ type: type, condition: condition }) end - when "decipher_magicscript" - Character.transaction do - # TODO: Add functionality - end when "activity" next if rand > (result[:chance] || 1) table_roll = rand @@ -108,6 +104,7 @@ class ActivityProcessor score = table_entry[:score] if table_roll >= score new_activity = Activity.find_by_gid(table_entry[:gid]) + raise "Invalid activity gid (#{table_entry[:gid]})" unless new_activity unless @character.learned_activities.exists?(activity: new_activity) @character.learned_activities.create(activity: new_activity) @results.push({ type: type, activity: new_activity }) diff --git a/app/views/application/_results.html.erb b/app/views/application/_results.html.erb index 691f1d5..a7dc002 100644 --- a/app/views/application/_results.html.erb +++ b/app/views/application/_results.html.erb @@ -13,7 +13,7 @@

You planted <%= link_to result[:hearth_planting].item.name, item_path(result[:hearth_planting].item) %> in the loam.

<% when "activity" %> -

You realized how to <%= result[:activity].name %>!

+

You learned how to <%= result[:activity].name %>!

<% when "monster" %>

You encountered a <%= result[:monster].name %>.

<%= result[:monster].description %>

diff --git a/data/activities.yml b/data/activities.yml index 66b7765..3202e7f 100644 --- a/data/activities.yml +++ b/data/activities.yml @@ -2904,9 +2904,9 @@ havencast_dazzle: - type: "xp" gid: "havencast" base: 5 -havencast_decipher_magicscript: - name: "Cast Decipher Magicscript" - description: "Cast the Decipher Magicscript cantrip." +havencast_decipher_simple_magicscript: + name: "Cast Decipher Simple Magicscript" + description: "Cast the Decipher Simple Magicscript cantrip." whatnot: tags: - "spell" @@ -2927,13 +2927,17 @@ havencast_decipher_magicscript: value: 1 cost: - type: "item" - gid: "spellpage" + gid: "simple_spellpage" quantity: 1 results: - type: "xp" gid: "havencast" - base: 7 - - type: "decipher_magicscript" + base: 10 + - type: "activity" + chance: 1 + table: + - gid: "havencast_stinging_rays" + score: 0 havencast_enchant_apprentice_wand: name: "Cast Enchant Apprentice Wand" description: "Cast the Enchant Apprentice Wand spell." diff --git a/data/items.yml b/data/items.yml index b20ab34..a89591e 100644 --- a/data/items.yml +++ b/data/items.yml @@ -1134,9 +1134,9 @@ faint_mana: - type: "stat_change" gid: "mana" modifier: 1 -spellpage: - name: "spellpage" - description: "A piece of parchment covered in magical script. Deciphering it can yield knowledge of a spell." +simple_spellpage: + name: "simple spellpage" + description: "An old piece of parchment covered in magical script. Deciphering it can yield knowledge of a spell." whatnot: tags: - - "materials" + - "material" -- 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/lib/activity_processor.rb') 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