From 73744a9c6840fb0ba6f285ca81f9fba75ec22d5f Mon Sep 17 00:00:00 2001 From: David Gay Date: Tue, 4 May 2021 17:55:28 -0400 Subject: Initial draft of timer setup, with results outputting and items being awarded --- app/controllers/activities_controller.rb | 11 +++++ app/controllers/game_controller.rb | 25 +++++++++++ .../controllers/activities/timer_controller.js | 43 +++++++++++++++++++ app/javascript/packs/application.js | 7 ++++ app/models/character.rb | 15 +++++++ app/views/activities/_results.html.erb | 7 ++++ app/views/activities/_timer.html.erb | 8 ++++ app/views/activities/show.html.erb | 11 +++++ app/views/game/finish_activity.js.erb | 12 ++++++ app/views/locations/show.html.erb | 3 +- config/routes.rb | 6 +++ data/activities.yml | 48 +++++++++++++--------- package.json | 1 + yarn.lock | 32 +++++++++++++++ 14 files changed, 208 insertions(+), 21 deletions(-) create mode 100644 app/controllers/activities_controller.rb create mode 100644 app/controllers/game_controller.rb create mode 100644 app/javascript/controllers/activities/timer_controller.js create mode 100644 app/views/activities/_results.html.erb create mode 100644 app/views/activities/_timer.html.erb create mode 100644 app/views/activities/show.html.erb create mode 100644 app/views/game/finish_activity.js.erb diff --git a/app/controllers/activities_controller.rb b/app/controllers/activities_controller.rb new file mode 100644 index 0000000..a535f99 --- /dev/null +++ b/app/controllers/activities_controller.rb @@ -0,0 +1,11 @@ +class ActivitiesController < ApplicationController + def show + @activity = Activity.find(params[:id]) + end + + def start + @activity = Activity.find(params[:id]) + current_char.update(activity: @activity, activity_started_at: Time.now) + redirect_to action: :show + end +end diff --git a/app/controllers/game_controller.rb b/app/controllers/game_controller.rb new file mode 100644 index 0000000..3516056 --- /dev/null +++ b/app/controllers/game_controller.rb @@ -0,0 +1,25 @@ +class GameController < ApplicationController + def finish_activity + @results = [] + return unless current_char.activity_time_remaining <= 0 + current_char.update(activity_started_at: Time.now) + current_char.activity.whatnot["results"].each do |result| + type = result["type"] + case type + when "item" + next if rand > result["chance"] + table_roll = rand + result["table"].sort_by { |_, v| -v["score"] }.each do |item_gid, item_data| + quantity = item_data["quantity"] || 1 + if table_roll >= item_data["score"] + current_char.shift_item(item_gid, quantity) + @results.push({ type: type, item: Item.find_by_gid(item_gid), quantity: quantity }) + break + end + end + else + raise "Invalid result type (#{type})" # TODO: Improve this. + end + end + end +end diff --git a/app/javascript/controllers/activities/timer_controller.js b/app/javascript/controllers/activities/timer_controller.js new file mode 100644 index 0000000..11057c0 --- /dev/null +++ b/app/javascript/controllers/activities/timer_controller.js @@ -0,0 +1,43 @@ +import { Controller } from "stimulus"; +import Rails from "@rails/ujs"; + +export default class extends Controller { + static targets = [ "timer" ]; + + static values = { + start: Number, + } + + initialize() { + this.counter = this.startValue; + this.timerTarget.textContent = this.counter; + } + + connect() { + this.startUpdating(); + } + + disconnect() { + this.stopUpdating(); + } + + startUpdating() { + this.timerInterval = setInterval(() => { + if (this.counter > 0) { + this.timerTarget.textContent = this.counter.toString(); + this.counter--; + } else if (this.counter === 0) { + Rails.ajax({ + type: "POST", + url: "/finish_activity", + }); + } + }, 1000); + } + + stopUpdating() { + if (this.timerInterval) { + clearInterval(this.timerInterval); + } + } +} diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 856724b..a18528e 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -13,3 +13,10 @@ Turbolinks.start() ActiveStorage.start() require("stylesheets/application.css") + +// Stimulus +import { Application } from "stimulus" +import { definitionsFromContext } from "stimulus/webpack-helpers" +const application = Application.start() +const context = require.context("../controllers", true, /\.js$/) +application.load(definitionsFromContext(context)) diff --git a/app/models/character.rb b/app/models/character.rb index 1e75b63..aa434ef 100644 --- a/app/models/character.rb +++ b/app/models/character.rb @@ -19,6 +19,21 @@ class Character < ApplicationRecord end end + def skill_level(gid) + self.character_skills.find_by(skill: Skill.find_by_gid(gid.to_s)).level + end + + def activity_time_remaining + return nil unless self.activity + duration_data = self.activity.whatnot["duration"] + duration = duration_data["base"] + duration_data["scaling"].each do |skill, scaling_amount| + duration -= self.skill_level(skill) * scaling_amount + end + duration = [duration, duration_data["minimum"]].max + duration - (Time.now - self.activity_started_at) + end + private def create_skills Skill.all.each { |skill| self.character_skills.create(skill: skill, xp: 0) } diff --git a/app/views/activities/_results.html.erb b/app/views/activities/_results.html.erb new file mode 100644 index 0000000..baa4ab0 --- /dev/null +++ b/app/views/activities/_results.html.erb @@ -0,0 +1,7 @@ +
+ <% results.each do |result| %> + <% if result[:type] == "item" %> +

