summaryrefslogtreecommitdiff
path: root/app/controllers/game_controller.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/controllers/game_controller.rb')
-rw-r--r--app/controllers/game_controller.rb80
1 files changed, 80 insertions, 0 deletions
diff --git a/app/controllers/game_controller.rb b/app/controllers/game_controller.rb
index 58644a7..c63fbc5 100644
--- a/app/controllers/game_controller.rb
+++ b/app/controllers/game_controller.rb
@@ -13,6 +13,23 @@ class GameController < ApplicationController
activity.whatnot[:results].each do |result|
type = result[:type]
case type
+ when "monster"
+ 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])
+ monster = Monster.find_by_gid(table_entry[:gid])
+ resolve_combat_with(monster)
+ end
+ end
when "item"
next if rand > (result[:chance] || 1)
@@ -83,4 +100,67 @@ class GameController < ApplicationController
current_char.shift_item(item, quantity)
@results.push({ type: "item", item: item, quantity: quantity, xp: xp_awards })
end
+
+ def resolve_combat_with(mon)
+ char = current_char
+ char_hp = current_char.max_hp
+ mon_hp = mon.max_hp
+ combat_message = ->(msg) { @results.push({ type: "message", body: "[#{char_hp}/#{char.max_hp}] #{msg}" }) }
+ combat_message.call("You encountered a #{mon.name}.")
+ char_initiative = roll(10) + char.speed
+ mon_initative = roll(10) + mon.speed
+ if char_initiative > mon_initative
+ turn_order = [char, mon]
+ elsif mon_initative > char_initiative
+ turn_order = [mon, char]
+ else
+ turn_order = [char, mon].shuffle
+ end
+ turn_order.cycle do |actor|
+ case actor
+ when char
+ accuracy_roll = roll(20) + char.accuracy
+ evasion_roll = roll(20) + mon.evasion
+ if accuracy_roll >= evasion_roll
+ dealt_damage = roll(4) + char.power # TODO: Replace d4 with weapon damage
+ if accuracy_roll >= (evasion_roll + 10)
+ combat_message.call("You landed a critical hit!")
+ dealt_damage = dealt_damage * 2
+ end
+ blocked_damage = (accuracy_roll >= (roll(20) + mon.block)) ? 0 : mon.block_value
+ resolved_damage = dealt_damage - blocked_damage
+ mon_hp -= resolved_damage
+ combat_message.call("You hit for #{resolved_damage} (#{dealt_damage} - #{blocked_damage} blocked)")
+ elsif evasion_roll > accuracy_roll
+ combat_message.call("The #{mon.name} evaded your attack.")
+ end
+ when mon
+ combat_message.call("Monsters don't get turns yet.")
+ else
+ raise "Invalid combatant (class is #{actor.class})"
+ end
+ if char_hp < 1 || mon_hp < 1
+ if char_hp < 1
+ combat_message.call("You were defeated! You retreat, wounded.")
+ char.increment(:wounds)
+ else
+ combat_message.call("You defeated the #{mon.name}.")
+ mon.whatnot[:awards]&.each do |award_data|
+ case award_data[:type]
+ when "xp"
+ skill = Skill.find_by_gid(award_data[:skill])
+ amount = award_data[:base]
+ char.add_skill_xp(skill, amount)
+ combat_message.call("You gained #{amount} #{skill.name} XP.")
+ else
+ raise "Invalid award type string (#{award_data[:type]})"
+ end
+ end
+ end
+ break
+ else
+ combat_message.call("-" * 20)
+ end
+ end
+ end
end