Skip to content

Commit

Permalink
events
Browse files Browse the repository at this point in the history
  • Loading branch information
MahtraDR committed Oct 28, 2024
1 parent 5e8ee14 commit fc31aeb
Show file tree
Hide file tree
Showing 6 changed files with 345 additions and 18 deletions.
4 changes: 4 additions & 0 deletions lib/dragonrealms/drinfomon/drdefs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ def convert2copper(amt, denomination)
end
end

def check_exp_mods
Lich::Util.issue_command("exp mods", /The following skills are currently under the influence of a modifier/, /^<output class=""/, quiet: true, include_end: false, usexml: false)
end

def convert2plats(copper)
denominations = [[10_000, 'platinum'], [1000, 'gold'], [100, 'silver'], [10, 'bronze'], [1, 'copper']]
denominations.inject([copper, []]) do |result, denomination|
Expand Down
2 changes: 2 additions & 0 deletions lib/dragonrealms/drinfomon/drinfomon.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@
require_relative "./drskill"
require_relative "./drstats"
require_relative "./drroom"
require_relative "./drspells"
require_relative "./events"
159 changes: 141 additions & 18 deletions lib/dragonrealms/drinfomon/drparser.rb
Original file line number Diff line number Diff line change
@@ -1,28 +1,47 @@
# frozen_string_literal: true

module DRParser

