Class: Lich::DragonRealms::DRSkill
- Inherits:
-
Object
- Object
- Lich::DragonRealms::DRSkill
- Defined in:
- documented/dragonrealms/drinfomon/drskill.rb
Overview
Represents a trainable character skill in DragonRealms and tracks its rank, experience mindstate, and learning progress.
The class maintains a shared registry (@@list) of all known skills and supports session-based tracking of skill gain via baseline/current mechanics. Capped skills (rank >= 1750) are fixed at 34/34 mindstate per game convention.
Instance Attribute Summary collapse
-
#baseline ⇒ Object
Returns the value of attribute baseline.
-
#current ⇒ Object
Returns the value of attribute current.
-
#exp ⇒ Object
Returns the value of attribute exp.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#percent ⇒ Object
Returns the value of attribute percent.
-
#rank ⇒ Object
Returns the value of attribute rank.
-
#skillset ⇒ Object
readonly
Returns the value of attribute skillset.
Class Method Summary collapse
-
.clear_mind(val) ⇒ Object
BUG FIX: Added nil guard - find_skill can return nil if skill not found.
-
.convert_rexp_str_to_seconds(time_string) ⇒ Integer
Converts a rested experience time string to total seconds.
-
.exp_modifiers ⇒ Hash<String, Integer>
Returns the hash of skill rank modifiers (e.g. from buffs or gear).
-
.find_skill(val) ⇒ DRSkill?
Finds a skill in the registry by name (canonical or alias).
-
.gained_exp(val) ⇒ Object
Returns the amount of ranks that have been gained since the baseline was last reset.
-
.gained_skills ⇒ Object
List of skills that have increased their learning rates.
-
.getmodrank(val) ⇒ Integer
Returns the trained rank of a skill plus any applied modifiers (buffs, gear, etc.).
-
.getpercent(val) ⇒ Object
BUG FIX: Added nil guard - find_skill can return nil if skill not found.
-
.getrank(val) ⇒ Object
BUG FIX: Added nil guard - find_skill can return nil if skill not found.
-
.getskillset(val) ⇒ Object
BUG FIX: Added nil guard - find_skill can return nil if skill not found.
-
.getxp(val) ⇒ Integer
Returns the learning rate mindstate (x/34) of a skill.
-
.handle_exp_change(name, new_exp) ⇒ Object
Updates DRStats.gained_skills if the learning rate increased.
-
.include?(val) ⇒ Boolean
Checks whether a skill name (canonical or colloquial) is registered.
-
.list ⇒ Array<DRSkill>
Returns the registry of all tracked skills.
-
.listall ⇒ void
Displays all tracked skills in the game output.
-
.lookup_alias(skill) ⇒ Object
Some guilds rename skills, like Barbarians call "Primary Magic" as "Inner Fire".
-
.reset ⇒ void
Resets the session baseline for all tracked skills to their current values.
-
.rested_active? ⇒ Boolean
Checks whether rested experience is both stored and available to use.
-
.rested_exp_refresh ⇒ Integer
Returns the time until rested experience refreshes, in seconds.
-
.rested_exp_stored ⇒ Integer
Returns the total rested experience stored, in seconds.
-
.rested_exp_usable ⇒ Integer
Returns the rested experience currently available to use, in seconds.
-
.start_time ⇒ Object
Primarily used by
learnedscript to track how long it's been tracking your experience gains this session. -
.update(name, rank, exp, percent) ⇒ void
Updates an existing skill or creates a new one with the latest game state.
-
.update_mods(name, rank) ⇒ void
Records a skill rank modifier (e.g. from buffs or gear bonuses).
-
.update_rested_exp(stored, usable, refresh) ⇒ void
Updates the rested experience state from the game.
Instance Method Summary collapse
-
#initialize(name, rank, exp, percent) ⇒ void
constructor
Initializes a skill instance and registers it in the shared skill list.
-
#lookup_skillset(skill) ⇒ Object
This is an instance method, do not prefix with
self.
Constructor Details
#initialize(name, rank, exp, percent) ⇒ void
Initializes a skill instance and registers it in the shared skill list.
Capped skills (rank >= 1750) automatically set exp to 34 to enforce the "capped == 34/34" convention that trainer scripts rely upon. Baseline and current are set to the same value: rank + (percent / 100.0).
45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 45 def initialize(name, rank, exp, percent) @name = name # skill name like 'Evasion' @rank = rank.to_i # earned ranks in the skill # Skill mindstate x/34 # Hardcode caped skills to 34/34 @exp = rank.to_i >= 1750 ? 34 : exp.to_i @percent = percent.to_i # percent to next rank from 0 to 100 @baseline = rank.to_i + (percent.to_i / 100.0) @current = rank.to_i + (percent.to_i / 100.0) @skillset = lookup_skillset(@name) @@list.push(self) unless @@list.find { |skill| skill.name == @name } end |
Instance Attribute Details
#baseline ⇒ Object
Returns the value of attribute baseline.
30 31 32 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 30 def baseline @baseline end |
#current ⇒ Object
Returns the value of attribute current.
30 31 32 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 30 def current @current end |
#exp ⇒ Object
Returns the value of attribute exp.
30 31 32 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 30 def exp @exp end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
29 30 31 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 29 def name @name end |
#percent ⇒ Object
Returns the value of attribute percent.
30 31 32 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 30 def percent @percent end |
#rank ⇒ Object
Returns the value of attribute rank.
30 31 32 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 30 def rank @rank end |
#skillset ⇒ Object (readonly)
Returns the value of attribute skillset.
29 30 31 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 29 def skillset @skillset end |
Class Method Details
.clear_mind(val) ⇒ Object
BUG FIX: Added nil guard - find_skill can return nil if skill not found
Capped skills (rank >= 1750) are pinned to 34/34 the same way
initialize and update do it. Without the cap guard, clearing the
mindstate here would reset exp to 0 and defeat the "capped == 34"
convention that trainer scripts rely on to avoid re-training a capped
skill.
236 237 238 239 240 241 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 236 def self.clear_mind(val) skill = find_skill(val) return unless skill skill.exp = skill.rank.to_i >= 1750 ? 34 : 0 end |
.convert_rexp_str_to_seconds(time_string) ⇒ Integer
Converts a rested experience time string to total seconds.
Parses formats like "4:38 hours", "6 hour", "38 minutes", and special cases like "none" or "less than a minute" (both return 0). Returns 0 for nil or empty strings. Time is always rounded to minute granularity (divisible by 60).
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 352 def self.convert_rexp_str_to_seconds(time_string) # Handle empty, nil, or specific "zero" cases (less than a minute is zero because it can get stuck there) return 0 if time_string.nil? || time_string.to_s.strip.empty? || time_string.include?('none') || time_string.include?('less than a minute') total_seconds = 0 # Extract hours and optional minutes (e.g., "4:38 hours" or "6 hour") # Ruby's match returns a MatchData object or nil if (hour_match = time_string.match(/(\d+):?(\d+)?\s*hour/)) hours = hour_match[1].to_i total_seconds += hours * 60 * 60 # Handle the minutes part of a "4:38" format if hour_match[2] total_seconds += hour_match[2].to_i * 60 return total_seconds end end # Extract standalone minutes (e.g., "38 minutes") if (minute_match = time_string.match(/(\d+)\s*minute/)) total_seconds += minute_match[1].to_i * 60 end total_seconds end |
.exp_modifiers ⇒ Hash<String, Integer>
Returns the hash of skill rank modifiers (e.g. from buffs or gear).
189 190 191 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 189 def self.exp_modifiers @@exp_modifiers end |
.find_skill(val) ⇒ DRSkill?
Finds a skill in the registry by name (canonical or alias).
Resolves guild-specific skill name aliases before searching. Returns nil if the skill is not found.
336 337 338 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 336 def self.find_skill(val) @@list.find { |data| data.name == lookup_alias(val) } end |
.gained_exp(val) ⇒ Object
Returns the amount of ranks that have been gained since the baseline was last reset. This allows you to track rank gain for a given play session.
Note, don't confuse the 'exp' in this method name with DRSkill.getxp(..) which returns the current learning rate of the skill.
92 93 94 95 96 97 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 92 def self.gained_exp(val) skill = find_skill(val) return 0.00 unless skill&.current (skill.current - skill.baseline).round(2) end |
.gained_skills ⇒ Object
List of skills that have increased their learning rates.
Primarily used by exp-monitor script to echo which skills
gained experience after you performed an action.
82 83 84 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 82 def self.gained_skills @@gained_skills end |
.getmodrank(val) ⇒ Integer
Returns the trained rank of a skill plus any applied modifiers (buffs, gear, etc.).
Returns 0 if the skill does not exist or no modifier is recorded. Modifiers are set via .update_mods and typically come from active buffs or equipment bonuses.
260 261 262 263 264 265 266 267 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 260 def self.getmodrank(val) skill = find_skill(val) return 0 unless skill rank = skill.rank.to_i modifier = exp_modifiers[skill.name].to_i rank + modifier end |
.getpercent(val) ⇒ Object
BUG FIX: Added nil guard - find_skill can return nil if skill not found
285 286 287 288 289 290 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 285 def self.getpercent(val) skill = find_skill(val) return 0 unless skill skill.percent.to_i end |
.getrank(val) ⇒ Object
BUG FIX: Added nil guard - find_skill can return nil if skill not found
244 245 246 247 248 249 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 244 def self.getrank(val) skill = find_skill(val) return 0 unless skill skill.rank.to_i end |
.getskillset(val) ⇒ Object
BUG FIX: Added nil guard - find_skill can return nil if skill not found
293 294 295 296 297 298 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 293 def self.getskillset(val) skill = find_skill(val) return nil unless skill skill.skillset end |
.getxp(val) ⇒ Integer
Returns the learning rate mindstate (x/34) of a skill.
Capped skills (rank >= 1750) always return 34. Returns 0 if the skill does not exist.
277 278 279 280 281 282 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 277 def self.getxp(val) skill = find_skill(val) return 0 unless skill skill.exp.to_i end |
.handle_exp_change(name, new_exp) ⇒ Object
Updates DRStats.gained_skills if the learning rate increased.
The original consumer of this data is the exp-monitor script.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 101 def self.handle_exp_change(name, new_exp) return unless Lich.display_expgains # Only track gains for skills that already exist # (skip initial skill discovery on login) skill = find_skill(name) return unless skill old_exp = skill.exp.to_i change = new_exp.to_i - old_exp if change > 0 @@gained_skills << { skill: name, change: change } end end |
.include?(val) ⇒ Boolean
Checks whether a skill name (canonical or colloquial) is registered.
122 123 124 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 122 def self.include?(val) !find_skill(val).nil? end |
.list ⇒ Array<DRSkill>
Returns the registry of all tracked skills.
322 323 324 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 322 def self.list @@list end |
.listall ⇒ void
311 312 313 314 315 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 311 def self.listall @@list.each do |i| Lich::Messaging.msg('plain', "DRSkill: #{i.name}: #{i.rank}.#{i.percent}% [#{i.exp}/34]") end end |
.lookup_alias(skill) ⇒ Object
Some guilds rename skills, like Barbarians call "Primary Magic" as "Inner Fire".
Given the canonical or colloquial name, this method returns the value
that's usable with the other methods like getxp(skill) and getrank(skill).
BUG FIX: Added safe navigation with .dig() for nested hash access. Original code crashed with NoMethodError if DRStats.guild was nil or if the guild wasn't in the aliases hash.
389 390 391 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 389 def self.lookup_alias(skill) @@skills_data.dig(:guild_skill_aliases, DRStats.guild, skill) || skill end |
.reset ⇒ void
This method returns an undefined value.
Resets the session baseline for all tracked skills to their current values.
Use this to mark a checkpoint in skill gain tracking, clearing the @@gained_skills list and resetting @@start_time to now. Subsequent calls to .gained_exp will measure rank gain from this new baseline.
67 68 69 70 71 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 67 def self.reset @@gained_skills = [] @@start_time = Time.now @@list.each { |skill| skill.baseline = skill.current } end |
.rested_active? ⇒ Boolean
Checks whether rested experience is both stored and available to use.
225 226 227 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 225 def self.rested_active? @@rexp_stored > 0 && @@rexp_usable > 0 end |
.rested_exp_refresh ⇒ Integer
Returns the time until rested experience refreshes, in seconds.
216 217 218 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 216 def self.rested_exp_refresh @@rexp_refresh end |
.rested_exp_stored ⇒ Integer
Returns the total rested experience stored, in seconds.
198 199 200 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 198 def self.rested_exp_stored @@rexp_stored end |
.rested_exp_usable ⇒ Integer
Returns the rested experience currently available to use, in seconds.
207 208 209 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 207 def self.rested_exp_usable @@rexp_usable end |
.start_time ⇒ Object
Primarily used by learned script to track how long it's
been tracking your experience gains this session.
75 76 77 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 75 def self.start_time @@start_time end |
.update(name, rank, exp, percent) ⇒ void
This method returns an undefined value.
Updates an existing skill or creates a new one with the latest game state.
If the skill already exists, updates its rank, exp mindstate, percent, and current progress. If it does not exist, creates a new DRSkill. Also triggers .handle_exp_change to track learning rate increases for the exp-monitor script. Capped skills (rank >= 1750) are forced to 34/34 mindstate.
140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 140 def self.update(name, rank, exp, percent) handle_exp_change(name, exp) skill = find_skill(name) if skill skill.rank = rank.to_i skill.exp = skill.rank.to_i >= 1750 ? 34 : exp.to_i skill.percent = percent.to_i skill.current = rank.to_i + (percent.to_i / 100.0) else DRSkill.new(name, rank, exp, percent) end end |
.update_mods(name, rank) ⇒ void
This method returns an undefined value.
Records a skill rank modifier (e.g. from buffs or gear bonuses).
Stores the modifier indexed by the canonical skill name (resolved via .lookup_alias) for retrieval by .getmodrank.
163 164 165 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 163 def self.update_mods(name, rank) exp_modifiers[lookup_alias(name)] = rank.to_i end |
.update_rested_exp(stored, usable, refresh) ⇒ void
This method returns an undefined value.
Updates the rested experience state from the game.
Converts human-readable time strings (e.g. "4:38 hours", "38 minutes") to seconds and stores them in class variables for access via the rested_exp_* methods.
178 179 180 181 182 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 178 def self.update_rested_exp(stored, usable, refresh) @@rexp_stored = convert_rexp_str_to_seconds(stored) @@rexp_usable = convert_rexp_str_to_seconds(usable) @@rexp_refresh = convert_rexp_str_to_seconds(refresh) end |
Instance Method Details
#lookup_skillset(skill) ⇒ Object
This is an instance method, do not prefix with self.
It is called from the initialize method (constructor).
When it was defined as a class method then the initialize method
complained that this method didn't yet exist.
BUG FIX: Added nil guard for .find result before calling .first
399 400 401 402 |
# File 'documented/dragonrealms/drinfomon/drskill.rb', line 399 def lookup_skillset(skill) result = @@skills_data[:skillsets].find { |_skillset, skills| skills.include?(skill) } result&.first end |