class GameController < ApplicationController def finish_activity @results = [] return unless current_char.activity_time_remaining <= 0 activity = current_char.activity return unless current_char.can_do_activity?(activity) # TODO: Add error message current_char.update(activity_started_at: Time.now) Character.transaction do current_char.pay_cost_for(activity) activity.whatnot[:results].each do |result| type = result[:type] case type when "item" next if rand > (result[:chance] || 1) if result[:table] table_roll = rand result[:table].sort_by { |t| -t[:score] }.each do |table_entry| quantity = table_entry[:quantity] || 1 score = table_entry[:score] table_scaling = result[:table_scaling] table_scaling&.each do |scale_entry| case scale_entry[:type] when "skill" score = score**(1 + (scale_entry[:scale_value] * current_char.skill_level(scale_entry[:gid]))) end end if table_roll >= score give_item_with_xp(table_entry, quantity) break end end else quantity = result[:quantity] || 1 give_item_with_xp(result, quantity) end when "hearth_amenity" bhi = current_char.hearth.built_hearth_amenities .find_or_initialize_by(hearth_amenity: HearthAmenity.find_by_gid(result[:gid])) bhi.update(level: result[:level]) @results.push({ type: type, hearth_amenity: bhi.hearth_amenity }) when "activity" next if rand > (result[:chance] || 1) table_roll = rand result[:table].sort_by { |t| -t[:score] }.each do |table_entry| score = table_entry[:score] result[:table_scaling]&.each do |scale_entry| case scale_entry[:type] when "skill" score = score**(1 + (scale_entry[:scale_value] * current_char.skill_level(scale_entry[:gid]))) end end if table_roll >= score activity = Activity.find_by_gid(table_entry[:gid]) unless current_char.learned_activities.exists?(activity: activity) current_char.learned_activities.create(activity: activity) @results.push({ type: type, activity: activity }) end end end else raise "Invalid result type (#{type})" # TODO: Improve this. end end end rescue ItemQuantityError @results.replace({ type: "error", message: "You don't have enough items to complete this activity." }) end private def give_item_with_xp(data, quantity) item = Item.find_by_gid(data[:gid]) xp_awards = data[:xp]&.map { |xpe| { skill: Skill.find_by_gid(xpe[:gid]), amount: xpe[:value] } } xp_awards&.each do |award| current_char.add_skill_xp(award[:skill], (award[:amount] * quantity)) end current_char.shift_item(item, quantity) @results.push({ type: "item", item: item, quantity: quantity, xp: xp_awards }) end end