Module: Lich::DragonRealms::DRCH
- Defined in:
- documented/dragonrealms/commons/common-healing.rb,
documented/dragonrealms/commons/common-healing-data.rb
Overview
DragonRealms Common Healing - utilities for querying and managing character health.
Provides methods to check health status via HEALTH and PERCEIVE HEALTH commands, parse wound/bleeder/parasite diagnostics, and perform wound tending.
Defined Under Namespace
Classes: HealthResult, Wound
Constant Summary collapse
- BLEED_RATE_TO_SEVERITY =
Maps bleed rates from
healthcommand to severity number. A partially tended wound is considered more severe than its non-tended counterpart because once the bandages come off then the wound is much worse so they should be triaged first. https://elanthipedia.play.net/Damage#Bleeding_LevelsSkill to tend based on https://elanthipedia.play.net/First_Aid_skill#Skill_to_Tend A 'nil' value means that can't be tended because already is tended or isn't bleeding. Maps bleed rates from
healthcommand to severity number.A partially tended wound is considered more severe than its non-tended counterpart because once the bandages come off then the wound is much worse so they should be triaged first.
{ 'tended' => { severity: 1, bleeding: false, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, '(tended)' => { severity: 1, bleeding: false, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'clotted' => { severity: 2, bleeding: false, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'clotted(tended)' => { severity: 3, bleeding: false, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'slight' => { severity: 3, bleeding: true, skill_to_tend: 30, skill_to_tend_internal: 600 }.freeze, 'slight(tended)' => { severity: 4, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'light' => { severity: 4, bleeding: true, skill_to_tend: 40, skill_to_tend_internal: 600 }.freeze, 'light(tended)' => { severity: 5, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'moderate' => { severity: 5, bleeding: true, skill_to_tend: 50, skill_to_tend_internal: 600 }.freeze, 'moderate(tended)' => { severity: 6, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'bad' => { severity: 6, bleeding: true, skill_to_tend: 60, skill_to_tend_internal: 620 }.freeze, 'bad(tended)' => { severity: 7, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'very bad' => { severity: 7, bleeding: true, skill_to_tend: 75, skill_to_tend_internal: 620 }.freeze, 'very bad(tended)' => { severity: 8, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'heavy' => { severity: 8, bleeding: true, skill_to_tend: 90, skill_to_tend_internal: 640 }.freeze, 'heavy(tended)' => { severity: 9, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'very heavy' => { severity: 9, bleeding: true, skill_to_tend: 105, skill_to_tend_internal: 640 }.freeze, 'very heavy(tended)' => { severity: 10, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'severe' => { severity: 10, bleeding: true, skill_to_tend: 120, skill_to_tend_internal: 660 }.freeze, 'severe(tended)' => { severity: 11, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'very severe' => { severity: 11, bleeding: true, skill_to_tend: 140, skill_to_tend_internal: 660 }.freeze, 'very severe(tended)' => { severity: 12, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'extremely severe' => { severity: 12, bleeding: true, skill_to_tend: 160, skill_to_tend_internal: 700 }.freeze, 'extremely severe(tended)' => { severity: 13, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'profuse' => { severity: 13, bleeding: true, skill_to_tend: 180, skill_to_tend_internal: 800 }.freeze, 'profuse(tended)' => { severity: 14, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'very profuse' => { severity: 14, bleeding: true, skill_to_tend: 205, skill_to_tend_internal: 800 }.freeze, 'very profuse(tended)' => { severity: 15, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'massive' => { severity: 15, bleeding: true, skill_to_tend: 230, skill_to_tend_internal: 850 }.freeze, 'massive(tended)' => { severity: 16, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'gushing' => { severity: 16, bleeding: true, skill_to_tend: 255, skill_to_tend_internal: 850 }.freeze, 'gushing(tended)' => { severity: 17, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'massive stream' => { severity: 17, bleeding: true, skill_to_tend: 285, skill_to_tend_internal: 1000 }.freeze, 'massive stream(tended)' => { severity: 18, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'gushing fountain' => { severity: 18, bleeding: true, skill_to_tend: 285, skill_to_tend_internal: 1200 }.freeze, 'gushing fountain(tended)' => { severity: 19, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'uncontrollable' => { severity: 19, bleeding: true, skill_to_tend: 400, skill_to_tend_internal: 1400 }.freeze, 'uncontrollable(tended)' => { severity: 20, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'unbelievable' => { severity: 20, bleeding: true, skill_to_tend: 500, skill_to_tend_internal: 1600 }.freeze, 'unbelievable(tended)' => { severity: 21, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'beyond measure' => { severity: 21, bleeding: true, skill_to_tend: 600, skill_to_tend_internal: 1750 }.freeze, 'beyond measure(tended)' => { severity: 22, bleeding: true, skill_to_tend: nil, skill_to_tend_internal: nil }.freeze, 'death awaits' => { severity: 22, bleeding: true, skill_to_tend: 700, skill_to_tend_internal: 1750 }.freeze, }.freeze
- LODGED_SEVERITY =
https://elanthipedia.play.net/Damage#Lodged_Items Maps lodged item descriptions to severity levels.
{ 'loosely hanging' => 1, 'shallowly' => 2, 'firmly' => 3, 'deeply' => 4, 'savagely' => 5 }.freeze
- WOUND_SEVERITY =
https://elanthipedia.play.net/Damage#Wound_Severity_Levels Maps wound descriptions to severity levels.
{ 'insignificant' => 1, 'negligible' => 2, 'minor' => 3, 'more than minor' => 4, 'harmful' => 5, 'very harmful' => 6, 'damaging' => 7, 'very damaging' => 8, 'severe' => 9, 'very severe' => 10, 'devastating' => 11, 'very devastating' => 12, 'useless' => 13 }.freeze
- PARASITES_REGEX =
https://elanthipedia.play.net/Damage#Parasites Regular expressions to match parasite descriptions.
[ /(?:small|large) (?:black|red) blood mite/, /(?:black|red|albino) (sand|forest) leech/, /(?:green|red) blood worm/, /retch maggot/ ].freeze
- PERCEIVE_HEALTH_SEVERITY_REGEX =
Parses the severity number out of the wound line from 'perceive health self'. For example, the 'negligible' in "Fresh External: light scratches -- negligible" Parses the severity number out of the wound line from 'perceive health self'.
/(?<freshness>Fresh|Scars) (?<location>External|Internal).+--\s+(?<severity>insignificant|negligible|minor|more than minor|harmful|very harmful|damaging|very damaging|severe|very severe|devastating|very devastating|useless)\b/- BODY_PART_REGEX =
/(?<part>(?:l\.|r\.|left|right)?\s?(?:\w+))/- WOUND_BODY_PART_REGEX =
Matches body parts in the
healthline for wounds and bleeders. /(?:inside)?\s?#{BODY_PART_REGEX}/- LODGED_BODY_PART_REGEX =
Matches body parts in the
healthline for lodged items. /lodged .* into your #{BODY_PART_REGEX}/- PARASITE_BODY_PART_REGEX =
Matches body parts in the
healthline for parasites. /on your #{BODY_PART_REGEX}/- BLEEDER_LINE_REGEX =
Matches body parts in the
healthline for bleeders. /^\b(inside\s+)?((l\.|r\.|left|right)\s+)?(head|eye|neck|chest|abdomen|back|arm|hand|leg|tail|skin)\b/- WOUND_SEVERITY_REGEX_MAP =
https://elanthipedia.play.net/Damage#Wounds Maps wound descriptions to severity levels using regular expressions.
{ # insignificant /minor abrasions to the #{WOUND_BODY_PART_REGEX}/ => { severity: 1, internal: false, scar: false }.freeze, /a few nearly invisible scars along the #{WOUND_BODY_PART_REGEX}/ => { severity: 1, internal: false, scar: true }.freeze, # negligible /some tiny scars (?:across|along) the #{WOUND_BODY_PART_REGEX}/ => { severity: 2, internal: false, scar: true }.freeze, /(?:light|tiny) scratches to the #{WOUND_BODY_PART_REGEX}/ => { severity: 2, internal: false, scar: false }.freeze, # minor / more than minor /a bruised (?<part>head)/ => { severity: 3, internal: true, scar: false }.freeze, /(?<skin>a small skin rash)/ => { severity: 3, internal: false, scar: false }.freeze, /(?<skin>loss of skin tone)/ => { severity: 3, internal: false, scar: true }.freeze, /(?<skin>some minor twitching)/ => { severity: 3, internal: true, scar: false }.freeze, /(?<skin>slight difficulty moving your fingers and toes)/ => { severity: 3, internal: true, scar: true }.freeze, /cuts and bruises about the #{WOUND_BODY_PART_REGEX}/ => { severity: 3, internal: false, scar: false }.freeze, /minor scar\w+ (?:about|along|across) the #{WOUND_BODY_PART_REGEX}/ => { severity: 3, internal: false, scar: true }.freeze, /minor swelling and bruising (?:around|in) the #{WOUND_BODY_PART_REGEX}/ => { severity: 3, internal: true, scar: false }.freeze, /occasional twitch\w* (?:on|in) the #{WOUND_BODY_PART_REGEX}/ => { severity: 3, internal: true, scar: true }.freeze, /a black and blue #{WOUND_BODY_PART_REGEX}/ => { severity: 3, internal: false, scar: false }.freeze, # harmful / very harmful /a deeply bruised (?<part>head)/ => { severity: 4, internal: true, scar: false }.freeze, /(?<skin>a large skin rash)/ => { severity: 4, internal: false, scar: false }.freeze, /(?<skin>minor skin discoloration)/ => { severity: 4, internal: false, scar: true }.freeze, /(?<skin>some severe twitching)/ => { severity: 4, internal: true, scar: false }.freeze, /(?<skin>slight numbness in your arms and legs)/ => { severity: 4, internal: true, scar: true }.freeze, /deep cuts (?:about|across) the #{WOUND_BODY_PART_REGEX}/ => { severity: 4, internal: false, scar: false }.freeze, /severe scarring (?:across|along|about) the #{WOUND_BODY_PART_REGEX}/ => { severity: 4, internal: false, scar: true }.freeze, /a severely swollen and\s?(?:deeply)? bruised #{WOUND_BODY_PART_REGEX}/ => { severity: 4, internal: true, scar: false }.freeze, /(?:occasional|constant) twitch\w* (?:on|in) the #{WOUND_BODY_PART_REGEX}/ => { severity: 4, internal: true, scar: true }.freeze, /a bruised and swollen (?<part>(?:right|left) (?:eye))/ => { severity: 4, internal: false, scar: false }.freeze, # damaging / very damaging /some deep slashes and cuts about the (?<part>head)/ => { severity: 5, internal: false, scar: false }.freeze, /severe scarring and ugly gashes about the #{WOUND_BODY_PART_REGEX}/ => { severity: 5, internal: false, scar: true }.freeze, /major swelling and bruising around the (?<part>head)/ => { severity: 5, internal: true, scar: false }.freeze, /an occasional twitch on the fore(?<part>head)/ => { severity: 5, internal: true, scar: true }.freeze, /a bruised,* swollen and bleeding #{WOUND_BODY_PART_REGEX}/ => { severity: 5, internal: false, scar: false }.freeze, /deeply scarred gashes across the #{WOUND_BODY_PART_REGEX}/ => { severity: 5, internal: false, scar: true }.freeze, /a severely swollen, bruised and crossed #{WOUND_BODY_PART_REGEX}/ => { severity: 5, internal: true, scar: false }.freeze, /a constant twitching in the #{WOUND_BODY_PART_REGEX}/ => { severity: 5, internal: true, scar: true }.freeze, /deep slashes across the #{WOUND_BODY_PART_REGEX}/ => { severity: 5, internal: false, scar: false }.freeze, /a severely swollen and deeply bruised #{WOUND_BODY_PART_REGEX}/ => { severity: 5, internal: true, scar: false }.freeze, /severely swollen and bruised #{WOUND_BODY_PART_REGEX}/ => { severity: 5, internal: true, scar: false }.freeze, /a constant twitching in the (?<part>chest) area and difficulty breathing/ => { severity: 5, internal: true, scar: true }.freeze, /(?<abdomen>a somewhat emaciated look)/ => { severity: 5, internal: true, scar: true }.freeze, /a constant twitching in the #{WOUND_BODY_PART_REGEX} and difficulty moving in general/ => { severity: 5, internal: true, scar: true }.freeze, /(?<skin>a body rash)/ => { severity: 5, internal: false, scar: false }.freeze, /severe (?<part>skin) discoloration/ => { severity: 5, internal: false, scar: true }.freeze, /(?<skin>difficulty controlling actions)/ => { severity: 5, internal: true, scar: false }.freeze, /(?<skin>numbness in your fingers and toes)/ => { severity: 5, internal: true, scar: true }.freeze, # severe / very severe /(?<head>a cracked skull with deep slashes)/ => { severity: 6, internal: false, scar: false }.freeze, /missing chunks out of the (?<part>head)/ => { severity: 6, internal: false, scar: true }.freeze, /a bruised, swollen and slashed #{WOUND_BODY_PART_REGEX}/ => { severity: 6, internal: false, scar: false }.freeze, /a punctured and shriveled #{WOUND_BODY_PART_REGEX}/ => { severity: 6, internal: false, scar: true }.freeze, /a severely swollen,* bruised and cloudy #{WOUND_BODY_PART_REGEX}/ => { severity: 6, internal: true, scar: false }.freeze, /a clouded #{WOUND_BODY_PART_REGEX}/ => { severity: 6, internal: true, scar: true }.freeze, /gaping holes in the #{WOUND_BODY_PART_REGEX}/ => { severity: 6, internal: false, scar: false }.freeze, /a broken #{WOUND_BODY_PART_REGEX} with gaping holes/ => { severity: 6, internal: false, scar: false }.freeze, /severe scarring and ugly gashes about the #{WOUND_BODY_PART_REGEX}/ => { severity: 6, internal: false, scar: true }.freeze, /severe scarring and chunks of flesh missing from the #{WOUND_BODY_PART_REGEX}/ => { severity: 6, internal: false, scar: true }.freeze, /a severely swollen and deeply bruised #{WOUND_BODY_PART_REGEX} with odd protrusions under the skin/ => { severity: 6, internal: true, scar: false }.freeze, /a severely swollen and deeply bruised (?<part>chest) area with odd protrusions under the skin/ => { severity: 6, internal: true, scar: false }.freeze, /a partially paralyzed #{WOUND_BODY_PART_REGEX}/ => { severity: 6, internal: true, scar: true }.freeze, /a painful #{WOUND_BODY_PART_REGEX} and difficulty moving without pain/ => { severity: 6, internal: true, scar: true }.freeze, /a painful (?<part>chest) area and difficulty getting a breath without pain/ => { severity: 6, internal: true, scar: true }.freeze, /a severely bloated and discolored #{WOUND_BODY_PART_REGEX} with strange round lumps under the skin/ => { severity: 6, internal: true, scar: false }.freeze, /(?<abdomen>a definite greenish pallor and emaciated look)/ => { severity: 6, internal: true, scar: true }.freeze, /(?<skin>a painful,* inflamed body rash)/ => { severity: 6, internal: false, scar: false }.freeze, /(?<skin>a painful,* enflamed body rash)/ => { severity: 6, internal: false, scar: false }.freeze, /some shriveled and oddly folded (?<part>skin)/ => { severity: 6, internal: false, scar: true }.freeze, /(?<skin>partial paralysis of the entire body)/ => { severity: 6, internal: true, scar: false }.freeze, /(?<skin>numbness in your arms and legs)/ => { severity: 6, internal: true, scar: true }.freeze, # devastating / very devastating /(?<head>a crushed skull with horrendous wounds)/ => { severity: 7, internal: false, scar: false }.freeze, /a mangled and malformed (?<part>head)/ => { severity: 7, internal: false, scar: true }.freeze, /a ghastly bloated (?<part>head) with bleeding from the ears/ => { severity: 7, internal: true, scar: false }.freeze, /a confused look with sporadic twitching of the fore(?<part>head)/ => { severity: 7, internal: true, scar: true }.freeze, /a bruised,* swollen and shattered #{WOUND_BODY_PART_REGEX}/ => { severity: 7, internal: false, scar: false }.freeze, /a painfully mangled and malformed #{WOUND_BODY_PART_REGEX} in a shattered eye socket/ => { severity: 7, internal: false, scar: true }.freeze, /a severely swollen,* bruised and blind #{WOUND_BODY_PART_REGEX}/ => { severity: 7, internal: true, scar: false }.freeze, /severely scarred,* mangled and malformed #{WOUND_BODY_PART_REGEX}/ => { severity: 7, internal: false, scar: true }.freeze, /a completely clouded #{WOUND_BODY_PART_REGEX}/ => { severity: 7, internal: true, scar: true }.freeze, /a shattered #{WOUND_BODY_PART_REGEX} with gaping wounds/ => { severity: 7, internal: false, scar: false }.freeze, /shattered (?<part>chest) area with gaping wounds/ => { severity: 7, internal: false, scar: false }.freeze, /a severely swollen and deeply bruised #{WOUND_BODY_PART_REGEX} with bones protruding out from the skin/ => { severity: 7, internal: true, scar: false }.freeze, /a severely swollen and deeply bruised #{WOUND_BODY_PART_REGEX} with ribs or vertebrae protruding out from the skin/ => { severity: 7, internal: true, scar: false }.freeze, /a severely paralyzed #{WOUND_BODY_PART_REGEX}/ => { severity: 7, internal: true, scar: true }.freeze, /a severely painful #{WOUND_BODY_PART_REGEX} with significant problems moving/ => { severity: 7, internal: true, scar: true }.freeze, /a severely painful (?<part>chest) area with significant problems breathing/ => { severity: 7, internal: true, scar: true }.freeze, /#{WOUND_BODY_PART_REGEX} deeply gouged with gaping wounds/ => { severity: 7, internal: false, scar: false }.freeze, /a severely bloated and discolored #{WOUND_BODY_PART_REGEX} with strange round lumps under the skin/ => { severity: 7, internal: true, scar: false }.freeze, /(?<abdomen>a severely yellow pallor and a look of starvation)/ => { severity: 7, internal: true, scar: true }.freeze, /boils and sores around the (?<part>skin)/ => { severity: 7, internal: false, scar: false }.freeze, /severely stiff and shriveled (?<part>skin) that seems to be peeling off the body/ => { severity: 7, internal: false, scar: true }.freeze, /(?<skin>severe paralysis of the entire body)/ => { severity: 7, internal: true, scar: false }.freeze, /(?<skin>general numbness all over)/ => { severity: 7, internal: true, scar: true }.freeze, # useless /pulpy stump for a (?<part>head)/ => { severity: 8, internal: false, scar: false }.freeze, /a stump for a (?<part>head)/ => { severity: 8, internal: false, scar: true }.freeze, /an ugly stump for a #{WOUND_BODY_PART_REGEX}/ => { severity: 8, internal: false, scar: false }.freeze, /a grotesquely bloated (?<part>head) with bleeding from the eyes and ears/ => { severity: 8, internal: true, scar: false }.freeze, /(?<head>a blank stare)/ => { severity: 8, internal: true, scar: true }.freeze, /a pulpy cavity for a #{WOUND_BODY_PART_REGEX}/ => { severity: 8, internal: false, scar: false }.freeze, /an empty #{WOUND_BODY_PART_REGEX} socket overgrown with bits of odd shaped flesh/ => { severity: 8, internal: false, scar: true }.freeze, /a severely swollen,* bruised and blind #{WOUND_BODY_PART_REGEX}/ => { severity: 8, internal: true, scar: false }.freeze, /a blind #{WOUND_BODY_PART_REGEX}/ => { severity: 8, internal: true, scar: true }.freeze, /a completely useless #{WOUND_BODY_PART_REGEX} with nearly all flesh and bone torn away/ => { severity: 8, internal: false, scar: false }.freeze, /a completely destroyed #{WOUND_BODY_PART_REGEX} with nearly all flesh and bone torn away revealing a gaping hole/ => { severity: 8, internal: false, scar: false }.freeze, /an ugly flesh stump for a #{WOUND_BODY_PART_REGEX}/ => { severity: 8, internal: false, scar: true }.freeze, /an ugly flesh stump for a #{WOUND_BODY_PART_REGEX} with little left to support the head/ => { severity: 8, internal: false, scar: true }.freeze, /a severely swollen and shattered #{WOUND_BODY_PART_REGEX} which appears completely useless/ => { severity: 8, internal: true, scar: false }.freeze, /a severely swollen and shattered #{WOUND_BODY_PART_REGEX} which appears useless to hold up the head/ => { severity: 8, internal: true, scar: false }.freeze, /a completely paralyzed #{WOUND_BODY_PART_REGEX}/ => { severity: 8, internal: true, scar: true }.freeze, /a mostly non-existent #{WOUND_BODY_PART_REGEX} filled with ugly chunks of scarred flesh/ => { severity: 8, internal: false, scar: true }.freeze, /a severely swollen (?<part>chest) area with a shattered rib cage/ => { severity: 8, internal: true, scar: false }.freeze, /an extremely painful #{WOUND_BODY_PART_REGEX} while gasping for breath in short shallow bursts/ => { severity: 8, internal: true, scar: true }.freeze, /a severely bloated and discolored #{WOUND_BODY_PART_REGEX} which appears oddly rearranged/ => { severity: 8, internal: true, scar: false }.freeze, /(?<abdomen>a death pallor and extreme loss of weight)/ => { severity: 8, internal: true, scar: true }.freeze, /a severely swollen #{WOUND_BODY_PART_REGEX} with a shattered spinal cord/ => { severity: 8, internal: true, scar: false }.freeze, /an extremely painful and bizarrely twisted #{WOUND_BODY_PART_REGEX} making it nearly impossible to move/ => { severity: 8, internal: true, scar: true }.freeze, /open and bleeding sores all over the (?<part>skin)/ => { severity: 8, internal: false, scar: false }.freeze, /severe (?<part>skin) loss exposing bone and internal organs/ => { severity: 8, internal: false, scar: true }.freeze, /(?<skin>complete paralysis of the entire body)/ => { severity: 8, internal: true, scar: false }.freeze, /(?<skin>general numbness all over and have difficulty thinking)/ => { severity: 8, internal: true, scar: true }.freeze, }.freeze
- WOUND_COMMA_SEPARATOR =
/(?<=swollen|bruised|scarred|painful),(?=\s(?:swollen|bruised|mangled|inflamed))/- TEND_SUCCESS_PATTERNS =
Tend action response patterns
[ /You work carefully at tending/, /You work carefully at binding/, /That area has already been tended to/, /That area is not bleeding/ ].freeze
- TEND_FAILURE_PATTERNS =
[ /You fumble/, /too injured for you to do that/, /TEND allows for the tending of wounds/, /^You must have a hand free/ ].freeze
- TEND_DISLODGE_PATTERNS =
[ /^You \w+ remove (a|the|some) (.*) from/, /^As you reach for the clay fragment/ ].freeze
Class Method Summary collapse
-
.bind_wound(body_part, person = 'my') ⇒ Boolean
Tends a wound on a body part, removing bandages and handling dislodged items.
-
.calculate_score(wounds_by_severity) ⇒ Object
Computes a weighted summary score from a wound severity map.
-
.check_health ⇒ Object
Uses HEALTH command to check for poisons, diseases, bleeders, parasites, and lodged items.
- .has_tendable_bleeders? ⇒ Boolean
-
.parse_bleeders(health_lines) ⇒ Object
Parses bleeder lines from HEALTH command output.
-
.parse_health_lines(health_lines) ⇒ Object
Parses stripped HEALTH command output lines into a HealthResult.
-
.parse_lodged_items(lodged_line) ⇒ Object
Parses the lodged item description line from HEALTH command output.
-
.parse_parasites(parasites_line) ⇒ Object
Parses the parasite description line from HEALTH command output.
-
.parse_perceived_health_lines(lines) ⇒ Object
Parses lines from PERCEIVE HEALTH SELF or TOUCH output into a HealthResult.
-
.parse_wounds(wounds_line) ⇒ Object
Parses the wound description line from HEALTH command output.
-
.perceive_health ⇒ Object
Uses PERCEIVE HEALTH SELF command to check for wounds and scars.
-
.perceive_health_other(target) ⇒ HealthResult?
Perceives the health of another character via empathic touch.
-
.skilled_to_tend_wound?(bleed_rate, internal = false) ⇒ Boolean
Skill check to tend a bleeding wound.
-
.strip_xml(lines) ⇒ Array<String>
Strips XML tags and decodes common HTML entities from game output lines.
-
.unwrap_wound(body_part, person = 'my') ⇒ void
Removes bandages from a tended wound.
Class Method Details
.bind_wound(body_part, person = 'my') ⇒ Boolean
Side effect: disposes of dislodged items to the worn trashcan
Tends a wound on a body part, removing bandages and handling dislodged items.
Issues a TEND command for the specified body part. If the tend dislodges an item (e.g., a crossbow bolt), removes and disposes of it before retrying the tend. Waits for roundtime before returning.
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 |
# File 'documented/dragonrealms/commons/common-healing.rb', line 391 def bind_wound(body_part, person = 'my') result = DRC.bput("tend #{person} #{body_part}", *TEND_SUCCESS_PATTERNS, *TEND_FAILURE_PATTERNS, *TEND_DISLODGE_PATTERNS) waitrt? case result when *TEND_DISLODGE_PATTERNS dislodge_match = result.match(/^You \w+ remove (?:a|the|some) (?<item>.+) from/) # Only dispose the item the tend just removed, and only while it is in # hand. A freshly dislodged item (e.g. a crossbow bolt) lands in a free # hand; disposing it there is safe. But if the item is gone (the maze # can yank you out and clear your hands the instant it drops), a blind # dispose_trash would GET a same-named item from a worn container -- # trashing the character's own ammunition -- so skip it in that case. if dislodge_match && DRCI.in_hands?(dislodge_match[:item]) DRCI.dispose_trash(dislodge_match[:item], get_settings.worn_trashcan, get_settings.worn_trashcan_verb) end bind_wound(body_part, person) when *TEND_FAILURE_PATTERNS false else true end end |
.calculate_score(wounds_by_severity) ⇒ Object
Computes a weighted summary score from a wound severity map. Higher severity wounds contribute quadratically more to the score.
444 445 446 |
# File 'documented/dragonrealms/commons/common-healing.rb', line 444 def calculate_score(wounds_by_severity) wounds_by_severity.map { |severity, wound_list| (severity**2) * wound_list.count }.reduce(:+) || 0 end |
.check_health ⇒ Object
Uses HEALTH command to check for poisons, diseases, bleeders, parasites, and lodged items. Returns a HealthResult with diagnostic information for healing prioritization.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'documented/dragonrealms/commons/common-healing.rb', line 28 def check_health health_lines = Lich::Util.issue_command( 'health', /^Your body feels\b/, /<prompt/, usexml: true, quiet: true, include_end: false ) if health_lines.nil? Lich::Messaging.msg("bold", "DRCH: Failed to capture HEALTH output (timeout).") return HealthResult.new end parse_health_lines(strip_xml(health_lines)) end |
.has_tendable_bleeders? ⇒ Boolean
22 23 24 |
# File 'documented/dragonrealms/commons/common-healing.rb', line 22 def has_tendable_bleeders? check_health.has_tendable_bleeders? end |
.parse_bleeders(health_lines) ⇒ Object
Parses bleeder lines from HEALTH command output. Returns a hash keyed by severity with arrays of bleeding Wounds.
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
# File 'documented/dragonrealms/commons/common-healing.rb', line 267 def parse_bleeders(health_lines) bleeders = Hash.new { |h, k| h[k] = [] } return bleeders unless health_lines.grep(/^Bleeding|^\s*\bArea\s+Rate\b/).any? health_lines .drop_while { |line| !(BLEEDER_LINE_REGEX =~ line) } .take_while { |line| BLEEDER_LINE_REGEX =~ line } .each do |line| match = line.match(WOUND_BODY_PART_REGEX) next unless match body_part = match.names.find { |name| match[name.to_sym] } body_part = match[:part] if body_part == 'part' body_part = body_part.gsub('l.', 'left').gsub('r.', 'right') rate_match = line.match(/(?:head|eye|neck|chest|abdomen|back|arm|hand|leg|tail|skin)\s+(?<rate>.+)/) next unless rate_match bleed_rate = rate_match[:rate].strip bleed_info = BLEED_RATE_TO_SEVERITY[bleed_rate] next unless bleed_info bleeders[bleed_info[:severity]] << Wound.new( body_part: body_part, severity: bleed_info[:severity], bleeding_rate: bleed_rate, is_internal: line.start_with?('inside') ) end bleeders end |
.parse_health_lines(health_lines) ⇒ Object
Parses stripped HEALTH command output lines into a HealthResult.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'documented/dragonrealms/commons/common-healing.rb', line 46 def parse_health_lines(health_lines) parasites_regex = Regexp.union(PARASITES_REGEX) wounds_line = nil parasites_line = nil lodged_line = nil diseased = false poisoned = false health_lines.each do |line| case line when /^Your body feels\b/, /^Your spirit feels\b/, /^You are .*fatigued/, /^You feel fully rested/ next when /^You have (?!no significant injuries)(?!.* lodged .* in(?:to)? your)(?!.* infection)(?!.* poison(?:ed)?)(?!.* #{parasites_regex})/ wounds_line = line when /^You have .* lodged .* in(?:to)? your/ lodged_line = line when /^You have a .* on your/, parasites_regex parasites_line = line when /^You have a dormant infection/, /^Your wounds are infected/, /^Your body is covered in open oozing sores/ diseased = true when /^You have .* poison(?:ed)?/, /^You feel somewhat tired and seem to be having trouble breathing/ poisoned = true end end bleeders = parse_bleeders(health_lines) wounds = parse_wounds(wounds_line) parasites = parse_parasites(parasites_line) lodged_items = parse_lodged_items(lodged_line) score = calculate_score(wounds) HealthResult.new( wounds: wounds, bleeders: bleeders, parasites: parasites, lodged: lodged_items, poisoned: poisoned, diseased: diseased, score: score ) end |
.parse_lodged_items(lodged_line) ⇒ Object
Parses the lodged item description line from HEALTH command output. Returns a hash keyed by severity with arrays of lodged item Wounds.
351 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 |
# File 'documented/dragonrealms/commons/common-healing.rb', line 351 def parse_lodged_items(lodged_line) lodged_items = Hash.new { |h, k| h[k] = [] } return lodged_items unless lodged_line lodged_line = lodged_line.gsub(/^You have\s+/, '').gsub(/\.$/, '') lodged_line.split(',').map(&:strip).each do |wound| match = wound.match(LODGED_BODY_PART_REGEX) next unless match body_part = match.names.find { |name| match[name.to_sym] } body_part = match[:part] if body_part == 'part' severity_match = wound.match(/\blodged\s+(?<depth>.+)\s+in(?:to)? your\b/) next unless severity_match severity = LODGED_SEVERITY[severity_match[:depth]] lodged_items[severity] << Wound.new( body_part: body_part, severity: severity, is_lodged_item: true ) end lodged_items end |
.parse_parasites(parasites_line) ⇒ Object
Parses the parasite description line from HEALTH command output. Returns a hash keyed by severity with arrays of parasite Wounds.
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 |
# File 'documented/dragonrealms/commons/common-healing.rb', line 330 def parse_parasites(parasites_line) parasites = Hash.new { |h, k| h[k] = [] } return parasites unless parasites_line parasites_line = parasites_line.gsub(/^You have\s+/, '').gsub(/\.$/, '') parasites_line.split(',').map(&:strip).each do |parasite| match = parasite.match(PARASITE_BODY_PART_REGEX) next unless match parasites[1] << Wound.new( body_part: match[:part], severity: 1, is_parasite: true ) end parasites end |
.parse_perceived_health_lines(lines) ⇒ Object
Parses lines from PERCEIVE HEALTH SELF or TOUCH output into a HealthResult.
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'documented/dragonrealms/commons/common-healing.rb', line 192 def parse_perceived_health_lines(lines) parasites_regex = Regexp.union(PARASITES_REGEX) poisons_regex = Regexp.union([ /^[\w]+ (?:has|have) a .* poison/, /having trouble breathing/, /Cyanide poison/ ]) diseases_regex = Regexp.union([ /^[\w]+ wounds are (?:badly )?infected/, /^[\w]+ (?:has|have) a dormant infection/, /^[\w]+ (?:body|skin) is covered (?:in|with) open oozing sores/ ]) dead_regex = /^(?:He|She) is dead/ vitality_regex = /has (\d+)% vitality remaining/ perceived_wounds = Hash.new { |h, k| h[k] = [] } perceived_parasites = Hash.new { |h, k| h[k] = [] } perceived_poison = false perceived_disease = false perceived_vitality = 100 wound_body_part = nil dead = false lines.each do |line| case line when dead_regex dead = true when vitality_regex perceived_vitality = Regexp.last_match(1).to_i when diseases_regex perceived_disease = true when poisons_regex perceived_poison = true when parasites_regex match = line.match(/.* on (?:his|her|your) (?<body_part>[\w\s]*)/) body_part = match[:body_part] if match perceived_parasites[1] << Wound.new(body_part: body_part, severity: 1) when /^Wounds to the / match = line.match(/^Wounds to the (?<body_part>.+):/) wound_body_part = match[:body_part] if match perceived_wounds[wound_body_part] = [] when /^(?:Fresh|Scars) (?:External|Internal)/ match = line.match(PERCEIVE_HEALTH_SEVERITY_REGEX) next unless match next unless wound_body_part severity = WOUND_SEVERITY[match[:severity]] perceived_wounds[wound_body_part] << Wound.new( body_part: wound_body_part, severity: severity, is_internal: match[:location] == 'Internal', is_scar: match[:freshness] == 'Scars' ) end end # Bucket wounds by severity. wounds = Hash.new { |h, k| h[k] = [] } perceived_wounds.values.flatten.each do |wound| wounds[wound.severity] << wound end HealthResult.new( wounds: wounds, parasites: perceived_parasites, poisoned: perceived_poison, diseased: perceived_disease, dead: dead, vitality: perceived_vitality, score: calculate_score(wounds) ) end |
.parse_wounds(wounds_line) ⇒ Object
Parses the wound description line from HEALTH command output. Returns a hash keyed by severity with arrays of Wounds.
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
# File 'documented/dragonrealms/commons/common-healing.rb', line 302 def parse_wounds(wounds_line) wounds = Hash.new { |h, k| h[k] = [] } return wounds unless wounds_line wounds_line = wounds_line.gsub(WOUND_COMMA_SEPARATOR, '') wounds_line = wounds_line.gsub(/^You have\s+/, '').gsub(/\.$/, '') wounds_line.split(',').map(&:strip).each do |wound| WOUND_SEVERITY_REGEX_MAP.each do |regex, template| match = wound.match(regex) next unless match body_part = match.names.find { |name| match[name.to_sym] } body_part = match[:part] if body_part == 'part' wounds[template[:severity]] << Wound.new( body_part: body_part, severity: template[:severity], is_internal: template[:internal], is_scar: template[:scar] ) end end wounds end |
.perceive_health ⇒ Object
Uses PERCEIVE HEALTH SELF command to check for wounds and scars. Returns a HealthResult with perceived wound details merged with check_health diagnostics.
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'documented/dragonrealms/commons/common-healing.rb', line 90 def perceive_health unless DRStats.empath? Lich::Messaging.msg("bold", "DRCH: Only empaths can perceive health.") return nil end lines = Lich::Util.issue_command( 'perceive health self', /injuries include\.\.\.|feel only an aching emptiness/, /<prompt/, usexml: true, quiet: true, include_end: false, timeout: 15 ) if lines.nil? Lich::Messaging.msg("bold", "DRCH: Failed to capture PERCEIVE HEALTH output (timeout).") return nil end lines = strip_xml(lines) if lines.any? { |line| line =~ /feel only an aching emptiness/ } waitrt? return check_health end perceived = parse_perceived_health_lines(lines) health_data = check_health waitrt? HealthResult.new( wounds: perceived.wounds, bleeders: health_data.bleeders, parasites: health_data.parasites, lodged: health_data.lodged, poisoned: health_data.poisoned, diseased: health_data.diseased, vitality: perceived.vitality, dead: perceived.dead, score: perceived.score ) end |
.perceive_health_other(target) ⇒ HealthResult?
The actual target name is extracted from the empathic link message and may differ from the input (e.g., case or abbreviation).
Perceives the health of another character via empathic touch.
Empaths only. Attempts to touch the target to establish an empathic link, then parses the perceived health lines to extract wound, disease, poison, and vitality information. Returns nil if the target cannot be touched or if the empath does not have the PERCEIVE HEALTH skill.
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'documented/dragonrealms/commons/common-healing.rb', line 151 def perceive_health_other(target) unless DRStats.empath? Lich::Messaging.msg("bold", "DRCH: Only empaths can perceive health of others.") return nil end touch_lines = Lich::Util.issue_command( "touch #{target}", /You sense a successful empathic link|Touch what|feels cold|avoids your touch|You quickly recoil/, /<prompt/, usexml: true, quiet: true, include_end: false, timeout: 10 ) if touch_lines.nil? Lich::Messaging.msg("bold", "DRCH: Failed to capture TOUCH output for #{target} (timeout).") return nil end touch_lines = strip_xml(touch_lines) if touch_lines.any? { |line| line =~ /Touch what|feels cold|avoids your touch|You quickly recoil/ } Lich::Messaging.msg("bold", "DRCH: Unable to perceive health of #{target}.") return nil end # Extract actual character name from the empathic link message. # The target passed to the method may be abbreviated or differently cased. touch_lines.each do |line| match = line.match(/between you and (?<name>\w+)\./) if match target = match[:name] break end end parse_perceived_health_lines(touch_lines) end |
.skilled_to_tend_wound?(bleed_rate, internal = false) ⇒ Boolean
Skill check to tend a bleeding wound. Returns false if unskilled - tending when unskilled may worsen the wound.
431 432 433 434 435 436 437 438 439 440 |
# File 'documented/dragonrealms/commons/common-healing.rb', line 431 def skilled_to_tend_wound?(bleed_rate, internal = false) bleed_info = BLEED_RATE_TO_SEVERITY[bleed_rate] return false unless bleed_info skill_target = internal ? :skill_to_tend_internal : :skill_to_tend min_skill = bleed_info[skill_target] return false if min_skill.nil? DRSkill.getrank('First Aid') >= min_skill end |
.strip_xml(lines) ⇒ Array<String>
Strips XML tags and decodes common HTML entities from game output lines.
18 19 20 |
# File 'documented/dragonrealms/commons/common-healing.rb', line 18 def strip_xml(lines) DRC.strip_xml(lines) end |
.unwrap_wound(body_part, person = 'my') ⇒ void
This method returns an undefined value.
Removes bandages from a tended wound.
Issues an UNWRAP command to reverse the effects of a prior TEND. Waits for roundtime after the command completes.
424 425 426 427 |
# File 'documented/dragonrealms/commons/common-healing.rb', line 424 def unwrap_wound(body_part, person = 'my') DRC.bput("unwrap #{person} #{body_part}", 'You unwrap .* bandages', 'That area is not tended', 'You may undo the affects of TENDing') waitrt? end |