You got <%= result[:quantity] %> <%= result[:item].name %>.

+ <% end %> + <% end %> +
diff --git a/app/views/activities/_timer.html.erb b/app/views/activities/_timer.html.erb new file mode 100644 index 0000000..418c378 --- /dev/null +++ b/app/views/activities/_timer.html.erb @@ -0,0 +1,8 @@ +<% if current_char.activity %> +
+ +
+ <%= link_to "Stop", location_path(current_char.activity.location) %> +<% end %> diff --git a/app/views/activities/show.html.erb b/app/views/activities/show.html.erb new file mode 100644 index 0000000..4e77061 --- /dev/null +++ b/app/views/activities/show.html.erb @@ -0,0 +1,11 @@ +

<%= @activity.name %>

+

<%= @activity.description %>

+ +
+
+ +
+ <%= render "timer" %> +
+ +<%= link_to "Start", start_activity_path(@activity), method: :post %> diff --git a/app/views/game/finish_activity.js.erb b/app/views/game/finish_activity.js.erb new file mode 100644 index 0000000..99d200c --- /dev/null +++ b/app/views/game/finish_activity.js.erb @@ -0,0 +1,12 @@ +var resultOutputDiv = document.getElementById("result_output"); +var resultControlsDiv = document.getElementById("result_controls"); + +var outputHTML = "<%= j render(partial: "activities/results", locals: { results: @results }) %>" + +if (resultOutputDiv) { + resultOutputDiv.innerHTML += outputHTML; +} + +if (resultControlsDiv) { + resultControlsDiv.innerHTML = "<%= j render(partial: "activities/timer") %>" +} diff --git a/app/views/locations/show.html.erb b/app/views/locations/show.html.erb index c3a75e1..bc63541 100644 --- a/app/views/locations/show.html.erb +++ b/app/views/locations/show.html.erb @@ -2,6 +2,7 @@ diff --git a/config/routes.rb b/config/routes.rb index 6442ec2..9e6fb82 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -11,6 +11,10 @@ Rails.application.routes.draw do put "users", to: "devise/registrations#update", as: "user_registration" end + resources :activities, only: [:show] do + post "start", on: :member + end + resources :characters, only: [:show, :new, :create] do scope module: :characters do resources :items, only: [:index] @@ -18,4 +22,6 @@ Rails.application.routes.draw do end resources :locations, only: [:index, :show] + + post "/finish_activity", to: "game#finish_activity" end diff --git a/data/activities.yml b/data/activities.yml index f03c15e..9ecd299 100644 --- a/data/activities.yml +++ b/data/activities.yml @@ -9,23 +9,31 @@ quarry_floret_mines: scaling: planequarry: 2 results: - - item: - chance: 1 - table: - stone: 0 - - item: - chance: 1 - table: - crude_iron_ore: 0 - iron_ore: 0.98 - pure_iron_ore: 0.996 - table_scaling: - skills: - planequarry: 1.25 - - item: - chance: 0.02 - table: - red_beryl: 0 - tourmaline: 0.45 - yellow_beryl: 0.90 - paraiba_tourmaline: 0.95 + - type: "item" + chance: 1 + table: + stone: + score: 0 + - type: "item" + chance: 1 + table: + crude_iron_ore: + score: 0 + iron_ore: + score: 0.98 + pure_iron_ore: + score: 0.996 + table_scaling: + skills: + planequarry: 1.25 + - type: "item" + chance: 0.02 + table: + red_beryl: + score: 0 + tourmaline: + score: 0.45 + yellow_beryl: + score: 0.90 + paraiba_tourmaline: + score: 0.95 diff --git a/package.json b/package.json index c34fc01..08a3d59 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "@rails/activestorage": "^6.0.0", "@rails/ujs": "^6.0.0", "@rails/webpacker": "5.2.1", + "stimulus": "^2.0.0", "tailwindcss": "npm:@tailwindcss/postcss7-compat", "turbolinks": "^5.2.0" }, diff --git a/yarn.lock b/yarn.lock index ca3be90..89f6c22 100644 --- a/yarn.lock +++ b/yarn.lock @@ -944,6 +944,30 @@ webpack-cli "^3.3.12" webpack-sources "^1.4.3" +"@stimulus/core@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@stimulus/core/-/core-2.0.0.tgz#140c85318d6a8a8210c0faf182223b8459348877" + integrity sha512-ff70GafKtzc8zQ1/cG+UvL06GcifPWovf2wBEdjLMh9xO2GOYURO3y2RYgzIGYUIBefQwyfX2CLfJdZFJrEPTw== + dependencies: + "@stimulus/mutation-observers" "^2.0.0" + +"@stimulus/multimap@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@stimulus/multimap/-/multimap-2.0.0.tgz#420cfa096ed6538df4a91dbd2b2842c1779952b2" + integrity sha512-pMBCewkZCFVB3e5mEMoyO9+9aKzHDITmf3OnPun51YWxlcPdHcwbjqm1ylK63fsoduIE+RowBpFwFqd3poEz4w== + +"@stimulus/mutation-observers@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@stimulus/mutation-observers/-/mutation-observers-2.0.0.tgz#3dbe37453bda47a6c795a90204ee8d77a799fb87" + integrity sha512-kx4VAJdPhIGBQKGIoUDC2tupEKorG3A+ckc2b1UiwInKTMAC1axOHU8ebcwhaJIxRqIrs8//4SJo9YAAOx6FEg== + dependencies: + "@stimulus/multimap" "^2.0.0" + +"@stimulus/webpack-helpers@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@stimulus/webpack-helpers/-/webpack-helpers-2.0.0.tgz#54296d2a2dffd4f962d2e802d99a3fdd84b8845f" + integrity sha512-D6tJWsAC024MwGEIKlUVYU8Ln87mlrmiwHvYAjipg+s8H4eLxUMQ3PZkWyPevfipH+oR3leuHsjYsK1gN5ViQA== + "@types/glob@^7.1.1": version "7.1.3" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" @@ -7096,6 +7120,14 @@ stdout-stream@^1.4.0: dependencies: readable-stream "^2.0.1" +stimulus@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/stimulus/-/stimulus-2.0.0.tgz#713c8b91a72ef90914b90955f0e705f004403047" + integrity sha512-xipy7BS5TVpg4fX6S8LhrYZp7cmHGjmk09WSAiVx1gF5S5g43IWsuetfUhIk8HfHUG+4MQ9nY0FQz4dRFLs/8w== + dependencies: + "@stimulus/core" "^2.0.0" + "@stimulus/webpack-helpers" "^2.0.0" + stream-browserify@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" -- cgit v1.2.3