module Pattern
ExpColumns = /(?:\s*(?<skill>[a-zA-Z\s]+)\b:\s*(?<rank>\d+)\s+(?<percent>\d+)%\s+(?<rate>[a-zA-Z\s]+)\b)/
BriefExpOn = %r{<component id='exp .*?<d cmd='skill (?<skill>[a-zA-Z\s]+)'.*:\s+(?<rank>\d+)\s+(?<percent>\d+)%\s*\[\s?(?<rate>\d+)\/34\].*?<\/component>}
BriefExpOff = %r{<component id='exp .*?\b(?<skill>[a-zA-Z\s]+)\b:\s+(?<rank>\d+)\s+(?<percent>\d+)%\s+\b(?<rate>[a-zA-Z\s]+)\b.*?<\/component>}
NameRaceGuild = /^Name:\s+\b(?<name>.+)\b\s+Race:\s+\b(?<race>.+)\b\s+Guild:\s+\b(?<guild>.+)\b\s+/
GenderAgeCircle = /^Gender:\s+\b(?<gender>.+)\b\s+Age:\s+\b(?<age>.+)\b\s+Circle:\s+\b(?<circle>.+)/
StatValue = /(?<stat>Strength|Agility|Discipline|Intelligence|Reflex|Charisma|Wisdom|Stamina|Favors|TDPs)\s+:\s+(?<value>\d+)/
TDPValue = /You have (\d+) TDPs\./
EncumbranceValue = /^\s*Encumbrance\s+:\s+(?<encumbrance>[\w\s'?!]+)$/
LuckValue = /^\s*Luck\s+:\s+.*\((?<luck>[-\d]+)\/3\)/
BalanceValue = /^(?:You are|\[You're) (?<balance>#{Regexp.union(DR_BALANCE_VALUES)}) balanced?/
ExpClearMindstate = %r{<component id='exp (?<skill>[a-zA-Z\s]+)'><\/component>}
RoomPlayers = %r{\'room players\'>Also here: (.*)\.</component>}
RoomPlayersEmpty = %r{\'room players\'></component>}
RoomObjs = %r{\'room objs\'>(.*)</component>}
RoomObjsEmpty = %r{\'room objs\'></component>}
RoomExits = /Obvious (exits|paths):/
GroupMembers = %r{<pushStream id="group"/> (\w+):}
GroupMembersEmpty = %r{<pushStream id="group"/>Members of your group:}
ExpColumns = /(?:\s*(?<skill>[a-zA-Z\s]+)\b:\s*(?<rank>\d+)\s+(?<percent>\d+)%\s+(?<rate>[a-zA-Z\s]+)\b)/.freeze
BriefExpOn = %r{<component id='exp .*?<d cmd='skill (?<skill>[a-zA-Z\s]+)'.*:\s+(?<rank>\d+)\s+(?<percent>\d+)%\s*\[\s?(?<rate>\d+)\/34\].*?<\/component>}.freeze
BriefExpOff = %r{<component id='exp .*?\b(?<skill>[a-zA-Z\s]+)\b:\s+(?<rank>\d+)\s+(?<percent>\d+)%\s+\b(?<rate>[a-zA-Z\s]+)\b.*?<\/component>}.freeze
NameRaceGuild = /^Name:\s+\b(?<name>.+)\b\s+Race:\s+\b(?<race>.+)\b\s+Guild:\s+\b(?<guild>.+)\b\s+/.freeze
GenderAgeCircle = /^Gender:\s+\b(?<gender>.+)\b\s+Age:\s+\b(?<age>.+)\b\s+Circle:\s+\b(?<circle>.+)/.freeze
StatValue = /(?<stat>Strength|Agility|Discipline|Intelligence|Reflex|Charisma|Wisdom|Stamina|Favors|TDPs)\s+:\s+(?<value>\d+)/.freeze
TDPValue = /You have (\d+) TDPs\./.freeze
EncumbranceValue = /^\s*Encumbrance\s+:\s+(?<encumbrance>[\w\s'?!]+)$/.freeze
LuckValue = /^\s*Luck\s+:\s+.*\((?<luck>[-\d]+)\/3\)/.freeze
BalanceValue = /^(?:You are|\[You're) (?<balance>#{Regexp.union(DR_BALANCE_VALUES)}) balanced?/.freeze
ExpClearMindstate = %r{<component id='exp (?<skill>[a-zA-Z\s]+)'><\/component>}.freeze
RoomPlayers = %r{\'room players\'>Also here: (.*)\.</component>}.freeze
RoomPlayersEmpty = %r{\'room players\'></component>}.freeze
RoomObjs = %r{\'room objs\'>(.*)</component>}.freeze
RoomObjsEmpty = %r{\'room objs\'></component>}.freeze
RoomExits = /Obvious (exits|paths):/.freeze
GroupMembers = %r{<pushStream id="group"/> (\w+):}.freeze
GroupMembersEmpty = %r{<pushStream id="group"/>Members of your group:}.freeze
ExpModsStart = /^(<.*?\/>)?The following skills are currently under the influence of a modifier/.freeze
MultiEnd = %r{^<output class=""/>}.freeze
ExpMods = /^<preset id="speech">(?<sign>\+|\-)+(?<value>\d+) \b(?<skill>[\w\s]+)\b<\/preset>/.freeze
end

@parsing_exp_mods_output = false

def self.check_events(server_string)
Flags.matchers.each do |key, regexes|
regexes.each do |regex|
if (matches = server_string.match(regex))
Flags.flags[key] = matches
break
end
end
end
server_string
end

def self.parse(line)
check_events(line)
begin
case line
when Pattern::GenderAgeCircle
Expand Down Expand Up @@ -78,6 +97,110 @@ def self.parse(line)
rate_as_number = DR_LEARNING_RATES.index(rate_as_word) # convert word to number
DRSkill.update(skill_value, rank_value, rate_as_number, percent_value)
end
when Pattern::ExpModsStart
@parsing_exp_mods_output = true
DRSkill.exp_modifiers.clear
when Pattern::ExpMods
if @parsing_exp_mods_output
skill = Regexp.last_match[:skill]
sign = Regexp.last_match[:sign]
value = Regexp.last_match[:value].to_i
value = (value * -1) if sign == '-'
DRSkill.update_mods(skill, value)
end
when Pattern::MultiEnd
@parsing_exp_mods_output = false
when /^You will .* (?<format>column-formatted|non-column) output for the SPELLS verb/
# Parse `toggle spellbook` command
DRSpells.spellbook_format = Regexp.last_match[:format]
when /^You recall the spells you have learned/
DRSpells.grabbing_known_spells = true
DRSpells.known_spells.clear()
DRSpells.known_feats.clear()
DRSpells.spellbook_format = 'non-column' # assume original format
when /^<output class="mono"\/>/
# Matched an xml tag while parsing spells, must be column-formatted output
if DRSpells.grabbing_known_spells
DRSpells.spellbook_format = 'column-formatted'
end
when /^[\w\s]+:/
# Matched the spellbook name in column-formatted output, ignore
when /Slot\(s\): \d+ \s+ Min Prep: \d+ \s+ Max Prep: \d+/
# Matched the spell info in column-formatted output, parse
if DRSpells.grabbing_known_spells && DRSpells.spellbook_format == 'column-formatted'
spell = line
.sub('<popBold/>', '') # remove xml tag at start of some lines
.slice(10, 32) # grab the spell name, after the alias and before Slots
.strip
if !spell.empty?
DRSpells.known_spells[spell] = true
end
end
when /^In the chapter entitled|^You have temporarily memorized|^From your apprenticeship you remember practicing/
if DRSpells.grabbing_known_spells
line
.sub(/^In the chapter entitled "[\w\s\'-]+", you have notes on the /, '')
.sub(/^You have temporarily memorized the /, '')
.sub(/^From your apprenticeship you remember practicing with the /, '')
.sub(/ spells?\./, '')
.sub(/,? and /, ',')
.split(',')
.map { |mapped_spell| mapped_spell.include?('[') ? mapped_spell.slice(0, mapped_spell.index('[')) : mapped_spell }
.map(&:strip)
.reject { |rejected_spell| rejected_spell.nil? || rejected_spell.empty? }
.each { |each_spell| DRSpells.known_spells[each_spell] = true }
end
when /^You recall proficiency with the magic feats of/
if DRSpells.grabbing_known_spells
# The feats are listed without the Oxford comma separating the last item.
# This makes splitting the string by comma difficult because the next to last and last
# items would be captured together. The workaround is we'll replace ' and ' with a comma
# and hope no feats ever have the word 'and' in them...
line
.sub(/^You recall proficiency with the magic feats of/, '')
.sub(/,? and /, ',')
.sub('.', '')
.split(',')
.map(&:strip)
.reject { |feat| feat.nil? || feat.empty? }
.each { |feat| DRSpells.known_feats[feat] = true }
end
when /^You can use SPELL STANCE|^You have (no|yet to receive any) training in the magical arts|You have no desire to soil yourself with magical trickery|^You really shouldn't be loitering here|\(Use SPELL|\(Use PREPARE/
DRSpells.grabbing_known_spells = false
when /^(<(push|pop)Bold\/>)?You know the (Berserks|Forms|Roars|Meditations):(<(push|pop)Bold\/>)?/
DRSpells.grabbing_known_spells = true
line
.sub(/^(<(push|pop)Bold\/>)?You know the (Berserks|Forms|Roars|Meditations):(<(push|pop)Bold\/>)?/, '')
.sub('.', '')
.split(',')
.map(&:strip)
.reject { |ability| ability.nil? || ability.empty? }
.each { |ability| DRSpells.known_spells[ability] = true }
when /^(<(push|pop)Bold\/>)?You know the (Masteries):(<(push|pop)Bold\/>)?/
# Barbarian masteries are the equivalent of magical feats.
if DRSpells.grabbing_known_spells
line
.sub(/^(<(push|pop)Bold\/>)?You know the (Masteries):(<(push|pop)Bold\/>)?/, '')
.sub('.', '')
.split(',')
.map(&:strip)
.reject { |mastery| mastery.nil? || mastery.empty? }
.each { |mastery| DRSpells.known_feats[mastery] = true }
end
when /^You recall that you have (\d+) training sessions? remaining with the Guild/
DRSpells.grabbing_known_spells = false
when /^From the (Subtlety|Finesse|Potence) tree, you know the following khri:/
DRSpells.grabbing_known_spells = true
line
.sub(/^From the (Subtlety|Finesse|Potence) tree, you know the following khri:/, '')
.sub('.', '')
.gsub(/\(.+?\)/, '')
.split(',')
.map(&:strip)
.reject { |ability| ability.nil? || ability.empty? }
.each { |ability| DRSpells.known_spells[ability] = true }
when /^You have (\d+) available slots?/
DRSpells.grabbing_known_spells = false
else
:noop
end
Expand Down
47 changes: 47 additions & 0 deletions lib/dragonrealms/drinfomon/drspells.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
module DRSpells
@@known_spells = {}
@@known_feats = {}
@@spellbook_format = nil # 'column-formatted' or 'non-column'

@@grabbing_known_spells = false

# Use this to silence the initial output
# of calling 'spells' command to populate our data.
@@silence_known_spells_hook = false

def self.active_spells
XMLData.dr_active_spells
end

def self.known_spells
@@known_spells
end

def self.known_feats
@@known_feats
end

def self.slivers
XMLData.dr_active_spells_slivers
end

def self.stellar_percentage
XMLData.dr_active_spells_stellar_percentage
end

def self.grabbing_known_spells
@@grabbing_known_spells
end

def self.grabbing_known_spells=(val)
@@grabbing_known_spells = val
end

def self.spellbook_format
@@spellbook_format
end

def self.spellbook_format=(val)
@@spellbook_format = val
end
end
117 changes: 117 additions & 0 deletions lib/dragonrealms/drinfomon/drvariables.rb
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,120 @@
"Shard" => ["[[Shard, Carousel Chamber]]"],
"Therenborough" => ["[[Therenborough, Carousel Chamber]]"]
}

# Some spells may last for an unknown duration,
# such as cyclic spells that last as long as
# the caster can harness mana for it.
# Or, barbarian abilities when the character
# doesn't have Power Monger mastery to see true
# durations but only vague guestimates.
# In those situations, we set use this value.
UNKNOWN_DURATION = 1000 unless defined?(UNKNOWN_DURATION)

$HOMETOWN_REGEX_MAP = {
"Arthe Dale" => /^(arthe( dale)?)$/i,
"Crossing" => /^(cross(ing)?)$/i,
"Darkling Wood" => /^(darkling( wood)?)$/i,
"Dirge" => /^(dirge)$/i,
"Fayrin's Rest" => /^(fayrin'?s?( rest)?)$/i,
"Leth Deriel" => /^(leth( deriel)?)$/i,
"Shard" => /^(shard)$/i,
"Steelclaw Clan" => /^(steel( )?claw( clan)?|SCC)$/i,
"Stone Clan" => /^(stone( clan)?)$/i,
"Tiger Clan" => /^(tiger( clan)?)$/i,
"Wolf Clan" => /^(wolf( clan)?)$/i,
"Riverhaven" => /^(river|haven|riverhaven)$/i,
"Rossman's Landing" => /^(rossman'?s?( landing)?)$/i,
"Therenborough" => /^(theren(borough)?)$/i,
"Langenfirth" => /^(lang(enfirth)?)$/i,
"Fornsted" => /^(fornsted)$/i,
"Hvaral" => /^(hvaral)$/i,
"Ratha" => /^(ratha)$/i,
"Aesry" => /^(aesry)$/i,
"Mer'Kresh" => /^(mer'?kresh)$/i,
"Throne City" => /^(throne( city)?)$/i,
"Hibarnhvidar" => /^(hib(arnhvidar)?)$/i,
"Raven's Point" => /^(raven'?s?( point)?)$/i,
"Boar Clan" => /^(boar( clan)?)$/i,
"Fang Cove" => /^(fang( cove)?)$/i,
"Muspar'i" => /^(muspar'?i)$/i,
"Ain Ghazal" => /^(ain( )?ghazal)$/i
}

# List of canonical town names, like 'Therenborough' and 'Langenfirth'.
$HOMETOWN_LIST = $HOMETOWN_REGEX_MAP.keys

# Union of regular expressions that match town names, like /^(theren(borough)?)$/i
$HOMETOWN_REGEX = Regexp.union($HOMETOWN_REGEX_MAP.values)

$ORDINALS = %w[first second third fourth fifth sixth seventh eighth ninth tenth eleventh twelfth thirteenth fourteenth fifteenth sixteenth seventeenth eighteenth nineteenth twentieth]

$CURRENCIES = %w[Kronars Lirums Dokoras]

$ENC_MAP = {
'None' => 0,
'Light Burden' => 1,
'Somewhat Burdened' => 2,
'Burdened' => 3,
'Heavy Burden' => 4,
'Very Heavy Burden' => 5,
'Overburdened' => 6,
'Very Overburdened' => 7,
'Extremely Overburdened' => 8,
'Tottering Under Burden' => 9,
'Are you even able to move?' => 10,
'It\'s amazing you aren\'t squashed!' => 11
}

$NUM_MAP = {
'zero' => 0,
'one' => 1,
'two' => 2,
'three' => 3,
'four' => 4,
'five' => 5,
'six' => 6,
'seven' => 7,
'eight' => 8,
'nine' => 9,
'ten' => 10,
'eleven' => 11,
'twelve' => 12,
'thirteen' => 13,
'fourteen' => 14,
'fifteen' => 15,
'sixteen' => 16,
'seventeen' => 17,
'eighteen' => 18,
'nineteen' => 19,
'twenty' => 20,
'thirty' => 30,
'forty' => 40,
'fifty' => 50,
'sixty' => 60,
'seventy' => 70,
'eighty' => 80,
'ninety' => 90
}

$box_regex = /((?:brass|copper|deobar|driftwood|iron|ironwood|mahogany|oaken|pine|steel|wooden) (?:box|caddy|casket|chest|coffer|crate|skippet|strongbox|trunk))/

$MANA_MAP = {
'weak' => %w[dim glowing bright],
'developing' => %w[faint muted glowing luminous bright],
'improving' => %w[faint hazy flickering shimmering glowing lambent shining fulgent glaring],
'good' => %w[faint dim hazy dull muted dusky pale flickering shimmering pulsating glowing lambent shining luminous radiant fulgent brilliant flaring glaring blazing blinding]
}

$PRIMARY_SIGILS_PATTERN = /\b(?:abolition|congruence|induction|permutation|rarefaction) sigil\b/
$SECONDARY_SIGILS_PATTERN = /\b(?:antipode|ascension|clarification|decay|evolution|integration|metamorphosis|nurture|paradox|unity) sigil\b/

$VOL_MAP = {
'enormous' => 20,
'massive' => 10,
'huge' => 5,
'large' => 4,
'medium' => 3,
'small' => 2,
'tiny' => 1
}
34 changes: 34 additions & 0 deletions lib/dragonrealms/drinfomon/events.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
class Flags
@@flags = {}
@@matchers = {}

def self.[](key)
@@flags[key]
end

def self.[]=(key, value)
@@flags[key] = value
end

def self.add(key, *matchers)
@@flags[key] = false
@@matchers[key] = matchers.map { |item| item.is_a?(Regexp) ? item : /#{item}/i }
end

def self.reset(key)
@@flags[key] = false
end

def self.delete(key)
@@matchers.delete key
@@flags.delete key
end

def self.flags
@@flags
end

def self.matchers
@@matchers
end
end

0 comments on commit fc31aeb

Please sign in to comment.