From f8cb7e774e6349a0bfd94d0e66f36b511fadc44c Mon Sep 17 00:00:00 2001 From: Matt Lowe Date: Wed, 12 Sep 2018 08:09:25 -0500 Subject: [PATCH] refresh after not using git for a time --- alchemy-recipes.lic | 637 +++++++--- alchemy.lic | 1043 +++++++++++------ answers.lic | 4 +- autoforage.lic | 412 ++++--- chargeimbed.lic | 98 +- ego2.lic | 147 +-- group_ajar.lic | 4 +- highlight_links.lic | 1 + inactivespells.lic | 5 +- invoke.lic | 13 +- keepsigns.lic | 32 +- markchargable.lic | 1 + measure-favor.lic | 3 +- passive-spellbot.lic | 48 +- prettybounty.lic | 5 +- rbolt.lic | 1 + rcast.lic | 1 + readscrolls.lic | 11 +- sexual-favors.lic | 2442 ++++++++++++++++----------------------- shield-size.lic | 5 +- short-haste-message.lic | 22 +- sorter.lic | 48 +- staminabar.lic | 5 +- trollhear.lic | 7 +- trollspeak.lic | 5 +- useherbs.lic | 1089 ++++++++++------- useimbed.lic | 146 ++- waggle.lic | 447 ++++--- waitloot.lic | 10 +- wander.lic | 334 ++++-- wiz_to_lich.lic | 121 +- xp.lic | 509 +++++--- zombie.lic | 36 +- 33 files changed, 4498 insertions(+), 3194 deletions(-) diff --git a/alchemy-recipes.lic b/alchemy-recipes.lic index 12340e5..989c24c 100644 --- a/alchemy-recipes.lic +++ b/alchemy-recipes.lic @@ -2,10 +2,46 @@ This script loads alchemy recipes into memory for the alchemy script. - https://github.com/matt-lowe/lich-scripts - tillmen@lichproject.org + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: alchemy, guild + version: 0.10 + + changelog: + 0.10 (2017-09-24): + fix shimmering silver potion (507) + 0.9 (2015-04-26): + rename some powdered Kezmonian honey beryl => some powdered honey beryl + rename minor holy oil => some minor holy oil + rename some faint mote of soul => faint mote of soul + 0.8 (2015-02-22): + add recipe for sisfu potion + +=end +=begin + + 0.7 (2015-01-26): + change start rank of grot'tkel potion from 15 to 13 + 0.6 (2015-01-22): + add grind and forage recipes for bone mushroom + 0.5 (2015-01-14): + added grind recipes for dragon's-tear diamond and clear glimaerstone =end +=begin + + 0.4 (2014-12-12): + added boar tusk value + 0.3 (2014-12-10): + added reagent cost and equivalents + 0.2 (2014-10-14): + fix buy some powdered gold nugget recipe + +=end + +# todo: crimson salt crystals recipe maybe +# thirdly ground lichen doesn't decipher between what kinda lichen. there's at least 2 different lichent hat become ground lichen." (04:07:13) +# you need to use alchemy examine to determine what it was before..." (04:07:24) $alchemy_recipes = [ @@ -71,7 +107,7 @@ $alchemy_recipes = [ :product => "grot'tkel potion", :steps => [ 'light', 'add flask of clear water', 'add ayana leaf', 'boil', 'add ayanad crystal', 'simmer', 'add some crystal core essence', 'seal' ], :type => 'alchemy', - :rank => [ 15, 25 ], + :rank => [ 13, 25 ], }, r = { :product => 'tincture of bolmara', @@ -236,7 +272,8 @@ $alchemy_recipes = [ :rank => [ 34, 51 ], }, r = { - :product => 'minor luck talisman', + :product => 'smooth stone talisman', + :nick => 'minor luck talisman', :steps => [ 'light', 'add vial of pearlescent oil', 'add some ground tkaro', 'add some ground tkaro', 'boil', 'add luckbloom blossom', "add s'ayanad crystal", 'simmer', 'add some powdered white pearl', "add pristine nymph's hair", 'infuse', 'add smooth stone', 'seal' ], :type => 'alchemy', :rank => [ 37, 55 ], @@ -526,6 +563,12 @@ $alchemy_recipes = [ :type => 'alchemy', :rank => [ 54, 62 ], }, + r = { + :product => 'vial of clear dye base', + :steps => [ 'light', 'add flask of clear water', 'add some ground murdroot', 'add some ground murdroot', 'add some ground murdroot', 'add some ground murdroot', "add t'ayanad crystal", "add t'ayanad crystal", 'simmer', 'add some powdered grey caederine', "add s'ayanad crystal", 'boil', 'add vial of farlook vitreous humor', 'infuse', 'seal' ], + :type => 'alchemy', + :rank => [ 54, 62 ], + }, r = { :product => 'sapphire blue vial of dye', :steps => [ 'light', 'add vial of clear dye base', 'add some ground blue moss', 'add some ground blue moss', 'simmer', 'add some powdered blue sapphire', 'boil', 'seal' ], @@ -637,7 +680,7 @@ $alchemy_recipes = [ }, r = { :product => 'temporary honey blonde hair dye', - :steps => [ 'light', 'add vial of hair dye base', 'add some mashed golden buttercup', 'add some powdered Kezmonian honey beryl', 'boil', 'seal' ], + :steps => [ 'light', 'add vial of hair dye base', 'add some mashed golden buttercup', 'add some powdered honey beryl', 'boil', 'seal' ], :type => 'alchemy', :rank => [ 26, 36 ], }, @@ -668,13 +711,6 @@ $alchemy_recipes = [ # # alchemic potions recipes # - r = { - :product => 'inky black potion', - :steps => [ 'light', 'add flask of clear water', 'add some essence of water', 'simmer', 'add some powdered uncut diamond', 'add some faintly radiant dust', 'infuse', 'add inky necrotic core', 'add flask of sparkling soul essence', 'chant 735', 'seal' ], - :type => 'potions', - :spell => '735', - :for => [ 'Sorcerer' ], - }, r = { :product => 'light blue potion', :steps => [ 'light', 'add flask of clear water', 'add ayana leaf', 'simmer', 'add some powdered turquoise stone', 'boil', 'add small daisy', 'add small daisy', 'chant 101', 'seal' ], @@ -829,7 +865,7 @@ $alchemy_recipes = [ :steps => [ 'light', 'add flask of clear water', 'add viper fang', 'boil', 'add some ground sweetfern stalk', 'add some ground sweetfern stalk', 'simmer', 'add some powdered green tourmaline', 'chant 105', 'seal' ], :type => 'potions', :spell => '105', - :rank => [ 12, 27 ], + :rank => [ 14, 27 ], :for => [ 'Cleric', 'Empath', 'Sorcerer' ], }, r = { @@ -888,7 +924,7 @@ $alchemy_recipes = [ :for => [ 'Wizard' ], }, r = { - :product => 'minor holy oil', + :product => 'some minor holy oil', :steps => [ 'light', 'add flask of blessed oil', 'add wraith talon', 'add wraith talon', 'add wraith talon', 'add wraith talon', 'add some powdered white jade', 'boil', 'add ayanad crystal', 'add some glowing white powder', 'simmer', 'chant 304', 'seal' ], :type => 'potions', :spell => '304', @@ -975,14 +1011,16 @@ $alchemy_recipes = [ :for => [ 'Cleric' ], }, r = { - :product => 'minor necromantic regeneration potion', + :product => 'thin murky greenish-black concoction', + :nick => 'minor necromantic regeneration potion', :steps => [ 'light', 'add flask of clear water', 'add some powdered black opal', 'add some powdered black opal', 'add some powdered green moonstone', 'add some glimmering blue essence dust', 'boil', 'add some essence of regeneration', 'simmer', 'chant 730', 'seal' ], :type => 'potions', :rank => [ 25, 41 ], :for => [ 'Sorcerer' ], }, r = { - :product => 'minor lockrot oil', + :product => 'flask of noxious brown tar', + :nick => 'minor lockrot oil', :steps => [ 'light', 'add flask of pure oil', 'add some powdered golden amber', 'add some powdered golden amber', "add s'ayanad crystal", 'add some powdered charcoal', 'add some powdered charcoal', 'boil', 'add some essence of water', 'seal' ], :type => 'potions', :rank => [ 26, 36 ], @@ -990,16 +1028,16 @@ $alchemy_recipes = [ }, r = { :product => 'shimmering silver potion', - :steps => [ 'light', 'add flask of clear water', 'add mountain lion skin', 'add some powdered silvery conch shell', 'simmer', 'chant 507', 'seal' ], + :steps => [ 'light', 'add flask of clear water', 'add mountain lion skin', 'add mountain lion skin', 'add some powdered silvery conch shell', 'simmer', 'chant 507', 'seal' ], :type => 'potions', :spell => '507', - :rank => [ 27, 41 ], +# :rank => [ 27, 41 ], # fixme: recipe failed :for => [ 'Wizard' ], }, r = { :product => 'foamy deep golden elixir', :nick => 'lesser health-well potion', - :steps => [ 'light', 'add flask of clear water', 'add yellow passionflower', 'add some powdered Kezmonian honey beryl', 'add large troll tooth', 'add some faintly glimmering dust', 'add some faintly glimmering dust', 'boil', 'seal' ], + :steps => [ 'light', 'add flask of clear water', 'add yellow passionflower', 'add some powdered honey beryl', 'add large troll tooth', 'add some faintly glimmering dust', 'add some faintly glimmering dust', 'boil', 'seal' ], :type => 'potions', :rank => [ 28, 38 ], :for => [ 'Empath' ], @@ -1154,14 +1192,16 @@ $alchemy_recipes = [ :for => [ 'Wizard', 'Sorcerer' ], }, r = { - :product => 'lesser lockrot oil', + :product => 'flask of noxious dark tar', + :nick => 'lesser lockrot oil', :steps => [ 'light', 'add flask of pure oil', 'add some powdered golden amber', 'add some powdered golden amber', "add s'ayanad crystal", 'add some powdered charcoal', 'add some powdered charcoal', 'boil', 'add dark glimmering crystal', 'infuse', 'add some essence of earth', 'seal' ], :type => 'potions', :rank => [ 44, 54 ], :for => [ 'Wizard' ], }, r = { - :product => 'lesser necromantic regeneration potion', + :product => 'thick murky greenish-black concoction', + :nick => 'lesser necromantic regeneration potion', :steps => [ 'light', 'add flask of clear water', 'add some powdered black deathstone', 'add some powdered black deathstone', 'add some powdered black deathstone', 'add some powdered black deathstone', 'refract moonlight through shadowglass lens', 'add some powdered uncut emerald', 'add some glowing violet essence dust', 'add troll blood', 'add some essence of regeneration', 'simmer', 'chant 730', 'seal' ], :type => 'potions', :rank => [ 45, 55 ], @@ -1175,6 +1215,14 @@ $alchemy_recipes = [ :rank => [ 47, 57 ], :for => [ 'Empath' ], }, + r = { + :product => 'sisfu potion', + :steps => [ 'light', 'add flask of clear water', 'add some ground ayana', 'add some ground ayana', 'add some ground ayana', 'add some essence of water', 'add some essence of water', 'add some essence of water', 'chant 925', 'add some faintly radiant dust', 'add some faintly radiant dust', 'refract moonlight through diamond lens', 'seal' ], + :type => 'potions', + :spell => '925', + :rank => [ 50, 62 ], + :for => [ 'Wizard' ], + }, r = { :product => 'glowing brilliant silver potion', :steps => [ 'light', 'add flask of clear water', 'add ayana leaf', 'add ayana leaf', 'add ayana leaf', 'simmer', 'add centaur hide', 'add centaur hide', 'add centaur hide', 'boil', 'add some powdered yellow sapphire', 'infuse', "add t'ayanad crystal", 'channel', 'chant 419', 'seal' ], @@ -1230,6 +1278,14 @@ $alchemy_recipes = [ :rank => [ 54, 62 ], :for => [ 'Cleric' ], }, + r = { + :product => 'viscous murky greenish-black concoction', + :nick => 'greater necromantic regeneration potion', + :steps => [ 'light', 'add flask of clear water', 'add some powdered black pearl', 'add some powdered black pearl', 'refract moonlight through shadowglass lens', 'add some powdered emerald blazestar', 'channel', 'add some radiant crimson essence dust', 'add troll blood', 'boil', 'add some essence of regeneration', 'simmer', 'chant 730', 'seal' ], + :type => 'potions', + :rank => [ 57, 63 ], + :for => [ 'Empath' ], + }, r = { :product => 'vivid blue bubbling potion', :nick => 'greater elemental focus potion', @@ -1255,7 +1311,7 @@ $alchemy_recipes = [ :for => [ 'Empath' ], }, r = { - :product => 'sparkling pink potion ', + :product => 'sparkling pink potion', :nick => 'greater wisdom potion', :steps => [ 'light', 'add flask of clear water', 'add wood violet', 'add split-back pink conch shell', 'infuse', 'add ayana leaf', 'add some powdered uncut diamond', 'simmer', "add n'ayanad crystal", 'add flask of sparkling mind essence', 'refract moonlight through amethyst lens', 'seal' ], :type => 'potions', @@ -1270,10 +1326,18 @@ $alchemy_recipes = [ :rank => [ 62, 62 ], :for => [ 'Wizard' ], }, + r = { + # fixme: unknown rank + :product => 'inky black potion', + :steps => [ 'light', 'add flask of clear water', 'add some essence of water', 'simmer', 'add some powdered uncut diamond', 'add some powdered uncut diamond', 'add some powdered uncut diamond', 'add some faintly radiant dust', 'infuse', 'add inky necrotic core', 'add flask of sparkling soul essence', 'chant 735', 'seal' ], + :type => 'potions', + :spell => '735', + :for => [ 'Sorcerer' ], + }, r = { # fixme: unknown rank :product => 'eoveneh potion', - :steps => [ 'light', 'add flask of clear water', 'add some powdered uncut diamond', 'add some essence of water', 'simmer', 'add minor holy oil', 'add some faintly radiant dust', 'infuse', 'add radiant white soulstone', 'chant 925', 'seal' ], + :steps => [ 'light', 'add flask of clear water', 'add some powdered uncut diamond', 'add some essence of water', 'simmer', 'add some minor holy oil', 'add some faintly radiant dust', 'infuse', 'add radiant white soulstone', 'chant 925', 'seal' ], :type => 'potions', :spell => '925', :for => [ 'Wizard' ], @@ -1286,10 +1350,11 @@ $alchemy_recipes = [ :for => [ 'Cleric' ], }, r = { - # fixme: unknown rank - :product => 'greater lockrot oil', + :product => 'flask of noxious black tar', + :nick => 'greater lockrot oil', :steps => [ 'light', 'add flask of pure oil', 'add some powdered golden amber', 'add some powdered golden amber', "add s'ayanad crystal", 'add some powdered charcoal', 'add some powdered charcoal', 'boil', 'add dark glimmering crystal', 'infuse', 'add some radiant crimson essence dust', 'refract moonlight through amethyst lens', 'seal' ], :type => 'potions', + :rank => [ 60, 62 ], # fixme: unknown start rank :for => [ 'Wizard' ], }, r = { @@ -1901,7 +1966,7 @@ $alchemy_recipes = [ :product => 'faceted topaz wand', :steps => [ 'light', 'add vial of viscous liquid', 'add some powdered smoky topaz', 'simmer', 'add bear hide', 'add bear hide', 'boil', 'add some coarse glittering earth', 'infuse', "add s'ayanad crystal", 'chant 510', 'seal' ], :type => 'trinkets', - :spell => '511', + :spell => '510', :rank => [ 39, 56 ], :for => [ 'Wizard' ], }, @@ -2062,7 +2127,7 @@ $alchemy_recipes = [ :steps => [ 'light', 'add vial of viscous liquid', 'add mammoth arachnid mandible', 'add mammoth arachnid mandible', 'add mammoth arachnid mandible', 'add some powdered selanthan bloodjewel', 'add flask of sparkling mind essence', 'simmer', 'channel', 'seal' ], :type => 'trinkets', :rank => [ 56, 62 ], - # fixme :for => [ '' ], + :for => [ 'Cleric', 'Empath', 'Sorcerer' ], }, r = { :product => 'glass amulet', @@ -2100,6 +2165,20 @@ $alchemy_recipes = [ :rank => [ 62, 62 ], :for => [ 'Empath' ], # fixme }, + r = { + # fixme: untested + :product => 'gleaming multicolored soulstone', + :steps => [ 'light', 'add vial of viscous liquid', 'add some powdered uncut emerald', 'refract moonlight through shadowglass lens', 'infuse', 'add some elemental core', 'add some elemental core', 'add some elemental core', 'add some elemental core', 'add some elemental core', 'channel', 'chant 735', 'seal' ], + :type => 'trinkets', + :for => [ 'Sorcerer' ], + }, + r = { + # fixme: untested + :product => 'elemental soulstone', + :steps => [ 'light', 'add vial of viscous liquid', 'add some powdered uncut emerald', 'refract sunlight through shadowglass lens', 'infuse', 'add some elemental core', 'add some elemental core', 'add some elemental core', 'add some elemental core', 'add some elemental core', 'channel', 'chant 735', 'seal' ], + :type => 'trinkets', + :for => [ 'Sorcerer' ], + }, r = { :product => 'greater constitution crystal', :steps => [ 'light', 'add vial of viscous liquid', 'add some ground strigae cactus', 'add some ground strigae cactus', 'add some ground strigae cactus', 'add some powdered blue diamond', 'add flask of sparkling body essence', 'simmer', "add n'ayanad crystal", 'add some fine alabaster dust', 'refract moonlight through diamond lens', 'seal' ], @@ -2135,7 +2214,7 @@ $alchemy_recipes = [ }, r = { :product => 'radiant white soulstone', - :steps => [ 'light', 'add vial of viscous liquid', 'add some powdered Kezmonian honey beryl', 'add minor holy oil', 'infuse', 'add some powdered uncut diamond', 'add some faint mote of soul', 'channel', 'seal' ], + :steps => [ 'light', 'add vial of viscous liquid', 'add some powdered honey beryl', 'add some minor holy oil', 'infuse', 'add some powdered uncut diamond', 'add faint mote of soul', 'channel', 'seal' ], :type => 'trinkets', :for => [ 'Cleric' ], }, @@ -2181,7 +2260,7 @@ $alchemy_recipes = [ r = { :product => 'vial of viscous liquid', :steps => [ "buy from #{Char.prof.downcase} alchemy shop" ], - :cost => 100 , + :cost => 100, }, r = { :product => 'vial of sand-like liquid', @@ -2683,7 +2762,7 @@ $alchemy_recipes = [ }, r = { :product => 'some powdered gold nugget', - :steps => [ "buy from Icemule Trace wizard alchemy shop" ], + :steps => [ "buy from Icemule wizard alchemy shop" ], :for => [ 'Wizard' ], :cost => 800, }, @@ -2955,6 +3034,8 @@ $alchemy_recipes = [ # # grind reagents # + r = { :product => "some powdered dragon's-tear diamond", :steps => [ "grind dragon's-tear diamond" ] }, + r = { :product => 'some powdered clear glimaerstone', :steps => [ 'grind clear glimaerstone' ] }, r = { :product => 'some powdered clear zircon', :steps => [ 'grind clear zircon' ] }, r = { :product => 'some powdered rock crystal', :steps => [ 'grind rock crystal' ] }, r = { :product => 'some powdered labradorite stone', :steps => [ 'grind iridescent labradorite stone' ] }, @@ -3043,7 +3124,7 @@ $alchemy_recipes = [ r = { :product => 'some powdered shimmarglin sapphire', :steps => [ 'grind shimmarglin sapphire' ] }, r = { :product => 'some powdered dragonseye sapphire', :steps => [ 'grind dragonseye sapphire' ] }, r = { :product => 'some powdered white marble', :steps => [ 'grind white marble' ] }, - r = { :product => 'some powdered Kezmonian honey beryl', :steps => [ 'grind Kezmonian honey beryl' ] }, + r = { :product => 'some powdered honey beryl', :steps => [ 'grind Kezmonian honey beryl' ] }, r = { :product => 'some powdered glossy black doomstone', :steps => [ 'grind glossy black doomstone' ] }, r = { :product => 'some powdered uncut diamond', :steps => [ 'grind uncut diamond' ] }, r = { :product => 'some powdered yellow hyacinth', :steps => [ 'grind yellow hyacinth' ] }, @@ -3072,6 +3153,7 @@ $alchemy_recipes = [ r = { :product => 'some powdered yellow diamond', :steps => [ 'grind large yellow diamond' ] }, r = { :product => 'some powdered blue diamond', :steps => [ 'grind blue diamond' ] }, r = { :product => 'some powdered star-of-Tamzyrr diamond', :steps => [ 'grind uncut star-of-Tamzyrr diamond' ] }, + r = { :product => 'some ground bone mushroom', :steps => [ 'grind bone mushroom' ] }, r = { :product => 'some ground sponge mushroom', :steps => [ 'grind sponge mushroom' ] }, r = { :product => 'some ground ironfern', :steps => [ 'grind ironfern root' ] }, r = { :product => 'some ground wolifrew', :steps => [ 'grind some wolifrew lichen' ] }, @@ -3100,6 +3182,12 @@ $alchemy_recipes = [ r = { :product => 'some ground orchil', :steps => [ 'grind some orchil lichen' ] }, r = { :product => 'some ground blackened moss', :steps => [ 'grind some blackened moss' ] }, r = { :product => 'some ground lichen', :steps => [ 'grind some red lichen' ] }, + r = { :product => 'some ground lichen', :steps => [ 'grind some glowing green lichen' ] }, +# fixme +# alchemy examine my lichen +# You examine the ground lichen, noting its unique characteristics and features. +# You determine that it is similar to ground green lichen in alchemical properties and application, and would likely make a suitable replacement in a recipe. + r = { :product => 'some ground longgrass', :steps => [ 'grind some longgrass' ] }, r = { :product => 'some ground arctic moss', :steps => [ 'grind some arctic moss' ] }, r = { :product => 'some ground woad leaves', :steps => [ 'grind cluster of woad leaves' ] }, @@ -3119,7 +3207,6 @@ $alchemy_recipes = [ r = { :product => 'some ground aloeas stem', :steps => [ 'grind some aloeas stem' ] }, r = { :product => 'some ground torban', :steps => [ 'grind some torban leaf' ] }, r = { :product => 'some ground pothinir', :steps => [ 'grind some pothinir grass' ] }, - r = { :product => 'some ground lichen', :steps => [ 'grind some glowing green lichen' ] }, r = { :product => 'some mashed pale yellow daffodil', :steps => [ 'grind pale yellow daffodil' ] }, r = { :product => 'some mashed pink rain lily', :steps => [ 'grind pink rain lily' ] }, r = { :product => 'some mashed nightshade', :steps => [ 'grind nightshade berry' ] }, @@ -3157,6 +3244,7 @@ $alchemy_recipes = [ r = { :product => 'some essence of regeneration', :steps => [ 'extract chipped troll tusk' ] }, r = { :product => 'some essence of regeneration', :steps => [ 'extract troll heart' ] }, r = { :product => 'some essence of regeneration', :steps => [ 'extract troll skin' ] }, + r = { :product => 'some essence of regeneration', :steps => [ 'extract scraggly swamp troll scalp' ] }, r = { :product => 'some essence of vitality', :steps => [ 'extract yabathilium fruit' ] }, r = { :product => 'some faintly glimmering dust', :steps => [ 'extract ayanad crystal' ] }, r = { :product => 'some faintly glowing dust', :steps => [ "extract s'ayanad crystal" ] }, @@ -3164,7 +3252,7 @@ $alchemy_recipes = [ r = { :product => 'some faintly shimmering dust', :steps => [ "extract n'ayanad crystal" ] }, r = { :product => 'some murdroot essence', :steps => [ 'extract murdroot' ] }, r = { :product => 'few lumps of charcoal', :steps => [ 'extract stick' ] }, - r = { :product => 'some faint mote of soul', :steps => [ 'extract inky necrotic core' ], :for => [ 'Cleric' ] }, + r = { :product => 'faint mote of soul', :steps => [ 'extract inky necrotic core' ], :for => [ 'Cleric' ] }, # # distill for reagants @@ -3176,109 +3264,110 @@ $alchemy_recipes = [ # # forage for reagants # - r = { :product => 'some acantha leaf', :steps => [ 'forage' ] }, - r = { :product => 'rose-marrow root', :steps => [ 'forage' ] }, - r = { :product => 'some ambrominas leaf', :steps => [ 'forage' ] }, - r = { :product => 'some cactacae spine', :steps => [ 'forage' ] }, - r = { :product => 'some aloeas stem', :steps => [ 'forage' ] }, - r = { :product => 'some haphip root', :steps => [ 'forage' ] }, - r = { :product => 'some pothinir grass', :steps => [ 'forage' ] }, - r = { :product => 'some basal moss', :steps => [ 'forage' ] }, - r = { :product => 'some ephlox moss', :steps => [ 'forage' ] }, - r = { :product => 'some calamia fruit', :steps => [ 'forage' ] }, - r = { :product => 'some sovyn clove', :steps => [ 'forage' ] }, - r = { :product => 'some wolifrew lichen', :steps => [ 'forage' ] }, - r = { :product => 'some woth flower', :steps => [ 'forage' ] }, - r = { :product => 'some torban leaf', :steps => [ 'forage' ] }, - r = { :product => 'ayana leaf', :steps => [ 'forage' ] }, - r = { :product => 'tkaro root', :steps => [ 'forage' ] }, - r = { :product => 'pepperthorn root', :steps => [ 'forage' ] }, - r = { :product => 'some talneo root', :steps => [ 'forage' ] }, - r = { :product => 'luckbloom blossom', :steps => [ 'forage' ] }, - r = { :product => 'wavepetal blossom', :steps => [ 'forage' ] }, - r = { :product => 'red trafel mushroom', :steps => [ 'forage' ] }, - r = { :product => 'slender twig', :steps => [ 'forage' ] }, - r = { :product => 'yabathilium fruit', :steps => [ 'forage' ] }, - r = { :product => 'small daisy', :steps => [ 'forage' ] }, - r = { :product => 'cuctucae berry', :steps => [ 'forage' ] }, - r = { :product => 'some bolmara lichen', :steps => [ 'forage' ] }, - r = { :product => 'some rose-marrow root', :steps => [ 'forage' ] }, - r = { :product => 'nightshade berry', :steps => [ 'forage' ] }, - r = { :product => 'sprig of larkspur', :steps => [ 'forage' ] }, - r = { :product => 'some brostheras grass', :steps => [ 'forage' ] }, - r = { :product => 'some wingstem root', :steps => [ 'forage' ] }, - r = { :product => 'sprig of foxglove', :steps => [ 'forage' ] }, - r = { :product => 'blue trafel mushroom', :steps => [ 'forage' ] }, - r = { :product => 'sprig of lavender', :steps => [ 'forage' ] }, - r = { :product => 'some cothinar flower', :steps => [ 'forage' ] }, - r = { :product => 'marallis berry', :steps => [ 'forage' ] }, - r = { :product => 'ironfern root', :steps => [ 'forage' ] }, - r = { :product => 'some valerian root', :steps => [ 'forage' ] }, - r = { :product => 'large white gardenia', :steps => [ 'forage' ] }, - r = { :product => 'murdroot', :steps => [ 'forage' ] }, - r = { :product => 'glowing firefly', :steps => [ 'forage' ] }, - r = { :product => 'giant glowing toadstool', :steps => [ 'forage' ] }, - r = { :product => 'Elanthian snow rose', :steps => [ 'forage' ] }, - r = { :product => 'crimson dragonstalk', :steps => [ 'forage' ] }, - r = { :product => 'fairy primrose', :steps => [ 'forage' ] }, - r = { :product => 'witchwood twig', :steps => [ 'forage' ] }, - r = { :product => 'sprig of columbine', :steps => [ 'forage' ] }, - r = { :product => 'handful of pinenuts', :steps => [ 'forage' ] }, - r = { :product => 'some bur-clover root', :steps => [ 'forage' ] }, - r = { :product => 'water chestnut', :steps => [ 'forage' ] }, - r = { :product => 'handful of oats', :steps => [ 'forage' ] }, - r = { :product => 'pale yellow daffodil', :steps => [ 'forage' ] }, - r = { :product => 'pink rain lily', :steps => [ 'forage' ] }, - r = { :product => 'stick', :steps => [ 'forage' ] }, - r = { :product => 'sprig of holly', :steps => [ 'forage' ] }, - r = { :product => 'white hook mushroom', :steps => [ 'forage' ] }, # fixme: can only forage at night - r = { :product => 'blue poppy', :steps => [ 'forage' ] }, - r = { :product => 'yellow passionflower', :steps => [ 'forage' ] }, - r = { :product => 'sprig of wild lilac', :steps => [ 'forage' ] }, - r = { :product => 'strand of seaweed', :steps => [ 'forage' ] }, - r = { :product => 'some cave moss', :steps => [ 'forage' ] }, - r = { :product => 'striped heart mushroom', :steps => [ 'forage' ] }, - r = { :product => 'white clover blossom', :steps => [ 'forage' ] }, - r = { :product => 'wood violet', :steps => [ 'forage' ] }, - r = { :product => 'soft white mushroom', :steps => [ 'forage' ] }, - r = { :product => 'bloodwood twig', :steps => [ 'forage' ] }, - r = { :product => 'twisted twig', :steps => [ 'forage' ] }, - r = { :product => 'some wheat grass', :steps => [ 'forage' ] }, - r = { :product => 'yew twig', :steps => [ 'forage' ] }, - r = { :product => 'sunburst blossom', :steps => [ 'forage' ] }, - r = { :product => 'nightbloom blossom', :steps => [ 'forage' ] }, - r = { :product => 'willow twig', :steps => [ 'forage' ] }, - r = { :product => 'genkew mushroom', :steps => [ 'forage' ] }, - r = { :product => 'ebony twig', :steps => [ 'forage' ] }, - r = { :product => 'stargazer lily', :steps => [ 'forage' ] }, - r = { :product => 'fragrant white lily', :steps => [ 'forage' ] }, - r = { :product => "ayana'al leaf", :steps => [ 'forage' ] }, - r = { :product => 'oak twig', :steps => [ 'forage' ] }, - r = { :product => 'sweetfern stalk', :steps => [ 'forage' ] }, - r = { :product => 'red poppy', :steps => [ 'forage' ] }, - r = { :product => 'pine cone', :steps => [ 'forage' ] }, - r = { :product => 'small wild rose', :steps => [ 'forage' ] }, - r = { :product => 'some alder bark', :steps => [ 'forage' ] }, - r = { :product => 'some orchil lichen', :steps => [ 'forage' ] }, - r = { :product => 'stalk of bluebells', :steps => [ 'forage' ] }, - r = { :product => 'some blackened moss', :steps => [ 'forage' ] }, - r = { :product => 'coppery rain lily', :steps => [ 'forage' ] }, - r = { :product => 'some longgrass', :steps => [ 'forage' ] }, - r = { :product => 'oxblood lily', :steps => [ 'forage' ] }, - r = { :product => 'sprig of mournbloom', :steps => [ 'forage' ] }, - r = { :product => 'some red lichen', :steps => [ 'forage' ] }, - r = { :product => 'handful of walnuts', :steps => [ 'forage' ] }, - r = { :product => 'some arctic moss', :steps => [ 'forage' ] }, - r = { :product => 'cluster of woad leaves', :steps => [ 'forage' ] }, - r = { :product => 'yellow clover blossom', :steps => [ 'forage' ] }, - r = { :product => 'layer of onion skin', :steps => [ 'forage' ] }, - r = { :product => 'cluster of gorse', :steps => [ 'forage' ] }, - r = { :product => 'bright red cranberry', :steps => [ 'forage' ] }, - r = { :product => 'orange begonia', :steps => [ 'forage' ] }, - r = { :product => 'wild beechnut', :steps => [ 'forage' ] }, - r = { :product => 'pine cone', :steps => [ 'forage' ] }, - r = { :product => 'pink hydrangea', :steps => [ 'forage' ] }, - r = { :product => 'heath aster', :steps => [ 'forage' ] }, + r = { :product => 'bone mushroom', :steps => [ 'forage' ] }, + r = { :product => 'some acantha leaf', :steps => [ 'forage' ] }, + r = { :product => 'rose-marrow root', :steps => [ 'forage' ] }, + r = { :product => 'some ambrominas leaf', :steps => [ 'forage' ] }, + r = { :product => 'some cactacae spine', :steps => [ 'forage' ] }, + r = { :product => 'some aloeas stem', :steps => [ 'forage' ] }, + r = { :product => 'some haphip root', :steps => [ 'forage' ] }, + r = { :product => 'some pothinir grass', :steps => [ 'forage' ] }, + r = { :product => 'some basal moss', :steps => [ 'forage' ] }, + r = { :product => 'some ephlox moss', :steps => [ 'forage' ] }, + r = { :product => 'some calamia fruit', :steps => [ 'forage' ] }, + r = { :product => 'some sovyn clove', :steps => [ 'forage' ] }, + r = { :product => 'some wolifrew lichen', :steps => [ 'forage' ] }, + r = { :product => 'some woth flower', :steps => [ 'forage' ] }, + r = { :product => 'some torban leaf', :steps => [ 'forage' ] }, + r = { :product => 'ayana leaf', :steps => [ 'forage' ] }, + r = { :product => 'tkaro root', :steps => [ 'forage' ] }, + r = { :product => 'pepperthorn root', :steps => [ 'forage' ] }, + r = { :product => 'some talneo root', :steps => [ 'forage' ] }, + r = { :product => 'luckbloom blossom', :steps => [ 'forage' ] }, + r = { :product => 'wavepetal blossom', :steps => [ 'forage' ] }, + r = { :product => 'red trafel mushroom', :steps => [ 'forage in sunlight' ] }, + r = { :product => 'slender twig', :steps => [ 'forage' ] }, + r = { :product => 'yabathilium fruit', :steps => [ 'forage' ] }, + r = { :product => 'small daisy', :steps => [ 'forage' ] }, + r = { :product => 'cuctucae berry', :steps => [ 'forage' ] }, + r = { :product => 'some bolmara lichen', :steps => [ 'forage' ] }, + r = { :product => 'some rose-marrow root', :steps => [ 'forage' ] }, + r = { :product => 'nightshade berry', :steps => [ 'forage' ] }, + r = { :product => 'sprig of larkspur', :steps => [ 'forage' ] }, + r = { :product => 'some brostheras grass', :steps => [ 'forage' ] }, + r = { :product => 'some wingstem root', :steps => [ 'forage' ] }, + r = { :product => 'sprig of foxglove', :steps => [ 'forage' ] }, + r = { :product => 'blue trafel mushroom', :steps => [ 'forage' ] }, + r = { :product => 'sprig of lavender', :steps => [ 'forage' ] }, + r = { :product => 'some cothinar flower', :steps => [ 'forage' ] }, + r = { :product => 'marallis berry', :steps => [ 'forage' ] }, + r = { :product => 'ironfern root', :steps => [ 'forage' ] }, + r = { :product => 'some valerian root', :steps => [ 'forage' ] }, + r = { :product => 'large white gardenia', :steps => [ 'forage' ] }, + r = { :product => 'murdroot', :steps => [ 'forage' ] }, + r = { :product => 'glowing firefly', :steps => [ 'forage' ] }, + r = { :product => 'giant glowing toadstool', :steps => [ 'forage' ] }, + r = { :product => 'Elanthian snow rose', :steps => [ 'forage' ] }, + r = { :product => 'crimson dragonstalk', :steps => [ 'forage' ] }, + r = { :product => 'fairy primrose', :steps => [ 'forage' ] }, + r = { :product => 'witchwood twig', :steps => [ 'forage' ] }, + r = { :product => 'sprig of columbine', :steps => [ 'forage' ] }, + r = { :product => 'handful of pinenuts', :steps => [ 'forage' ] }, + r = { :product => 'some bur-clover root', :steps => [ 'forage' ] }, + r = { :product => 'water chestnut', :steps => [ 'forage' ] }, + r = { :product => 'handful of oats', :steps => [ 'forage' ] }, + r = { :product => 'pale yellow daffodil', :steps => [ 'forage' ] }, + r = { :product => 'pink rain lily', :steps => [ 'forage' ] }, + r = { :product => 'stick', :steps => [ 'forage' ] }, + r = { :product => 'sprig of holly', :steps => [ 'forage' ] }, + r = { :product => 'white hook mushroom', :steps => [ 'forage in moonlight' ] }, + r = { :product => 'blue poppy', :steps => [ 'forage' ] }, + r = { :product => 'yellow passionflower', :steps => [ 'forage' ] }, + r = { :product => 'sprig of wild lilac', :steps => [ 'forage' ] }, + r = { :product => 'strand of seaweed', :steps => [ 'forage' ] }, + r = { :product => 'some cave moss', :steps => [ 'forage' ] }, + r = { :product => 'striped heart mushroom', :steps => [ 'forage' ] }, + r = { :product => 'white clover blossom', :steps => [ 'forage' ] }, + r = { :product => 'wood violet', :steps => [ 'forage' ] }, + r = { :product => 'soft white mushroom', :steps => [ 'forage' ] }, + r = { :product => 'bloodwood twig', :steps => [ 'forage' ] }, + r = { :product => 'twisted twig', :steps => [ 'forage' ] }, + r = { :product => 'some wheat grass', :steps => [ 'forage' ] }, + r = { :product => 'yew twig', :steps => [ 'forage' ] }, + r = { :product => 'sunburst blossom', :steps => [ 'forage' ] }, + r = { :product => 'nightbloom blossom', :steps => [ 'forage' ] }, + r = { :product => 'willow twig', :steps => [ 'forage' ] }, + r = { :product => 'genkew mushroom', :steps => [ 'forage' ] }, + r = { :product => 'ebony twig', :steps => [ 'forage' ] }, + r = { :product => 'stargazer lily', :steps => [ 'forage' ] }, + r = { :product => 'fragrant white lily', :steps => [ 'forage' ] }, + r = { :product => "ayana'al leaf", :steps => [ 'forage' ] }, + r = { :product => 'oak twig', :steps => [ 'forage' ] }, + r = { :product => 'sweetfern stalk', :steps => [ 'forage' ] }, + r = { :product => 'red poppy', :steps => [ 'forage' ] }, + r = { :product => 'pine cone', :steps => [ 'forage' ] }, + r = { :product => 'small wild rose', :steps => [ 'forage' ] }, + r = { :product => 'some alder bark', :steps => [ 'forage' ] }, + r = { :product => 'some orchil lichen', :steps => [ 'forage' ] }, + r = { :product => 'stalk of bluebells', :steps => [ 'forage' ] }, + r = { :product => 'some blackened moss', :steps => [ 'forage' ] }, + r = { :product => 'coppery rain lily', :steps => [ 'forage' ] }, + r = { :product => 'some longgrass', :steps => [ 'forage' ] }, + r = { :product => 'oxblood lily', :steps => [ 'forage' ] }, + r = { :product => 'sprig of mournbloom', :steps => [ 'forage' ] }, + r = { :product => 'some red lichen', :steps => [ 'forage' ] }, + r = { :product => 'handful of walnuts', :steps => [ 'forage' ] }, + r = { :product => 'some arctic moss', :steps => [ 'forage' ] }, + r = { :product => 'cluster of woad leaves', :steps => [ 'forage' ] }, + r = { :product => 'yellow clover blossom', :steps => [ 'forage' ] }, + r = { :product => 'layer of onion skin', :steps => [ 'forage' ] }, + r = { :product => 'cluster of gorse', :steps => [ 'forage' ] }, + r = { :product => 'bright red cranberry', :steps => [ 'forage' ] }, + r = { :product => 'orange begonia', :steps => [ 'forage' ] }, + r = { :product => 'wild beechnut', :steps => [ 'forage' ] }, + r = { :product => 'pine cone', :steps => [ 'forage' ] }, + r = { :product => 'pink hydrangea', :steps => [ 'forage' ] }, + r = { :product => 'heath aster', :steps => [ 'forage' ] }, r = { :product => 'wild orchid', :steps => [ 'forage' ] }, r = { :product => 'wild pansy blossom', :steps => [ 'forage' ] }, r = { :product => 'small dandelion', :steps => [ 'forage' ] }, @@ -3301,11 +3390,9 @@ $alchemy_recipes = [ r = { :product => 'blue passionflower', :steps => [ 'forage' ] }, r = { :product => 'some angelica root', :steps => [ 'forage' ] }, r = { :product => 'some strigae cactus', :steps => [ 'forage' ] }, - r = { :product => 'red trafel mushroom', :steps => [ 'forage' ] }, r = { :product => 'golden aster', :steps => [ 'forage' ] }, -# fixme: can only forage in moonlight? -# r = { :product => 'trollfear mushroom', :steps => [ 'forage' ] }, -# r = { :product => 'moonlight cactus-bloom', :steps => [ 'forage' ] }, + r = { :product => 'trollfear mushroom', :steps => [ 'forage in moonlight' ] }, + r = { :product => 'moonlight cactus-bloom', :steps => [ 'forage in moonlight' ] }, # # kill for reagents @@ -3388,6 +3475,9 @@ $alchemy_recipes = [ r = { :product => 'some essence of fire', :steps => [ 'kill fire rat' ], }, r = { :product => 'elemental core', :steps => [ 'kill fire cat' ], }, r = { :product => 'elemental core', :steps => [ 'kill fire rat' ], }, + r = { :product => 'some essence of water', :steps => [ 'kill frost giant' ], }, + r = { :product => 'some essence of water', :steps => [ 'kill arctic titan' ], }, + r = { :product => 'some essence of water', :steps => [ 'kill ice troll' ], }, r = { :product => 'orc knuckle', :steps => [ 'kill Neartofar orc' ], }, r = { :product => 'black leopard paw', :steps => [ 'kill black leopard' ], }, r = { :product => 'kiramon tongue', :steps => [ 'kill kiramon defender' ], }, @@ -3404,4 +3494,271 @@ $alchemy_recipes = [ ] +$alchemy_equivalents = [ + [ 'ayana leaf', 'ayana lichen', 'ayana weed', 'ayana berry', 'ayana root' ], + [ "ayana'al leaf", "ayana'al lichen", "ayana'al weed", "ayana'al berry", "ayana'al root" ], + [ 'some ground ayana', 'some ground ayana leaf', 'some ground ayana lichen', 'some ground ayana weed', 'some ground ayana berry', 'some ground ayana root' ], + [ 'myklian scale', 'orange myklian scale', 'red myklian scale', 'yellow myklian scale', 'green myklian scale' ], + [ 'white pearl', 'large white pearl', 'medium white pearl', 'small white pearl', 'tiny white pearl' ], + [ 'black pearl', 'large black pearl', 'medium black pearl', 'small black pearl', 'tiny black pearl' ], + [ 'pink pearl', 'tiny pink pearl', 'small pink pearl', 'medium pink pearl', 'large pink pearl' ], + [ 'stick', 'thick stick', 'stained stick', 'slender stick', 'pointed stick', 'twisted stick', 'long stick', 'slim stick', 'charred stick', 'flexible stick', 'sturdy stick', 'dark stick', 'hefty stick', 'cracked stick', 'thin stick', 'small stick', 'bent stick', 'short stick', 'heavy stick' ], + [ 'vial of concentrated firethorn essence', 'vial concentrated firethorn essence' ], + [ 'some powdered rhodochrosite stone', 'some powdered pink rhodochrosite stone' ], + [ 'some powdered chrysoberyl gem', 'some powdered bright chrysoberyl gem' ], + [ 'some powdered malachite stone', 'some powdered green malachite stone' ], + [ 'some powdered spessartine garnet', 'some powdered orange spessartine garnet' ], + [ 'some powdered pink coral', 'some powdered polished pink coral' ], + [ 'some powdered blue coral', 'some powdered polished blue coral' ], + [ 'some powdered red coral', 'some powdered polished red coral' ], + [ 'some powdered water sapphire', 'some powdered pale water sapphire' ], + [ 'some powdered fire pearl', 'some powdered billiant fire pearl' ], + [ 'some powdered cowrie shell', 'some powdered snake-head cowrie shell' ], + [ 'some powdered iridescent mother-of-pearl', 'some powdered iridescent piece of mother-of-pearl' ], + [ 'some powdered silvery conch shell', 'some powdered sparkling silvery conch shell' ], + [ 'some powdered imperial topaz', 'some powdered orange imperial topaz' ], + [ 'some powdered green moonstone', 'some powdered pale green moonstone' ], + [ 'some powdered pale blue moonstone', 'some powdered blue moonstone' ], + [ 'some powdered beryl gem', 'some powdered golden beryl gem' ], + [ 'crystalline globe', 'corked crystalline globe filled with glowing mineral water', ], + [ 'tkaro root', 'shiny tkaro root' ], + [ 'tufted hawk-owl ear', 'hawk-owl ear' ], + [ 'fire cat claw', 'cat claw' ], +] + +# +# average amount you can get for selling reagents; used as opportunity cost when determining the best (cheapest/fastest) recipe +# +$alchemy_reagent_op_cost = { + "yellow hyacinth" => 0, + "white sunstone" => 0, + "emerald blazestar" => 0, + "uncut maernstrike diamond" => 0, + "olivine feanor-bloom" => 0, + "white starstone" => 0, + "cloud agate" => 0, + "grey chalcedony" => 0, + "white chalcedony" => 0, + "shimmarglin sapphire" => 0, + "dragonseye sapphire" => 0, + "white marble" => 0, + "glossy black doomstone" => 0, + "pink dreamstone" => 0, + "blue peridot" => 0, + "green peridot" => 0, + "blue spinel" => 0, + "large yellow diamond" => 0, + "blue diamond" => 0, + "uncut star-of-Tamzyrr diamond" => 0, + "white clam shell" => 0, + "ruby-lined nassa shell" => 0, + "sea urchin shell" => 0, + "scaly burgee shell" => 0, + "faceted crystal crab shell" => 0, + "clear topaz" => 10, + "rock crystal" => 10, + "clear sapphire" => 20, + "dark red-green bloodstone" => 20, + "clear zircon" => 25, + "some polished blue coral" => 30, + "iridescent labradorite stone" => 50, + "black jasper" => 50, + "almandine garnet" => 65, + "rose quartz" => 80, + "citrine quartz" => 80, + "clear tourmaline" => 90, + "blue starstone" => 100, + "blue tourmaline" => 100, + "black tourmaline" => 100, + "azurite" => 100, + "green tourmaline" => 110, + "piece of golden amber" => 150, + "fire agate" => 180, + "fire opal" => 186, + "bright chrysoberyl gem" => 200, + "deep purple amethyst" => 220, + "golden beryl gem" => 240, + "white jade" => 250, + "aquamarine gem" => 350, + "some polished pink coral" => 350, + "some polished red coral" => 362, + "pink topaz" => 400, + "pale water sapphire" => 400, + "gold nugget" => 400, + "turquoise stone" => 400, + "green sphene" => 400, + "snake-head cowrie shell" => 450, + "smoky topaz" => 500, + "green malachite stone" => 500, + "pink rhodochrosite stone" => 500, + "blood red garnet" => 500, + "brown jade" => 500, + "iridescent piece of mother-of-pearl" => 500, + "brown sphene" => 500, + "golden topaz" => 600, + "spiderweb turquoise" => 600, + "blue lapis lazuli" => 600, + "orange spessartine garnet" => 700, + "green garnet" => 700, + "black sphene" => 700, + "shimmertine shard" => 700, + "orange imperial topaz" => 800, + "white opal" => 800, + "green jade" => 800, + "yellow sapphire" => 900, + "green sapphire" => 900, + "sparkling silvery conch shell" => 900, + "clear glimaerstone" => 900, + "violet sapphire" => 1000, + "smoky glimaerstone" => 1000, + "fiery jacinth" => 1000, + "green starstone" => 1000, + "pale blue moonstone" => 1100, + "pale green moonstone" => 1100, + "star ruby" => 1200, + "star sapphire" => 1200, + "rainbow quartz" => 1200, + "deep blue eostone" => 1200, + "cats-eye moonstone" => 1200, + "bright bluerock" => 1200, + "brilliant fire pearl" => 1300, + "pearl nautilus shell" => 1300, + "grey pearl" => 2000, + "pink pearl" => 2103, + "black opal" => 2388, + "pink sapphire" => 2596, + "white pearl" => 2500, + "golden moonstone" => 2500, + "Kezmonian honey beryl" => 2703, + "black pearl" => 2796, + "moonglae opal" => 2800, + "blue sapphire" => 3000, + "dragonfire opal" => 3000, + "uncut ruby" => 3110, + "dragon's-tear diamond" => 4600, + "uncut diamond" => 5103, + "uncut emerald" => 5280, + "skeleton bone" => 0, + "skeletal giant bone" => 0, + "wraith talon" => 0, + "lump of grey ambergris" => 0, + "some waxy grey caederine" => 0, + "aster opal" => 0, + "copper fang" => 0, + "silver fang" => 0, + "troll hide" => 0, + "troll beard" => 0, + "ice troll scalp" => 0, + "pale troll tongue" => 0, + "troll scalp" => 0, + "chipped troll tusk" => 0, + "troll heart" => 0, + "troll skin" => 0, + "scraggly swamp troll scalp" => 0, + "skeletal giant bone" => 0, + "giant skin" => 0, + "cockatrice plume" => 0, + "wight skin" => 0, + "ghoul nail" => 0, + "bear paw" => 0, + "wraith talon" => 0, + "ghoul finger" => 0, + "mist wraith eye" => 0, + "wight skull" => 0, + "wight mane" => 0, + "kappa fin" => 0, + "bear hide" => 285, + "troll heart" => 0, + "ogre tooth" => 0, + "stone-grey lizard tail" => 0, + "troll toe" => 0, + "troll skin" => 0, + "cougar tail" => 0, + "tawny brindlecat hide" => 0, + "spotted leopard pelt" => 0, + "ogre nose" => 0, + "cyclops eye" => 0, + "mottled faeroth crest" => 0, + "ghoul scraping" => 0, + "spider leg" => 0, + "warcat whisker" => 0, + "golem bone" => 0, + "basilisk crest" => 0, + "faintly glowing worm skin" => 0, + "silvery tail" => 0, + "silver-tipped horseshoe" => 0, + "fire cat claw" => 300, + "fire rat tail" => 0, + "centaur hide" => 450, + "snowy cockatrice tailfeather" => 0, + "glistening black eye" => 0, + "troll beard" => 0, + "mountain lion skin" => 530, + "shelfae crest" => 116, + "silvery hoof" => 1180, + "vesperti claw" => 680, + "yellowed boar tusk" => 0, + "vruul skin" => 0, + "soft blue griffin feather" => 0, + "myklian scale" => 241, + "silver mane" => 0, + "ursian tusk" => 0, + "viper fang" => 0, + "tree viper fang" => 0, + "troll fang" => 0, + "goat hoof" => 0, + "scraggly orc scalp" => 0, + "faeroth fang" => 0, + "fenghai fur" => 0, + "plains lion skin" => 0, + "roa'ter skin" => 0, + "boar tusk" => 218, + "tegu tailspike" => 0, + "tufted hawk-owl ear" => 0, + "skeleton bone" => 0, + "troll hide" => 0, + "ice troll scalp" => 0, + "kobold skin" => 0, + "pale troll tongue" => 0, + "orc knuckle" => 0, + "black leopard paw" => 0, + "kiramon tongue" => 0, + "ruff of raptor feathers" => 0, + "mummy's shroud" => 0, + "mammoth arachnid mandible" => 0, + "ayanad crystal" => 64, + "crystal core" => 64, + "cluster of ayanad crystals" => 127, + "elemental core" => 128, + "cracked soulstone" => 150, # fixme + "s'ayanad crystal" => 255, + "some essence of air" => 255, + "some essence of earth" => 255, + "some essence of fire" => 255, + "some essence of water" => 255, + "pristine nymph's hair" => 255, + "small troll tooth" => 319, + "glimmering blue essence shard" => 319, + "some glimmering blue essence dust" => 383, + "glimmering blue mote of essence" => 383, + "cluster of s'ayanad crystals" => 509, + "glowing violet essence shard" => 638, + "crystalline globe" => 765, + "t'ayanad crystal" => 893, + "pristine sprite's hair" => 893, + "glowing violet mote of essence" => 1148, + "some glowing violet essence dust" => 1148, + "perfect myklian belly scale" => 1275, + "large troll tooth" => 1275, + "vial of farlook vitreous humor" => 1275, + "inky necrotic core" => 1275, + "tiny golden seed" => 1275, + "cluster of t'ayanad crystals" => 1785, + "radiant crimson essence shard" => 1913, + "pristine siren's hair" => 2040, + "n'ayanad crystal" => 2678, + "some radiant crimson essence dust" => 3443, + "radiant crimson mote of essence" => 3443, +} + $alchemy_recipes.delete_if { |recipe| !recipe[:for].nil? and !recipe[:for].include?(Char.prof) } diff --git a/alchemy.lic b/alchemy.lic index 9b327c6..64c08d1 100644 --- a/alchemy.lic +++ b/alchemy.lic @@ -1,13 +1,50 @@ =begin - slightly faster alchemy script of doom!!!1!one + Alchemy Script of Doom!!!1!one ;alchemy help - tillmen@lichproject.org + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: alchemy, guild + version: 0.14 + required: alchemy-recipes.lic >= 0.3 + + changelog: + 0.14 (2017-11-11): + fix squelching of gld verb for inactive members + 0.13 (2017-01-14): + make grind task work with "set sortedview on" + 0.12 (2015-07-08): + added support for more scripted containers =end +=begin + 0.11 (2015-07-08): + fix a bug where the wrong version of a recipe might be used when a specific step is required + 0.10 (2015-04-27): + add options to clear helper scripts + 0.9 (2014-12-12): + fix sunlight detection + 0.8 (2014-12-11): + bugfix for Ruby 1.8 + 0.7 (2014-12-10): + move equivalents and reagent values (not complete) into alchemy-recipes.lic + add time and value of each item to recipe check summary + allow containts to be set using the script instead of ;settings/;vars + 0.6 (2014-11-12): + recognize gld messaging for inactive members + 0.5 (2014-10-09): + added message for scripted container (You carefully attach) + 0.4 (2014-10-07): + more Mist Harbor fixes + 0.3 (2014-10-07): + use Mist Harbor promissory note on Mist Harbor + 0.2 (2014-10-07): + fix issue with finding recipes for alchemy masters task + +=end # fixme: run outta money # fixme: full containers @@ -16,10 +53,11 @@ # fixme: Khelorof says, "To rise to the top, you must diversify. You need to learn 2 rank(s) of other skills before I can promote you in this skill again." # fixme: recast haste on armor hindrance # fixme: option to use symbol of dreams when waiting for spirit -# fixme: pick the best npc to kill in travel range instead of the closest -# fixme: wrong note when running to a different town to buy +# fixme: use time verb for sunlight test +# fixme: The surface of the solution in the iron cauldron shimmers in response! +# fixme: The diamond lens shatters! -silence_me +silence_me unless $alchemy_debug unless defined?($alchemy_recipes) and ($alchemy_recipes.class == Array) and not $alchemy_recipes.empty? unless Script.exists?('alchemy-recipes') @@ -36,7 +74,16 @@ unless defined?($alchemy_recipes) and ($alchemy_recipes.class == Array) and not echo 'no recipes' exit end - $alchemy_recipes.delete_if { |recipe| !recipe[:for].nil? and !recipe[:for].include?(Char.prof) } + unless defined?($alchemy_reagent_op_cost) + start_script 'repository', [ 'download', 'alchemy-recipes' ] + wait_while { running?('repository') } + start_script 'alchemy-recipes' + wait_while { running?('alchemy-recipes') } + unless defined?($alchemy_reagent_op_cost) + echo 'error: failed to download a new enough version of alchemy-recipes' + exit + end + end end CharSettings['hide-gld-check'] = true if CharSettings['hide-gld-check'].nil? @@ -52,6 +99,12 @@ CharSettings['max-forage-time'] ||= 300 CharSettings['cost-per-second'] ||= 15 CharSettings['favorite-recipes'] ||= Array.new +echo CharSettings['kill time'].inspect if $alchemy_debug + +put_regex = /^You (?:attempt to shield .*? from view as you |discreetly |carefully |absent-mindedly )?(?:put|place|slip|tuck|add|hang|drop|untie your|find an incomplete bundle|wipe off .*? and sheathe)|^A sigh of grateful pleasure can be heard as you feed .*? to your|^As you place|^I could not find what you were referring to\.$|^Your bundle would be too large|^The .+ is too large to be bundled\.|^As you place your|^The .*? is already a bundle|^Your .*? won't fit in .*?\.$|^You can't .+ It's closed!$/ +get_regex = /^You (?:shield the opening of .*? from view as you |discreetly |carefully |deftly )?(?:remove|draw|grab|reach|slip|tuck|retrieve|already have|unsheathe|detach)|^Get what\?$|^Why don't you leave some for others\?$|^You need a free hand|^You already have that/ +cauldron_noun = /^(?:cauldron|vat|kettle|boiler)$/ + elusive_reagent_cost = { 'cluster of ayanad crystals' => 64, 'ayanad crystal' => 128, @@ -88,35 +141,40 @@ elusive_reagent_cost = { 'radiant crimson mote of essence' => 6885, } -equivalent = [ - [ 'ayana leaf', 'ayana lichen', 'ayana weed', 'ayana berry', 'ayana root' ], - [ "ayana'al leaf", "ayana'al lichen", "ayana'al weed", "ayana'al berry", "ayana'al root" ], - [ 'some ground ayana', 'some ground ayana leaf', 'some ground ayana lichen', 'some ground ayana weed', 'some ground ayana berry', 'some ground ayana root' ], - [ 'myklian scale', 'orange myklian scale', 'red myklian scale', 'yellow myklian scale', 'green myklian scale' ], - [ 'white pearl', 'large white pearl', 'medium white pearl', 'small white pearl', 'tiny white pearl' ], - [ 'black pearl', 'large black pearl', 'medium black pearl', 'small black pearl', 'tiny black pearl' ], - [ 'pink pearl', 'tiny pink pearl', 'small pink pearl', 'medium pink pearl', 'large pink pearl' ], - [ 'stick', 'thick stick', 'stained stick', 'slender stick', 'pointed stick', 'twisted stick', 'long stick', 'slim stick', 'charred stick', 'flexible stick', 'sturdy stick', 'dark stick', 'hefty stick', 'cracked stick', 'thin stick', 'small stick', 'bent stick', 'short stick', 'heavy stick' ], - [ 'vial of concentrated firethorn essence', 'vial concentrated firethorn essence' ], - [ 'some powdered rhodochrosite stone', 'some powdered pink rhodochrosite stone' ], - [ 'some powdered chrysoberyl gem', 'some powdered bright chrysoberyl gem' ], - [ 'some powdered malachite stone', 'some powdered green malachite stone' ], - [ 'some powdered spessartine garnet', 'some powdered orange spessartine garnet' ], - [ 'some powdered pink coral', 'some powdered polished pink coral' ], - [ 'some powdered blue coral', 'some powdered polished blue coral' ], - [ 'some powdered red coral', 'some powdered polished red coral' ], - [ 'some powdered water sapphire', 'some powdered pale water sapphire' ], - [ 'some powdered fire pearl', 'some powdered billiant fire pearl' ], - [ 'some powdered cowrie shell', 'some powdered snake-head cowrie shell' ], - [ 'some powdered iridescent mother-of-pearl', 'some powdered iridescent piece of mother-of-pearl' ], - [ 'some powdered silvery conch shell', 'some powdered sparkling silvery conch shell' ], - [ 'some powdered imperial topaz', 'some powdered orange imperial topaz' ], - [ 'some powdered green moonstone', 'some powdered pale green moonstone' ], - [ 'some powdered pale blue moonstone', 'some powdered blue moonstone' ], - [ 'some powdered beryl gem', 'some powdered golden beryl gem' ], - [ 'crystalline globe', 'corked crystalline globe filled with glowing mineral water', ], - [ 'tkaro root', 'shiny tkaro root' ], -] +if $alchemy_equivalents + equivalent = $alchemy_equivalents +else + equivalent = [ + [ 'ayana leaf', 'ayana lichen', 'ayana weed', 'ayana berry', 'ayana root' ], + [ "ayana'al leaf", "ayana'al lichen", "ayana'al weed", "ayana'al berry", "ayana'al root" ], + [ 'some ground ayana', 'some ground ayana leaf', 'some ground ayana lichen', 'some ground ayana weed', 'some ground ayana berry', 'some ground ayana root' ], + [ 'myklian scale', 'orange myklian scale', 'red myklian scale', 'yellow myklian scale', 'green myklian scale' ], + [ 'white pearl', 'large white pearl', 'medium white pearl', 'small white pearl', 'tiny white pearl' ], + [ 'black pearl', 'large black pearl', 'medium black pearl', 'small black pearl', 'tiny black pearl' ], + [ 'pink pearl', 'tiny pink pearl', 'small pink pearl', 'medium pink pearl', 'large pink pearl' ], + [ 'stick', 'thick stick', 'stained stick', 'slender stick', 'pointed stick', 'twisted stick', 'long stick', 'slim stick', 'charred stick', 'flexible stick', 'sturdy stick', 'dark stick', 'hefty stick', 'cracked stick', 'thin stick', 'small stick', 'bent stick', 'short stick', 'heavy stick' ], + [ 'vial of concentrated firethorn essence', 'vial concentrated firethorn essence' ], + [ 'some powdered rhodochrosite stone', 'some powdered pink rhodochrosite stone' ], + [ 'some powdered chrysoberyl gem', 'some powdered bright chrysoberyl gem' ], + [ 'some powdered malachite stone', 'some powdered green malachite stone' ], + [ 'some powdered spessartine garnet', 'some powdered orange spessartine garnet' ], + [ 'some powdered pink coral', 'some powdered polished pink coral' ], + [ 'some powdered blue coral', 'some powdered polished blue coral' ], + [ 'some powdered red coral', 'some powdered polished red coral' ], + [ 'some powdered water sapphire', 'some powdered pale water sapphire' ], + [ 'some powdered fire pearl', 'some powdered billiant fire pearl' ], + [ 'some powdered cowrie shell', 'some powdered snake-head cowrie shell' ], + [ 'some powdered iridescent mother-of-pearl', 'some powdered iridescent piece of mother-of-pearl' ], + [ 'some powdered silvery conch shell', 'some powdered sparkling silvery conch shell' ], + [ 'some powdered imperial topaz', 'some powdered orange imperial topaz' ], + [ 'some powdered green moonstone', 'some powdered pale green moonstone' ], + [ 'some powdered pale blue moonstone', 'some powdered blue moonstone' ], + [ 'some powdered beryl gem', 'some powdered golden beryl gem' ], + [ 'crystalline globe', 'corked crystalline globe filled with glowing mineral water', ], + [ 'tkaro root', 'shiny tkaro root' ], + [ 'tufted hawk-owl ear', 'hawk-owl ear' ], + ] +end herb_doses = { 'some acantha leaf' => 10, @@ -134,7 +192,7 @@ herb_doses = { 'some torban leaf' => 3, } -sea_water_flask = /^(?:small|faceted) crystal flask$|^dark sphene-inset flask$/ +sea_water_flask = /^(?:small|small opaque|faceted) crystal flask$|^dark sphene-inset flask$/ sea_water_vial = /^(?:clouded|warped|chipped|tapered|smoky|thick|slender|clear|blackened) glass vial$|^polished glaes vial$/ bundled_herb = /^some acantha leaf$|^some cactacae spine$|^some ambrominas leaf$|^some torban leaf$|^some wolifrew lichen$|^some sovyn clove$|^some ephlox moss$|^some pothinir grass$|^some haphip root$|^some calamia fruit$|^some aloeas stem$|^some basal moss$|^some woth flower$/ @@ -198,7 +256,7 @@ gld = proc { nil end else - if server_string =~ /^You are (?:a member|Guild Master)/ + if server_string =~ /^You are (?:a member|an inactive member|Guild Master)/ started = true nil else @@ -210,10 +268,23 @@ gld = proc { end undo_silent = !script.silent script.silent = true - dothistimeout 'gld', 10, /^You are (?:a member|Guild Master)/ + result = dothistimeout 'gld', 15, /^You are (?:a member|an inactive member|Guild Master)|^You have no guild affiliation./ script.silent = false if undo_silent + if result =~ /^You have no guild affiliation./ + echo 'join a guild' + exit + elsif result.nil? + echo 'fixme 20983238453' + end while (line = get) and (line !~ /= recipe[:rank].min and gld_var[type][:rank] <= recipe[:rank].max and recipe[:steps].any? { |step| step =~ /^#{required_step}/ } and not recipe[:steps].any? { |step| step =~ /^refract/ } }.collect { |recipe| recipe[:product] } + gld_var[type][:recipes] = $alchemy_recipes.find_all { |recipe| recipe[:type].include?(type) and recipe[:rank] and gld_var[type][:rank] >= recipe[:rank].min and gld_var[type][:rank] <= recipe[:rank].max and recipe[:steps].any? { |step| step =~ /^#{required_step}/ } and not recipe[:steps].any? { |step| step =~ /^refract/ } } else - gld_var[type][:recipes] = $alchemy_recipes.find_all { |recipe| recipe[:type].include?(type) and recipe[:rank] and gld_var[type][:rank] >= recipe[:rank].min and gld_var[type][:rank] <= recipe[:rank].max and recipe[:steps].any? { |step| step =~ /^#{required_step}/ } }.collect { |recipe| recipe[:product] } + gld_var[type][:recipes] = $alchemy_recipes.find_all { |recipe| recipe[:type].include?(type) and recipe[:rank] and gld_var[type][:rank] >= recipe[:rank].min and gld_var[type][:rank] <= recipe[:rank].max and recipe[:steps].any? { |step| step =~ /^#{required_step}/ } } end elsif gld_var[type][:task] =~ /follow some tough recipes and create some items|visit a skilled master for a lesson/ - gld_var[type][:recipes] = $alchemy_recipes.find_all { |recipe| (recipe[:product] != 'flask of pure water') and recipe[:type].include?(type) and recipe[:rank] and gld_var[type][:rank] >= recipe[:rank].min and gld_var[type][:rank] <= recipe[:rank].max }.collect { |recipe| recipe[:product] } + gld_var[type][:recipes] = $alchemy_recipes.find_all { |recipe| (recipe[:product] != 'flask of pure water') and recipe[:type].include?(type) and recipe[:rank] and gld_var[type][:rank] >= recipe[:rank].min and gld_var[type][:rank] <= recipe[:rank].max } elsif gld_var[type][:task] == 'practice distilling for reagents' - gld_var[type][:recipes] = $alchemy_recipes.find_all { |recipe| recipe[:product] == 'flask of pure water' }.collect { |recipe| recipe[:product] } + gld_var[type][:recipes] = $alchemy_recipes.find_all { |recipe| recipe[:product] == 'flask of pure water' } elsif gld_var[type][:task] == 'practice extracting for reagents' - gld_var[type][:recipes] = $alchemy_recipes.find_all { |recipe| recipe[:product] == 'handful of sea salt' }.collect { |recipe| recipe[:product] } + gld_var[type][:recipes] = $alchemy_recipes.find_all { |recipe| recipe[:product] == 'handful of sea salt' } else gld_var[type][:recipes] = Array.new end + end + end + gld_var +} + +gld_suggestions2 = proc { + gld.call + if gld_var.values.any? { |hash| hash[:recipes].nil? } + for type in gld_var.keys + gld_var[type][:recipes] = $alchemy_recipes.find_all { |recipe| (recipe[:product] != 'flask of pure water') and recipe[:type].include?(type) and recipe[:rank] and gld_var[type][:rank] >= recipe[:rank].min and gld_var[type][:rank] <= recipe[:rank].max }.collect { |recipe| recipe[:product] } gld_var[type][:recipes] = gld_var[type][:recipes] | gld_var[type][:recipes] end end @@ -280,7 +361,7 @@ close_alchemy_sack_var = false alchemy_sack = proc { if alchemy_sack_var.nil? if UserVars.alchemysack.nil? or UserVars.alchemysack.empty? - echo 'warning: alchemysack is not set (;set change alchemysack )' + echo 'warning: alchemysack is not set (#{$clean_lich_char}#{script.name} set alchemysack )' sleep 1 else alchemy_sack_var = GameObj.inv.find { |obj| obj.name =~ /#{Regexp.escape(UserVars.alchemysack.strip)}/i } || GameObj.inv.find { |obj| obj.name =~ /#{Regexp.escape(UserVars.alchemysack).sub(' ', ' .*')}/i } @@ -310,7 +391,7 @@ close_loot_sack_var = false loot_sack = proc { if loot_sack_var.nil? if UserVars.lootsack.nil? or UserVars.lootsack.empty? - echo 'warning: lootsack is not set (;set change lootsack )' + echo 'warning: lootsack is not set (#{$clean_lich_char}#{script.name} set lootsack )' sleep 1 else loot_sack_var = GameObj.inv.find { |obj| obj.name =~ /#{Regexp.escape(UserVars.lootsack.strip)}/i } || GameObj.inv.find { |obj| obj.name =~ /#{Regexp.escape(UserVars.lootsack).sub(' ', ' .*')}/i } @@ -340,7 +421,7 @@ close_herb_sack_var = false herb_sack = proc { if herb_sack_var.nil? if UserVars.herbsack.nil? or UserVars.herbsack.empty? - echo 'warning: herbsack is not set (;set change herbsack )' + echo 'warning: herbsack is not set (#{$clean_lich_char}#{script.name} set herbsack )' sleep 1 else herb_sack_var = GameObj.inv.find { |obj| obj.name =~ /#{Regexp.escape(UserVars.herbsack.strip)}/i } || GameObj.inv.find { |obj| obj.name =~ /#{Regexp.escape(UserVars.herbsack).sub(' ', ' .*')}/i } @@ -387,12 +468,12 @@ all_sack_contents = proc { cauldron = nil drop_cauldron = proc { error = false - unless (checkroom == '[A Secluded Corner]') or GameObj.room_desc.find { |obj| obj.noun == 'cauldron' } or GameObj.loot.find { |obj| obj.noun =~ /^(?:cauldron|vat|kettle)$/ } - unless cauldron = all_sack_contents.call.find { |obj| obj.noun =~ /^(?:cauldron|vat|kettle)$/ } + unless (checkroom == '[A Secluded Corner]') or GameObj.room_desc.find { |obj| obj.noun == 'cauldron' } or GameObj.loot.find { |obj| obj.noun =~ cauldron_noun } + unless cauldron = all_sack_contents.call.find { |obj| obj.noun =~ cauldron_noun } echo 'error: missing cauldron' error = true end - dothis "get ##{cauldron.id}", /^You remove|^You already have that|^You detach/ + dothis "get ##{cauldron.id}", get_regex # Upon further reflection, you decide it would be best if you just used the already present training cauldron. dothis "drop ##{cauldron.id}", /^You drop/ put "drag #{cauldron.noun}" @@ -402,11 +483,11 @@ drop_cauldron = proc { force_drop_cauldron = proc { error = false - unless cauldron = all_sack_contents.call.find { |obj| obj.noun =~ /^(?:cauldron|vat|kettle)$/ } + unless cauldron = all_sack_contents.call.find { |obj| obj.noun =~ cauldron_noun } echo 'error: missing cauldron' error = true else - dothis "get ##{cauldron.id}", /^You remove|^You already have that|^You detach/ + dothis "get ##{cauldron.id}", get_regex # Upon further reflection, you decide it would be best if you just used the already present training cauldron. dothis "drop ##{cauldron.id}", /^You drop/ put "drag #{cauldron.noun}" @@ -416,7 +497,7 @@ force_drop_cauldron = proc { get_cauldron = proc { if cauldron - dothis "_drag ##{cauldron.id} ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ + dothis "_drag ##{cauldron.id} ##{alchemy_sack.call.id}", put_regex fput 'drag stop' cauldron = nil end @@ -424,19 +505,22 @@ get_cauldron = proc { where_is_previous_var = nil where_is_shortest_distances_var = nil +where_is_history = Hash.new where_is = proc { |place| - if where_is_previous_var.nil? + if where_is_history[place] + where_is_history[place] + elsif where_is_previous_var.nil? if Room.current if home_room = Room.current.find_nearest_by_tag("#{Char.prof.downcase} alchemy administrator") home_room = Room[home_room] - if (home_room == Room.current) or Map.estimate_time(Room.current.path_to(home_room)) <= CharSettings['max-travel-time'] - where_is_previous_var, where_is_shortest_distances_var = home_room.dijkstra - else - echo 'warning: nearest guild exceeds max travel time' - where_is_previous_var = false - end else echo 'warning: failed to find your guild' + home_room = Room.current + end + if (home_room == Room.current) or Map.estimate_time(Room.current.path_to(home_room)) <= CharSettings['max-travel-time'] + where_is_previous_var, where_is_shortest_distances_var = home_room.dijkstra + else + echo 'warning: nearest guild exceeds max travel time' where_is_previous_var = false end else @@ -449,10 +533,15 @@ where_is = proc { |place| else results = Array.new Map.list.each { |room| results.push(room.id) if room.tags.include?(place) } + if place == 'ayana leaf' + ["ayana berry", "ayana leaf", "ayana root", "ayana weed", "ayana lichen"].each { |other_place| Map.list.each { |room| results.push(room.id) if room.tags.include?(other_place) and not results.include?(room.id) } } + #"ayana'al berry", "ayana'al root", "ayana'al lichen" + end results.delete_if { |room_id| where_is_shortest_distances_var[room_id].nil? or where_is_shortest_distances_var[room_id] > CharSettings['max-travel-time'] } # ignore the Caravansary results.delete_if { |room_id| Room[room_id].title.any? { |t| t =~ /^(?:\['Tain't Much Magic, Emporium\]|\['Tain't Much Magic, Consignment\]|\[Finders-Sellers Pawnshop\]|\[Clenchfist Bros. Banking, Lobby\])$/ } } - results.sort { |a,b| where_is_shortest_distances_var[a] <=> where_is_shortest_distances_var[b] } + where_is_history[place] = results.sort { |a,b| where_is_shortest_distances_var[a] <=> where_is_shortest_distances_var[b] } + where_is_history[place] end } @@ -508,6 +597,29 @@ note_name = proc { end } +note_name_from_place = proc { |place| + if place =~ /Icemule/ + 'Icemule promissory note' + elsif place =~ /Ta'Illistim|Ta'Vaalor/ + 'City-States promissory note' + elsif place =~ /River's Rest/ + 'Torren promissory note' + elsif place =~ /Solhaven/ + 'Vornavis promissory note' + elsif place =~ /Kharam-Dzu/ + 'Borthuum Mining Company scrip' + elsif place =~ /Wehnimer's Landing/ + "Wehnimer's promissory note" + elsif place =~ /Zul Logoth/ + 'mining chit' + elsif place =~ /Mist Harbor/ + 'Mist Harbor promissory note' + else + nil + end +} + +is_sunlight_cache = nil is_sunlight = proc { # fixme: guessing times for light # mid-morning: 11:26 - 11:26 @@ -526,20 +638,40 @@ is_sunlight = proc { # mid morning: 08:34 - 11:59 (sunlight) # afternoon: 12:00 - ? (sunlight) + # June 3, 2014 + # late afternoon: 15:37 - 19:13 (sunlight) + # evening twilight: 19:14 - 19:43 (moonlight) + # late evening: 19:44 - 23:59 (moonlight) + # after midnight: 0:00 - 4:14 (moonlight) + # morning twilight: 4:15 - 4:44 + # early morning: 4:45 - 8:23 (sunlight) + # mid morning: 8:24 - 11:59 (sunlight) + # afternoon: 12:00 - 15:36 (sunlight) + # fixme: daylight savings time? - time = Time.at(Time.now.to_i + XMLData.server_time_offset) - time = time - (21600 + time.utc_offset) - (time.hour > 5 or (time.hour == 5 and time.min > 7)) and (time.hour < 18 or (time.hour == 18 and time.min < 51)) - - # (server_time.hour > 4 or (server_time.hour == 4 and server_time.min > 30)) and (server_time.hour < 16 or (server_time.hour == 16 and server_time.min < 30)) - # offset = -18000 - # if Time.now.dst? - # offset += 3600 - # end - # fixme: getlocal doesn't take an offset on Ruby 1.8 - # time = Time.at(Time.now.to_f + XMLData.server_time_offset.to_f).getlocal(offset) - # (time.hour > 5 or (time.hour == 5 and time.min > 7)) and (time.hour < 18 or (time.hour == 18 and time.min < 51)) + seconds = (XMLData.server_time - (5*60*60)) % (60*60*24) # seconds since midnight, elven time standard + hours = seconds/(60*60) + seconds = seconds % (60*60) + minutes = seconds/60 + seconds = seconds % 60 + + if ((hours > 6) or ((hours == 6) and (minutes > 30))) and (hours < 18) + true + elsif (hours < 5) or (hours > 20) + false + elsif is_sunlight_cache and is_sunlight_cache[0] == "#{Time.now.hour}:#{Time.now.min}" + is_sunlight_cache[1] + else + result = dothis 'time', /^Today is / + if result =~ /early morning|mid morning|afternoon|late afternoon/ + is_sunlight_cache = [ "#{Time.now.hour}:#{Time.now.min}", true ] + true + else + is_sunlight_cache = [ "#{Time.now.hour}:#{Time.now.min}", false ] + false + end + end } is_moonlight = proc { !is_sunlight.call } @@ -681,6 +813,26 @@ read_menu = proc { menu } +add_commas = proc { |num| + num.to_s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse +} + +trading_sell = proc { |silvers| + if Skills.trading > 6 + (silvers*((((Skills.to_bonus(Skills.trading) + Stats.inf[1])/12)/100.0)+1)).floor + else + silvers + end +} + +trading_buy = proc { |silvers| + if Skills.trading > 6 + silvers - (silvers * (((Skills.to_bonus(Skills.trading) + Stats.inf[1])/12)/100.0)).floor + else + silvers + end +} + check_channel_spirit = proc { needed_spirit = 3 needed_spirit += 1 if Spell[9912].active? @@ -706,7 +858,7 @@ check_ingredient = proc { |ingredient_name,temp_claimed_ingredients,temp_ingredi elsif bundle = all_sack_contents.call.find { |obj| equivalent_ingredients.include?(obj.name) and (obj.name =~ bundled_herb) and (temp_ingredient_count[obj.id].nil? or temp_ingredient_count[obj.id] > 0) } if temp_ingredient_count[bundle.id].nil? empty_hand - dothistimeout "get ##{bundle.id}", 10, /^You remove|^You already have that/ + dothistimeout "get ##{bundle.id}", 10, get_regex measure_result = dothistimeout "measure ##{bundle.id}", 10, /^(?:You can't tell exactly, but the|The) .*? (?:has 1 bite|has 2 bites|looks like it has a few bites|looks like it has several bites|seems to have plenty of bites) left\./ if measure_result =~ /1 bite/ temp_ingredient_count[bundle.id] = 1 @@ -728,7 +880,7 @@ check_ingredient = proc { |ingredient_name,temp_claimed_ingredients,temp_ingredi ingredient_count[bundle.id] = 1 echo "error: unmatched measure result: #{measure_result.inspect}" end - dothistimeout "put ##{bundle.id} in ##{herb_sack.call.id}", 10, /^You put|^I could not find what you were referring to\./ + dothistimeout "put ##{bundle.id} in ##{herb_sack.call.id}", 10, put_regex fill_hand end temp_ingredient_count[bundle.id] = temp_ingredient_count[bundle.id] - 1 @@ -779,9 +931,9 @@ get_ingredient = proc { |ingredient_name| ingredient = nil equivalent_ingredients = (equivalent.find { |list| list.include?(ingredient_name) } || [ ingredient_name ]) if ingredient = all_sack_contents.call.find { |obj| equivalent_ingredients.include?(obj.name) and (obj.name !~ bundled_herb) } - dothistimeout "get ##{ingredient.id}", 10, /^You remove|^You already have that/ + dothistimeout "get ##{ingredient.id}", 10, get_regex elsif bundle = all_sack_contents.call.find { |obj| equivalent_ingredients.include?(obj.name) and (obj.name =~ bundled_herb) } - dothistimeout "get ##{bundle.id}", 10, /^You remove|^You already have that/ + dothistimeout "get ##{bundle.id}", 10, get_regex bundle_remove_result = dothistimeout 'bundle remove', 10, /^You (?:carefully )?remove|^Those were the last two|^You only have one/ if bundle_remove_result =~ /^You only have one/ correct_herb_count.delete(bundle.id) @@ -789,7 +941,7 @@ get_ingredient = proc { |ingredient_name| ingredient = bundle elsif correct_herb_count.include?(bundle.id) ingredient_count[bundle.id] = ingredient_count[bundle.id] - 1 - dothistimeout "put ##{bundle.id} in ##{herb_sack.call.id}", 10, /^You put|^I could not find what you were referring to\./ + dothistimeout "put ##{bundle.id} in ##{herb_sack.call.id}", 10, put_regex if checkleft ingredient = GameObj.left_hand else @@ -824,7 +976,7 @@ get_ingredient = proc { |ingredient_name| else ingredient_count[bundle.id] = [(ingredient_count[bundle.id] - 1), min_count].max end - dothistimeout "put ##{bundle.id} in ##{herb_sack.call.id}", 10, /^You put|^I could not find what you were referring to\./ + dothistimeout "put ##{bundle.id} in ##{herb_sack.call.id}", 10, put_regex if checkleft ingredient = GameObj.left_hand else @@ -836,9 +988,9 @@ get_ingredient = proc { |ingredient_name| ingredient_count[jar.id] = ingredient_count[jar.id] - 1 ingredient_count.delete(jar.id) if ingredient_count[jar.id] < 1 end - dothistimeout "get ##{jar.id}", 10, /^You remove|^You already have that/ + dothistimeout "get ##{jar.id}", 10, get_regex dothistimeout "shake ##{jar.id}", 10, /^You .*shake/ - dothistimeout "put ##{jar.id} in ##{alchemy_sack.call.id}", 10, /^You put|^I could not find what you were referring to\./ + dothistimeout "put ##{jar.id} in ##{alchemy_sack.call.id}", 10, put_regex if checkleft ingredient = GameObj.left_hand else @@ -849,9 +1001,9 @@ get_ingredient = proc { |ingredient_name| ingredient_count[bundle.id] = ingredient_count[bundle.id] - 1 ingredient_count.delete(bundle.id) if ingredient_count[bundle.id] < 2 end - dothistimeout "get ##{bundle.id}", 10, /^You remove|^You already have that/ + dothistimeout "get ##{bundle.id}", 10, get_regex unbundle_result = dothistimeout 'bundle remove', 10, /^You remove|^Those were the last two/ - dothistimeout "put ##{bundle.id} in ##{alchemy_sack.call.id}", 10, /^You put|^I could not find what you were referring to\./ + dothistimeout "put ##{bundle.id} in ##{alchemy_sack.call.id}", 10, put_regex if checkleft ingredient = GameObj.left_hand else @@ -864,27 +1016,34 @@ get_ingredient = proc { |ingredient_name| put_crap_away = proc { if (GameObj.right_hand.name =~ /ayanad crystals$/) or (GameObj.left_hand.name =~ /ayanad crystals$/) dothis "get crystal from my crystals", /You separate/ - dothis "put ##{GameObj.right_hand.id} in ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ - dothis "put ##{GameObj.left_hand.id} in ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ + dothis "put ##{GameObj.right_hand.id} in ##{alchemy_sack.call.id}", put_regex + dothis "put ##{GameObj.left_hand.id} in ##{alchemy_sack.call.id}", put_regex end if checkright if is_reagent.call(GameObj.right_hand.name) - dothis "put ##{GameObj.right_hand.id} in ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ + dothis "put ##{GameObj.right_hand.id} in ##{alchemy_sack.call.id}", put_regex else - dothis "put ##{GameObj.right_hand.id} in ##{loot_sack.call.id}", /^You put|^I could not find what you were referring to\./ + dothis "put ##{GameObj.right_hand.id} in ##{loot_sack.call.id}", put_regex end end if checkleft if is_reagent.call(GameObj.left_hand.name) - dothis "put ##{GameObj.left_hand.id} in ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ + dothis "put ##{GameObj.left_hand.id} in ##{alchemy_sack.call.id}", put_regex else - dothis "put ##{GameObj.left_hand.id} in ##{loot_sack.call.id}", /^You put|^I could not find what you were referring to\./ + dothis "put ##{GameObj.left_hand.id} in ##{loot_sack.call.id}", put_regex end end } +recursive_padding = 0 recursive_check_recipe = proc { |recipe,tracker,top_level| + recipe_start = Time.now + respond "#{''.ljust(recursive_padding)}start recipe: #{recipe[:product]}" if $alchemy_debug + recursive_padding += 3 recipe[:steps].each { |step| + step_start = Time.now + respond "#{''.ljust(recursive_padding)}start step: #{step}" if $alchemy_debug + recursive_padding += 3 if step =~ /^(?:add|grind|extract|distill|separate)\s+(.*)/ ingredient_name = $1 if step =~ /^grind/ @@ -903,20 +1062,21 @@ recursive_check_recipe = proc { |recipe,tracker,top_level| end if tracker[:extra_ingredients].include?(ingredient_name) tracker[:extra_ingredients].delete_at(tracker[:extra_ingredients].index(ingredient_name)) - tracker[:found][ingredient_name] = tracker[:found][ingredient_name].to_i + 1 else found_this, temp_claimed_ingredients, temp_ingredient_count = check_ingredient.call(ingredient_name, tracker[:claimed_ingredients].dup, tracker[:ingredient_count].dup) if found_this tracker[:claimed_ingredients] = temp_claimed_ingredients tracker[:ingredient_count] = temp_ingredient_count tracker[:found][ingredient_name] = tracker[:found][ingredient_name].to_i + 1 - tracker[:cost] += elusive_reagent_cost[ingredient_name].to_i + if $alchemy_reagent_op_cost[ingredient_name] + tracker[:cost] += trading_sell.call($alchemy_reagent_op_cost[ingredient_name]) + end else support_recipe_list = $alchemy_recipes.find_all { |r| r[:product] == ingredient_name } if support_recipe_list.length > 0 tracker_list = Array.new for support_recipe in support_recipe_list - temp_tracker = { :error => tracker[:error].dup, :recipe_count => tracker[:recipe_count].dup, :claimed_ingredients => tracker[:claimed_ingredients].dup, :ingredient_count => tracker[:ingredient_count].dup, :extra_ingredients => tracker[:extra_ingredients].dup, :found => tracker[:found].dup, :buy => tracker[:buy].dup, :forage => tracker[:forage].dup, :kill_for => tracker[:kill_for].dup, :steps => tracker[:steps].dup, :prepare_steps => tracker[:prepare_steps].dup, :finish_steps => tracker[:finish_steps].dup, :cost => tracker[:cost], :time => tracker[:time] } + temp_tracker = { :error => tracker[:error].dup, :recipe_count => tracker[:recipe_count].dup, :claimed_ingredients => tracker[:claimed_ingredients].dup, :ingredient_count => tracker[:ingredient_count].dup, :extra_ingredients => tracker[:extra_ingredients].dup, :found => tracker[:found].dup, :buy => tracker[:buy].dup, :forage => tracker[:forage].dup, :kill_for => tracker[:kill_for].dup, :steps => tracker[:steps].dup, :prepare_steps => tracker[:prepare_steps].dup, :finish_steps => tracker[:finish_steps].dup, :cost => tracker[:cost], :time => tracker[:time], :itime => tracker[:itime].dup, :icost => tracker[:icost].dup } temp_tracker = recursive_check_recipe.call(support_recipe.dup, temp_tracker, _top_level=false) tracker_list.push(temp_tracker) ingredient_count.each_pair { |ingredient_id,count| tracker[:ingredient_count][ingredient_id] ||= count } @@ -941,27 +1101,40 @@ recursive_check_recipe = proc { |recipe,tracker,top_level| place = $1 room_list = where_is.call(place) if room_list.empty? - tracker[:error][place] = 1 + tracker[:error]["#{place} to buy #{recipe[:product]}"] = tracker[:error]["#{place} to buy #{recipe[:product]}"].to_i + 1 else unless tracker[:buy].keys.any? { |key| key =~ /^#{place};/ } - tracker[:time] += tavel_time.call(room_list.first) * 2 + foo = tavel_time.call(room_list.first) * 2 + tracker[:time] += foo + tracker[:itime][recipe[:product]] = tracker[:itime][recipe[:product]].to_i + foo end - tracker[:cost] += recipe[:cost].to_i + foo = trading_buy.call(recipe[:cost].to_i) + tracker[:cost] += foo + tracker[:icost][recipe[:product]] += foo tracker[:buy]["#{place};#{recipe[:product]}"] = tracker[:buy]["#{place};#{recipe[:product]}"].to_i + 1 end - elsif step =~ /^forage/ + elsif step =~ /^forage( in sunlight| in moonlight)?/ + light = $1 room_list = where_is.call(recipe[:product]) if room_list.empty? tracker[:error][recipe[:product]] = tracker[:error][recipe[:product]].to_i + 1 + elsif (light == ' in sunlight') and is_moonlight.call + tracker[:error]["sunlight to forage for #{recipe[:product]}"] = tracker[:error]["sunlight to forage for #{recipe[:product]}"].to_i + 1 + elsif (light == ' in moonlight') and is_sunlight.call + tracker[:error]["moonlight to forage for #{recipe[:product]}"] = tracker[:error]["moonlight to forage for #{recipe[:product]}"].to_i + 1 else if tracker[:forage][recipe[:product]].nil? - tracker[:time] += tavel_time.call(room_list.first) * 2 + foo = tavel_time.call(room_list.first) * 2 + tracker[:time] += foo + tracker[:itime][recipe[:product]] = tracker[:itime][recipe[:product]].to_i + foo end CharSettings['forage time'] ||= Hash.new if CharSettings['forage time'][recipe[:product]].nil? CharSettings['forage time'][recipe[:product]] = [ 1, 1 ] end - tracker[:time] += CharSettings['forage time'][recipe[:product]][0] / CharSettings['forage time'][recipe[:product]][1].to_f + foo = CharSettings['forage time'][recipe[:product]][0] / CharSettings['forage time'][recipe[:product]][1].to_f + tracker[:time] += foo + tracker[:itime][recipe[:product]] = tracker[:itime][recipe[:product]].to_i + foo tracker[:forage][recipe[:product]] = tracker[:forage][recipe[:product]].to_i + 1 end elsif step =~ /^kill\s+(.*)/ @@ -972,25 +1145,27 @@ recursive_check_recipe = proc { |recipe,tracker,top_level| # tracker[:error][npc] = tracker[:error][npc].to_i + 1 else if CharSettings['attack-script'] - if tracker[:kill_for][recipe[:product]].nil? - tracker[:time] += tavel_time.call(room_list.first) * 2 + tracker[:kill_for][npc] ||= Hash.new + if tracker[:kill_for][npc].empty? + foo = tavel_time.call(room_list.first) * 2 + tracker[:time] += foo + tracker[:itime][recipe[:product]] = tracker[:itime][recipe[:product]].to_i + foo end CharSettings['kill time'] ||= Hash.new CharSettings['kill time'][npc] ||= Hash.new if CharSettings['kill time'][npc][recipe[:product]].nil? CharSettings['kill time'][npc][recipe[:product]] = [ 1, 1 ] end - tracker[:time] += CharSettings['kill time'][npc][recipe[:product]][0] / CharSettings['kill time'][npc][recipe[:product]][1].to_f - tracker[:kill_for][recipe[:product]] = tracker[:kill_for][recipe[:product]].to_i + 1 + foo = CharSettings['kill time'][npc][recipe[:product]][0] / CharSettings['kill time'][npc][recipe[:product]][1].to_f + tracker[:time] += foo + tracker[:itime][recipe[:product]] = tracker[:itime][recipe[:product]].to_i + foo + tracker[:kill_for][npc][recipe[:product]] = tracker[:kill_for][npc][recipe[:product]].to_i + 1 else tracker[:error]['attack-script'] = 1 end end elsif step =~ /^light/ -# unless top_level -# tracker[:recipe_count][recipe[:product]] = tracker[:recipe_count][recipe[:product]].to_i + 1 -# end - unless (checkroom == '[A Secluded Corner]') or GameObj.room_desc.any? { |obj| obj.noun == 'cauldron' } or GameObj.loot.any? { |obj| obj.noun =~ /^(?:cauldron|vat|kettle)$/ } or all_sack_contents.call.any? { |obj| obj.noun =~ /^(?:cauldron|vat|kettle)$/ } + unless (checkroom == '[A Secluded Corner]') or GameObj.room_desc.any? { |obj| obj.noun == 'cauldron' } or GameObj.loot.any? { |obj| obj.noun =~ cauldron_noun } or all_sack_contents.call.any? { |obj| obj.noun =~ cauldron_noun } tracker[:error]['cauldron'] = 1 end elsif step =~ /^special/ @@ -1035,6 +1210,8 @@ recursive_check_recipe = proc { |recipe,tracker,top_level| else echo "warning: unkown step: #{step}" end + recursive_padding -= 3 + respond "#{''.ljust(recursive_padding)}end step: #{step}: #{Time.now - step_start}" if $alchemy_debug } if top_level tracker[:recipe_count][recipe[:product]] = tracker[:recipe_count][recipe[:product]].to_i + 1 @@ -1046,21 +1223,28 @@ recursive_check_recipe = proc { |recipe,tracker,top_level| if recipe[:product] =~ /^(?:s'|t')?ayanad crystal$/ tracker[:extra_ingredients].push(recipe[:product]) end + recursive_padding -= 3 + respond "#{''.ljust(recursive_padding)}end recipe: #{recipe[:product]}: #{Time.now - recipe_start}" if $alchemy_debug tracker } -check_recipe = proc { |recipe_name,repetitions| - tracker = { :error => Hash.new, :recipe_count => Hash.new, :claimed_ingredients => Array.new, :ingredient_count => ingredient_count.dup, :extra_ingredients => Array.new, :found => Hash.new, :buy => Hash.new, :forage => Hash.new, :kill_for => Hash.new, :steps => Array.new, :prepare_steps => Array.new, :finish_steps => Array.new, :cost => 0, :time => 0 } - if recipe_name.class == Array - recipe_list = $alchemy_recipes.find_all { |recipe| recipe_name.include?(recipe[:product]) } - else - recipe_list = $alchemy_recipes.find_all { |recipe| recipe[:product] == recipe_name } - end - repetitions.times { +check_recipe = proc { |args| + if args[:name] + recipe_list = $alchemy_recipes.find_all { |recipe| recipe[:product] == args[:name] } + elsif args[:names] + recipe_list = $alchemy_recipes.find_all { |recipe| args[:names].include?(recipe[:product]) } + elsif args[:recipe] + recipe_list = [ args[:recipe] ] + elsif args[:recipes] + recipe_list = args[:recipes] + end + tracker = { :error => Hash.new, :recipe_count => Hash.new, :claimed_ingredients => Array.new, :ingredient_count => ingredient_count.dup, :extra_ingredients => Array.new, :found => Hash.new, :buy => Hash.new, :forage => Hash.new, :kill_for => Hash.new, :steps => Array.new, :prepare_steps => Array.new, :finish_steps => Array.new, :cost => 0, :time => 0, :itime => Hash.new, :icost => Hash.new } + args[:reps] ||= 1 + args[:reps].times { if recipe_list.length > 0 tracker_list = Array.new for recipe in recipe_list - temp_tracker = { :error => tracker[:error].dup, :recipe_count => tracker[:recipe_count].dup, :claimed_ingredients => tracker[:claimed_ingredients].dup, :ingredient_count => tracker[:ingredient_count].dup, :extra_ingredients => tracker[:extra_ingredients].dup, :found => tracker[:found].dup, :buy => tracker[:buy].dup, :forage => tracker[:forage].dup, :kill_for => tracker[:kill_for].dup, :steps => tracker[:steps].dup, :prepare_steps => tracker[:prepare_steps].dup, :finish_steps => tracker[:finish_steps].dup, :cost => tracker[:cost], :time => tracker[:time] } + temp_tracker = { :error => tracker[:error].dup, :recipe_count => tracker[:recipe_count].dup, :claimed_ingredients => tracker[:claimed_ingredients].dup, :ingredient_count => tracker[:ingredient_count].dup, :extra_ingredients => tracker[:extra_ingredients].dup, :found => tracker[:found].dup, :buy => tracker[:buy].dup, :forage => tracker[:forage].dup, :kill_for => tracker[:kill_for].dup, :steps => tracker[:steps].dup, :prepare_steps => tracker[:prepare_steps].dup, :finish_steps => tracker[:finish_steps].dup, :cost => tracker[:cost], :time => tracker[:time], :itime => tracker[:itime].dup, :icost => tracker[:icost].dup } temp_tracker = recursive_check_recipe.call(recipe, temp_tracker, top_level=true) tracker_list.push(temp_tracker) ingredient_count.each_pair { |ingredient_id,count| tracker[:ingredient_count][ingredient_id] ||= count } @@ -1084,31 +1268,76 @@ check_recipe = proc { |recipe_name,repetitions| tracker } +other_check_recipe = proc { |recipe,repetitions| + tracker = { :error => Hash.new, :recipe_count => Hash.new, :claimed_ingredients => Array.new, :ingredient_count => ingredient_count.dup, :extra_ingredients => Array.new, :found => Hash.new, :buy => Hash.new, :forage => Hash.new, :kill_for => Hash.new, :steps => Array.new, :prepare_steps => Array.new, :finish_steps => Array.new, :cost => 0, :time => 0, :itime => Hash.new, :icost => Hash.new } + repetitions.times { + tracker_list = Array.new + temp_tracker = { :error => tracker[:error].dup, :recipe_count => tracker[:recipe_count].dup, :claimed_ingredients => tracker[:claimed_ingredients].dup, :ingredient_count => tracker[:ingredient_count].dup, :extra_ingredients => tracker[:extra_ingredients].dup, :found => tracker[:found].dup, :buy => tracker[:buy].dup, :forage => tracker[:forage].dup, :kill_for => tracker[:kill_for].dup, :steps => tracker[:steps].dup, :prepare_steps => tracker[:prepare_steps].dup, :finish_steps => tracker[:finish_steps].dup, :cost => tracker[:cost], :time => tracker[:time], :itime => tracker[:itime].dup, :icost => tracker[:icost].dup } + temp_tracker = recursive_check_recipe.call(recipe, temp_tracker, top_level=true) + tracker_list.push(temp_tracker) + ingredient_count.each_pair { |ingredient_id,count| tracker[:ingredient_count][ingredient_id] ||= count } + tracker_list.sort! { |a,b| (a[:cost] + (a[:time] * CharSettings['cost-per-second'])) <=> (b[:cost] + (b[:time] * CharSettings['cost-per-second'])) } + tracker = tracker_list.find { |t| t[:error].empty? } || tracker_list.first + } + fixed_buy = Hash.new + tracker[:buy].each_pair { |where_what,how_many| + where, what = where_what.split(';') + fixed_buy[where] ||= Hash.new + fixed_buy[where][what] = how_many + } + tracker[:buy] = fixed_buy + tracker.delete(:claimed_ingredients) + tracker.delete(:ingredient_count) + tracker.delete(:extra_ingredients) + tracker +} + show_check = proc { |check_info| output = "\n" output.concat check_info[:recipe_count].collect { |n,c| if c == 1; n; else; "#{n} (#{c})"; end }.join(', ').to_s output.concat "\n" + max_width = 0 + check_info[:found].each_pair { |n,c| max_width = [ max_width, n.sub(/s*\#.*$/, '').length ].max } + check_info[:forage].each_pair { |n,c| max_width = [ max_width, n.sub(/s*\#.*$/, '').length ].max } + check_info[:kill_for].each { |npc,foo| foo.each_pair { |n,c| max_width = [ max_width, n.sub(/s*\#.*$/, '').length ].max } } + check_info[:buy].values.each { |place| place.each_pair { |n,c| max_width = [ max_width, n.sub(/s*\#.*$/, '').length ].max } } unless check_info[:found].empty? output.concat " have:\n" check_info[:found].each_pair { |n,c| - output.concat " #{n.sub(/s*\#.*$/, '')}" - output.concat " (#{c})" if c > 1 + str = n.sub(/s*\#.*$/, '') + str.concat " (#{c})" if c > 1 + output.concat " #{str.ljust(max_width+8)}" + if $alchemy_reagent_op_cost[n] + output.concat add_commas.call(trading_sell.call($alchemy_reagent_op_cost[n])*c).rjust(7) + else + output.concat ' -' + end output.concat "\n" } end + unless check_info[:kill_for].empty? + output.concat " kill for:\n" + check_info[:kill_for].each_pair { |npc,foo| + foo.each_pair { |n,c| + str = n.sub(/s*\#.*$/, '') + str.concat " (#{c})" if c > 1 + output.concat " #{str.ljust(max_width + 8)}" + if bar = check_info[:itime][n] + output.concat((bar/60.0).as_time) + end + output.concat "\n" + } + } + end unless check_info[:forage].empty? output.concat " forage:\n" check_info[:forage].each_pair { |n,c| - output.concat " #{n.sub(/s*\#.*$/, '')}" - output.concat " (#{c})" if c > 1 - output.concat "\n" - } - end - unless check_info[:kill_for].empty? - output.concat " kill for:\n" - check_info[:kill_for].each_pair { |n,c| - output.concat " #{n.sub(/s*\#.*$/, '')}" - output.concat " (#{c})" if c > 1 + str = n.sub(/s*\#.*$/, '') + str.concat " (#{c})" if c > 1 + output.concat " #{str.ljust(max_width + 8)}" + if foo = check_info[:itime][n] + output.concat((foo/60.0).as_time) + end output.concat "\n" } end @@ -1116,8 +1345,12 @@ show_check = proc { |check_info| output.concat " buy:\n" check_info[:buy].values.each { |place| place.each_pair { |n,c| - output.concat " #{n.sub(/s*\#.*$/, '')}" - output.concat " (#{c})" if c > 1 + str = n.sub(/s*\#.*$/, '') + str.concat " (#{c})" if c > 1 + output.concat " #{str.ljust(max_width + 8)}" + if foo = check_info[:icost][n] + output.concat add_commas.call(foo).rjust(7) + end output.concat "\n" } } @@ -1130,7 +1363,7 @@ show_check = proc { |check_info| output.concat "\n" } end - output.concat "\ncost: #{check_info[:cost]}, time: #{(check_info[:time]/60.0).as_time}\n\n" + output.concat "\ncost: #{add_commas.call(check_info[:cost])} time: #{(check_info[:time]/60.0).as_time}\n\n" if defined?(_respond) _respond output else @@ -1212,10 +1445,10 @@ do_steps = proc { |steps| if action == 'add' dothis "put ##{ingredient.id} in #{cauldron.noun || 'cauldron'}", /^You place|^You pour/ if GameObj.right_hand.name == 'empty flask' - dothis "put ##{GameObj.right_hand.id} in ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ + dothis "put ##{GameObj.right_hand.id} in ##{alchemy_sack.call.id}", put_regex need_empty_flask = true elsif GameObj.left_hand.name == 'empty flask' - dothis "put ##{GameObj.left_hand.id} in ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ + dothis "put ##{GameObj.left_hand.id} in ##{alchemy_sack.call.id}", put_regex need_empty_flask = true end elsif action == 'grind' @@ -1223,8 +1456,8 @@ do_steps = proc { |steps| dothis 'swap', /^You swap/ end mortar = all_sack_contents.call.find { |obj| obj.noun == 'mortar' } - dothis "get ##{mortar.id}", /^You remove|^You already have that/ - dothis "put ##{ingredient.id} in ##{mortar.id}", /^You put|^I could not find what you were referring to\./ + dothis "get ##{mortar.id}", get_regex + dothis "put ##{ingredient.id} in ##{mortar.id}", put_regex loop { haste = Spell[506] haste.cast if haste.known? and haste.affordable? and not haste.active? @@ -1237,7 +1470,7 @@ do_steps = proc { |steps| error = true break end - dothis "_drag ##{pestle.id} ##{mortar.id}", /^You put|^I could not find what you were referring to\./ + dothis "_drag ##{pestle.id} ##{mortar.id}", put_regex elsif grind_result =~ /appears to be as ground as it'?s going to get|^Grind what/ break end @@ -1248,9 +1481,9 @@ do_steps = proc { |steps| end for item in mortar.contents next if item.noun == 'pestle' - dothis "_drag ##{item.id} ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ + dothis "_drag ##{item.id} ##{alchemy_sack.call.id}", put_regex end - dothis "put ##{mortar.id} in ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ + dothis "put ##{mortar.id} in ##{alchemy_sack.call.id}", put_regex elsif action == 'extract' unless checkright dothis 'swap', /^You swap/ @@ -1325,9 +1558,9 @@ do_steps = proc { |steps| echo 'waiting for mana...' wait_until { mana >= 10 } end - boil_result = dothis 'alchemy boil', /^You focus on the [\w\s\-]+ (?:cauldron|vat|kettle) and push mana into it. The flame beneath it (flickers briefly, but then dies down|quickly flares up wildly, bringing the contents to a rolling boil)\.$/ + boil_result = dothis 'alchemy boil', /^You focus on the [\w\s\-]+ (?:cauldron|vat|kettle|boiler) and push mana into it. The flame beneath it (flickers briefly, but then dies down|quickly flares up wildly, bringing the contents to a rolling boil)\.$/ waitrt? - break if boil_result =~ /^You focus on the [\w\s\-]+ (?:cauldron|vat|kettle) and push mana into it. The flame beneath it quickly flares up wildly, bringing the contents to a rolling boil\.$/ + break if boil_result =~ /^You focus on the [\w\s\-]+ (?:cauldron|vat|kettle|boiler) and push mana into it. The flame beneath it quickly flares up wildly, bringing the contents to a rolling boil\.$/ } elsif step == 'simmer' loop { @@ -1335,7 +1568,7 @@ do_steps = proc { |steps| echo 'waiting for mana...' wait_until { mana >= 10 } end - # simmer_result = dothis 'alchemy simmer', /^You focus on the [\w\s\-]+ (?:cauldron|vat|kettle) and gently push mana into it\. The flame beneath it (flickers briefly, but then dies down|quickly flares to life, bringing the contents to a slow simmer)\.$/ + # simmer_result = dothis 'alchemy simmer', /^You focus on the [\w\s\-]+ (?:cauldron|vat|kettle|boiler) and gently push mana into it\. The flame beneath it (flickers briefly, but then dies down|quickly flares to life, bringing the contents to a slow simmer)\.$/ simmer_result = dothis 'alchemy simmer', /flickers briefly, but then dies down|quickly flares to life, bringing the contents to a slow simmer/ waitrt? break if simmer_result =~ /quickly flares to life, bringing the contents to a slow simmer/ @@ -1383,17 +1616,17 @@ do_steps = proc { |steps| error = true break end - dothistimeout "get ##{lens.id}", 10, /^You remove|^You already have that/ + dothistimeout "get ##{lens.id}", 10, get_regex dothistimeout 'alchemy refract', 10, /^The surface of the solution in .* shimmers in response!/ waitrt? - dothistimeout "put ##{lens.id} in ##{alchemy_sack.call.id}", 10, /^You put|^I could not find what you were referring to\./ + dothistimeout "put ##{lens.id} in ##{alchemy_sack.call.id}", 10, put_regex elsif step == 'seal' unless mana >= 20 echo 'waiting for mana...' wait_until { mana >= 20 } end if need_empty_flask - dothis "get empty flask from ##{alchemy_sack.call.id}", /^You remove|^Get what\?/ + dothis "get empty flask from ##{alchemy_sack.call.id}", get_regex end fput "look in #{cauldron.noun || 'cauldron'}" dothis 'alchemy seal', /^You hold your hands over/ @@ -1405,19 +1638,19 @@ do_steps = proc { |steps| elsif step == 'special' vial = all_sack_contents.call.find { |obj| obj.name =~ sea_water_vial } flask = all_sack_contents.call.find { |obj| obj.name =~ sea_water_flask } - dothis "get ##{vial.id}", /^You remove|^You already have that/ - dothis "get ##{flask.id}", /^You remove|^You already have that/ + dothis "get ##{vial.id}", get_regex + dothis "get ##{flask.id}", get_regex dothis "open ##{flask.id}", /^You gently twist the stopper on the flask|^It's already open\.$/ - pour_result = dothis "pour ##{flask.id} in ##{vial.id}", /^You pour|^It looks like your glass vial is already full\.$|^But your crystal flask is empty!$/ - if pour_result == 'But your crystal flask is empty!' - dothis "put ##{vial.id} in ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ + pour_result = dothis "pour ##{flask.id} in ##{vial.id}", /^You pour|^It looks like your glass vial is already full\.$|^But your .*? flask is empty!$/ + if pour_result =~ /But your .*? flask is empty!/ + dothis "put ##{vial.id} in ##{alchemy_sack.call.id}", put_regex get_cauldron.call if room_id = where_is.call('alchemy sea water').first return_room = Room.current start_script 'go2', [ room_id.to_s ] wait_while { running?('go2') } dothis "collect water with ##{flask.id}", /under water until it is filled|is already filled/ - dothis "get ##{vial.id}", /^You remove|^You already have that/ + dothis "get ##{vial.id}", get_regex dothis "collect water with ##{vial.id}", /under water until it is filled|is already filled/ start_script 'go2', [ return_room.id.to_s ] wait_while { running?('go2') } @@ -1428,7 +1661,7 @@ do_steps = proc { |steps| end end dothis "close ##{flask.id}", /^You draw up the slick crystal cork|^It's already corked\.$/ - dothis "put ##{flask.id} in ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ + dothis "put ##{flask.id} in ##{alchemy_sack.call.id}", put_regex unless is_workshop.call return_room = Room.current get_cauldron.call @@ -1447,7 +1680,7 @@ do_steps = proc { |steps| } sleep 1 waitrt? - dothistimeout "put ##{vial.id} in ##{alchemy_sack.call.id}", 3, /^You put|^I could not find what you were referring to\./ + dothistimeout "put ##{vial.id} in ##{alchemy_sack.call.id}", 3, put_regex put_crap_away.call if return_room start_script 'go2', [ return_room.id.to_s ] @@ -1505,20 +1738,24 @@ forage = proc { |forage_list| presence.cast if presence.known? and presence.affordable? and not presence.active? end if (id = GameObj.right_hand.id) - dothis "put ##{id} in ##{herb_sack.call.id}", /^You put|^I could not find what you were referring to\./ +# dothis "put ##{id} in ##{herb_sack.call.id}", put_regex + dothis "put ##{id} in ##{alchemy_sack.call.id}", put_regex end if (id = GameObj.left_hand.id) - dothis "put ##{id} in ##{herb_sack.call.id}", /^You put|^I could not find what you were referring to\./ +# dothis "put ##{id} in ##{herb_sack.call.id}", put_regex + dothis "put ##{id} in ##{alchemy_sack.call.id}", put_regex end forage_result = dothistimeout "forage for #{name.sub(/^(?:cluster|layer|mass|sprig|handful) of |^luminescent |^black\-tipped /, '').sub(/^(?:some fetid )/, 'some ')}", 10, /^You forage|^You make so much noise that only the dead would not notice you thrashing about in your unsuccessful search\.$|^You stumble about in a fruitless attempt at foraging\.$|you are unable to find anything useful|^As you carefully forage around you (can find no hint|see no evidence) of what you are looking for(?: right now, though you are fairly certain this is where it can be found)?\.|^You begin to forage around when your hand comes into contact with something that stabs you in the finger\.$|^As you forage around you suddenly feel a sharp pain in your right hand!|^You begin to forage around when suddenly you feel a burning sensation in your hand\.$|^You fumble about so badly in your search that you can only hope no one was watching you\.$/ sleep 0.5 waitrt? if forage_result =~ /^You forage briefly and manage to find/ if id = GameObj.right_hand.id - dothis "put ##{id} in ##{herb_sack.call.id}", /^You put|^I could not find what you were referring to\./ +# dothis "put ##{id} in ##{herb_sack.call.id}", put_regex + dothis "put ##{id} in ##{alchemy_sack.call.id}", put_regex end if id = GameObj.left_hand.id - dothis "put ##{id} in ##{herb_sack.call.id}", /^You put|^I could not find what you were referring to\./ +# dothis "put ##{id} in ##{herb_sack.call.id}", put_regex + dothis "put ##{id} in ##{alchemy_sack.call.id}", put_regex end if herb_doses[name] forage_list[name] = forage_list[name] - herb_doses[name] @@ -1574,31 +1811,32 @@ buy = proc { |shopping_list| empty_hands get_cauldron.call for place,hash in shopping_list.dup - unless note = all_sack_contents.call.find { |obj| obj.name == note_name.call } - echo 'error: you are too poor for alchemy' - break - end unless room_id = where_is.call(place).first echo "error: don't know where #{place} is" break end + the_note_name = (note_name_from_place.call(Room[room_id].location) || note_name_from_place.call(place) || note_name.call) + unless note = all_sack_contents.call.find { |obj| obj.name == the_note_name } + echo "error: missing #{the_note_name}" + break + end start_script 'go2', [ room_id.to_s ] wait_while { running?('go2') } if place =~ /^(?:Icemule|River's Rest) empath guild entrance$/ - get_result = dothis "get ##{note.id}", /^You remove|^You already have that|^Get what\?/ + get_result = dothis "get ##{note.id}", get_regex for name,num in hash.dup if name == 'vial of faintly glowing aelotoi tears' num.times { dothis 'buy aelotoi tears', /^A sales clerk .* Handing it to you/ - dothis "put ##{GameObj.left_hand.id} in ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ + dothis "put ##{GameObj.left_hand.id} in ##{alchemy_sack.call.id}", put_regex } shopping_list[place].delete(name) end end - dothis "put ##{note.id} in ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ + dothis "put ##{note.id} in ##{alchemy_sack.call.id}", put_regex else menu = read_menu.call - get_result = dothis "get ##{note.id}", /^You remove|^You already have that|^Get what\?/ + get_result = dothis "get ##{note.id}", get_regex if get_result =~ /^Get what\?/ echo "error: can't find bank note" break @@ -1627,7 +1865,11 @@ buy = proc { |shopping_list| dothis "empty my package in ##{alchemy_sack.call.id}", /everything falls in/ waitrt? dothis 'throw my package', /^You throw away/ - shopping_list[place][name] -= 10 + if herb_doses[name] + shopping_list[place][name] -= (herb_doses[name] * 10) + else + shopping_list[place][name] -= 10 + end } num = num % 10 if num > 1 @@ -1637,17 +1879,25 @@ buy = proc { |shopping_list| dothis "empty my package in ##{alchemy_sack.call.id}", /everything falls in/ waitrt? dothis 'throw my package', /^You throw away/ - shopping_list[place][name] -= num + if herb_doses[name] + shopping_list[place][name] -= (herb_doses[name] * num) + else + shopping_list[place][name] -= num + end elsif num == 1 dothis "order #{order_number}", /BUY/ fput 'buy' 100.times { break if checkleft; sleep 0.1 } - dothis "put ##{GameObj.left_hand.id} in ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ - shopping_list[place][name] -= 1 + dothis "put ##{GameObj.left_hand.id} in ##{alchemy_sack.call.id}", put_regex + if herb_doses[name] + shopping_list[place][name] -= (herb_doses[name] * 1) + else + shopping_list[place][name] -= 1 + end end - shopping_list[place].delete(name) if shopping_list[place][name] == 0 + shopping_list[place].delete(name) if shopping_list[place][name] < 1 end - dothis "put ##{note.id} in ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ + dothis "put ##{note.id} in ##{alchemy_sack.call.id}", put_regex end shopping_list.delete(place) if shopping_list[place].empty? end @@ -1664,66 +1914,68 @@ kill_for = proc { |kill_for_list| start_script(CharSettings['before-hunt-script']) wait_while { running?(CharSettings['before-hunt-script']) } end - for ingredient_name,count in kill_for_list.dup - recipe_list = $alchemy_recipes.find_all { |r| (r[:product] == ingredient_name) and (r[:steps].first =~ /^kill/) } - target_list = recipe_list.collect { |r| /^kill\s+(.+)/.match(r[:steps].first).captures.first } - wander_room_list = Array.new - target_list.each { |t| wander_room_list.concat(where_is.call(t).collect { |num| num.to_s }) } - seen_targets = Array.new - start_kill_room = wander_room_list.first - if start_kill_room - current_ingredient_count = start_ingredient_count = all_sack_contents.call.find_all { |obj| obj.name == ingredient_name }.length - start_script 'go2', [ start_kill_room.to_s ] - wait_while { running?('go2') } - start_time = Time.now - $alchemy_abort_room = false - $alchemy_abort_hunt = false - start_hunt_time = Time.now - while (Time.now - start_hunt_time) < CharSettings['max-hunt-time'] - sleep 0.1 - wander.call - next if checkpcs - next if GameObj.loot.find { |obj| (obj.noun == 'disk') and (obj.name !~ /#{Char.name}/) } + for npc,foo in kill_for_list.dup + for ingredient_name,count in foo.dup + recipe_list = $alchemy_recipes.find_all { |r| (r[:product] == ingredient_name) and (r[:steps].first =~ /^kill/) } + target_list = recipe_list.collect { |r| /^kill\s+(.+)/.match(r[:steps].first).captures.first } + wander_room_list = where_is.call(npc).collect { |num| num.to_s } + start_kill_room = wander_room_list.first + if start_kill_room + current_ingredient_count = start_ingredient_count = all_sack_contents.call.find_all { |obj| obj.name == ingredient_name }.length + start_script 'go2', [ start_kill_room.to_s ] + wait_while { running?('go2') } + start_time = Time.now + $alchemy_abort_room = false + $alchemy_abort_hunt = false + start_hunt_time = Time.now while (Time.now - start_hunt_time) < CharSettings['max-hunt-time'] - target_ids = GameObj.npcs.find_all { |npc| target_list.include?(npc.name) and (npc.status !~ /dead/) }.collect { |npc| npc.id } - if target_ids.length > 0 - if checkrt > 0 or checkcastrt > 0 - sleep 0.1 - else - seen_targets = (seen_targets | (GameObj.npcs.to_a.collect { |npc| npc.name } & target_list)) - start_script(CharSettings['attack-script'], target_ids) - wait_while { running?(CharSettings['attack-script']) } - if $alchemy_abort_room or $alchemy_abort_hunt - $alchemy_abort_room = false - break + wander.call + sleep 0.1 + next if checkpcs + next if GameObj.loot.find { |obj| (obj.noun == 'disk') and (obj.name !~ /#{Char.name}/) } + if GameObj.npcs.nil? + sleep 0.1 + (rand(10)/10.0) + next if GameObj.npcs.nil? + end + while (Time.now - start_hunt_time) < CharSettings['max-hunt-time'] + target_ids = GameObj.npcs.find_all { |npc| target_list.include?(npc.name) and (npc.status !~ /dead/) }.collect { |npc| npc.id } + if target_ids.length > 0 + if checkrt > 0 or checkcastrt > 0 + sleep 0.1 + else + start_script(CharSettings['attack-script'], target_ids) + wait_while { running?(CharSettings['attack-script']) } + if $alchemy_abort_room or $alchemy_abort_hunt + $alchemy_abort_room = false + break + end end + else + break + end + if $alchemy_abort_hunt + $alchemy_abort_hunt = false + break end - else - break - end - if $alchemy_abort_hunt - $alchemy_abort_hunt = false - break end + current_ingredient_count = all_sack_contents.call.find_all { |obj| obj.name == ingredient_name }.length + break unless current_ingredient_count < start_ingredient_count + count + break if Time.now - start_time > CharSettings['max-hunt-time'] end - current_ingredient_count = all_sack_contents.call.find_all { |obj| obj.name == ingredient_name }.length - break unless current_ingredient_count < start_ingredient_count + count - break if Time.now - start_time > CharSettings['max-hunt-time'] - end - end_time = Time.now - CharSettings['kill time'] ||= Hash.new - for npc in seen_targets + end_time = Time.now + CharSettings['kill time'] ||= Hash.new CharSettings['kill time'][npc] ||= Hash.new if CharSettings['kill time'][npc][ingredient_name].nil? CharSettings['kill time'][npc][ingredient_name] = [ 1, 1 ] end - CharSettings['kill time'][npc][ingredient_name][0] += (end_time - start_time) / seen_targets.length.to_f - CharSettings['kill time'][npc][ingredient_name][1] += (current_ingredient_count - start_ingredient_count) / seen_targets.length.to_f + CharSettings['kill time'][npc][ingredient_name][0] += (end_time - start_time) + CharSettings['kill time'][npc][ingredient_name][1] += (current_ingredient_count - start_ingredient_count) + kill_for_list[npc][ingredient_name] = kill_for_list[npc][ingredient_name] - (current_ingredient_count - start_ingredient_count) + kill_for_list[npc].delete(ingredient_name) if kill_for_list[npc][ingredient_name] < 1 + kill_for_list.delete(npc) if kill_for_list[npc].empty? + else + echo 'error: kill: failed to find starting room' end - kill_for_list[ingredient_name] = kill_for_list[ingredient_name] - (current_ingredient_count - start_ingredient_count) - kill_for_list.delete(ingredient_name) if kill_for_list[ingredient_name] < 1 - else - echo 'error: kill: failed to find starting room' end end if CharSettings['after-hunt-script'] @@ -1744,21 +1996,21 @@ go_get_crap = proc { |check_info| unless check_info[:kill_for].empty? check_info[:kill_for] = kill_for.call(check_info[:kill_for]) unless check_info[:kill_for].empty? - echo "error: failed to find: #{check_info[:kill_for].keys.join(', ')}" + echo "error: failed to find: #{check_info[:kill_for].values.inspect}" error = true end end unless error or check_info[:forage].empty? check_info[:forage] = forage.call(check_info[:forage]) unless check_info[:forage].empty? - echo "error: failed to find: #{check_info[:forage].keys.join(', ')}" + echo "error: failed to find: #{check_info[:forage].inspect}" error = true end end unless error or check_info[:buy].empty? check_info[:buy] = buy.call(check_info[:buy]) unless check_info[:buy].empty? - echo "error: failed to buy: #{check_info[:buy].keys.join(', ')}" + echo "error: failed to buy: #{check_info[:buy].inspect}" error = true end end @@ -1807,16 +2059,13 @@ do_task_assembly = proc { } do_task_distill = proc { - room_list = where_is.call("#{Char.prof.downcase} alchemy workshop") - if room_list.length > 0 - if room_list.include?(Room.current.id) - return_room = nil - else - return_room = Room.current - get_cauldron.call - start_script 'go2', [ room_list.first.to_s ] - wait_while { running?('go2') } - end + return_room = nil + unless is_workshop.call + return_room = Room.current + get_cauldron.call + go_empty_workshop.call + end + if is_workshop.call haste = Spell[506] loop { haste.cast if haste.known? and haste.affordable? and not haste.active? @@ -1964,7 +2213,7 @@ do_task_grind = proc { start_script 'go2', [ room_id.to_s ] wait_while { running?('go2') } haste = Spell[506] - clerk = checknpcs.find { |npc_name| npc_name =~ /^clerk$|acolyte$|^hobgoblin$|^gnome$|^apothecary$/ } || 'clerk' + clerk = checknpcs.find { |npc_name| npc_name =~ /^clerk$|acolyte$|^hobgoblin$|^gnome$|^apothecary$|^apprentice$/ } || 'clerk' empty_hands result = dothis 'get mortars', /^You take|^You already have a stone mortar|^Get what\?/ if result =~ /^Get what\?/ @@ -1974,18 +2223,18 @@ do_task_grind = proc { loop { script.want_downstream = false script.want_downstream_xml = true - contents_line = dothis "look on ##{shelf.id}", /On the .*? you see|There is nothing on there\./ + contents_line = dothis "look on ##{shelf.id}", /On the .*? you see|There is nothing on there\.|^Special/ if contents_line =~ /There is nothing on there\./ script.want_downstream = true script.want_downstream_xml = false dothistimeout "ask #{clerk} about ingredients", 10, /^You ask the .*? about ingredients\.$/ script.want_downstream = false script.want_downstream_xml = true - contents_line = dothis "look on ##{shelf.id}", /On the .*? you see|There is nothing on there$/ + contents_line = dothis "look on ##{shelf.id}", /On the .*? you see|There is nothing on there$|^Special/ end script.want_downstream = true script.want_downstream_xml = false - grindable_id, grindable_noun = /you see .*?Special.*?) .*? Hash.new, :recipe_count => Hash.new, :claimed_ingredients => Array.new, :ingredient_count => ingredient_count.dup, :extra_ingredients => Array.new, :found => Hash.new, :buy => Hash.new, :forage => Hash.new, :kill_for => Hash.new, :steps => Array.new, :prepare_steps => Array.new, :finish_steps => Array.new, :cost => 0, :time => 0 } + tracker = { :error => Hash.new, :recipe_count => Hash.new, :claimed_ingredients => Array.new, :ingredient_count => ingredient_count.dup, :extra_ingredients => Array.new, :found => Hash.new, :buy => Hash.new, :forage => Hash.new, :kill_for => Hash.new, :steps => Array.new, :prepare_steps => Array.new, :finish_steps => Array.new, :cost => 0, :time => 0, :itime => Hash.new, :icost => Hash.new } tracker = recursive_check_recipe.call(recipe, tracker, top_level=true) fixed_buy = Hash.new tracker[:buy].each_pair { |where_what,how_many| @@ -2071,24 +2320,43 @@ do_task = proc { |type| if checkpoison # fixme: failed echo "masters won't talk to you while you're poisoned..." wait_while { checkpoison } + start_script 'go2', [ room_id.to_s ] + wait_while { running?('go2') } end dothistimeout "ask #{GameObj.npcs.last.noun} about training #{type}", 10, /^#{GameObj.npcs.last.noun}/ while line = get - if line =~ /try a recipe with (.*?) as a component/ + if line =~ /First, we light the cauldron\. Go ahead\.|Please #{XMLData.name}, LIGHT the cauldron/ + fput 'light cauldron' + elsif line =~ /Excellent, now try to extinguish it\.|Please #{XMLData.name}, EXTINGUISH the cauldron\./ + fput 'extinguish cauldron' + elsif line =~ /\[Use the ALCHEMY SEAL command to seal the solution inside the training cauldron\.\]|\[You can use the ALCHEMY verb to SEAL the mixture in the cauldron\.\]/ + fput 'alchemy seal' + elsif line =~ /try a recipe with (.*?) as a component/ required_step = $1.downcase - recipe_list = gld_suggestions.call[type][:recipes] - recipe_list.delete_if { |recipe_name| !$alchemy_recipes.any? { |recipe| (recipe[:product] == recipe_name) and recipe[:steps].any? { |step| step =~ /^#{required_step}/ } } } - check_info = check_recipe.call(recipe_list, 1) + echo "required_step: #{required_step.inspect}" if $alchemy_debug + recipe_list = gld_suggestions.call[type][:recipes].dup + echo "recipe_list: #{recipe_list.inspect}" if $alchemy_debug + recipe_list.delete_if { |r| not r[:steps].any? { |step| step =~ /^#{required_step}/ } } + echo "recipe_list: #{recipe_list.inspect}" if $alchemy_debug + check_info = check_recipe.call(:recipes => recipe_list, :reps => 1) if !check_info[:error].empty? or check_info[:steps].any? { |step| step =~ /^extract|^distill|^special/ } or not check_info[:buy].empty? or not check_info[:forage].empty? or not check_info[:kill_for].empty? move 'out' - reps = gld.call[type][:reps] + if ((silvers = check_silvers.call) > 0) and room_id = where_is.call('bank').first + start_script 'go2', [ room_id.to_s ] + wait_while { running?('go2') } + fput "deposit #{silvers}" + end + reps = [gld.call[type][:reps], 3].min while reps > 0 - check_info = check_recipe.call(recipe_list, reps) + check_info = check_recipe.call(:recipes => recipe_list, :reps => reps) +# echo "reps: #{reps.inspect}" +# echo "check_info: #{check_info.inspect}" break if check_info[:error].empty? reps -= 1 end if reps < 1 - echo 'error: failed to find a decent recipe' + echo 'error: failed to find a decent recipe (use ";alchemy suggest" to help figure out why)' +# echo "gld_suggestions.call[type][:recipes]: #{gld_suggestions.call[type][:recipes].inspect}" sleep 0.5 error = true break @@ -2106,6 +2374,12 @@ do_task = proc { |type| if room_id = where_is.call("#{Char.prof.downcase} alchemy masters").first start_script 'go2', [ room_id.to_s ] wait_while { running?('go2') } + if checkpoison + echo "masters won't talk to you while you're poisoned..." + wait_while { checkpoison } + start_script 'go2', [ room_id.to_s ] + wait_while { running?('go2') } + end dothistimeout "ask #{GameObj.npcs.last.noun} about training #{type}", 10, /^#{GameObj.npcs.last.noun}/ else echo 'error: failed to find alchemy masters' @@ -2119,6 +2393,11 @@ do_task = proc { |type| elsif line == '[You have completed your training task.]' invalid_gld.call move 'out' + if ((silvers = check_silvers.call) > 0) and room_id = where_is.call('bank').first + start_script 'go2', [ room_id.to_s ] + wait_while { running?('go2') } + fput "deposit #{silvers}" + end break end end @@ -2127,7 +2406,7 @@ do_task = proc { |type| error = true end elsif gld.call[type][:task] =~ /^practice creating tough solutions|follow some tough recipes and create some items|^practice (?:distilling|extracting) for reagents/ - check_info = check_recipe.call(gld_suggestions.call[type][:recipes], gld_suggestions.call[type][:reps]) + check_info = check_recipe.call(:recipes => gld_suggestions.call[type][:recipes], :reps => gld_suggestions.call[type][:reps]) if check_info[:error].empty? get_cauldron.call show_check.call(check_info) @@ -2144,11 +2423,11 @@ do_task = proc { |type| error = true end else - echo "warning: failed to find a decent recipe" + echo 'warning: failed to find a decent recipe (use ";alchemy suggest" to help figure out why)' error = true end elsif gld.call[type][:task] =~ /^visit the cauldron workshop and practice making solutions/ - check_info = check_recipe.call(gld_suggestions.call[type][:recipes], gld_suggestions.call[type][:reps]) + check_info = check_recipe.call(:recipes => gld_suggestions.call[type][:recipes], :reps => gld_suggestions.call[type][:reps]) if check_info[:error].empty? if cauldron_room_id = where_is.call("#{Char.prof.downcase} alchemy training cauldron").first get_cauldron.call @@ -2176,7 +2455,7 @@ do_task = proc { |type| error = true end else - echo "warning: failed to find a decent recipe" + echo 'warning: failed to find a decent recipe (use ";alchemy suggest" to help figure out why)' error = true end elsif gld.call[type][:task] == 'practice grinding various ingredients with a mortar and pestle' @@ -2212,19 +2491,19 @@ top_off_jars = proc { got_jar = false for item in all_sack_contents.call.find_all { |obj| jar.after_name =~ /containing #{obj.name.sub('some ', '(?:some )?').sub('handful of ', '(?:handful of )?').sub('sprig of ', '(?:sprig of )?').sub('tooth', '(?:teeth|tooth)').sub('leaf', '(?:leaf|leaves)').sub(/y\b/, '(?:y|ie)').split(' ').join('s? ')}/ } unless got_jar - dothis "get ##{jar.id}", /^You remove|^You already have that/ + dothis "get ##{jar.id}", get_regex got_jar = true end result = dothis "_drag ##{item.id} ##{jar.id}", /^You add|is full/ if result =~ /is full/ - dothis "put ##{item.id} in ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ + dothis "put ##{item.id} in ##{alchemy_sack.call.id}", put_regex break else ingredient_count[jar.id] = ingredient_count[jar.id] + 1 unless ingredient_count[jar.id].nil? end end if got_jar - dothis "put ##{jar.id} in ##{alchemy_sack.call.id}", /^You put|^I could not find what you were referring to\./ + dothis "put ##{jar.id} in ##{alchemy_sack.call.id}", put_regex end end fill_hands @@ -2239,17 +2518,19 @@ look_in_jars = proc { throw_away = proc { if room_id = where_is.call('trash').first - trash_items = loot_sack.call.contents.to_a.find_all { |obj| (obj.name =~ /^tincture of (?:acantha|tkaro|wolifrew|basal|ambrominas|ephlox|aloeas|cactacae|bolmara|pothinir|haphip|torban|calamia|sovyn|woth|brostheras)$|silvery potion|^flask of pure water$|^grot t'kel potion$|^spirit shard$|^handful of sea salt$|^some powdered|^some ground/) and (obj.name !~ /#{UserVars.needed_reagents}/) } +# trash_items = loot_sack.call.contents.to_a.find_all { |obj| (obj.name =~ /^tincture of (?:acantha|tkaro|wolifrew|basal|ambrominas|ephlox|aloeas|cactacae|bolmara|pothinir|haphip|torban|calamia|sovyn|woth|brostheras|yabathilium|talneo)$|silvery potion|^flask of pure water$|^grot t'kel potion$|^spirit shard$|^handful of sea salt$|^some powdered|^some ground/) and (obj.name !~ /#{UserVars.needed_reagents}/) } +# trash_items = [ loot_sack.call.contents.to_a + alchemy_sack.call.contents.to_a ].flatten.find_all { |obj| (obj.name =~ /^tincture of (?:acantha|tkaro|wolifrew|basal|ambrominas|ephlox|aloeas|cactacae|bolmara|pothinir|haphip|torban|calamia|sovyn|woth|brostheras|yabathilium|talneo)$|silvery potion|^flask of pure water$|^grot t'kel potion$|^spirit shard$|^handful of sea salt$|^some powdered|^some ground/) and (obj.name !~ /#{UserVars.needed_reagents}/) } + trash_items = [ loot_sack.call.contents.to_a + alchemy_sack.call.contents.to_a ].flatten.find_all { |obj| (obj.name =~ /^tincture of (?:acantha|tkaro|wolifrew|basal|ambrominas|ephlox|aloeas|cactacae|bolmara|pothinir|haphip|torban|calamia|sovyn|woth|brostheras|yabathilium|talneo)$|^flask of pure water$|^spirit shard$|^handful of sea salt$|^some powdered|^some ground/) and (obj.name !~ /#{UserVars.needed_reagents}/) } unless trash_items.empty? start_script 'go2', [ room_id.to_s ] wait_while { running?('go2') } if trash_container = GameObj.loot.find { |obj| obj.noun =~ /^(?:receptacle|bin|barrel|trashcan)$/ } empty_hand for item in trash_items - dothistimeout "get ##{item.id}", 3, /^You remove/ - dothistimeout "put ##{item.id} in ##{trash_container.id}", 3, /^You put|^As you place|^There appears .*? significant value|^Are you crazy\?!\? Do you know what that's worth!\?!/ + dothistimeout "get ##{item.id}", 3, get_regex + dothistimeout "put ##{item.id} in ##{trash_container.id}", 3, put_regex if (GameObj.right_hand.id == item.id) or (GameObj.left_hand.id == item.id) - dothistimeout "put ##{item.id} in ##{lootsack.call.id}", 3, /^You put/ + dothistimeout "put ##{item.id} in ##{lootsack.call.id}", 3, put_regex end end fill_hand @@ -2261,7 +2542,8 @@ throw_away = proc { } sell = proc { - sell_items = loot_sack.call.contents.to_a.find_all { |obj| obj.name =~ /^(?:iron wand)$/ } +# sell_items = loot_sack.call.contents.to_a.find_all { |obj| obj.name =~ /^(?:iron wand|polished bloodwood wand)$/ } + sell_items = loot_sack.call.contents.to_a.find_all { |obj| obj.name =~ /^(?:polished bloodwood wand)$/ } unless sell_items.empty? if room_id = where_is.call('pawnshop').first start_script 'go2', [ room_id.to_s ] @@ -2277,7 +2559,7 @@ sell = proc { echo 'warning: failed to find a pawnshop within max-travel-time' end end - sell_items = loot_sack.call.contents.to_a.find_all { |obj| obj.name =~ /^(?:pale green potion|dark shimmering oil|iridescent opal wand|some dull silvery dust|rohnuru potion|minor mana potion|sarmoc potion|minor mana potion|lesser mana potion|smooth crystalline wand|lesser health potion|glowing blue potion|clear potion|lesser mana regeneration potion|hazy glass vial|silvery potion)$/ or (obj.noun == 'vial' and obj.after_name == 'containing fine white powder') } + sell_items = loot_sack.call.contents.to_a.find_all { |obj| obj.name =~ /^(?:pale green potion|dark shimmering oil|iridescent opal wand|some dull silvery dust|rohnuru potion|minor mana potion|sarmoc potion|minor mana potion|lesser mana potion|smooth crystalline wand|lesser health potion|glowing blue potion|clear potion|lesser mana regeneration potion|hazy glass vial|silvery potion|pale sea\-green potion|lesser mana potion|some pale glimmering dust|scintillating pale blue potion|smooth stone talisman|lesser mana-well potion|prismatic oil|glowing red potion|dark translucent crystal|foggy grey crystal|blue bubbling potion|sky-blue potion|aquamarine potion|shadowy dark crystal wand|greater mana-well potion|greater mana potion|greater mana regeneration potion)$/ or (obj.noun == 'vial' and obj.after_name == 'containing fine white powder') } unless sell_items.empty? if room_id = where_is.call('consignment').first start_script 'go2', [ room_id.to_s ] @@ -2297,8 +2579,9 @@ sell = proc { buy_elusive = proc { unless UserVars.needed_reagents.nil? or UserVars.needed_reagents.empty? - if note = all_sack_contents.call.find { |obj| obj.name == note_name.call } - if room_id = where_is.call('reagent shop').first and (adj_room_id = Room[room_id].wayto.keys.first) and (way = Room[adj_room_id].wayto[room_id.to_s]) and (way.class == String) + if room_id = where_is.call('reagent shop').first and (adj_room_id = Room[room_id].wayto.keys.first) and (way = Room[adj_room_id].wayto[room_id.to_s]) and (way.class == String) + the_note_name = (note_name_from_place.call(Room[room_id].location) || note_name_from_place.call(place) || note_name.call) + if note = all_sack_contents.call.find { |obj| obj.name == the_note_name } start_script 'go2', [ adj_room_id ] wait_while { running?('go2') } move way @@ -2321,7 +2604,7 @@ buy_elusive = proc { unless table_contents.empty? if table_contents.any? { |obj| obj.name =~ /#{UserVars.needed_reagents}/ } empty_hands - dothistimeout "get ##{note.id}", 10, /^You remove|^You already have that\./ + dothistimeout "get ##{note.id}", 10, get_regex for obj in table_contents if obj.name =~ /#{UserVars.needed_reagents}/ unless count[obj.name] @@ -2348,11 +2631,11 @@ buy_elusive = proc { count[obj.name] = count[obj.name].to_i + 1 fput 'unhide' if invisible? fput "buy ##{obj.id}" - dothistimeout "put my #{obj.noun} in ##{alchemy_sack.call.id}", 10, /^You put|^I could not find what you were referring to\./ + dothistimeout "put my #{obj.noun} in ##{alchemy_sack.call.id}", 10, put_regex end end end - dothistimeout "put ##{note.id} in ##{alchemy_sack.call.id}", 10, /^You put|^I could not find what you were referring to\./ + dothistimeout "put ##{note.id} in ##{alchemy_sack.call.id}", 10, put_regex sleep 0.05 top_off_jars.call empty_jar_list = alchemy_sack.call.contents.find_all { |obj| obj.noun =~ /^(?:jar|beaker|bottle)$/ and obj.after_name.nil? } @@ -2363,17 +2646,17 @@ buy_elusive = proc { important_stuff_count = important_stuff_count.sort { |a,b| b[1] <=> a[1] }.collect { |n| n[0] } for empty_jar in empty_jar_list if name = important_stuff_count.pop - dothistimeout "get ##{empty_jar.id}", 10, /^You remove|^You already have that/ + dothistimeout "get ##{empty_jar.id}", 10, get_regex for obj in all_sack_contents.call if obj.name == name result = dothistimeout "_drag ##{obj.id} ##{empty_jar.id}", 10, /^You add|^You put|is full/ if result =~ /is full/ - dothistimeout "put ##{obj.id} in ##{alchemy_sack.call.id}", 10, /^You put|^I could not find what you were referring to\./ + dothistimeout "put ##{obj.id} in ##{alchemy_sack.call.id}", 10, put_regex break end end end - dothistimeout "put ##{empty_jar.id} in ##{alchemy_sack.call.id}", 10, /^You put|^I could not find what you were referring to\./ + dothistimeout "put ##{empty_jar.id} in ##{alchemy_sack.call.id}", 10, put_regex end end end @@ -2384,10 +2667,10 @@ buy_elusive = proc { echo 'error: no table' end else - echo 'error: failed to find a reagent shop' + echo "error: missing #{the_note_name}" end else - echo 'error: you are too poor for alchemy' + echo 'error: failed to find a reagent shop' end end } @@ -2403,9 +2686,25 @@ if script.vars[1].downcase == 'set' elsif (script.vars[2] =~ /^(?:attack\-script|before\-hunt\-script|after\-hunt\-script|before\-forage\-script|after\-forage\-script)$/i) and script.vars[3] CharSettings[script.vars[2].downcase] = script.vars[3] echo 'setting saved' + elsif (script.vars[2].downcase == 'alchemysack') and script.vars[3] + UserVars.alchemysack = script.vars[3..-1].join(' ') + echo 'setting saved' + elsif (script.vars[2].downcase == 'lootsack') and script.vars[3] + UserVars.lootsack = script.vars[3..-1].join(' ') + echo 'setting saved' + elsif (script.vars[2].downcase == 'herbsack') and script.vars[3] + UserVars.herbsack = script.vars[3..-1].join(' ') + echo 'setting saved' else - echo "you're doing it wrong" - end + echo "you're doing it wrong; try #{$clean_lich_char}#{script.name} help" + end +elsif script.vars[1].downcase == 'clear' + if (script.vars[2] =~ /^(?:attack\-script|before\-hunt\-script|after\-hunt\-script|before\-forage\-script|after\-forage\-script)$/i) + CharSettings[script.vars[2].downcase] = nil + echo 'setting cleared' + else + echo "you're doing it wrong; try #{$clean_lich_char}#{script.name} help" + end elsif script.vars[1].downcase == 'add' if (script.vars[2].downcase == 'fav') and (search_string = script.vars[3..-1].join(' ')) matching_recipes = $alchemy_recipes.find_all { |r| r[:spell] == search_string }.collect { |r| r[:product] } @@ -2474,27 +2773,39 @@ elsif script.vars[1].downcase == 'del' end elsif script.vars[1].downcase == 'suggest' output = "\n" - for type in [ 'alchemy', 'potions', 'trinkets' ] + for type in [ 'alchemy' , 'potions', 'trinkets' ] output.concat "\n#{type}:\n" if gld_suggestions.call[type][:recipes].nil? or gld_suggestions.call[type][:recipes].empty? or gld_suggestions.call[type][:reps].zero? output.concat " (none)\n" else max_recipe_name = 0 - gld_suggestions.call[type][:recipes].each { |recipe_name| max_recipe_name = [max_recipe_name,recipe_name.length].max } - for recipe_name in gld_suggestions.call[type][:recipes] - recipe = $alchemy_recipes.find { |r| r[:product] == recipe_name } - output.concat " #{recipe_name.ljust(max_recipe_name)} ranks: #{recipe[:rank][0].to_s.rjust(2)}-#{recipe[:rank][1].to_s.rjust(2)}" - check = check_recipe.call(recipe_name, gld_suggestions.call[type][:reps]) - output.concat " cost: #{check[:cost].to_i.to_s.rjust(5)} time: #{(check[:time]/60.0).as_time}" + recipe_list = gld_suggestions.call[type][:recipes] + recipe_list.each { |r| max_recipe_name = [max_recipe_name,r[:product].length].max } + recipe_output_list = Array.new + for recipe in recipe_list + start = Time.now + check = check_recipe.call(:recipe => recipe, :reps => gld_suggestions.call[type][:reps]) + echo "#{recipe[:product]}: #{Time.now - start}" if $alchemy_debug + if check[:error].empty? + recipe_output = " #{monsterbold_start}#{recipe[:product].ljust(max_recipe_name)}#{monsterbold_end}" + else + recipe_output = " #{recipe[:product].ljust(max_recipe_name)}" + end + recipe_output.concat " ranks: #{recipe[:rank][0].to_s.rjust(2)}-#{recipe[:rank][1].to_s.rjust(2)}" + recipe_output.concat " cost: #{check[:cost].to_i.to_s.rjust(5)} time: #{(check[:time]/60.0).as_time}" has_step = Array.new recipe[:steps].each { |step| if step =~ /^(boil|infuse|simmer|chant|distill|extract|channel)/ and not has_step.include?($1); has_step.push($1); end } - output.concat " includes: #{has_step.join(', ')}" unless has_step.empty? + recipe_output.concat " includes: #{has_step.sort.join(', ')}" unless has_step.empty? + recipe_output.concat "\n" unless check[:error].empty? - missing = check[:error].collect { |a,b| "#{a} (#{b})" } - output.concat " #{monsterbold_start}missing:#{monsterbold_end} #{missing.join(', ')}" + check[:error].each_pair { |thing,count| + recipe_output.concat " #{''.ljust(max_recipe_name)} missing: #{thing} (#{count})\n" + } end - output.concat "\n" + recipe_output_list.push([check[:cost], recipe_output]) end + recipe_output_list.sort { |a,b| a[0] <=> b[0] }.each { |o| output.concat(o[1]) } + recipe_output_list = nil end end output.concat "\n" @@ -2541,7 +2852,7 @@ elsif script.vars[1] =~ /^(check|make|prepare)$/i and not script.vars[2].nil? echo 'no matching recipe' exit end - check_info = check_recipe.call(recipe_name, repetitions) + check_info = check_recipe.call(:name => recipe_name, :reps => repetitions) show_check.call(check_info) if check_info[:error].empty? and not check_only echo 'starting in 3 seconds...' @@ -2593,26 +2904,6 @@ elsif script.vars[1].downcase == 'buy' close_sacks.call elsif script.vars[1].downcase == 'need' set_needed_reagents.call -elsif script.vars[1].downcase == 'test' -# respond gld.call.inspect -# exit - all_reagents = Array.new - $alchemy_recipes.each { |recipe| - recipe[:steps].each { |step| - if step =~ /^(?:add|extract|distill|grind) (.+)$/ - reagent = $1 - all_reagents.push(reagent) unless all_reagents.include?(reagent) - end - } - } - all_reagents.delete_if { |reagent| - elusive_reagent_cost.keys.include?(reagent) or $alchemy_recipes.any? { |recipe| recipe[:product] == reagent } or (grind_recipe = $alchemy_recipes.find { |recipe| recipe[:steps].first == "grind #{reagent}" } and $alchemy_recipes.any? { |recipe| (recipe[:product] == grind_recipe[:product]) and (recipe[:steps].first !~ /^grind/) }) - } - respond all_reagents - exit - results = check_recipe.call('dark translucent crystal', 1) - show_check.call(results) - echo results.inspect elsif script.vars[1].downcase == 'auto' if script.vars[2].downcase =~ /^(alchemy|trinkets|potions)$/ type_list = [ $1 ] @@ -2637,17 +2928,17 @@ elsif script.vars[1].downcase == 'auto' if CharSettings['sell-crap'] sell.call end + if ((silvers = check_silvers.call) > 0) and room_id = where_is.call('bank').first + start_script 'go2', [ room_id.to_s ] + wait_while { running?('go2') } + fput "deposit #{silvers}" + end # fixme: not sure what the real limit is.. $last_alchemy_buy ||= Time.now - 481 if CharSettings['buy-crap'] and (Time.now - $last_alchemy_buy) > 480 buy_elusive.call $last_alchemy_buy = Time.now end - if ((silvers = check_silvers.call) > 0) and room_id = where_is.call('bank').first - start_script 'go2', [ room_id.to_s ] - wait_while { running?('go2') } - fput "deposit #{silvers}" - end sleep 0.5 } elsif script.vars[1].downcase == 'list' @@ -2662,7 +2953,7 @@ elsif script.vars[1].downcase == 'list' output.concat " hide-jar-check: #{fix_option[CharSettings['hide-jar-check']]}\n" output.concat " cast-sanctuary: #{fix_option[CharSettings['cast-sanctuary']]}\n" output.concat " buy-crap: #{fix_option[CharSettings['buy-crap']]}\n" - output.concat " trow-away-crap: #{fix_option[CharSettings['throw-away-crap']]}\n" + output.concat " throw-away-crap: #{fix_option[CharSettings['throw-away-crap']]}\n" output.concat " sell-crap: #{fix_option[CharSettings['sell-crap']]}\n" output.concat " attack-script: #{CharSettings['attack-script']}\n" output.concat " before-hunt-script: #{CharSettings['before-hunt-script']}\n" @@ -2678,70 +2969,114 @@ elsif script.vars[1].downcase == 'list' output.concat "\n" end respond output +elsif script.vars[1].downcase == 'sell' + sell.call else output = "\n" - output.concat "Setup:\n" - output.concat " #{$clean_lich_char}set change alchemysack \n" - output.concat " #{$clean_lich_char}set change lootsack \n" - output.concat " #{$clean_lich_char}set change herbsack \n" + output.concat "setup:\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} set alchemysack Where to put away reagents and alchemy equipment.\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} set lootsack Where to put away end-products and miscellaneous stuff.\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} set herbsack Where to put away herbs.\n" + output.concat "\n" + output.concat " (the script will look for what it needs in all three of the above containers)\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} set cost-per-second <#> Used to convert time into silvers when finding the \n" + output.concat " #{''.rjust(script.name.length) } fastest/cheapest recipe.\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} set max-travel-time <#> Places that go2 thinks is more than # of seconds away\n" + output.concat " #{''.rjust(script.name.length) } from your guild will be assumed to not exist.\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} set max-hunt-time <#> Give up hunting for reagents after # seconds.\n" output.concat "\n" - output.concat " #{$clean_lich_char}#{script.name} set cost-per-second <#>\n" - output.concat " #{$clean_lich_char}#{script.name} set max-travel-time <#>\n" - output.concat " #{$clean_lich_char}#{script.name} set max-hunt-time <#>\n" - output.concat " #{$clean_lich_char}#{script.name} set hide-gld-check \n" - output.concat " #{$clean_lich_char}#{script.name} set hide-bundle-check \n" - output.concat " #{$clean_lich_char}#{script.name} set hide-jar-check \n" - output.concat " #{$clean_lich_char}#{script.name} set cast-sanctuary \n" - output.concat " #{$clean_lich_char}#{script.name} set buy-crap \n" - output.concat " #{$clean_lich_char}#{script.name} set throw-away-crap \n" - output.concat " #{$clean_lich_char}#{script.name} set sell-crap \n" - output.concat " #{$clean_lich_char}#{script.name} set attack-script \n" - output.concat " #{$clean_lich_char}#{script.name} set before-hunt-script \n" - output.concat " #{$clean_lich_char}#{script.name} set after-hunt-script \n" - output.concat " #{$clean_lich_char}#{script.name} set before-forage-script \n" - output.concat " #{$clean_lich_char}#{script.name} set after-forage-script \n" + output.concat " #{$clean_lich_char}#{script.name} set hide-gld-check Hide spam from the script using the gld verb.\n" output.concat "\n" - output.concat " #{$clean_lich_char}#{script.name} add fav \n" - output.concat " #{$clean_lich_char}#{script.name} del fav \n" + output.concat " #{$clean_lich_char}#{script.name} set hide-bundle-check Hide spam from the script measuring bundles.\n" output.concat "\n" - output.concat " #{$clean_lich_char}#{script.name} list\n" + output.concat " #{$clean_lich_char}#{script.name} set hide-jar-check Hide spam from the script measuring jars.\n" output.concat "\n" - output.concat "Usage:\n" - output.concat " #{$clean_lich_char}#{script.name} make \n" + output.concat " #{$clean_lich_char}#{script.name} set cast-sanctuary Cast sanctuary before foraging in a room.\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} set buy-crap Buy things from the alchemist reagent shop (in auto mode).\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} set throw-away-crap Throw away a pre-defined list (incomplete) of alchemy\n" + output.concat " #{''.rjust(script.name.length) } byproducts that can't be sold (in auto mode).\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} set sell-crap Sell alchemy products (in auto mode).\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} set attack-script A script you provide that will kill and loot the\n" + output.concat " #{''.rjust(script.name.length) } monsters whose ids are passed to it.\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} set before-hunt-script A script you provide that will get your hunting\n" + output.concat " #{''.rjust(script.name.length) } gear out (or any other pre-hunt actions)\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} set after-hunt-script A script you provide that will put your gear away\n" + output.concat " #{''.rjust(script.name.length) } (or any other post-hunt actions: make sure you\n" + output.concat " #{''.rjust(script.name.length) } don't sell the reagents it just collected)\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} set before-forage-script A script you provide that does anything you might\n" + output.concat " #{''.rjust(script.name.length) } need before going to to forage\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} set after-forage-script A script you provide that does anything you might\n" + output.concat " #{''.rjust(script.name.length) } need after going to to forage\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} clear -script Clears one of the previous script settings\n" + output.concat "\n" + output.concat "commands:\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} list Show current settings.\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} make Follows the given recipe.\n" output.concat " #{$clean_lich_char}#{script.name} make x\n" output.concat "\n" - output.concat " #{$clean_lich_char}#{script.name} prepare buys, forages, and makes all the requirements, so you\n" - output.concat " #{$clean_lich_char}#{script.name} prepare x can make the recipe later without having to run around\n" + output.concat " #{$clean_lich_char}#{script.name} prepare Buys, forages, and makes all the requirements, so you\n" + output.concat " #{$clean_lich_char}#{script.name} prepare x can make the recipe later without having to run around.\n" output.concat "\n" - output.concat " #{$clean_lich_char}#{script.name} check gives the same summary as make, but does nothing\n" + output.concat " #{$clean_lich_char}#{script.name} check Gives the same summary as make, but does nothing.\n" output.concat " #{$clean_lich_char}#{script.name} check x\n" output.concat "\n" - output.concat " #{$clean_lich_char}#{script.name} suggest attempts to list the recipes you'll get ranks for\n" + output.concat " #{$clean_lich_char}#{script.name} suggest Attempts to list the recipes you'll get ranks for\n" + output.concat " #{''.rjust(script.name.length) } (and one of many possible reasons you can't use it).\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} jar Fills jars in your alchemy sack with loose items of\n" + output.concat " #{''.rjust(script.name.length) } the same type.\n" output.concat "\n" - output.concat " #{$clean_lich_char}#{script.name} jar fills your jars with loose items of the same type\n" + output.concat " #{$clean_lich_char}#{script.name} buy Buys reagents you need from the alchemist reagent shop\n" + output.concat " #{''.rjust(script.name.length) } (up to a max of 20 of each item on you)\n" output.concat "\n" - output.concat " #{$clean_lich_char}#{script.name} buy\n" + output.concat " #{$clean_lich_char}#{script.name} need Puts the names of all reagents you could use to get reps\n" + output.concat " #{''.rjust(script.name.length) } from into a variable that can be accessed by other scripts\n" + output.concat " #{''.rjust(script.name.length) } (in auto mode, this command is done for you). loot-be-gone\n" + output.concat " #{''.rjust(script.name.length) } uses this to automatically avoid selling things you need.\n" output.concat "\n" - output.concat " #{$clean_lich_char}#{script.name} need\n" + output.concat " #{$clean_lich_char}#{script.name} add fav The reagents for the given recipe will be included in the\n" + output.concat " #{''.rjust(script.name.length) } above \"need\" variable even if you can't get reps from it.\n" output.concat "\n" - output.concat " #{$clean_lich_char}#{script.name} task alchemy\n" - output.concat " #{$clean_lich_char}#{script.name} task potions\n" - output.concat " #{$clean_lich_char}#{script.name} task trinkets\n" + output.concat " #{$clean_lich_char}#{script.name} del fav Undo the above commanmd.\n" output.concat "\n" - output.concat " #{$clean_lich_char}#{script.name} task distill\n" - output.concat " #{$clean_lich_char}#{script.name} task assembly\n" - output.concat " #{$clean_lich_char}#{script.name} task grind\n" - output.concat " #{$clean_lich_char}#{script.name} task grind-mine\n" - output.concat " #{$clean_lich_char}#{script.name} task crucible\n" - output.concat " #{$clean_lich_char}#{script.name} task sweep\n" + output.concat " #{$clean_lich_char}#{script.name} task alchemy Attempt to complete one task in general alchemy.\n" output.concat "\n" - output.concat " #{$clean_lich_char}#{script.name} auto gain ranks afk (somewhat buggy)\n" - output.concat " #{$clean_lich_char}#{script.name} auto only work on the given area\n" + output.concat " #{$clean_lich_char}#{script.name} task potions Attempt to complete one task in potions.\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} task trinkets Attempt to complete one task in trinkets.\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} task distill Does the \"distill water for the guild's supply\" task.\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} task assembly Does the \"polish tarnished lens assemblies\" task.\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} task grind Does the \"grind some ingredients for the guild's supply\" task.\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} task grind-mine Does the \"grinding various ingredients\" task.\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} task crucible Does the \"clean alchemic equipment\" task.\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} task sweep Does the \"sweep the alchemy labs\" task.\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} auto Attempts to do everything until you master.\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} auto Only work on the given area(s).\n" output.concat "\n" respond output end - -=begin - The surface of the solution in the iron cauldron shimmers in response! - The diamond lens shatters! -=end diff --git a/answers.lic b/answers.lic index 5e7c45c..9fa074b 100644 --- a/answers.lic +++ b/answers.lic @@ -2,7 +2,9 @@ This script answers all your questions. - tillmen@lichproject.org + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: jail, hooligan =end diff --git a/autoforage.lic b/autoforage.lic index 69d2c9d..81a5234 100644 --- a/autoforage.lic +++ b/autoforage.lic @@ -1,219 +1,193 @@ -=begin - - This script runs around foraging for herbs until you have a herbsack with 50 bites of each herb - - tillmen@lichproject.org - -=end - -unless defined?(Map.dijkstra) and defined?(dothis) - echo 'Your version of Lich is too old for this script.' - exit -end - -unless Lich.herbsack - echo 'No herbsack has been set. Use ;settings change herbsack ' - exit -end - -unless Lich.lootsack - echo 'No lootsack has been set. Use ;settings change lootsack ' - exit -end - -herb_rooms = { - 'acantha leaf' => [ 6090, 10297, 10269, 10292, 10295, 10296, 6095, 6094, 10170, 10169, 10168, 10167, 284, 290, 291, 10271, 6526, 10282, 10286, 10283, 10284, 10285, 3263, 3262, 3261, 3260, 3253, 10195, 10196, 10198, 10197, 10189, 10183, 10200, 10201, 10184, 10202, 10209, 10236, 10234, 10235, 10233, 10218, 10219, 10220, 10221, 10222, 14035, 14042, 377, 14041, 256, 5831, 5023, 5026, 4612, 4990, 4991, 4992, 312, 4993, 311, 310, 300, 299, 298, 296, 3741, 288, 1298, 1299, 10877, 10876, 10875, 10874, 10866, 10869, 10864, 9244, 9243, 225, 224, 14047, 14048, 10854, 10852, 10856, 10857, 10842, 9624, 9625, 9622, 9627, 9628, 11022, 11021, 11020, 11018, 11006, 11023, 11024, 11025, 10463, 10461, 11028, 11029, 11030, 11032, 673, 10453, 10452, 10450, 10443, 10444, 10445, 10446, 10885, 10449, 10886, 10448, 10884, 10447, 10883, 10882, 10878, 10873, 6002, 6001, 6000, 5999, 6003, 6004, 6010, 5992, 5993, 5991, 5990, 1820, 5975, 10478, 5973, 5968, 5967, 5963, 10479, 5964, 5962, 5961, 5470, 5469, 5468, 5467, 5956, 5466, 5465, 6083, 6074, 6078, 6079, 6075, 6077, 6076, 6024, 6023, 10489, 6022, 1697, 6026, 6012, 10486, 10485, 6042, 6059, 6060, 6061, 6062, 6063, 5099, 6044, 6045, 6046, 6048, 6058, 6055, 6054, 6047, 6049, 6057, 6032, 6040, 6039, 6033, 6034, 6038, 6035, 6037, 6036, 9890, 9887, 9886, 9885, 9884, 56, 12087, 12086, 11961, 11960, 11959, 11958, 11962, 11963, 11965, 7210, 7209, 7208, 547, 9140, 9143, 1714, 1713, 8580, 8579, 8578, 8577, 8576, 7281, 8575, 7282, 7157, 7277, 7276, 7275, 7274, 7199, 7198, 7188, 7261, 7255, 3564, 3831, 3565, 3566, 3567, 3568, 3569, 1280, 7251, 7203, 7202, 7201, 7197, 7185, 3571, 3570, 3574, 4135, 4134, 7016, 7948, 7944, 7945, 7946, 7947, 7939, 7942, 7943, 7941, 8306, 8296, 8311, 8302, 8324, 8295, 8298, 8300, 8288, 8290, 7929, 7927, 7930, 7928, 3759, 7966, 8280, 8278, 8277, 8276, 7996, 8320, 222, 410, 6909, 6888, 6772, 6773, 6774, 6775, 6779, 6798, 8317, 8316, 8315, 8314, 8312, 8318, 7924, 7923, 7922, 439, 13037, 13036, 13035, 13034, 13033, 221, 411, 447, 448, 450, 13038, 452, 4300, 463, 6744, 6756, 6755, 6754, 6753, 6762, 6763, 6764, 6767, 6768, 6765, 6766, 6769, 6282, 6275, 6266, 6263, 6262, 427, 426, 424, 213, 6960, 12058, 12059, 12060, 416, 6319, 6317, 6318, 415, 417, 418, 7998, 9700, 9701, 10139, 10256, 10253, 10254, 10230, 10229, 10261, 10257, 10258, 10259, 10255, 3891, 3892, 6091, 6092, 6093, 10291, 10290, 10289, 6100, 6098, 10293, 10294, 6510, 6511, 6512, 10165, 10164, 10163, 10162, 11314, 229, 228, 285, 295, 292, 10272, 10273, 10274, 10275, 10278, 10276, 10277, 10281, 10279, 10280, 1368, 1369, 1412, 1411, 12384, 10194, 10193, 10192, 10190, 10191, 12379, 10199, 227, 276, 10203, 10205, 10207, 10214, 10212, 10210, 10208, 10215, 10213, 10211, 10217, 10225, 10224, 10227, 10223, 10216, 10232, 10231, 10226, 10228, 14046, 14045, 14044, 13983, 13980, 254, 316, 313, 258, 3890, 314, 315, 309, 308, 305, 304, 303, 301, 9256, 223, 10870, 10861, 10853, 14049, 13997, 13991, 294, 13990, 13989, 13988, 13998, 293, 10840, 10849, 10848, 10847, 10838, 10844, 10845, 9629, 1188, 9621, 1235, 1234, 1233, 1232, 10394, 11007, 10460, 10462, 10459, 10457, 10458, 10456, 11033, 10454, 10455, 10442, 10441, 10451, 6005, 6006, 6008, 6009, 5995, 5996, 5997, 5998, 5994, 86, 9830, 9831, 5988, 5989, 5987, 5986, 5985, 1831, 1832, 1833, 1834, 1835, 5060, 5965, 5476, 5966, 5969, 5474, 5058, 5972, 5473, 5971, 5970, 5472, 5958, 5959, 5960, 5957, 5053, 5052, 6084, 6085, 6086, 6089, 6088, 6087, 6073, 6082, 6081, 6080, 6041, 10488, 6020, 6013, 4268, 1701, 4267, 6069, 6068, 6072, 6070, 6071, 6067, 6066, 6065, 6064, 6043, 10493, 6052, 6053, 6050, 6051, 6030, 6029, 6028, 6027, 6031, 49, 50, 51, 52, 53, 54, 55, 9888, 9889, 9891, 12076, 12079, 12078, 12077, 12082, 12083, 12084, 11964, 11957, 11956, 11955, 11966, 11967, 7248, 7250, 7249, 7207, 7287, 7286, 7285, 7284, 7283, 7278, 7279, 7280, 7161, 7162, 7156, 1287, 1286, 1285, 1284, 7196, 1282, 1281, 7191, 7193, 7194, 7190, 7189, 7186, 7187, 3562, 3563, 7155, 475, 1277, 8431, 1278, 7266, 1279, 7267, 7270, 7252, 3572, 3573, 7184, 8496, 7170, 8495, 7171, 7169, 7165, 10791, 4139, 4138, 8319, 8310, 8308, 8304, 7937, 7940, 7938, 7933, 7934, 7935, 7932, 7931, 8292, 8293, 8286, 8284, 8322, 8323, 8321, 8283, 8282, 8281, 3607, 3606, 3605, 3603, 3602, 3601, 4259, 6778, 6780, 6783, 6781, 6782, 6785, 6784, 464, 442, 443, 444, 445, 438, 432, 430, 433, 434, 454, 455, 6749, 6750, 6751, 456, 6752, 6745, 6746, 6747, 6748, 6776, 6777, 3769, 6723, 6725, 6722, 6284, 6267, 6265, 6269, 6261, 12051, 12056, 12057, 214, 215, 216, 217, 218, 419, 220, 6315, 6314, 12067, 12073, 12074, 12075, 420, 435, 436, 437, 441, 421, 422, 429, 431, 4816, 564, 10260, 10238, 10239, 562, 2010, 2008, 2007, 2006, 2003, 2001, 1999, 1998, 1997, 1995, 12533, 1967, 12385, 12566, 12568, 2005, 2004, 2021, 2009, 12569, 12570, 2000, 2002, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 12586, 12585, 2056, 2057, 2058, 2059, 2060, 2066, 2067, 2071, 2072, 2074, 2073, 12652, 2076, 2075, 2083, 2082, 2081, 2080, 2079, 2078, 2077, 12638, 2084, 2053, 2085, 2086, 2087, 2088, 2089, 2091, 2093, 2100, 2102 ], - 'ambrominas leaf' => [ 10297, 10269, 10292, 10295, 10296, 6095, 6530, 6531, 10172, 10171, 10177, 10178, 10179, 10180, 10181, 10182, 10195, 10196, 10198, 10197, 10189, 10183, 10200, 10201, 10184, 10209, 10236, 10234, 10235, 10233, 10866, 10869, 10864, 9626, 10463, 11027, 10461, 11028, 11029, 11030, 10453, 10452, 10450, 10443, 10444, 10445, 10446, 10449, 10448, 10447, 6002, 6001, 6000, 5999, 6003, 6004, 5676, 5980, 5981, 5992, 5993, 5979, 5982, 5991, 5990, 5975, 10478, 5973, 5968, 5967, 5963, 10479, 5964, 5962, 5961, 1414, 1413, 5956, 5466, 5465, 6083, 6074, 6078, 6079, 6075, 6077, 6076, 6060, 6061, 6062, 6063, 6045, 6046, 6048, 6058, 6055, 6054, 6047, 6049, 6057, 42, 6032, 6040, 6039, 6033, 6038, 6035, 6037, 6036, 6380, 6382, 6383, 1634, 1293, 8542, 8580, 8579, 8578, 8577, 8576, 8575, 539, 540, 4134, 7944, 7945, 7946, 7947, 7939, 7942, 7943, 7941, 8296, 8311, 8302, 8324, 8295, 8298, 8300, 8288, 7929, 7927, 7930, 7996, 8320, 410, 3770, 6773, 6774, 6775, 6788, 6790, 6794, 6791, 6796, 6795, 8316, 8315, 8312, 8318, 447, 449, 452, 453, 6766, 6769, 423, 6960, 12058, 4201, 10261, 10257, 3892, 6091, 6092, 6093, 10291, 10290, 10289, 6100, 6098, 10293, 10294, 11314, 10176, 10175, 10174, 10173, 10194, 10193, 10192, 10190, 10191, 10185, 10186, 10187, 10188, 10199, 10214, 10212, 10210, 1372, 10208, 1373, 10215, 10213, 1374, 10211, 13983, 9926, 1219, 10871, 10870, 10460, 10462, 10459, 10457, 10458, 10456, 10454, 10455, 10442, 10441, 10451, 6005, 5254, 6006, 6007, 6008, 6009, 5995, 5996, 5997, 5998, 11864, 5994, 11860, 11863, 11859, 11862, 11858, 5978, 5495, 5983, 5988, 5989, 5977, 5984, 5987, 5986, 5985, 5976, 5965, 5966, 5969, 5972, 5066, 5971, 5970, 5958, 5071, 5959, 5960, 5957, 6084, 6085, 6086, 6089, 6088, 6087, 6073, 6082, 6081, 6080, 1652, 6069, 6068, 6072, 6070, 6071, 6067, 6066, 6065, 6064, 10493, 6052, 6053, 6050, 6051, 6030, 6029, 6028, 6027, 6031, 49, 50, 51, 52, 53, 12077, 12082, 2115, 5063, 11967, 5062, 5061, 8319, 8310, 8308, 8304, 7937, 7940, 7938, 7933, 7934, 7935, 7932, 7931, 8293, 8286, 8284, 8323, 8283, 6792, 6780, 6783, 6781, 6782, 6784, 6787, 6786, 6789, 442, 443, 444, 445, 4341, 8038, 8039, 8040, 12056, 12057, 12073, 12074, 12075, 436, 437, 441, 4200, 10238, 10239, 12586, 12585, 2056, 2057, 2058, 2059, 2060 ], - 'cactacae spine' => [ 10265, 318, 10125, 188, 376, 4086, 288, 8689, 10867, 5358, 5359, 5331, 10375, 10063, 10484, 10482, 6011, 5074, 5075, 5077, 5078, 5080, 5081, 3495, 5119, 5118, 5117, 10483, 8508, 8509, 8279, 6258, 12052, 13343, 13346, 13347, 13344, 13345, 10244, 10247, 10243, 10249, 10250, 10251, 10252, 10262, 10263, 10264, 13325, 380, 379, 675, 10861, 10863, 10841, 10373, 10374, 5327, 10457, 5072, 5073, 5049, 5048, 5124, 5123, 5122, 5121, 5120, 8461, 446, 12053, 10237, 10246, 10245, 10240, 10241, 10242, 10248, 10267, 10266, 12567 ], - 'aloeas stem' => [ 1358, 3263, 3262, 3261, 3260, 3253, 5295, 11006, 11023, 11024, 11025, 11032, 1826, 1825, 1824, 1823, 1822, 1821, 7210, 7209, 7208, 8536, 7281, 7282, 7275, 7200, 7199, 7198, 7188, 7261, 7263, 7203, 7204, 7205, 7202, 7201, 7185, 7936, 7928, 3759, 3758, 3608, 4347, 440, 4300, 6282, 6275, 6266, 6263, 6262, 6961, 12046, 12065, 12064, 1356, 1357, 10838, 11007, 11033, 10092, 10093, 7248, 7250, 7249, 7207, 7296, 7297, 7287, 7286, 7285, 7284, 7283, 7278, 7279, 7280, 1283, 7196, 7191, 7193, 7194, 7190, 7189, 7186, 7187, 7266, 7270, 7184, 7170, 7171, 7169, 7165, 4138, 7288, 7289, 7290, 7291, 7292, 7293, 7294, 7295, 6265, 6269, 12070, 12071, 12072, 10126, 2061, 2062 ], - 'haphip root' => [ 10265, 9722, 6090, 574, 570, 569, 568, 6094, 566, 10170, 10169, 10168, 10167, 318, 10125, 3727, 10271, 10282, 10286, 10283, 10284, 10285, 10204, 10206, 10218, 10219, 10220, 10221, 10222, 5831, 5023, 5026, 5027, 4612, 4990, 4991, 4992, 4993, 5002, 5000, 5013, 5014, 5012, 5015, 5005, 5004, 5006, 288, 5011, 8692, 8693, 8689, 8690, 8691, 9931, 10375, 5455, 5451, 3495, 6034, 56, 12086, 11960, 11963, 1633, 1635, 1636, 7157, 7255, 3564, 3565, 3566, 3569, 1280, 8280, 8277, 222, 6258, 6772, 6779, 7924, 7923, 7922, 13037, 13036, 13035, 13034, 13033, 13038, 6762, 6763, 6764, 6767, 6768, 6765, 416, 6319, 6317, 6318, 9700, 9701, 9729, 9728, 10256, 9725, 10253, 9726, 10254, 10230, 9712, 10229, 10258, 10259, 10255, 9719, 9718, 9717, 9727, 591, 590, 10244, 10247, 10243, 580, 10249, 579, 10250, 10251, 10252, 10262, 10263, 10264, 587, 589, 573, 585, 583, 577, 10165, 10164, 10163, 10162, 10272, 10273, 10274, 10275, 10278, 10276, 10277, 10281, 10279, 10280, 10217, 10225, 10224, 10227, 10223, 10216, 10232, 10231, 10226, 10228, 4994, 4995, 4996, 4998, 4999, 5001, 9929, 5003, 5007, 5008, 5010, 9961, 9960, 9959, 10373, 10374, 86, 9830, 4268, 4267, 55, 11966, 11967, 7161, 7162, 7156, 1287, 1286, 1285, 1284, 1282, 1281, 3563, 7155, 475, 1277, 8431, 1278, 1279, 7267, 3572, 8282, 8281, 3605, 3600, 6778, 4214, 454, 6776, 6777, 216, 6315, 6314, 435, 4816, 564, 9704, 10126, 9713, 9714, 9716, 9715, 9721, 9720, 10260, 9711, 10237, 9710, 9709, 9708, 10246, 10245, 10240, 10241, 10242, 10248, 625, 561, 560, 559, 10267, 9724, 10266, 9723, 2010, 2008, 2007, 2006, 2003, 2001, 1999, 1998, 12379, 12566, 12567, 12568, 2005, 2004, 2021, 2009, 12569, 12570, 2000, 2002, 2022, 2023, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2082, 2081, 2079, 2078, 2077, 2090 ], - 'pothinir grass' => [ 1269, 1095, 9953, 16272, 16273, 16274, 16275, 9895, 5152, 5153, 5154, 5156, 5157, 5159, 5160, 5161, 8580, 8579, 8578, 8577, 8576, 8575, 7258, 7257, 7259, 7256, 3624, 3564, 3826, 3831, 3565, 3566, 3569, 3571, 3570, 3574, 4196, 6291, 6292, 6290, 6296, 6289, 6288, 8187, 4202, 5784, 5789, 5788, 3890, 1221, 1220, 1101, 9976, 16279, 16256, 16280, 16270, 16271, 5287, 1222, 1223, 5148, 5149, 2180, 3562, 3825, 3563, 7269, 7264, 7271, 3572, 3573, 3600, 6287, 6286, 6277, 6278, 5812, 5810, 5792, 5791, 5790, 5783, 5782, 12578, 12577, 12576, 12575, 2017, 2016, 2015, 2014, 2012, 2011, 2010, 2008, 2007, 2006, 2003, 2001, 1999, 1998, 14798, 12568, 2005, 2004, 2021, 2009, 12569, 12570, 2000, 2002, 2022, 2023, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2013, 2018, 2019, 2020, 12579, 12580, 12581, 2066, 2067, 2072, 2074, 2073, 2076, 2075, 2083, 2082, 2081, 2080, 2079, 2078, 2077, 12638, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2093, 2102 ], - 'basal moss' => [ 6090, 6094, 10170, 10169, 10168, 10167, 10271, 10282, 10286, 10283, 10284, 10285, 10218, 10219, 10220, 10221, 10222, 5831, 5026, 5027, 4612, 4990, 4991, 4992, 4993, 5015, 5006, 5322, 1142, 10856, 10857, 10886, 5261, 5262, 5455, 4269, 5116, 5115, 5099, 6034, 56, 12086, 11961, 11960, 11959, 11958, 11962, 11963, 11965, 6823, 222, 4215, 13037, 13036, 13035, 13034, 13033, 13038, 463, 6319, 6317, 6318, 10256, 10253, 10254, 10230, 10229, 10258, 10259, 10255, 10165, 10164, 10163, 10162, 10272, 10273, 10274, 10275, 10278, 10276, 10277, 10281, 10279, 10280, 12379, 10217, 10225, 10224, 10227, 10223, 10216, 10232, 10231, 10226, 10228, 4994, 4995, 4996, 4998, 4999, 151, 5007, 5008, 1143, 11026, 5249, 5252, 5253, 5674, 86, 9830, 9831, 4268, 4267, 4270, 4271, 5109, 5100, 54, 55, 12083, 11964, 11957, 11956, 11955, 11954, 11966, 7161, 7162, 1282, 7155, 475, 1277, 8431, 1278, 1279, 3603, 3602, 3601, 4214, 454, 456, 12054, 12067, 435, 564, 10260 ], - 'ephlox moss' => [ 5293, 1136, 1135, 1123, 5290, 5292, 5638, 1822, 1821, 1820, 1713, 7281, 7282, 7277, 4135, 448, 427, 426, 424, 213, 5639, 5288, 5289, 10090, 10091, 10092, 10093, 1831, 1832, 1833, 1834, 1835, 7287, 7286, 7285, 7284, 7283, 7278, 7279, 7280, 8476, 8496, 8495, 4139, 4138, 3603, 3602, 3601, 432, 430, 433, 434, 6261, 214, 215, 217, 218, 421, 422, 429, 431 ], - 'calamia fruit' => [ 10265, 6090, 6094, 10170, 10169, 10168, 10167, 318, 233, 289, 290, 232, 291, 10125, 10271, 188, 10282, 10286, 10283, 10284, 10285, 10204, 10206, 10202, 9337, 10218, 10219, 10220, 10221, 10222, 14035, 376, 256, 5831, 5026, 5027, 4086, 4085, 312, 311, 310, 300, 299, 298, 296, 3741, 288, 361, 1142, 8692, 8693, 8689, 225, 224, 286, 14047, 14048, 10854, 10852, 10856, 14033, 14034, 1157, 10375, 11022, 11021, 11020, 11019, 11042, 11043, 89, 5261, 6010, 5262, 5480, 3495, 6024, 6023, 10489, 6022, 4292, 4269, 4293, 4294, 4295, 6026, 6012, 10486, 10485, 6042, 6059, 6044, 6034, 12087, 12086, 11961, 11960, 11959, 11958, 11962, 11963, 11965, 547, 548, 550, 1636, 7157, 7199, 7198, 7261, 7255, 3564, 3565, 3567, 3569, 1280, 7203, 7202, 3571, 3570, 3574, 7948, 8306, 8290, 7928, 3759, 8280, 8279, 8278, 8277, 222, 6258, 6772, 6779, 6798, 8317, 8314, 7924, 7923, 7922, 439, 13037, 13036, 13035, 13034, 13033, 221, 411, 13038, 463, 6744, 6756, 6755, 6754, 6753, 6762, 6763, 6764, 6767, 6768, 6765, 12052, 12065, 12064, 416, 6319, 6317, 6318, 415, 417, 418, 8187, 9700, 9701, 10256, 10253, 10254, 10230, 10229, 10258, 10259, 10255, 10244, 10247, 10243, 10249, 10250, 10251, 10252, 10262, 10263, 10264, 10165, 10164, 10163, 10162, 11314, 1356, 1357, 231, 228, 292, 10272, 10273, 10274, 10275, 10278, 10276, 10277, 10281, 10279, 10280, 1369, 1410, 276, 10203, 10205, 10207, 9336, 10217, 10225, 10224, 10227, 10223, 10216, 10232, 10231, 10226, 10228, 14046, 14045, 14044, 14043, 234, 254, 316, 313, 380, 379, 4999, 3890, 5001, 314, 315, 309, 308, 305, 304, 303, 301, 1221, 223, 10861, 10863, 10853, 14049, 14050, 13997, 13991, 294, 13990, 13998, 13999, 14001, 293, 10840, 1143, 10373, 10374, 11035, 11036, 11037, 11038, 11039, 11040, 11041, 5249, 5252, 5253, 88, 87, 6041, 10488, 6020, 6013, 4296, 4268, 4267, 4270, 4271, 4297, 4272, 4273, 4274, 4298, 6043, 54, 55, 62, 12079, 12078, 12083, 12084, 11964, 11966, 11951, 11950, 1653, 7161, 7162, 7156, 1287, 1286, 1285, 1284, 1282, 1281, 3563, 7155, 475, 1277, 8431, 1278, 7266, 1279, 7267, 7270, 3573, 8292, 8322, 8321, 8282, 8281, 3607, 3606, 3605, 3600, 6778, 6785, 438, 4197, 454, 455, 6749, 6750, 6751, 456, 457, 6752, 6745, 6746, 6747, 6748, 6776, 6777, 3769, 6284, 6267, 12053, 216, 419, 220, 6315, 6314, 12067, 420, 435, 4816, 9704, 9705, 10126, 10260, 10237, 10246, 10245, 10240, 10241, 10242, 10248, 562, 625, 561, 560, 10267, 10266, 2010, 2008, 2007, 2006, 2003, 2001, 1999, 1998, 1997, 1995, 1967, 12379, 12384, 12385, 12566, 12567, 12568, 2005, 2004, 2021, 2009, 12569, 12570, 2000, 2002, 2022, 2023, 2024, 2025, 2026, 2027, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2066, 2067, 2071, 2072, 2074, 2073, 2076, 2075, 2083, 2082, 2081, 2080, 2079, 2078, 2077, 12638, 2084, 2053, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2093, 2100, 2102 ], - 'sovyn clove' => [ 10265, 10297, 10269, 10292, 10295, 10296, 6095, 318, 284, 289, 290, 291, 10125, 188, 10195, 10196, 10198, 10197, 10189, 10183, 10200, 10201, 10184, 259, 260, 273, 10209, 10236, 10234, 10235, 10233, 319, 14042, 14041, 14039, 238, 312, 311, 310, 300, 299, 298, 296, 3741, 288, 8692, 8693, 8689, 8690, 8691, 10866, 10869, 10864, 225, 224, 14048, 10854, 10852, 14034, 5017, 5019, 10375, 10463, 11027, 10461, 11028, 11029, 11030, 11031, 10453, 10452, 10450, 10443, 10444, 10445, 10446, 10449, 10448, 10447, 10878, 6002, 6001, 6000, 5999, 6003, 6004, 6010, 5992, 5993, 5991, 5990, 5975, 10478, 5973, 5968, 5967, 5963, 10479, 5964, 5962, 5961, 5469, 5468, 5467, 5956, 5466, 5083, 6083, 3495, 6074, 6078, 6079, 6075, 6077, 6076, 6024, 6023, 10489, 6022, 6026, 6012, 10486, 10485, 6042, 6059, 6060, 6061, 6062, 6063, 6044, 6045, 6046, 6048, 6058, 6055, 6054, 6047, 6049, 6057, 6032, 6040, 6039, 6033, 6038, 6035, 6037, 6036, 59, 11968, 470, 471, 472, 4134, 7948, 7944, 7945, 7946, 7947, 7939, 7942, 7943, 7941, 8306, 8296, 8311, 8302, 8324, 8295, 8298, 8300, 8288, 8290, 7929, 7927, 7930, 8278, 7996, 8320, 410, 6258, 4252, 4253, 6773, 6774, 6775, 8151, 6798, 8317, 8316, 8315, 8314, 8312, 8318, 439, 221, 411, 447, 452, 6766, 6769, 6960, 12061, 12058, 12062, 415, 417, 418, 10261, 10257, 10244, 10247, 10243, 10249, 10250, 10251, 10252, 3892, 10262, 10263, 10264, 6091, 6092, 6093, 10291, 10290, 10289, 6100, 6098, 10293, 10294, 231, 230, 229, 228, 285, 295, 292, 1412, 10194, 10193, 10192, 10190, 10191, 10199, 276, 10214, 10212, 10210, 10208, 1373, 10215, 10213, 1374, 10211, 275, 324, 239, 14043, 13983, 254, 316, 313, 314, 315, 309, 308, 305, 304, 303, 301, 223, 10870, 10861, 10863, 10853, 14049, 14050, 13997, 13991, 294, 13990, 13989, 13988, 13998, 293, 10840, 9978, 10373, 10374, 5323, 5324, 10460, 10462, 10459, 10457, 10458, 10456, 10454, 10455, 10442, 10441, 10451, 6005, 6006, 6008, 6009, 5995, 5996, 5997, 5998, 5994, 5988, 5989, 5987, 5986, 5985, 5060, 5965, 5059, 5966, 5969, 5058, 5972, 5066, 5971, 5970, 5958, 5071, 5959, 5960, 5957, 5053, 5052, 6084, 6085, 6086, 6089, 6088, 6087, 6073, 6082, 6081, 6080, 6041, 10488, 6020, 6013, 6069, 6068, 6072, 6070, 6071, 6067, 6066, 6065, 6064, 6043, 10493, 6052, 6053, 6050, 6051, 6030, 6029, 6028, 6027, 6031, 49, 50, 51, 52, 12077, 12082, 5063, 11967, 5062, 5061, 8435, 8319, 8310, 8308, 8304, 7937, 7940, 7938, 7933, 7934, 7935, 7932, 7931, 8292, 8293, 8286, 8284, 8322, 8323, 8321, 8283, 3607, 3606, 6780, 6783, 6781, 6782, 6784, 442, 443, 444, 445, 438, 412, 413, 4199, 4198, 4197, 3769, 6284, 6267, 12055, 12056, 12057, 419, 220, 12073, 12074, 12075, 420, 436, 437, 441, 10237, 10238, 10239, 10246, 10245, 10240, 10241, 10242, 10248, 10267, 10266, 1997, 1995, 1967, 12384, 12385, 12567, 12586, 12585, 2056, 2057, 2058, 2059, 2060, 2053 ], - 'wolifrew lichen' => [ 3263, 3262, 3261, 3260, 3253, 8554, 1319, 1320, 1820, 7231, 7228, 7230, 7227, 7226, 7225, 7229, 9079, 9080, 9081, 9082, 9085, 9088, 9092, 9091, 9089, 9090, 7224, 7214, 7246, 7247, 7212, 7213, 7211, 7210, 7209, 7208, 1713, 7277, 7276, 7275, 7188, 7260, 7201, 7197, 7185, 4135, 8073, 448, 450, 4318, 4321, 6282, 6275, 6274, 6272, 6273, 6266, 6263, 6262, 427, 426, 424, 213, 5822, 5821, 5820, 5819, 5818, 5807, 5806, 5797, 5805, 5804, 5803, 5801, 5800, 5799, 4855, 1370, 1371, 8570, 1104, 1103, 11084, 11085, 10090, 1831, 1832, 1833, 1834, 1835, 1819, 1818, 55, 7233, 7234, 7232, 7774, 9076, 9077, 9083, 9075, 7221, 7220, 7219, 7218, 7217, 7216, 7222, 7215, 7223, 9087, 9084, 9086, 9071, 9072, 7248, 7250, 7249, 7207, 7196, 7191, 7193, 7194, 7190, 7189, 7186, 7187, 7184, 8496, 7170, 8495, 7171, 7169, 7165, 4139, 4138, 7959, 7956, 7957, 7958, 7955, 7953, 7951, 7954, 7952, 3603, 3602, 3601, 7964, 7963, 7962, 7960, 7961, 432, 430, 433, 434, 1258, 1257, 1256, 4319, 6723, 6725, 6722, 6265, 6269, 6283, 6261, 6276, 6279, 6281, 6280, 214, 215, 217, 218, 421, 422, 429, 431, 5817, 5816, 5815, 5814, 5813, 5809, 5808, 5798, 5796, 5795, 5794, 5793 ], - 'woth flower' => [ 16275, 7157, 7255, 3564, 3565, 3566, 3569, 1280, 3571, 3570, 3574, 7924, 7156, 1287, 1286, 1285, 1284, 1281, 3563, 7267, 3572, 3573, 2010, 2008, 2007, 2006, 2003, 2001, 1999, 1998, 12568, 2005, 2004, 2021, 2009, 12569, 12570, 2000, 2002, 2022, 2023, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2082, 2081, 2079, 2078, 2077 ], - 'torban leaf' => [ 6090, 6094, 10170, 10169, 10168, 10167, 10271, 10282, 10286, 10283, 10284, 10285, 1407, 10218, 10219, 10220, 10221, 10222, 5831, 5023, 5026, 5027, 4612, 4990, 4991, 4992, 4993, 5002, 5000, 5013, 5014, 5012, 5015, 5005, 5004, 5006, 5011, 10877, 10876, 10875, 10874, 10856, 10857, 9931, 11022, 11021, 11020, 11019, 11018, 11014, 10873, 5455, 4292, 4269, 4293, 4294, 4295, 6034, 9887, 9886, 9885, 9884, 11965, 546, 547, 548, 549, 550, 1633, 8280, 8277, 222, 6772, 6779, 460, 459, 7923, 7922, 13037, 13036, 13035, 13034, 13033, 13038, 463, 6762, 6763, 6764, 6767, 6768, 6765, 416, 6319, 6317, 6318, 9700, 9701, 10256, 10253, 10254, 10230, 10229, 10258, 10259, 10255, 10165, 10164, 10163, 10162, 11314, 10272, 10273, 10274, 10275, 10278, 10276, 10277, 10281, 10279, 10280, 12379, 10217, 10225, 10224, 10227, 10223, 10216, 10232, 10231, 10226, 10228, 4994, 4995, 4996, 4998, 4999, 5001, 9929, 5003, 5007, 5008, 5010, 9961, 9960, 9959, 11012, 11013, 11026, 5249, 86, 9830, 4296, 4268, 4267, 4270, 4271, 4297, 4273, 4274, 4298, 9888, 9889, 9891, 11955, 11966, 7161, 7162, 1282, 7155, 475, 1277, 8431, 1278, 8282, 8281, 3605, 4223, 4222, 6778, 4264, 454, 456, 457, 6776, 6777, 12054, 216, 6315, 6314, 435, 4816, 9704, 10260, 625, 12566 ] -} - -# -# list of herbs that will be foraged for -# -herb_list = [ 'haphip root', 'pothinir grass', 'ephlox moss', 'calamia fruit', 'sovyn clove', 'wolifrew lichen', 'woth flower', 'torban leaf', 'acantha leaf', 'ambrominas leaf', 'cactacae spine', 'basal moss', 'aloeas stem' ] - -# -# where to go when done foraging -# -# done_goto = 'Upper Dragonsclaw, Boulder' -done_goto = Room.current.id.to_s - -# -# returns the room closest to you -# -find_nearest = proc { |target_list| - start_room = Room.current - least_time = nil - least_target = nil - previous, shortest_distances = Map.dijkstra(start_room.id) - for target in target_list - if start_room.id == target - least_target = target - least_time = 0 - break - end - est_time = shortest_distances[target] - if !est_time.nil? and (least_time.nil? or least_time > est_time) - least_target = target - least_time = est_time - end - end - if least_time < 30 - least_target - else - nil - end -} - -# -# this function handles all the foraging and bundling in a room -# returns true if the bundle is full and we should move on to the next herb -# returns false if the room ran dry -# -forage = proc { |herb| - bundle_full = false - begin - # - # forage faster - # - if (Spells.majorelemental >= 6) and not checkspell(506) and checkmana(6) - fput 'incant 506' - elsif (Spells.minorelemental >= 2) and not checkspell(402) and checkmana(2) - fput 'incant 402' - end - # - # paranoia - # - if checkleft - dothis 'stow left', /^You put|^You are not holding anything in your left hand\.$/ - end - if checkright - dothis 'stow right', /^You put|^You are not holding anything in your right hand\.$/ - end - # - # forage - # - forage_result = dothistimeout 'forage for ' + herb, 5, /^You forage|^You make so much noise that only the dead would not notice you thrashing about in your unsuccessful search\.$|^You stumble about in a fruitless attempt at foraging\.$|you are unable to find anything useful|^As you carefully forage around you (can find no hint|see no evidence) of what you are looking for\.|^You begin to forage around when your hand comes into contact with something that stabs you in the finger\.$|^As you forage around you suddenly feel a sharp pain in your right hand!|^You begin to forage around when suddenly you feel a burning sensation in your hand\.$|^You fumble about so badly in your search that you can only hope no one was watching you\.$/ - sleep 0.5 - waitrt? - if forage_result =~ /^You forage briefly and manage to find/ - # - # we found something, try to bundle it - # - get_result = dothis 'get my ' + herb + ' from my ' + Lich.herbsack, /^You remove|^Get what/ - if get_result =~ /^You remove/ - # - # bundle; if theres too much to bundle, eat and try again - # - loop { - bundle_result = dothistimeout 'bundle', 3, /^Carefully, you combine|^If you add anything more to this bundle|^You do not have anything to bundle!$/ - if bundle_result =~ /^Carefully, you combine/ - dothis 'put my ' + herb + ' in my ' + Lich.herbsack, /^You put|^I could not find what you were referring to\.$/ - break - elsif bundle_result =~ /^If you add anything more to this bundle/ - dothis 'eat my ' + herb, /^You take a bite/ - # - # stop foraging for this herb - # - bundle_full = true - else - break - end - } - else - # - # there's nothing to bundle with, just put it away and continue - # - dothis 'put my ' + herb + ' in my ' + Lich.herbsack, /^You put|^I could not find what you were referring to\.$/ - end - elsif forage_result =~ /^As you forage around you suddenly feel a sharp pain in your right hand!/ - if (limb_repair = Spell[1102]) and limb_repair.known? and limb_repair.affordable? - limb_repair.cast - else - start_script 'useherbs' - wait_while { running? 'useherbs' } - end - end - # - # try again unless the room is dry or the bundle is full - # - end until (bundle_full == true) or forage_result.nil? or (forage_result =~ /you are unable to find anything useful|^As you carefully forage around you (can find no hint|see no evidence) of what you are looking for\./) - bundle_full -} - - -# -# try to open the herb pouch, remember to close it or not -# -open_result = dothis 'open my ' + Lich.herbsack, /^You open|^That is already open\.$/ -if open_result =~ /^You open/ - close_herbsack = true -else - close_herbsack = false -end - -empty_hands - -used_rooms = Array.new - -for herb in herb_list - - loop { - # - # goto a room with this herb, or move on to the next herb - # - this_room = Map.current - next_room = find_nearest.call(herb_rooms[herb] - used_rooms) - if next_room.nil? - break - else - used_rooms.push(next_room) - start_script 'go2', [ next_room.to_s, '_disable_confirm_' ] - wait_while { running? 'go2' } - if this_room == Map.current - break - else - unless checkpcs or checknpcs - # - # forage until the room is dry or the bundle is full - # - bundle_full = forage.call(herb) - # - # move on to the next herb if the bundle is full - # - break if bundle_full - end - end - end - } - -end - -fill_hands - -# -# close the herbsack if we opened it -# -if close_herbsack - dothis 'close my ' + Lich.herbsack, /^You close|^That is already closed\.$/ -end - -# -# go somewhere nice -# -if done_goto - start_script 'go2', [ done_goto, '_disable_confirm_' ] - wait_while { running? 'go2' } -end - -#start_script('autorest') unless running?('autorest') +=begin + + This script runs around foraging for herbs until you have a herbsack with 50 bites of each herb + + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: herbs + version: 0.2 + required: Lich >= 4.6.0 + + changelog: + 0.2 (2015-04-27): + add support for scripted containers + don't heal when injured if Troll's Blood is active + use map tags instead of hard-coded room numbers + cast 603 if known and not active + cast sanctury if known and kneel + +=end + +unless Vars.herbsack + echo 'error: No herbsack has been set. Use ;vars set herbsack=' + exit +end + +unless Vars.lootsack + echo 'error: No lootsack has been set. Use ;vars set lootsack=' + exit +end + +# fixme: add options for use_sanct, max_travel_time, herb_list, and done_goto +use_sanct = true +max_travel_time = 30 +done_goto = Room.current.id +herb_list = [ 'haphip root', 'pothinir grass', 'ephlox moss', 'calamia fruit', 'sovyn clove', 'wolifrew lichen', 'woth flower', 'torban leaf', 'acantha leaf', 'ambrominas leaf', 'cactacae spine', 'basal moss', 'aloeas stem' ] +put_regex = /^You (?:attempt to shield .*? from view as you |discreetly |carefully |absent-mindedly )?(?:put|place|slip|tuck|add|hang|drop|untie your|find an incomplete bundle|wipe off .*? and sheathe)|^A sigh of grateful pleasure can be heard as you feed .*? to your|^As you place|^I could not find what you were referring to\.$|^Your bundle would be too large|^The .+ is too large to be bundled\.|^As you place your|^The .*? is already a bundle|^Your .*? won't fit in .*?\.$|^You can't .+ It's closed!$/ +get_regex = /^You (?:shield the opening of .*? from view as you |discreetly |carefully |deftly )?(?:remove|draw|grab|reach|slip|tuck|retrieve|already have|unsheathe)|^Get what\?$|^Why don't you leave some for others\?$|^You need a free hand/ +get_success_regex = /^You (?:shield the opening of .*? from view as you |discreetly |carefully |deftly )?(?:remove|draw|grab|reach|slip|tuck|retrieve|already have|unsheathe)/ +last_sanct_id = nil + +# +# this proc handles all the foraging and bundling in a room +# returns true if the bundle is full and we should move on to the next herb +# returns false if the room ran dry +# +forage = proc { |herb| + bundle_full = false + begin + # + # Bring up minor sanctuary for safety and quiet and kneels to speed things up + # + if use_sanct and Spell[213].known? and Spell[213].affordable? and (last_sanct_id != Room.current.id) + Spell[213].cast + fput 'kneel' + last_sanct_id = Room.current.id + end + # + # forage faster + # + if Spell[506].known? and Spell[506].affordable? and not Spell[506].active? + Spell[506].cast + elsif Spell[402].known? and Spell[402].affordable? and not Spell[402].active? + Spell[402].cast + elsif Spell[602].known? and Spell[603].affordable? and not Spell[603].active? + Spell[603].cast + end + # + # paranoia + # + if checkleft + dothis 'stow left', put_regex + end + if checkright + dothis 'stow right', put_regex + end + # + # forage + # + forage_result = dothistimeout "forage for #{herb}", 5, /^You forage|^You make so much noise that only the dead would not notice you thrashing about in your unsuccessful search\.$|^You stumble about in a fruitless attempt at foraging\.$|you are unable to find anything useful|^As you carefully forage around you (can find no hint|see no evidence) of what you are looking for\.|^You begin to forage around when your hand comes into contact with something that stabs you in the finger\.$|^As you forage around you suddenly feel a sharp pain in your right hand!|^You begin to forage around when suddenly you feel a burning sensation in your hand\.$|^You fumble about so badly in your search that you can only hope no one was watching you\.$/ + sleep 0.5 + waitrt? + if forage_result =~ /^You forage briefly and manage to find/ + # + # we found something, try to bundle it + # + get_result = dothis "get my #{herb} from my #{Vars.herbsack}", get_regex + if get_result =~ get_success_regex + # + # bundle; if theres too much to bundle, eat and try again + # + loop { + bundle_result = dothistimeout 'bundle', 3, /^Carefully, you combine|^If you add anything more to this bundle|^You do not have anything to bundle!$/ + if bundle_result =~ /^Carefully, you combine/ + dothis "put my #{herb} in my #{Vars.herbsack}", put_regex + break + elsif bundle_result =~ /^If you add anything more to this bundle/ + dothis "eat my #{herb}", /^You take a bite/ + # + # stop foraging for this herb + # + bundle_full = true + else + break + end + } + else + # + # there's nothing to bundle with, just put it away and continue + # + dothis "put my #{herb} in my #{Vars.herbsack}", put_regex + end + elsif forage_result =~ /^As you forage around you suddenly feel a sharp pain in your right hand!/ + if Spell[1125].active? + # Troll's Blood + elsif Spell[1102].known? and Spell[1102].affordable? + Spell[1102].cast # Limb Repair + else + Script.run('useherbs') + end + end + # + # try again unless the room is dry or the bundle is full + # + end until (bundle_full == true) or forage_result.nil? or (forage_result =~ /you are unable to find anything useful|^As you carefully forage around you (can find no hint|see no evidence) of what you are looking for\./) + bundle_full +} + + +# +# try to open the herb pouch, remember to close it or not +# +open_result = dothis "open my #{Vars.herbsack}", /^You open|^That is already open\.$/ +if open_result =~ /^You open/ + close_herbsack = true +else + close_herbsack = false +end + +empty_hands + +for herb in herb_list + room_list = Room.list.find_all { |r| r.tags.include?("some #{herb}") }.collect { |r| r.id } + room_list.delete(3603) + room_list.delete(3602) + room_list.delete(3601) + until room_list.empty? + # + # goto a room with this herb, or move on to the next herb + # + this_room = Room.current + next_room = this_room.find_nearest(room_list) + room_list.delete(next_room) + break if next_room.nil? + unless (next_room == Room.current.id) + path = Room.current.path_to(next_room) + break if path.nil? + path.push(next_room) + if (Map.estimate_time(path) > max_travel_time) + echo "nearest room with #{herb} exceeds max_travel_time setting" + break + end + Script.run('go2', next_room.to_s) + if (this_room == Room.current) + echo 'move appears to have failed' + break + end + end + unless checkpcs or checknpcs + # + # forage until the room is dry or the bundle is full + # + bundle_full = forage.call(herb) + # + # move on to the next herb if the bundle is full + # + break if bundle_full + end + end +end + +fill_hands + +# +# close the herbsack if we opened it +# +if close_herbsack + dothis "close my #{Vars.herbsack}", /^You close|^That is already closed\.$/ +end + +# +# go somewhere nice +# +Script.run('go2', done_goto.to_s) if done_goto diff --git a/chargeimbed.lic b/chargeimbed.lic index bad900d..f0a57bd 100644 --- a/chargeimbed.lic +++ b/chargeimbed.lic @@ -7,14 +7,21 @@ imbed as you use it, this script updates that tracking as you charge the item (unless it's a common item). - tillmen@lichproject.org + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: magic + version: 0.2 + + changelog: + 2015-07-06 (0.2): + pull mana directly from the XML stream to avoid race conditions =end added_mana = 0 added_charges = 0 item_id = nil -items = Hash.new +$items ||= Hash.new start_mana = XMLData.mana common_items = { @@ -38,6 +45,8 @@ common_items = { 'smooth amber wand' => 1708, 'crystal wand' => 1710, 'etched crystal wand' => 1710, + 'heavy quartz orb' => 1711, + 'small statue' => 1712, 'scattering of deathstone granules' => 1713, 'some fine firestone dust' => 1715, } @@ -64,13 +73,13 @@ mana_per_charge = proc { |spell_num| [spell_level, (base_cost - (Skills.emc/5))].max } -before_dying { +show_stats = proc { respond respond '--- Charge Session Stats' respond respond 'item name charges mana' respond '------------------------------- ------- ----' - items.each_pair { |item_id,hash| + $items.each_pair { |item_id,hash| if hash[:added_charges] respond "#{hash[:name].ljust(31)} #{hash[:added_charges].to_s.rjust(7)}" else @@ -80,51 +89,70 @@ before_dying { respond } +before_dying { + show_stats.call +} + status_tags loop { line = get - if line =~ /(.*?)<\/a> near it\./ - end_mana = XMLData.mana - item_id = $1 - items[item_id] ||= Hash.new - items[item_id][:name] ||= $2 + if line =~ /<.*progressBar id='mana' .*?text='mana (\d+)\/\d+'.*>You gesture over the pulsating orb while holding (?:a |an )?(.*?)<\/a> near it\./ + end_mana = $1.to_i + item_id = $2 + $items[item_id] ||= Hash.new + $items[item_id][:name] ||= $3 # Report the number of charges or mana added - if spell_num = common_items[items[item_id][:name]] + if spell_num = common_items[$items[item_id][:name]] added_charges = ((start_mana - end_mana)/mana_per_charge[spell_num].to_f).round added_mana = nil - items[item_id][:added_charges] = items[item_id][:added_charges].to_i + added_charges - respond "[ charges added: #{added_charges}, total added: #{items[item_id][:added_charges]} ]" - elsif spell_num = UserVars.imbeds[items[item_id][:name]][:spell] + $items[item_id][:added_charges] = $items[item_id][:added_charges].to_i + added_charges + sleep 0.1 + respond "[ charges added: #{added_charges}, total added: #{$items[item_id][:added_charges]} ]" + elsif spell_num = UserVars.imbeds[$items[item_id][:name]][:spell] added_charges = ((start_mana - end_mana)/mana_per_charge[spell_num].to_f).round added_mana = nil - items[item_id][:added_charges] = items[item_id][:added_charges].to_i + added_charges - UserVars.imbeds[items[item_id][:name]][:charges] = UserVars.imbeds[items[item_id][:name]][:charges].to_i + added_charges - respond "[ charges added: #{added_charges}, total added: #{items[item_id][:added_charges]} ]" - respond "[ #{items[item_id][:name]}: #{UserVars.imbeds[items[item_id][:name]][:charges]} charges remaining. ]" + $items[item_id][:added_charges] = $items[item_id][:added_charges].to_i + added_charges + UserVars.imbeds[$items[item_id][:name]][:charges] = UserVars.imbeds[$items[item_id][:name]][:charges].to_i + added_charges + sleep 0.1 + respond "[ charges added: #{added_charges}, total added: #{$items[item_id][:added_charges]} ]" + respond "[ #{$items[item_id][:name]}: #{UserVars.imbeds[$items[item_id][:name]][:charges]} charges remaining. ]" else added_charges = nil added_mana = start_mana - end_mana - items[item_id][:added_mana] = items[item_id][:added_mana].to_i + added_mana - respond "[ mana added: #{added_mana}, total added: #{items[item_id][:added_mana]} ]" + $items[item_id][:added_mana] = $items[item_id][:added_mana].to_i + added_mana + sleep 0.1 + respond "[ mana added: #{added_mana}, total added: #{$items[item_id][:added_mana]} ]" + end + start_mana = end_mana + else + if line =~ /<.*progressBar id='mana' .*?text='mana (\d+)\/\d+'.*>/ + start_mana = $1.to_i end - elsif line =~ /^You feel terribly drained\!/ - # incorrectly figured the lost mana as charges added, undo that - respond "[ thats not right... ]" - if items[item_id][:added_charges] - items[item_id][:added_charges] -= added_charges - if UserVars.imbeds[items[item_id][:name]] - UserVars.imbeds[items[item_id][:name]][:charges] =- added_charges - respond "[ #{items[item_id][:name]}: #{UserVars.imbeds[items[item_id][:name]][:charges]} charges remaining. ]" + if line =~ /^You feel terribly drained\!/ + # incorrectly figured the lost mana as charges added, undo that + respond "[ thats not right... ]" + if $items[item_id][:added_charges] + $items[item_id][:added_charges] -= added_charges + if UserVars.imbeds[$items[item_id][:name]] + UserVars.imbeds[$items[item_id][:name]][:charges] =- added_charges + sleep 0.1 + respond "[ #{$items[item_id][:name]}: #{UserVars.imbeds[$items[item_id][:name]][:charges]} charges remaining. ]" + else + sleep 0.1 + end + respond "[ charges added: 0, total added: #{$items[item_id][:added_charges]} ]" + else + $items[item_id][:added_mana] -= added_mana + sleep 0.1 + respond "[ mana added: 0, total added: #{$items[item_id][:added_mana]} ]" end - respond "[ charges added: 0, total added: #{items[item_id][:added_charges]} ]" - else - items[item_id][:added_mana] -= added_mana - respond "[ mana added: 0, total added: #{items[item_id][:added_mana]} ]" + elsif line =~ /^The pulsating orb (?:quickly|suddenly) implodes/ + show_stats.call +# break + elsif line =~ /expands into a blue pulsating orb!/ + minutes = 0 + Thread.new { loop { sleep 60; minutes += 1; echo "orb is #{minutes} minutes old" } } end - elsif line =~ /^The pulsating orb (?:quickly|suddenly) implodes/ - break end } diff --git a/ego2.lic b/ego2.lic index d5464bf..15638e9 100644 --- a/ego2.lic +++ b/ego2.lic @@ -22,27 +22,24 @@ ;ego2 help - https://github.com/matt-lowe/lich-scripts - https://www.gittip.com/matt-lowe - matt@lichproject.org + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: bounty + version: 0.5 + + changelog: + 0.5 (2015-04-07): + ignore disabled people's disabled bandits + don't use "a tiny shard of jet black crystal" as an indicator of who owns the bandits + pay attention to disks + 0.4 (2014-11-04): + fixed poaching issue where escort id wasn't being checked when he exclaims, "It's an ambush!" + 0.3 (2014-09-29): + reworked ambush detection to prevent false positives (poaching other peoples bandits) + removed code to download gameobj-data.xml =end -if defined?(GameObj.type_data) - GameObj.load_data if GameObj.type_data.empty? or GameObj.type_data.nil? - if GameObj.type_data.nil? - wait_while { running?('updater') } - wait_while { running?('repository') } - start_script 'repository', [ 'download', 'gameobj-data.xml' ] - wait_while { running?('repository') } - wait_while { running?('updater') } - start_script 'updater', [ 'add', 'gameobj-data.xml' ] - wait_while { running?('updater') } - GameObj.load_data - exit if GameObj.type_data.nil? - end -end - fix_setting = { 'on' => true, 'off' => false, 'true' => true, 'false' => false, 'yes' => true, 'no' => false } script.vars.shift @@ -94,6 +91,7 @@ justice_count = 0 fell_off_rope = false lost_escort = 0 sanct_count = -1 +wait_num = 45 options = script.vars.find_all { |var| var =~ /^\-\-/ } script.vars.delete_if { |var| var =~ /^\-\-/ } @@ -155,7 +153,6 @@ CharSettings['untargetable'] ||= Array.new destination_room = nil path = nil escort_id = nil -my_ambush = false ambush_room_count = XMLData.room_count no_hide_rooms = [ 1192, 1191, 1190, 1156, 1155, 1154, 1153 ] no_haste_rooms = [ 1191 ] @@ -187,7 +184,7 @@ escort_dropoff = { $ego2_travel_cost ||= { "Wehnimer's Landing" => { - "Icemule Trace" => 5, + "Icemule Trace" => 0, "Zul Logoth" => 20, "Solhaven" => 0, "Ta'Vaalor" => 4020, @@ -202,28 +199,28 @@ $ego2_travel_cost ||= { }, "Zul Logoth" => { "Wehnimer's Landing" => 2020, - "Icemule Trace" => 2025, + "Icemule Trace" => 2020, "Solhaven" => 2020, "Ta'Vaalor" => 2000, "Ta'Illistim" => 2000, }, "Solhaven" => { "Wehnimer's Landing" => 0, - "Icemule Trace" => 5, + "Icemule Trace" => 0, "Zul Logoth" => 20, "Ta'Vaalor" => 4020, "Ta'Illistim" => 4020, }, "Ta'Vaalor" => { "Wehnimer's Landing" => 4020, - "Icemule Trace" => 4025, + "Icemule Trace" => 4020, "Zul Logoth" => 2000, "Solhaven" => 4020, "Ta'Illistim" => 0, }, "Ta'Illistim" => { "Wehnimer's Landing" => 4020, - "Icemule Trace" => 4025, + "Icemule Trace" => 4020, "Zul Logoth" => 2000, "Solhaven" => 4020, "Ta'Vaalor" => 0, @@ -284,25 +281,30 @@ check_escort = proc { GameObj.npcs.any? { |npc| npc.id == escort_id } } -check_ambush = proc { - if my_ambush and (ambush_room_count == XMLData.room_count) - true - elsif check_escort.call - ambush_room_count = XMLData.room_count - my_ambush = true - else - last_line = $_SERVERBUFFER_.reverse.find { |line| line =~ /|An? .*? fearfully exclaims, "It's an ambush!"|carefully concealed metal jaws|nearly invisible length of razor wire|carefully concealed inflated pouch|tiny shard of jet black crystal|carefully concealed looped rope|a carefully concealed net/ } - if last_line.nil? - my_ambush - elsif last_line =~ // - my_ambush = false - else - # echo 'my ambush' - ambush_room_count = XMLData.room_count - my_ambush = true +$ego2_my_ambush = false +$ego2_staggered_ambush = false +exec_string = " + hide_me + status_tags + before_dying { kill_script(#{script.name.inspect}) if running?(#{script.name.inspect}) } + Thread.new { wait_while { running?(#{Script.self.name.inspect}) }; Script.self.kill } + while (line = get) + if line =~ /.*?(?:quickly approaches|suddenly leaps from|leaps out of|suddenly jumps out of the shadows)|carefully concealed metal jaws|nearly invisible length of razor wire|length of nearly invisible razor wire|carefully concealed inflated pouch|carefully concealed looped rope|a carefully concealed net|carefully concealed pit|Suddenly, the ground gives out from under you as you fall into a shallow pit filled with tiny spikes!/ + # removed cause it caused a poach: tiny shard of jet black crystal + $ego2_my_ambush = true + echo 'my ambush' if $ego2_debug + if line =~ /.*?(?:quickly approaches|suddenly leaps from|leaps out of|suddenly jumps out of the shadows)/ + $ego2_staggered_ambush = true + echo 'staggered ambush' if $ego2_debug + end end end -} +" +start_exec_script(exec_string, flags={ :quiet => true }) check_room = proc { if hide @@ -310,15 +312,17 @@ check_room = proc { end loop { while unknown_npc = GameObj.npcs.find { |npc| not CharSettings['targetable'].include?(npc.name) and not CharSettings['untargetable'].include?(npc.name) } - target_result = dothistimeout "target ##{unknown_npc.id}", 10, /^You are now targeting|^You can't target/ + target_result = dothistimeout "target ##{unknown_npc.id}", 10, /^You are now targeting|^You can't target|^Usage: TARGET/ if target_result =~ /^You are now targeting/ CharSettings['targetable'].push(unknown_npc.name) elsif target_result =~ /^You can't target/ CharSettings['untargetable'].push(unknown_npc.name) end end - npcs = GameObj.npcs.to_a.find_all { |npc| CharSettings['targetable'].include?(npc.name) and not (npc.name =~ ignorable_npcs) and (npc.noun !~ escort_noun) and (npc.type =~ /bandit/ or npc.status !~ disabled) and (npc.status !~ /dead/) } - pcs = GameObj.pcs.to_a.find_all { |pc| pc.status.nil? } + npcs = GameObj.npcs.to_a.find_all { |npc| CharSettings['targetable'].include?(npc.name) and not (npc.name =~ ignorable_npcs) and (npc.noun !~ escort_noun) and (($ego2_my_ambush and npc.type =~ /bandit/) or npc.status !~ disabled) and (npc.status !~ /dead/) } + all_pcs = GameObj.pcs.to_a + pcs = all_pcs.find_all { |pc| pc.status.nil? or pc.status =~ /hiding|hidden/ } + disks = GameObj.loot.to_a.find_all { |loot| (loot.noun == 'disk') and (loot.name !~ /#{Char.name}/) and (all_pcs.empty? or (loot.name !~ /#{all_pcs.collect { |pc| pc.noun }.join('|')}/)) } jerks = GameObj.pcs.to_a.find_all { |pc| UserVars.attacked_me.to_a.include?(pc.noun) and (pc.status !~ /dead/) } unless jerks.empty? unless justice_count == XMLData.room_count @@ -335,7 +339,7 @@ check_room = proc { end end break if sanct_count == XMLData.room_count - if (poach and npcs.length > 0) or (npcs.length > 0 and (check_ambush.call or pcs.empty?)) or (attack_script and jerks.length > 0) + if (poach and npcs.length > 0) or (npcs.length > 0 and ($ego2_my_ambush or (pcs.empty? and disks.empty?))) or (attack_script and jerks.length > 0) if attack_script if (checkrt > 0) waitrt? @@ -362,11 +366,21 @@ check_room = proc { use_herbs = proc { if useherbs - if ([Wounds.head, Wounds.neck, Wounds.torso, Wounds.limbs, Wounds.nerves, Scars.head, Scars.neck, Scars.torso, Scars.limbs, Scars.nerves].max > 0) or ((checkhealth + 50) < maxhealth) - start_script 'useherbs', [ '--buy-missing=off' ] - wait_while { running?('useherbs') } + if XMLData.name == 'Tillmen' and XMLData.game == 'GSIV' + if ([Wounds.head, Wounds.neck, Wounds.torso, Wounds.limbs, Wounds.nerves, Scars.head, Scars.neck, Scars.torso, Scars.nerves].max > 0) or (Scars.limbs > 1) or ((checkhealth + 50) < maxhealth) + start_script 'useherbs', [ '--buy-missing=off' ] + wait_while { running?('useherbs') } + if ([Wounds.head, Wounds.neck, Wounds.torso, Wounds.limbs, Wounds.nerves, Scars.head, Scars.neck, Scars.torso, Scars.nerves].max > 0) or (Scars.limbs > 1) or ((checkhealth + 50) < maxhealth) + useherbs = false + end + end + else if ([Wounds.head, Wounds.neck, Wounds.torso, Wounds.limbs, Wounds.nerves, Scars.head, Scars.neck, Scars.torso, Scars.limbs, Scars.nerves].max > 0) or ((checkhealth + 50) < maxhealth) - useherbs = false + start_script 'useherbs', [ '--buy-missing=off' ] + wait_while { running?('useherbs') } + if ([Wounds.head, Wounds.neck, Wounds.torso, Wounds.limbs, Wounds.nerves, Scars.head, Scars.neck, Scars.torso, Scars.limbs, Scars.nerves].max > 0) or ((checkhealth + 50) < maxhealth) + useherbs = false + end end end end @@ -1706,7 +1720,7 @@ unless escort_id # start_script 'go2', [ pickup_room.to_s ] wait_while { running?('go2') } - dothistimeout 'wait', 10, /^Time drags on by\.\.\.$/ + dothistimeout 'wait', 20, /^Time drags on by\.\.\.$/ checked_npc_ids = Array.new 130.times { sleep 0.1 @@ -1716,6 +1730,8 @@ unless escort_id result = dothistimeout "tell ##{npc.id} to follow", 8, /#{npc.noun} nods and says to you|#{npc.noun} says to you, "But I already am!"|#{npc.noun} says to you, "The guild didn't hire you to guide me\."|^The merchant gives you a strange look\.$/ if result =~ /#{npc.noun} nods and says to you|#{npc.noun} says to you, "But I already am!"/ escort_id = npc.id + before_dying { $ego2_escort_id = nil } + $ego2_escort_id = escort_id break end end @@ -1751,6 +1767,10 @@ loop { check_room.call + use_herbs.call + + check_room.call + hide_me.call check_room.call @@ -1814,25 +1834,18 @@ fput 'unhide' if hidden? =begin - You spy a set of carefully concealed metal jaws just as you are about to step on them! - Suddenly, you hear a loud *clink* as a large pair of carefully concealed metal jaws slam shut on your left leg! - - You spy a nearly invisible length of razor wire just moments before you are about to step into it! - Suddenly, you feel an intense pain in your right leg! as you realize that you've stumbled right into a length of nearly invisible razor wire! - - You spy a carefully concealed inflated pouch on the path just ahead of you! - - Suddenly, the ground gives out from under you as you fall into a shallow pit filled with tiny spikes! - - Suddenly, a tiny shard of jet black crystal flies from the shadows toward you! You manage to avoid being hit by the crystal as it shatters harmlessly nearby! - You spy a carefully concealed looped rope on the path just ahead of you! - Suddenly, a carefully concealed looped rope springs up from the ground, wrapping around your ankle and tossing you up into the air! - - You spy a carefully concealed net on the path just ahead of you! - Suddenly, a carefully concealed net springs up from the ground, completely entangling you! - You finally reach the shore and you pull yourself to safety. Your body aches all over and you can't seem to move again just yet. + A giantman traveller looks faint. + A giantman traveller mumbles, "I'm bleeding." + A half-elven rogue turns to a giantman traveller and exclaims, "I've got ya now!" + A half-elven rogue swings a backsword at a giantman traveller! + AS: +414 vs DS: +204 with AvD: +38 + d100 roll: +49 = +297 + ... and hits for 117 points of damage! + The giantman traveller twists away but is caught with a hard slash! + The giantman traveller is knocked to the ground! + The giantman traveller is stunned! + =end diff --git a/group_ajar.lic b/group_ajar.lic index a17ab88..ee35386 100644 --- a/group_ajar.lic +++ b/group_ajar.lic @@ -8,7 +8,9 @@ ;group_ajar help - tillmen@lichproject.org + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + version: 0.1 =end diff --git a/highlight_links.lic b/highlight_links.lic index f26b53d..602378a 100644 --- a/highlight_links.lic +++ b/highlight_links.lic @@ -2,6 +2,7 @@ This script changes the highlight color of links in the room description in the Wizard frontend. + https://github.com/matt-lowe/lich-scripts tillmen@lichproject.org =end diff --git a/inactivespells.lic b/inactivespells.lic index 627768b..5c92cf3 100644 --- a/inactivespells.lic +++ b/inactivespells.lic @@ -2,7 +2,10 @@ Shows all your inactive spells in a window. - tillmen@lichproject.org + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: magic + version: 0.1 =end diff --git a/invoke.lic b/invoke.lic index da84a87..6e584b8 100644 --- a/invoke.lic +++ b/invoke.lic @@ -4,8 +4,9 @@ It will empty your hands if needed. If a target is provided, it will cast at the target. If not, it will leave the spell prepared. - Lich.scrollsack should be set (;set change scrollsack ) + UserVars.scrollsack should be set (;set change scrollsack ) + https://github.com/matt-lowe/lich-scripts tillmen@lichproject.org =end @@ -14,7 +15,7 @@ unless defined?(dothis) echo 'Your version of Lich is too old for this script.' exit end -if Lich.scrollsack.nil? or Lich.scrollsack.empty? +if UserVars.scrollsack.nil? or UserVars.scrollsack.empty? echo 'You need to set your scrollsack. ;setting change scrollsack ' exit end @@ -34,7 +35,7 @@ end return_scroll = proc { if checkleft =~ /(scroll|paper|papyrus|vellum|palimpsest|parchment)/ || checkright =~ /(scroll|paper|papyrus|vellum|palimpsest|parchment)/ - put 'put my ' + $1 + ' in my ' + Lich.scrollsack + put 'put my ' + $1 + ' in my ' + UserVars.scrollsack end } @@ -45,11 +46,11 @@ empty_hands # close_scrollsack = false loop { - rummage_result = dothis "rummage in my #{Lich.scrollsack} for spell #{spell}", /^What spell are you looking for\?$|^What were you wanting to rummage through\?$|^You'll have to open|^(In the .+)?You rummage/ + rummage_result = dothis "rummage in my #{UserVars.scrollsack} for spell #{spell}", /^What spell are you looking for\?$|^What were you wanting to rummage through\?$|^You'll have to open|^(In the .+)?You rummage/ if rummage_result =~ /and remove/ break elsif rummage_result =~ /^You'll have to open/ - dothis "open my #{Lich.scrollsack}", /^You open/ + dothis "open my #{UserVars.scrollsack}", /^You open/ close_scrollsack = true next else @@ -87,5 +88,5 @@ fill_hands # close the scrollsack if it was opened # if close_scrollsack - dothis "close my #{Lich.scrollsack}", /^(In the.+)?You close/ + dothis "close my #{UserVars.scrollsack}", /^(In the.+)?You close/ end diff --git a/keepsigns.lic b/keepsigns.lic index 6eb773f..c5000ab 100644 --- a/keepsigns.lic +++ b/keepsigns.lic @@ -4,6 +4,7 @@ Open the script and comment/uncomment some lines to pick your signs. + https://github.com/matt-lowe/lich-scripts tillmen@lichproject.org =end @@ -15,16 +16,27 @@ clear sign_list = Array.new -sign_list.push 'Warding' -sign_list.push 'Striking' -# sign_list.push 'Thought' -sign_list.push 'Defending' -sign_list.push 'Smiting' -sign_list.push 'Staunching' -sign_list.push 'Deflection' -sign_list.push 'Swords' -sign_list.push 'Shields' -sign_list.push 'Dissipation' +if script.vars[1] == 'conf' + echo 'confluence' + sign_list.push 'Warding' + sign_list.push 'Defending' + sign_list.push 'Striking' + sign_list.push 'Smiting' + sign_list.push 'Swords' + sign_list.push 'Staunching' + sign_list.push 'Dissipation' +else + sign_list.push 'Warding' + sign_list.push 'Striking' + # sign_list.push 'Thought' + sign_list.push 'Defending' + sign_list.push 'Smiting' + sign_list.push 'Staunching' + sign_list.push 'Deflection' + sign_list.push 'Swords' + #sign_list.push 'Shields' + sign_list.push 'Dissipation' +end sign_list.delete_if { |sign| !Spell[sign].known? } diff --git a/markchargable.lic b/markchargable.lic index c0d2b7c..65331fc 100644 --- a/markchargable.lic +++ b/markchargable.lic @@ -3,6 +3,7 @@ This script might take gems out of a container, loresing to them for their purpose, mark them as unsellable if they're mage rechargable, and put them back in the container. + https://github.com/matt-lowe/lich-scripts tillmen@lichproject.org =end diff --git a/measure-favor.lic b/measure-favor.lic index 8a2c79c..685ca7f 100644 --- a/measure-favor.lic +++ b/measure-favor.lic @@ -4,6 +4,7 @@ Intened for use near Wehnimer's landing. You won't have any favor when the script finishes. + https://github.com/matt-lowe/lich-scripts tillmen@lichproject.org =end @@ -103,7 +104,7 @@ get_favor = proc { # fixme end end - death_count = GameObj.npcs.find_all { |npc| npc.noun == 'wraith' and npc.status =~ /dead/ } + death_count = GameObj.npcs.find_all { |npc| npc.noun == 'wraith' and npc.status =~ /dead/ }.length if death_count > 0 if running?('loot') 10.times { break unless GameObj.npcs.any? { |npc| npc.status == 'dead' }; sleep 0.2 } diff --git a/passive-spellbot.lic b/passive-spellbot.lic index 986f6f0..c8d39e0 100644 --- a/passive-spellbot.lic +++ b/passive-spellbot.lic @@ -11,7 +11,13 @@ ;passive-spellbot help - tillmen@lichproject.org + author: Tillmen (tillmen@lichproject.org + game: Gemstone + tags: magic + version: 0.2 + + 0.2 (2016-09-19): + add support for 1204 (Bitash) =end @@ -19,6 +25,7 @@ settings = CharSettings.to_hash settings['mode'] ||= 'exclude' settings['include'] ||= Array.new settings['exclude'] ||= Array.new +settings['exclude-on-refuse'] = true if settings['exclude-on-refuse'].nil? if script.vars[1].downcase == 'add' and script.vars[2] settings[settings['mode']].push(script.vars[2].capitalize) @@ -40,17 +47,28 @@ elsif script.vars[1].downcase =~ /mode=(include|exclude)/ settings['mode'] = $1 echo "Changed to #{settings['mode']} mode." exit +elsif script.vars[1].downcase =~ /exclude-on-refuse=(yes|no)/ + if $1 == 'yes' + settings['exclude-on-refuse'] = true + echo "People who refuse an LNet spells request will be excluded from spells (if using exclude mode)." + else + settings['exclude-on-refuse'] = false + echo "People who refuse an LNet spells request will get spells anyway." + end + exit elsif script.vars[1].downcase == 'list' output = "\n" - output.concat " mode: #{settings['mode']}\n" - output.concat " exclude list: #{if settings['exclude'].empty?; '(empty)'; else; settings['exclude'].join(', '); end}\n" - output.concat " include list: #{if settings['include'].empty?; '(empty)'; else; settings['include'].join(', '); end}\n" + output.concat " mode: #{settings['mode']}\n" + output.concat " exclude-on-refuse: #{if settings['exclude-on-refuse']; 'yes'; else; 'no'; end}\n" + output.concat " exclude list: #{if settings['exclude'].empty?; '(empty)'; else; settings['exclude'].join(', '); end}\n" + output.concat " include list: #{if settings['include'].empty?; '(empty)'; else; settings['include'].join(', '); end}\n" output.concat "\n" respond output elsif script.vars[1] output = "\n" output.concat " #{$clean_lich_char}#{script.name} mode= Cast only at people on the include list, or\n" output.concat " #{''.ljust(script.name.length + 1)} only at people not on the exclude list.\n" + output.concat " #{$clean_lich_char}#{script.name} exclude-on-refuse= Auto exclude people who refuse an LNet spells request.\n" output.concat " #{$clean_lich_char}#{script.name} add Add a name to the current list.\n" output.concat " #{$clean_lich_char}#{script.name} delete Delete a name from the current list.\n" output.concat " #{$clean_lich_char}#{script.name} clear Clear the current list.\n" @@ -77,6 +95,14 @@ hook_proc = proc { |client_string| respond "[#{script_name}: #{vars[1].capitalize} was not in the #{settings['mode']} list.]" end nil + elsif vars[0].downcase =~ /exclude-on-refuse=(yes|no)/ + if $1 == 'yes' + settings['exclude-on-refuse'] = true + respond "[#{script_name}: People who refuse an LNet spells request will be excluded from spells (if using exclude mode).]" + else + settings['exclude-on-refuse'] = false + respond "[#{script_name}: People who refuse an LNet spells request will get spells anyway.]" + end elsif vars[0].downcase == 'clear' settings[settings['mode']].clear echo "#{settings['mode']} list cleared." @@ -87,9 +113,10 @@ hook_proc = proc { |client_string| nil elsif vars[0].downcase == 'list' output = "\n" - output.concat " mode: #{settings['mode']}\n" - output.concat " exclude list: #{if settings['exclude'].empty?; '(empty)'; else; settings['exclude'].join(', '); end}\n" - output.concat " include list: #{if settings['include'].empty?; '(empty)'; else; settings['include'].join(', '); end}\n" + output.concat " mode: #{settings['mode']}\n" + output.concat " exclude-on-refuse: #{if settings['exclude-on-refuse']; 'yes'; else; 'no'; end}\n" + output.concat " exclude list: #{if settings['exclude'].empty?; '(empty)'; else; settings['exclude'].join(', '); end}\n" + output.concat " include list: #{if settings['include'].empty?; '(empty)'; else; settings['include'].join(', '); end}\n" output.concat "\n" respond output nil @@ -97,6 +124,7 @@ hook_proc = proc { |client_string| output = "\n" output.concat " #{$clean_lich_char}#{script.name} mode= Cast only at people on the include list, or\n" output.concat " #{''.ljust(script.name.length + 1)} only at people not on the exclude list.\n" + output.concat " #{$clean_lich_char}#{script.name} exclude-on-refuse= Auto exclude people who refuse an LNet spells request.\n" output.concat " #{$clean_lich_char}#{script.name} add Add a name to the current list.\n" output.concat " #{$clean_lich_char}#{script.name} delete Delete a name from the current list.\n" output.concat " #{$clean_lich_char}#{script.name} clear Clear the current list.\n" @@ -118,7 +146,7 @@ hook_proc = proc { |client_string| before_dying { UpstreamHook.remove(script_name) } UpstreamHook.add(script_name, hook_proc) -cast_list = [ 101, 103, 107, 202, 401, 406, 414, 503, 509, 602, 618, 1601 ] +cast_list = [ 101, 103, 107, 202, 401, 406, 414, 503, 509, 602, 618, 1204, 1601 ] stackable_max = 15000 refreshable_min = 600 disk_frequency = 43200 @@ -142,6 +170,7 @@ spell_messages = { 509 => /^([A-Z][a-z]+)<\/a> looks considerably more imposing\.\r?$/, 602 => /^The air about ([A-Z][a-z]+)<\/a> shimmers slightly\.\r?$/, 618 => /^([A-Z][a-z]+)<\/a> suddenly looks much more dextrous\.\r?$/, + 1204 => /^([A-Z][a-z]+)<\/a> gazes into the distance before adopting a thoughtful expression\.\r?$/, 1601 => /^(?:The dully illuminated mantle surrounding|A whirl of spiritual energy streaks down from above, creating a dully illuminated mantle around) ([A-Z][a-z]+)'s? form(?: seems to gain some cohesion)?\.\r?$/, } @@ -259,6 +288,9 @@ begin if $passive_spellbot_last_check[target_name].nil? or (Time.now - $passive_spellbot_last_check[target_name]) > 3600 data = LNet.get_data(target_name, 'spells') if data.nil? + if settings['exclude-on-refuse'] and (settings['mode'] == 'exclude') + settings['exclude'].push(target_name) + end echo "spell data for #{target_name}: refused" elsif data == false echo "spell data for #{target_name}: failed" diff --git a/prettybounty.lic b/prettybounty.lic index 4c99423..f8def43 100644 --- a/prettybounty.lic +++ b/prettybounty.lic @@ -4,7 +4,10 @@ how many tasks have been completed recently, and how many bounty points have been gained recently. - tillmen@lichproject.org + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: cosmetic + version: 0.1 =end diff --git a/rbolt.lic b/rbolt.lic index b247aa2..11ea4ae 100644 --- a/rbolt.lic +++ b/rbolt.lic @@ -2,6 +2,7 @@ Cast at something with rapid fire until it dies. + https://github.com/matt-lowe/lich-scripts tillmen@lichproject.org =end diff --git a/rcast.lic b/rcast.lic index 9309a40..01f3670 100644 --- a/rcast.lic +++ b/rcast.lic @@ -2,6 +2,7 @@ Cast spells with rapid-fire. + https://github.com/matt-lowe/lich-scripts tillmen@lichproject.org =end diff --git a/readscrolls.lic b/readscrolls.lic index 6b2fefe..7edfbc0 100644 --- a/readscrolls.lic +++ b/readscrolls.lic @@ -2,6 +2,7 @@ This script reads every scroll in your scrollsack and displays a list of all the spells, and how many times they appear. + https://github.com/matt-lowe/lich-scripts tillmen@lichproject.org =end @@ -11,20 +12,20 @@ unless defined?(GameObj) exit end -unless Lich.scrollsack +unless UserVars.scrollsack echo 'scrollsack is not set. Use ;setting change scrollsack ' exit end status_tags -scrollsack = GameObj.inv.find { |obj| obj.name =~ /#{Lich.scrollsack}/ } +scrollsack = GameObj.inv.find { |obj| obj.name =~ /#{UserVars.scrollsack}/ } if scrollsack.nil? - scrollsack = GameObj.inv.find { |obj| obj.name =~ /#{Lich.scrollsack.gsub(/\s+/, '.*')}/ } + scrollsack = GameObj.inv.find { |obj| obj.name =~ /#{UserVars.scrollsack.gsub(/\s+/, '.*')}/ } echo scrollsack end if scrollsack.nil? - echo "failed to find scrollsack (#{Lich.scrollsack}) in your inventory" + echo "failed to find scrollsack (#{UserVars.scrollsack}) in your inventory" exit end if scrollsack.contents.nil? or scrollsack.contents.empty? @@ -73,7 +74,7 @@ respond exit -look_result = dothis 'look in my ' + Lich.scrollsack, /^In the(?:.*?In the)? ]+>[\w\s]+<\/a> you see/ +look_result = dothis 'look in my ' + UserVars.scrollsack, /^In the(?:.*?In the)? ]+>[\w\s]+<\/a> you see/ look_result = look_result.split(/(]+>)/) scroll_list = Array.new for link in look_result diff --git a/sexual-favors.lic b/sexual-favors.lic index 0e4d587..17c1e55 100644 --- a/sexual-favors.lic +++ b/sexual-favors.lic @@ -1,63 +1,124 @@ =begin - I think you know what this script does... + I think you know what this script does... + + This script keeps track of favor gained and used. + Set the script to start on login. + Type "favor" with the script running to see how much favor you have. + Type "favor clear" to set symbol favor to 0. + Type "favor set " to set symbol favor to something else. + Touch the globe to raise or lower symbol favor to the correct range. + To disable this, use ;vars set globe_sets_favor=no + + 1 favor is defined as the amount of favor it takes to do "sym thought ab", + which is equivalent to 1/1000th of a globe revolution. + + Favor gain formula is accurate, but the undead level is not always known. The + script may use the undead's TD to calculate the exact level. Calculating the + exact level for other hunting methods may not be practical. + + The script can tell the difference between kill favor and spectator favor, but + only for attacks that the script knows about. If you land the killing blow and + the script reports it as spectator favor, send me a log of it and I'll fix it. + + The script will check the weapon name when you use symbol of blessing to figure + out which blessing cost to use. It's only looking for a magical metal or wood + in the weapon name. If it's wrong, let me know and I'll try to fix it. + + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: voln + version: 0.34 + + changelog: + 0.34 (2018-06-23): + don't divide by 0 at Voln rank 0 + abort script if you're not in Voln + 0.33 (2018-01-12): + added Bramble Patch (SpiffyJr) + 0.32 (2016-05-05): + add another message to recognize Maelstrom - 1 favor is defined as the amount of favor it takes to do "sym thought ab", - which is equivalent to 1/1000th of a globe revolution. - - This script keeps track of favor gained and used. - Set the script as a favorite. Type "favor" with the script running. - - Type "favor clear" to set symbol favor to 0. - Type "favor set " to set symbol favor to something else. - Touch the globe to raise or lower symbol favor to the correct range. - - Favor costs are accurate for levels 3 through 42, and 100. The other levels - are guessed, but won't be too far off. Still working on getting them perfect. - You can help by running the measure-favor script. - - Favor gain formula is accurate, but the undead level is not always known. The - script may use the undead's TD to calculate the exact level. Calculating the - exact level for other hunting methods may not be practical. - - The script can tell the difference between kill favor and spectator favor, but - only for attacks that the script knows about. If you land the killing blow and - the script reports it as spectator favor, send me a log of it and I'll fix it. - - The script will check the weapon name when you use symbol of blessing to figure - out which blessing cost to use. It's only looking for a magical metal or wood - in the weapon name. If it's wrong, let me know and I'll try to fix it. - - https://github.com/matt-lowe/lich-scripts +=end +=begin - author: Tillmen - email: tillmen@lichproject.org - tags: voln, utility - version: 0.3 + 0.31 (2016-04-25): + update lesser vruul td offsets + 0.30 (2016-04-19): + add new Frozen Bramble area monsters + 0.29 (2015-07-22): + add support for Pestilence (716) + 0.28 (2015-07-12): + fix gross f/h in favor verb + add percentage completed to step to favor verb + 0.27 (2015-05-14): + favor clear bug again + 0.26 (2015-04-14): + fix "favor clear" bug + 0.25 (2014-12-20): + added frenzied monk + 0.24 (2014-12-20): + added bog spectre + 0.23 (2014-11-23): + added sacristan spirit + 0.22 (2014-11-21): + add more td offsets + 0.21 (2014-11-21): + add more messages for symbol of turning + add more td offsets + 0.17-0.20 (2014-11-18): + add more td offsets + 0.16 (2014-11-14): + fix bug with "favor set" + 0.15 (2014-11-13): + added accurate symbol cost for level 99 + 0.14 (2014-11-10): + added accurate symbol cost for level 98 + added minor elemental/spirit and sorcerer TD offset for triton defender + 0.13 (2014-10-12): + changed the critter levels for deadfall, still just estimates + 0.12 (2014-10-12): + fix bone shatter insta-death message + 0.11 (2014-10-11): + added more npcs + 0.10 (2014-10-11): + added message for bone shatter insta-death + 0.9 (2014-10-04): + added accurate symbol cost for level 97 =end +if Society.status !~ /Voln/ + dothistimeout 'society', 15, /You may view your society|You may reset your society|Past society affiliations/ + if Society.status !~ /Voln/ + echo "You don't seem to be a member of Voln. This script isn't for you." + exit + end +end + hide_me script.want_downstream = false script.want_downstream_xml = true -if Char.name == 'Useless' - globe_sets_favor = false -else - globe_sets_favor = true -end - $favor = CharSettings.to_hash $favor[:symbol] ||= 0 $favor[:step] ||= 0 -start_time = Time.now -start_step_favor = $favor[:step] -start_symbol_favor = $favor[:symbol] -guessed_globe = nil +$favor[:symbol_error] ||= 0 +$favor[:step_error] ||= 0 +# level 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 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, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100 +level_factor = [ nil, nil, nil, 1.225, 2.133, 3.133, 4.275, 5.55, 6.95, 8.45, 9.95, 11.633, 13.317, 15.05, 16.867, 18.725, 20.633, 22.55, 24.55, 26.55, 28.55, 30.633, 32.725, 34.817, 36.95, 39.05, 41.225, 43.367, 45.55, 47.775, 49.95, 52.225, 54.45, 56.725, 58.95, 61.225, 63.55, 65.817, 68.133, 70.45, 72.725, 75.05, 77.367, 79.683, 82.05, 84.367, 86.725, 89.05, 91.45, 93.775, 96.133, 98.55, 100.867, 103.275, 105.633, 108.05, 110.45, 112.817, 115.225, 117.633, 120.0, 122.45, 124.817, 127.225, 129.633, 132.05, 134.45, 136.867, 139.275, 141.683, 144.133, 146.55, 149.4, 151.367, 153.817, 156.225, 158.683, 161.133, 163.55, 165.95, 168.45, 170.867, 173.275, 175.725, 178.183, 180.633, 183.05, 185.55, 187.95, 190.45, 192.867, 195.317, 197.775, 200.225, 202.633, 205.133, 207.55, 210.05, 212.45, 214.95, 217.337 ] +globe_offset = [ nil, nil, nil, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21 ] +script_start = Time.now +step_start = Time.now +symbol_favor_gained = 0 +step_favor_gained = 0 +favor_used = 0 npc_td = LimitedArray.new npc_td.max_size = 50 immolated = LimitedArray.new immolated.max_size = 15 +pestilenced = LimitedArray.new +pestilenced.max_size = 15 weapon_fired = LimitedArray.new weapon_fired.max_size = 15 maelstromed = LimitedArray.new @@ -66,1453 +127,948 @@ lightning_called = LimitedArray.new lightning_called.max_size = 15 holy_bolted = LimitedArray.new holy_bolted.max_size = 15 -banshee_defence = LimitedArray.new -banshee_defence.max_size = 15 +banshee_defense = LimitedArray.new +banshee_defense.max_size = 15 deity = nil divine_wrath_active = false +na = nil npc = { - 'lesser ghoul' => { :lvl => 1 }, - 'skeleton' => { :lvl => 1 }, - 'zombie rolton' => { :lvl => 1 }, - 'frost shade' => { :lvl => 2 }, - 'moaning phantom' => { :lvl => 2 }, - 'ghost' => { :lvl => 2 }, - 'lesser shade' => { :lvl => 2 }, - 'phantom' => { :lvl => 2 }, - 'greater ghoul' => { :lvl => 3 }, - 'ice skeleton' => { :lvl => 3 }, - 'revenant' => { :lvl => 4 }, - 'mist wraith' => { :lvl => 4 }, - 'dark apparition' => { :lvl => 5 }, - 'spectral fisherman' => { :lvl => 6 }, - 'lesser mummy' => { :lvl => 6 }, - 'firephantom' => { :lvl => 6 }, - 'bone golem' => { :lvl => 8 }, - 'snow spectre' => { :lvl => 9 }, - 'death dirge' => { :lvl => 9 }, - 'werebear' => { :lvl => 10 }, - 'darkwoode' => { :lvl => 13 }, - 'shadowy spectre' => { :lvl => 14 }, - 'specter' => { :lvl => 14 }, - 'wolfshade' => { :lvl => 15 }, - 'tomb wight' => { :lvl => 15 }, - 'wraith' => { :lvl => 15 }, - 'ghoul master' => { :lvl => 16 }, - 'ghost wolf' => { :lvl => 16 }, - 'elder ghoul master' => { :lvl => 18 }, - 'ghostly warrior' => { :lvl => 18 }, - 'nedum vereri' => { :lvl => 18 }, - 'krolvin pirate' => { :lvl => 18 }, -# mnsp mjsp clrc mnel mjel rngr sorc wzrd bard emph mnme pldn - 'arch wight' => { :lvl => 20, :td_mod => [ nil, 0, 0, 0, 0, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Graveyard, Wehnimer's Landing - 'wood wight' => { :lvl => 20, :td_mod => [ nil, 0, 0, 0, 3, nil, nil, 1, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Marshtown, Solhaven - 'ancient ghoul master' => { :lvl => 21, :td_mod => [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Graveyard, Wehnimer's Landing - 'zombie' => { :lvl => 23, :td_mod => [ nil, 3, 3, 1, 8, nil, nil, 5, nil, nil, nil, nil, 0, nil, nil, nil, nil ] }, # Danjirland, Wehnimer's Landing + Icemule Environs, Icemule Trace - 'nonomino' => { :lvl => 23, :td_mod => [ nil, 0, 0, -2, 9, nil, nil, 3, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Castle Anwyn, Wehnimer's Landing - 'niirsha' => { :lvl => 23, :td_mod => [ nil, -5, -5, -7, 9, 8, nil, nil, nil, 8, nil, nil, nil, nil, nil, nil, nil ] }, # Lunule Weald, Ta'Vaalor - 'crazed zombie' => { :lvl => 23, :td_mod => [ nil, 3, 3, 1, 8, 7, nil, nil, nil, 7, nil, nil, nil, nil, nil, nil, nil ] }, # Lunule Weald, Ta'Vaalor - 'rotting woodsman' => { :lvl => 23, :td_mod => [ nil, 3, 3, 1, 8, nil, nil, 5, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Marshtown, Solhaven - 'night hound' => { :lvl => 24, :td_mod => [ nil, 29, 29, 27, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Graveyard, Wehnimer's Landing - 'spectral monk' => { :lvl => 25, :td_mod => [ nil, 15, 15, 13, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # The Monastery, Wehnimer's Landing - 'carceris' => { :lvl => 25, :td_mod => [ nil, 7, 7, 5, nil, nil, nil, 8, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Castle Anwyn, Wehnimer's Landing - 'tree spirit' => { :lvl => 26, :td_mod => [ nil, 6, 6, 4, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Lunule Weald, Ta'Vaalor + Foggy Valley, Solhaven + Danjirland, Wehnimer's Landing - 'monastic lich' => { :lvl => 27, :td_mod => [ nil, 24, 24, 23, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # The Monastary, Wehnimer's landing - 'moaning spirit' => { :lvl => 28, :td_mod => [ nil, 9, 9, 7, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Castle Anwyn, Wehnimer's landing + The Graveyard, Wehnimer's Landing - 'elder tree spirit' => { :lvl => 30, :td_mod => [ nil, 21, 21, 19, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Icemule Environs, Icemule Trace - 'ice troll' => { :lvl => 31, :td_mod => [ nil, 0, 0, 0, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Frozen Battlefield, Icemule Trace - 'ghostly mara' => { :lvl => 32, :td_mod => [ nil, 11, 11, 10, 13, 14, nil, nil, nil, 14, nil, nil, nil, nil, nil, nil, nil ] }, # Wraithenmist, Ta'Illistim - 'rotting farmhand' => { :lvl => 32, :td_mod => [ nil, 8, 8, 7, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Icemule Environs, Icemule Trace - 'rotting corpse' => { :lvl => 32, :td_mod => [ nil, 13, 13, 12, 23, nil, nil, 18, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Castle Varunar, Wehnimer's Landing/Solhaven - 'skeletal giant' => { :lvl => 33, :td_mod => [ nil, 7, 7, 6, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Sentoph, Wehnimer's Landing -# mnsp mjsp clrc mnel mjel rngr sorc wzrd bard emph mnme pldn - 'ghostly pooka' => { :lvl => 33, :td_mod => [ nil, 11, 11, 10, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Shadow Valley, Wehnimer's Landing - 'troll zombie' => { :lvl => 34, :td_mod => [ nil, 15, 15, 14, 27, 27, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Troll Burial Grounds, Zul Logoth - 'skeletal soldier' => { :lvl => 34, :td_mod => [ nil, 7, 7, 6, 19, 19, nil, nil, nil, 19, nil, nil, nil, nil, nil, nil, nil ] }, # Miasmal Forest, River's Rest - 'skeletal warrior' => { :lvl => 34, :td_mod => [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # fixme: does this exist? - 'spectral warrior' => { :lvl => 34, :td_mod => [ nil, 0, 0, 0, 1, 1, nil, nil, nil, 1, nil, nil, nil, nil, nil, nil, nil ] }, # The Citadel, River's Rest - 'troll wraith' => { :lvl => 35, :td_mod => [ nil, 11, 11, 11, 8, 8, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Troll Burial Grounds, Zul Logoth - 'spectral shade' => { :lvl => 35, :td_mod => [ nil, 24, 24, 24, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Foggy Valley, Solhaven - 'barghest' => { :lvl => 35, :td_mod => [ nil, 16, 16, 16, 29, 29, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Black Moor, Ta'Illistim - 'spectral woodsman' => { :lvl => 35, :td_mod => [ nil, 19, 19, 19, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Icemule Environs, Icemule Trace - 'spectral lord' => { :lvl => 36, :td_mod => [ nil, 0, 0, 0, 5, 6, nil, nil, nil, 6, nil, nil, nil, nil, nil, nil, nil ] }, # Wraithenmist, Ta'Illistim - 'shadow mare' => { :lvl => 37, :td_mod => [ nil, -1, -1, -2, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Shadow Valley, Wehnimer's Landing - 'skeletal warhorse' => { :lvl => 37, :td_mod => [ nil, 0, 0, 0, 0, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Castle Varunar, Wehnimer's Landing/Solhaven - 'lesser moor wight' => { :lvl => 37, :td_mod => [ nil, -1, -1, -2, 14, 14, nil, nil, nil, 14, nil, nil, nil, nil, nil, nil, nil ] }, # Miasmal Forest, River's Rest - 'shadow steed' => { :lvl => 38, :td_mod => [ nil, 18, 18, 17, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Shadow Valley, Wehnimer's Landing - 'vourkha' => { :lvl => 39, :td_mod => [ nil, 21, 21, 21, 25, 26, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Black Moor, Ta'Illistim - 'greater moor wight' => { :lvl => 39, :td_mod => [ nil, 28, 28, 28, 44, 45, nil, nil, nil, 45, nil, nil, nil, nil, nil, nil, nil ] }, # Black Moor, Ta'Illistim + Miasmal Forest, River's Rest - 'spectral miner' => { :lvl => 40, :td_mod => [ nil, 7, 7, 7, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Shadow Valley, Wehnimer's Landing - 'bog wraith' => { :lvl => 41, :td_mod => [ nil, -50, -50, -50, 13, 13, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Miasmal Forest, River's Rest -# mnsp mjsp clrc mnel mjel rngr sorc wzrd bard emph mnme pldn - 'skeletal lord' => { :lvl => 41, :td_mod => [ nil, 0, 0, 0, 15, nil, nil, 7, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Castle Varunar, Wehnimer's Landing/Solhaven - 'phantasma' => { :lvl => 42, :td_mod => [ nil, 0, 0, 1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Castle Varunar, Wehnimer's Landing/Solhaven - 'baesrukha' => { :lvl => 42, :td_mod => [ nil, 16, 16, 16, 12, 12, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Black Moor, Ta'Illistim - 'frozen corpse' => { :lvl => 42, :td_mod => [ nil, 16, 16, 17, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Nightmare Gorge, Wehnimer's Landing + Artic Tundra, Pinefar - 'night mare' => { :lvl => 43, :td_mod => [ nil, -14, -14, -13, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Shadow Valley, Wehnimer's Landing - 'spectral servant' => { :lvl => 44, :td_mod => [ nil, 36, 36, 37, 54, 55, nil, nil, nil, 55, nil, nil, nil, nil, nil, nil, nil ] }, # Marsh Keep, River's Rest - 'bog wight' => { :lvl => 44, :td_mod => [ nil, 12, 12, 13, 30, 31, nil, nil, nil, 31, nil, nil, nil, nil, nil, nil, nil ] }, # Fethayl Bog, Ta'Vaalor - 'ice wraith' => { :lvl => 45, :td_mod => [ nil, 31, 31, 31, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Nightmare Gorge, Wehnimer's Landing + Artic Tundra, Pinefar - 'lesser vruul' => { :lvl => 45, :td_mod => [ nil, -5, -5, -5, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # The Broken Lands, Wehnimer's Landing # immune to 400's, 500's, 900's - 'rotting chimera' => { :lvl => 46, :td_mod => [ nil, 29, 29, 30, 41, 42, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Marsh Keep, River's Rest - 'dybbuk' => { :lvl => 48, :td_mod => [ nil, 31, 31, 32, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Bonespear Tower, Solhaven - 'necrotic snake' => { :lvl => 48, :td_mod => [ nil, 31, 31, 32, 51, 52, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Marsh Keep, River's Rest - 'warrior shade' => { :lvl => 48, :td_mod => [ nil, 31, 31, 32, 51, 52, nil, nil, nil, 52, nil, nil, nil, nil, nil, nil, nil ] }, # Fethayl Bog, Ta'Vaalor - 'waern' => { :lvl => 49, :td_mod => [ nil, 32, 32, 33, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Bonespear Tower, Solhaven - 'banshee' => { :lvl => 50, :td_mod => [ nil, 43, 43, 45, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Darkstone Castle, Wehnimer's Landing + Fhorian Village - 'flesh golem' => { :lvl => 50, :td_mod => [ nil, 33, 33, 35, 54, 55, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Marsh Keep, River's Rest - 'seeker' => { :lvl => 52, :td_mod => [ nil, 31, 31, 33, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Mount Aenatumgana, Pinefar - 'mage apprentice' => { :lvl => 54, :td_mod => [ nil, 48, 48, 50, 71, 72, nil, nil, nil, 72, nil, nil, nil, nil, nil, nil, nil ] }, # The Citadel, River's Rest - 'nightmare steed' => { :lvl => 55, :td_mod => [ nil, 49, 49, 51, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Darkstone Castle, Wehnimer's Landing + The Broken Lands, Wehnimer's Landing - 'eidolon' => { :lvl => 55, :td_mod => [ nil, 27, 27, 29, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Bonespear Tower, Solhaven -# mnsp mjsp clrc mnel mjel rngr sorc wzrd bard emph mnme pldn - 'Citadel guardsman' => { :lvl => 56, :td_mod => [ nil, 13, 13, 15, 37, 38, nil, nil, nil, 38, nil, nil, nil, nil, nil, nil, nil ] }, # The Citadel, River's Rest - 'Citadel arbalester' => { :lvl => 58, :td_mod => [ nil, 25, 25, 28, 50, 52, nil, nil, nil, 52, nil, nil, nil, nil, nil, nil, nil ] }, # The Citadel, River's Rest - 'Citadel herald' => { :lvl => 60, :td_mod => [ nil, 56, 56, 59, 83, 84, nil, nil, nil, 84, nil, nil, nil, nil, nil, nil, nil ] }, # The Citadel, River's Rest - 'bestial swordsman' => { :lvl => 62, :td_mod => [ nil, 47, 47, 50, 74, 76, nil, nil, nil, 76, nil, nil, nil, nil, nil, nil, nil ] }, # The Citadel, River's Rest - 'soul golem' => { :lvl => 63, :td_mod => [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Temple of Luukos, Teras Isle - 'wind wraith' => { :lvl => 63, :td_mod => [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Temple of Luukos, Teras Isle - 'greater vruul' => { :lvl => 75, :td_mod => [ nil, -5, -5, -5, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # The Broken Lands, Wehnimer's Landing # immune to 400's, 500's, 900's - 'naisirc' => { :lvl => 75, :td_mod => [ nil, 71, 71, 76, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # The Rift, Pinefar - 'shrickhen' => { :lvl => 76, :td_mod => [ nil, 63, 63, 68, 88, 91, nil, nil, nil, 91, nil, nil, nil, nil, nil, nil, nil ] }, # Blighted Forest, Ta'Illistim - 'seraceris' => { :lvl => 78, :td_mod => [ nil, 41, 41, 46, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # The Rift, Pinefar - "lich qyn'arj" => { :lvl => 84, :td_mod => [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, - "n'ecare" => { :lvl => 87, :td_mod => [ nil, 59, 59, 65, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # The Rift, Pinefar - 'lost soul' => { :lvl => 91, :td_mod => [ nil, 82, 82, 89, 106, 109, nil, nil, nil, 109, nil, nil, nil, nil, nil, nil, nil ] }, # The Rift, Pinefar - 'vaespilon' => { :lvl => 93, :td_mod => [ nil, 46, 46, 54, 90, 93, nil, nil, nil, 93, nil, nil, nil, nil, nil, nil, nil ] }, # The Rift, Pinefar - 'fallen crusader' => { :lvl => 97, :td_mod => [ nil, -8, -8, 0, 57, 60, nil, nil, nil, 60, nil, nil, nil, nil, nil, nil, nil ] }, # The Rift, Pinefar - 'triton defender' => { :lvl => 98, :td_mod => [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Temple Nelemar, Teras Isle - 'triton sentry' => { :lvl => 103, :td_mod => [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Temple Nelemar, Teras Isle - 'soul siphon' => { :lvl => 106, :td_mod => [ nil, 103, 103, 112, 135, 139, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # The Rift, Icemule - 'infernal lich' => { :lvl => 110, :td_mod => [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # The Rift, Icemule - 'frostborne lich' => { :lvl => 110, :td_mod => [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # The Rift, Icemule + 'lesser ghoul' => { :lvl => 1 }, + 'skeleton' => { :lvl => 1 }, + 'zombie rolton' => { :lvl => 1 }, + 'frost shade' => { :lvl => 2 }, + 'moaning phantom' => { :lvl => 2 }, + 'ghost' => { :lvl => 2 }, + 'lesser shade' => { :lvl => 2 }, + 'phantom' => { :lvl => 2 }, + 'greater ghoul' => { :lvl => 3 }, + 'ice skeleton' => { :lvl => 3 }, + 'revenant' => { :lvl => 4 }, + 'mist wraith' => { :lvl => 4 }, + 'dark apparition' => { :lvl => 5 }, + 'spectral fisherman' => { :lvl => 6 }, + 'lesser mummy' => { :lvl => 6 }, + 'firephantom' => { :lvl => 6 }, + 'bone golem' => { :lvl => 8 }, + 'snow spectre' => { :lvl => 9 }, + 'death dirge' => { :lvl => 9 }, + 'werebear' => { :lvl => 10 }, + 'darkwoode' => { :lvl => 13 }, + 'shadowy spectre' => { :lvl => 14 }, + 'spectre' => { :lvl => 14 }, + 'wolfshade' => { :lvl => 15 }, + 'tomb wight' => { :lvl => 15 }, + 'wraith' => { :lvl => 15 }, + 'ghoul master' => { :lvl => 16 }, + 'ghost wolf' => { :lvl => 16 }, + 'elder ghoul master' => { :lvl => 18 }, + 'ghostly warrior' => { :lvl => 18 }, + 'nedum vereri' => { :lvl => 18 }, + 'krolvin pirate' => { :lvl => 18 }, +# mnsp mjsp clrc mnel mjel rngr sorc wzrd bard emph mnme pldn + 'arch wight' => { :lvl => 20, :td_mod => [ na, 0, 0, 0, 0, 0, nil, 0, na, 0, nil, -19, nil, na, na, na, nil ] }, # Graveyard, Wehnimer's Landing + 'wood wight' => { :lvl => 20, :td_mod => [ na, 0, 0, 0, 3, 2, nil, 1, na, na, nil, nil, nil, na, na, na, nil ] }, # Marshtown, Solhaven + 'ancient ghoul master' => { :lvl => 21, :td_mod => [ na, nil, nil, nil, nil, nil, nil, nil, na, nil, nil, nil, nil, na, na, na, nil ] }, # Graveyard, Wehnimer's Landing + 'zombie' => { :lvl => 23, :td_mod => [ na, 3, 3, 1, 8, 7, 0, 5, na, na, 0, 3, nil, na, na, na, nil ] }, # Danjirland, Wehnimer's Landing + Icemule Environs, Icemule Trace + 'nonomino' => { :lvl => 23, :td_mod => [ na, 0, 0, -2, 9, 8, nil, 3, na, 8, nil, nil, nil, na, na, na, nil ] }, # Castle Anwyn, Wehnimer's Landing + 'niirsha' => { :lvl => 23, :td_mod => [ na, -5, -5, -7, 9, 8, nil, 3, na, 8, nil, nil, nil, na, na, na, nil ] }, # Lunule Weald, Ta'Vaalor + 'crazed zombie' => { :lvl => 23, :td_mod => [ na, 3, 3, 1, 8, 7, nil, 5, na, 7, nil, nil, nil, na, na, na, nil ] }, # Lunule Weald, Ta'Vaalor + 'rotting woodsman' => { :lvl => 23, :td_mod => [ na, 3, 3, 1, 8, 7, nil, 5, na, 7, nil, nil, nil, na, na, na, nil ] }, # Marshtown, Solhaven + 'night hound' => { :lvl => 24, :td_mod => [ na, 29, 29, 27, 35, 40, nil, 32, na, na, nil, 18, nil, na, na, na, nil ] }, # Graveyard, Wehnimer's Landing + 'spectral monk' => { :lvl => 25, :td_mod => [ na, 15, 15, 13, 23, 23, nil, 21, na, 23, nil, nil, nil, na, na, na, nil ] }, # The Monastery, Wehnimer's Landing + 'carceris' => { :lvl => 25, :td_mod => [ na, 7, 7, 5, 11, 11, nil, 9, na, na, nil, nil, nil, na, na, na, nil ] }, # Castle Anwyn, Wehnimer's Landing + 'sacristan spirit' => { :lvl => 25, :td_mod => [ na, nil, nil, nil, nil, nil, nil, nil, na, nil, nil, nil, nil, na, na, na, nil ] }, # Lunule Weald, Ta'Vaalor + 'tree spirit' => { :lvl => 26, :td_mod => [ na, 6, 6, 4, 13, 13, nil, 10, na, na, nil, nil, nil, na, na, na, nil ] }, # Lunule Weald, Ta'Vaalor + Foggy Valley, Solhaven + Danjirland, Wehnimer's Landing + 'monastic lich' => { :lvl => 27, :td_mod => [ na, 24, 24, 23, 34, 34, nil, 31, na, 34, nil, nil, nil, na, na, na, nil ] }, # The Monastary, Wehnimer's landing + 'frenzied monk' => { :lvl => 27, :td_mod => [ na, nil, nil, nil, nil, nil, nil, nil, na, nil, nil, nil, nil, na, na, na, nil ] }, # Lunule Weald, Ta'Vaalor + 'moaning spirit' => { :lvl => 28, :td_mod => [ na, 9, 9, 7, 17, 18, nil, 13, na, na, nil, nil, nil, na, na, na, nil ] }, # Castle Anwyn, Wehnimer's landing + The Graveyard, Wehnimer's Landing + 'elder tree spirit' => { :lvl => 30, :td_mod => [ na, 21, 21, 19, 30, 30, 3, 25, na, na, 9, 21, nil, na, na, na, nil ] }, # Icemule Environs, Icemule Trace + 'ice troll' => { :lvl => 31, :td_mod => [ na, 0, 0, 0, 0, 0, nil, 0, na, 0, nil, nil, nil, na, na, na, nil ] }, # Frozen Battlefield, Icemule Trace + 'ghostly mara' => { :lvl => 32, :td_mod => [ na, 11, 11, 10, 13, 14, nil, 14, na, 14, nil, nil, nil, na, na, na, nil ] }, # Wraithenmist, Ta'Illistim + 'rotting farmhand' => { :lvl => 32, :td_mod => [ na, 8, 8, 7, 18, 19, 0, 13, na, 19, 0, 8, nil, na, na, na, nil ] }, # Icemule Environs, Icemule Trace + 'rotting corpse' => { :lvl => 32, :td_mod => [ na, 13, 13, 12, 23, 24, nil, 18, na, 24, nil, nil, nil, na, na, na, nil ] }, # Castle Varunar, Wehnimer's Landing/Solhaven + 'skeletal giant' => { :lvl => 33, :td_mod => [ na, 7, 7, 6, 18, 19, nil, 13, na, 19, nil, nil, nil, na, na, na, nil ] }, # Sentoph, Wehnimer's Landing + 'ghostly pooka' => { :lvl => 33, :td_mod => [ na, 14, nil, nil, 27, nil, nil, 23, na, na, nil, nil, nil, na, na, na, nil ] }, # Shadow Valley, Wehnimer's Landing +# mnsp mjsp clrc mnel mjel rngr sorc wzrd bard emph mnme pldn + 'troll zombie' => { :lvl => 34, :td_mod => [ na, 15, 15, 14, 27, 27, nil, 21, na, na, nil, nil, nil, na, na, na, nil ] }, # Troll Burial Grounds, Zul Logoth + 'skeletal soldier' => { :lvl => 34, :td_mod => [ na, 7, 7, 6, 19, 19, nil, 13, na, 19, nil, nil, nil, na, na, na, nil ] }, # Miasmal Forest, River's Rest + 'spectral warrior' => { :lvl => 34, :td_mod => [ na, 0, 0, 0, 1, 1, nil, 0, na, 1, nil, nil, nil, na, na, na, nil ] }, # The Citadel, River's Rest + 'troll wraith' => { :lvl => 35, :td_mod => [ na, 11, 11, 11, 8, 8, nil, 12, na, na, nil, nil, nil, na, na, na, nil ] }, # Troll Burial Grounds, Zul Logoth + 'spectral shade' => { :lvl => 35, :td_mod => [ na, 24, 24, 24, 35, 35, nil, 30, na, 35, nil, nil, nil, na, na, na, nil ] }, # Foggy Valley, Solhaven + 'barghest' => { :lvl => 35, :td_mod => [ na, 16, 16, 16, 29, 29, nil, 23, na, na, nil, nil, nil, na, na, na, nil ] }, # Black Moor, Ta'Illistim + 'spectral woodsman' => { :lvl => 35, :td_mod => [ na, 19, 19, 19, 30, 30, nil, 25, na, 30, nil, nil, nil, na, na, na, nil ] }, # Icemule Environs, Icemule Trace + 'spectral lord' => { :lvl => 36, :td_mod => [ na, 0, 0, 0, 5, 6, nil, 0, na, 6, nil, nil, nil, na, na, na, nil ] }, # Wraithenmist, Ta'Illistim + 'icy bush' => { :lvl => 36, :td_mod => [ na, 21, nil, nil, 33, 34, nil, 27, na, na, nil, nil, nil, na, na, na, nil ] }, # Icemule, Frozen Bramble + 'shadow mare' => { :lvl => 37, :td_mod => [ na, -1, -1, -2, 22, 22, nil, 10, na, na, nil, nil, nil, na, na, na, nil ] }, # Shadow Valley, Wehnimer's Landing + 'skeletal warhorse' => { :lvl => 37, :td_mod => [ na, 3, nil, nil, 3, nil, nil, 3, na, na, nil, nil, nil, na, na, na, nil ] }, # Castle Varunar, Wehnimer's Landing/Solhaven + 'lesser moor wight' => { :lvl => 37, :td_mod => [ na, -1, -1, -2, 14, 14, nil, 8, na, 14, nil, nil, nil, na, na, na, nil ] }, # Miasmal Forest, River's Rest + 'shadow steed' => { :lvl => 38, :td_mod => [ na, 18, 18, 17, 30, 30, nil, 24, na, na, nil, nil, nil, na, na, na, nil ] }, # Shadow Valley, Wehnimer's Landing + 'decaying tumbleweed' => { :lvl => 38, :td_mod => [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Bramble Patch + 'vourkha' => { :lvl => 39, :td_mod => [ na, 21, 21, 21, 25, 26, nil, 23, na, na, nil, nil, nil, na, na, na, nil ] }, # Black Moor, Ta'Illistim + 'greater moor wight' => { :lvl => 39, :td_mod => [ na, 28, 28, 28, 44, 45, nil, 38, na, 45, nil, nil, nil, na, na, na, nil ] }, # Black Moor, Ta'Illistim + Miasmal Forest, River's Rest + 'decaying tumbleweed' => { :lvl => 39, :td_mod => [ na, 24, nil, nil, 38, 39, nil, 31, na, na, nil, nil, nil, na, na, na, nil ] }, # Icemule, Frozen Bramble + 'spectral miner' => { :lvl => 40, :td_mod => [ na, 7, 7, 7, 31, 32, nil, 21, na, 32, nil, nil, nil, na, na, na, nil ] }, # Shadow Valley, Wehnimer's Landing + 'frost-glazed vine' => { :lvl => 40, :td_mod => [ na, 45, nil, nil, 60, 61, nil, 53, na, na, nil, nil, nil, na, na, na, nil ] }, # Icemule, Frozen Bramble + 'bog wraith' => { :lvl => 41, :td_mod => [ na, -50, -50, -50, 13, 13, nil, -18, na, na, nil, nil, nil, na, na, na, nil ] }, # Miasmal Forest, River's Rest + 'skeletal lord' => { :lvl => 41, :td_mod => [ na, 3, nil, nil, 18, nil, nil, 10, na, nil, nil, nil, nil, na, na, na, nil ] }, # Castle Varunar, Wehnimer's Landing/Solhaven + 'phantasma' => { :lvl => 42, :td_mod => [ na, 0, 0, 1, 16, 16, nil, 12, na, 16, nil, nil, nil, na, na, na, nil ] }, # Castle Varunar, Wehnimer's Landing/Solhaven + 'baesrukha' => { :lvl => 42, :td_mod => [ na, 15, 16, 16, 12, 12, nil, 16, na, na, nil, nil, nil, na, na, na, nil ] }, # Black Moor, Ta'Illistim + 'frozen corpse' => { :lvl => 42, :td_mod => [ na, 16, 16, 17, 33, 33, nil, 25, na, 33, nil, nil, nil, na, na, na, nil ] }, # Nightmare Gorge, Wehnimer's Landing + Artic Tundra, Icemule +# mnsp mjsp clrc mnel mjel rngr sorc wzrd bard emph mnme pldn + 'night mare' => { :lvl => 43, :td_mod => [ na, -14, -14, -13, 20, 21, nil, 7, na, na, nil, nil, nil, na, na, na, nil ] }, # Shadow Valley, Wehnimer's Landing + 'spectral servant' => { :lvl => 44, :td_mod => [ na, 36, 36, 37, 54, 55, nil, 45, na, 55, nil, nil, nil, na, na, na, nil ] }, # Marsh Keep, River's Rest + 'bog wight' => { :lvl => 44, :td_mod => [ na, 12, 12, 13, 30, 31, nil, 21, na, 31, nil, nil, nil, na, na, na, nil ] }, # Fethayl Bog, Ta'Vaalor + 'frosty plant' => { :lvl => 44, :td_mod => [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Bramble Patch + 'ice wraith' => { :lvl => 45, :td_mod => [ na, 31, 31, 31, 37, 37, nil, 34, na, 37, nil, nil, nil, na, na, na, nil ] }, # Nightmare Gorge + Artic Tundra, Icemule + 'lesser vruul' => { :lvl => 45, :td_mod => [ na, -2, nil, nil, na, na, nil, 21, na, na, nil, nil, nil, na, na, na, nil ] }, # The Broken Lands, Wehnimer's Landing + 'frosty plant' => { :lvl => 45, :td_mod => [ na, 51, nil, nil, 69, 69, nil, 60, na, na, nil, nil, nil, na, na, na, nil ] }, # Icemule, Frozen Bramble + 'rotting chimera' => { :lvl => 46, :td_mod => [ na, 29, 29, 30, 47, 48, nil, 38, na, na, nil, nil, nil, na, na, na, nil ] }, # Marsh Keep, River's Rest + 'bog spectre' => { :lvl => 47, :td_mod => [ na, nil, nil, nil, nil, nil, nil, nil, na, na, nil, nil, nil, na, na, na, nil ] }, # Fethayl Bog, Ta'Vaalor + 'dybbuk' => { :lvl => 48, :td_mod => [ na, 31, 31, 32, 51, 52, nil, 41, na, 52, nil, nil, nil, na, na, na, nil ] }, # Bonespear Tower, Solhaven + 'necrotic snake' => { :lvl => 48, :td_mod => [ na, 31, 31, 32, 51, 52, nil, 41, na, na, nil, nil, nil, na, na, na, nil ] }, # Marsh Keep, River's Rest + 'warrior shade' => { :lvl => 48, :td_mod => [ na, 31, 31, 32, 51, 52, nil, 41, na, 52, nil, nil, nil, na, na, na, nil ] }, # Fethayl Bog, Ta'Vaalor + 'thorned shrub' => { :lvl => 48, :td_mod => [ na, 34, nil, nil, 54, 55, nil, 44, na, na, nil, nil, nil, na, na, na, nil ] }, # Icemule, Frozen Bramble + 'waern' => { :lvl => 49, :td_mod => [ na, 32, 32, 33, 52, 53, nil, 43, na, na, nil, nil, nil, na, na, na, nil ] }, # Bonespear Tower, Solhaven + 'icy creeper' => { :lvl => 49, :td_mod => [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Bramble Patch + 'thorned shrub' => { :lvl => 49, :td_mod => [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] }, # Bramble Patch + 'banshee' => { :lvl => 50, :td_mod => [ na, 43, 43, 45, 64, 65, nil, 54, na, na, nil, nil, nil, na, na, na, nil ] }, # Darkstone Castle, Wehnimer's Landing + Fhorian Village + 'flesh golem' => { :lvl => 50, :td_mod => [ na, 33, 33, 35, 54, 55, nil, 44, na, na, nil, nil, nil, na, na, na, nil ] }, # Marsh Keep, River's Rest + 'icy creeper' => { :lvl => 50, :td_mod => [ na, 36, nil, nil, 57, 58, nil, 47, na, na, nil, nil, nil, na, na, na, nil ] }, # Icemule, Frozen Bramble + 'seeker' => { :lvl => 52, :td_mod => [ na, 31, 31, 33, 58, 60, 19, 47, na, 60, 22, 46, nil, na, na, na, nil ] }, # Mount Aenatumgana, Icemule + 'mage apprentice' => { :lvl => 54, :td_mod => [ na, 48, 48, 50, 71, 72, nil, 60, na, 72, nil, nil, nil, na, na, na, nil ] }, # The Citadel, River's Rest + 'nightmare steed' => { :lvl => 55, :td_mod => [ na, 49, 49, 51, 72, 74, nil, 61, na, na, nil, nil, nil, na, na, na, nil ] }, # Darkstone Castle, Wehnimer's Landing + The Broken Lands, Wehnimer's Landing + 'eidolon' => { :lvl => 55, :td_mod => [ na, 27, 27, 29, 52, 54, nil, 44, na, na, nil, nil, nil, na, na, na, nil ] }, # Bonespear Tower, Solhaven + 'Citadel guardsman' => { :lvl => 56, :td_mod => [ na, 13, 13, 15, 37, 38, nil, 26, na, 38, nil, nil, nil, na, na, na, nil ] }, # The Citadel, River's Rest + 'Citadel arbalester' => { :lvl => 58, :td_mod => [ na, 25, 25, 28, 50, 52, nil, 38, na, 52, nil, nil, nil, na, na, na, nil ] }, # The Citadel, River's Rest + 'Citadel herald' => { :lvl => 60, :td_mod => [ na, 56, 56, 59, 83, 84, nil, 70, na, 84, nil, nil, nil, na, na, na, nil ] }, # The Citadel, River's Rest +# mnsp mjsp clrc mnel mjel rngr sorc wzrd bard emph mnme pldn + 'bestial swordsman' => { :lvl => 62, :td_mod => [ na, 47, 47, 50, 74, 76, nil, 61, na, 76, nil, nil, nil, na, na, na, nil ] }, # The Citadel, River's Rest + 'soul golem' => { :lvl => 63, :td_mod => [ na, na, nil, nil, na, na, nil, na, na, na, nil, nil, nil, na, na, na, nil ] }, # Temple of Luukos, Teras Isle + 'wind wraith' => { :lvl => 63, :td_mod => [ na, 58, nil, nil, 86, 87, nil, 73, na, na, nil, nil, nil, na, na, na, nil ] }, # Temple of Luukos, Teras Isle + 'greater vruul' => { :lvl => 75, :td_mod => [ na, -5, -5, -5, na, na, nil, nil, na, na, nil, nil, nil, na, na, na, nil ] }, # The Broken Lands, Wehnimer's Landing + 'naisirc' => { :lvl => 75, :td_mod => [ na, 51, 51, 56, 95, 97, nil, 75, na, na, nil, nil, nil, na, na, na, nil ] }, # The Rift, Icemule + 'shrickhen' => { :lvl => 76, :td_mod => [ na, 63, 63, 68, 88, 91, nil, 79, na, 91, nil, nil, nil, na, na, na, nil ] }, # Blighted Forest, Ta'Illistim + 'seraceris' => { :lvl => 78, :td_mod => [ na, 41, 41, 46, 84, 86, nil, 68, na, na, nil, nil, nil, na, na, na, nil ] }, # The Rift, Icemule + "lich qyn'arj" => { :lvl => 84, :td_mod => [ na, nil, nil, nil, nil, nil, nil, nil, na, nil, nil, nil, nil, na, na, na, nil ] }, + "n'ecare" => { :lvl => 87, :td_mod => [ na, 59, 59, 65, 98, 101, nil, 81, na, 101, nil, nil, nil, na, na, na, nil ] }, # The Rift, Icemule + 'lost soul' => { :lvl => 91, :td_mod => [ na, 82, 82, 89, 106, 109, nil, 99, na, 109, nil, nil, nil, na, na, na, nil ] }, # The Rift, Icemule + 'vaespilon' => { :lvl => 93, :td_mod => [ na, 46, 46, 54, 90, 93, nil, 75, na, 93, nil, nil, nil, na, na, na, nil ] }, # The Rift, Icemule + 'fallen crusader' => { :lvl => 97, :td_mod => [ na, 27, -8, 0, 92, 60, nil, 64, na, 60, nil, nil, nil, na, na, na, nil ] }, # The Rift, Icemule + 'triton defender' => { :lvl => 98, :td_mod => [ na, 59, nil, nil, 102, 106, nil, 85, na, 106, nil, nil, nil, na, na, na, nil ] }, # Temple Nelemar, Teras Isle + 'triton sentry' => { :lvl => 103, :td_mod => [ na, 63, nil, nil, 122, 127, nil, 98, na, 127, nil, nil, nil, na, na, na, nil ] }, # Temple Nelemar, Teras Isle + 'soul siphon' => { :lvl => 106, :td_mod => [ na, 103, 103, 112, 135, 139, nil, 125, na, na, nil, nil, nil, na, na, na, nil ] }, # The Rift, Icemule + 'infernal lich' => { :lvl => 110, :td_mod => [ na, nil, nil, nil, nil, nil, nil, nil, na, nil, nil, nil, nil, na, na, na, nil ] }, # The Rift, Icemule + 'frostborne lich' => { :lvl => 110, :td_mod => [ na, nil, nil, nil, nil, nil, nil, nil, na, nil, nil, nil, nil, na, na, na, nil ] }, # The Rift, Icemule + "Wehnimer's militiaman"=> { :lvl => 104 }, # level not checked + "Taladorian mage" => { :lvl => 104 }, # level not checked + "Taladorian knights" => { :lvl => 104 }, # level not checked + "night serpent" => { :lvl => 97 }, # level not checked } spell_bonus = { -# mnsp mjsp clrc mnel mjel rngr sorc wzrd bard emph mnme pldn - /^The light blue glow leaves/ => [ nil, 10, 10, 10, 5, 5, 10, 8, nil, 5, 5, 10, nil, nil, nil, nil, 10 ], # 101 - /^The deep blue glow leaves/ => [ nil, 15, 15, 15, 7, 7, 15, 11, nil, 7, 7, 15, nil, nil, nil, nil, 15 ], # 107 - /^The very powerful look leaves/ => [ nil, 20, 20, 20, 10, 10, 20, 15, nil, 10, 10, 20, nil, nil, nil, nil, 20 ], # 120 -# /^The white light leaves/ => [ nil, 20, 20, 20, 10, 10, 20, 15, nil, 10, 10, 20, nil, nil, nil, nil, 20 ], # 120 gives two messages - /^The opalescent aura fades from around/ => [ nil, 30, 30, 30, 15, 15, 30, 22, nil, 15, 15, 30, nil, nil, nil, nil, 30 ], # 219 - /seems slightly different\.$/ => [ nil, 20, 20, 20, 10, 10, 20, 15, nil, 10, 10, 20, nil, nil, nil, nil, 20 ], # 310 - /^A subtle light fades from/ => [ nil, 10, 10, 10, 5, 5, 10, 8, nil, 5, 5, 10, nil, nil, nil, nil, 10 ], # 313 - /^The silvery luminescence fades from around/ => [ nil, 2, 2, 2, 5, 5, 2, 4, nil, 5, 5, 2, nil, nil, nil, nil, 2 ], # 401 - /^The bright luminescence fades from around/ => [ nil, 5, 5, 5, 10, 10, 5, 8, nil, 10, 10, 5, nil, nil, nil, nil, 5 ], # 406 - /^The brilliant luminescence fades from around/ => [ nil, 7, 7, 7, 15, 15, 7, 11, nil, 15, 15, 7, nil, nil, nil, nil, 7 ], # 414 - /^The tingling sensation and sense of security leaves/ => [ nil, 15, 15, 15, 30, 30, 15, nil, nil, 30, 30, 15, nil, nil, nil, nil, 15 ], # 430 - /appears somehow different\.$/ => [ nil, 10, 10, 10, 20, 20, 10, 15, nil, 20, 20, 10, nil, nil, nil, nil, 10 ], # 508 - /seems to lose an aura of confidence\.$/ => [ nil, 20, 20, 20, 10, 10, 20, 15, nil, 10, 10, 20, nil, nil, nil, nil, 20 ], # 613 - # fixme: 625 - /^A shadow seems to detach itself from/ => [ nil, 27, 27, 27, 13, 13, 20, 15, nil, 13, 13, 27, nil, nil, nil, nil, 27 ], # 712 # fixme -# /^A luminescent aura fades from around/ => [ ? ] # 913 - # fixme: 1109 - # fixme: 1119 - # fixme: 1208 - # fixme: 1601 - # fixme: 1619 +# mnsp mjsp clrc mnel mjel rngr sorc wzrd bard emph mnme pldn + /^The light blue glow leaves/ => [ na, 10, 10, 10, 5, 5, 10, 8, na, 5, 5, 10, nil, na, na, na, 10 ], # 101 + /^The deep blue glow leaves/ => [ na, 15, 15, 15, 7, 7, 15, 11, na, 7, 7, 15, nil, na, na, na, 15 ], # 107 + /^The very powerful look leaves/ => [ na, 20, 20, 20, 10, 10, 20, 15, na, 10, 10, 20, nil, na, na, na, 20 ], # 120 +# /^The white light leaves/ => [ na, 20, 20, 20, 10, 10, 20, 15, na, 10, 10, 20, nil, na, na, na, 20 ], # 120 gives two messages + /^The opalescent aura fades from around/ => [ na, 30, 30, 30, 15, 15, 30, 23, na, 15, 15, 30, nil, na, na, na, 30 ], # 219 + /seems slightly different\.$/ => [ na, 20, 20, 20, 10, 10, 20, 15, na, 10, 10, 20, nil, na, na, na, 20 ], # 310 + /^A subtle light fades from/ => [ na, 10, 10, 10, 5, 5, 10, 7, na, 5, 5, 10, nil, na, na, na, 10 ], # 313 + /^The silvery luminescence fades from around/ => [ na, 2, 2, 2, 5, 5, 2, 3, na, 5, 5, 2, nil, na, na, na, 2 ], # 401 + /^The bright luminescence fades from around/ => [ na, 5, 5, 5, 10, 10, 5, 8, na, 10, 10, 5, nil, na, na, na, 5 ], # 406 + /^The brilliant luminescence fades from around/ => [ na, 7, 7, 7, 15, 15, 7, 11, na, 15, 15, 7, nil, na, na, na, 7 ], # 414 + /^The tingling sensation and sense of security leaves/ => [ na, 15, 15, 15, 30, 30, 15, 23, na, 30, 30, 15, nil, na, na, na, 15 ], # 430 # fixme: guessed sorc + /appears somehow different\.$/ => [ na, 10, 10, 10, 20, 20, 10, 15, na, 20, 20, 10, nil, na, na, na, 10 ], # 508 + /seems to lose an aura of confidence\.$/ => [ na, 20, 20, 20, 10, 10, 20, 15, na, 10, 10, 20, nil, na, na, na, 20 ], # 613 + # fixme: 625 + /^A shadow seems to detach itself from/ => [ na, 27, 27, 27, 13, 13, 20, 15, nil, 13, 13, 27, nil, na, na, na, 27 ], # 712 # fixme +# /^A luminescent aura fades from around/ => [ ? ] # 913 + # fixme: 1109 + # fixme: 1119 + # fixme: 1208 + # fixme: 1601 + # fixme: 1619 } divine_wrath_message = { - 'Charl' => /^White sparks flicker around you, and you sense electrical energy gathering in the instant before a massive bolt of lightning spears toward/, - 'Cholen' => /^A throwing knife formed of shimmering golden light hurtles from the hand of one of the spirit jesters toward/, - 'Eonak' => /^Within the reddish haze swirling beside/, - 'Imaera' => /^A brown stag materializes in midair, leaping out of nowhere to try to impale/, - 'Jastev' => /^A beam of .*? light lances away from the rainbow around you to strike/, - 'Koar' => /^An aura of divine golden light blazes into existence around/, - 'Lorminstra' => /^As several faintly glowing snowflakes settle upon/, - 'Lumnis' => /^Guided by the knowledge within you, you concentrate upon/, - 'Ronan' => /^Seen only by your spirit gaze, one of the dream unicorns lowers its head and charges fiercely toward/, - 'Tonis' => /^Accompanied by a particularly impressive gust of wind, a fleeting golden blur flashes past/, - 'Gosaena' => /^An ethereal pair of feathered white wings materializes from midair and closes around/, - 'Zelia' => /^You notice .*? nearby\. How marvelous!/, - 'Eorgina' => /^Shimmering black flames lash out toward/, - 'Fash\'lo\'nae' => /^A matte grey scalpel appears from midair, and it moves with evident purpose to take a deliberate, methodical slice at/, - 'Luukos' => /^Long, spectral talons materialize from midair to tear viciously at the body of/, - 'Marlu' => /^A tendril of black mist suddenly senses the proximity of/, - 'Mularos' => /^The ethereal barbed whip that lies loosely coiled around you uncoils at terrifying speed\. It snaps out toward/, - 'Sheru' => /^Suddenly, .*? tries to bolt away, but instead smashes into a wall of spectral force hidden within the shadows!/, - 'V\'tull' => /^Divine will surges through you, and you command the scimitar to strike at/, - 'the Huntress' => /^A silver-bladed scythe materializes from thin air, spinning end over end as it hurtles toward/, - 'Laethe' => /^A shadowy black rose touches/, - 'Leya' => /^A dagger of ivory light suddenly flashes away from the aura surrounding you to strike at/, - 'Niima' => /^As the song from the pillar of water crescendos, it reaches a pitch that normally only trained bards can achieve, and the intense waves of elegant sound focus upon/, - 'Voaris' => /^A glowing golden rose touches/, - # fixme: missing Kai, Oleani, Phoen, Andelas, Ivas, Aeia, Amasalen, Arachne, Jaston, Kuon, Onar, Tilamaire, Voln + 'Charl' => /^White sparks flicker around you, and you sense electrical energy gathering in the instant before a massive bolt of lightning spears toward/, + 'Cholen' => /^A throwing knife formed of shimmering golden light hurtles from the hand of one of the spirit jesters toward/, + 'Eonak' => /^Within the reddish haze swirling beside/, + 'Imaera' => /^A brown stag materializes in midair, leaping out of nowhere to try to impale/, + 'Jastev' => /^A beam of .*? light lances away from the rainbow around you to strike/, + 'Koar' => /^An aura of divine golden light blazes into existence around/, + 'Lorminstra' => /^As several faintly glowing snowflakes settle upon/, + 'Lumnis' => /^Guided by the knowledge within you, you concentrate upon/, + 'Ronan' => /^Seen only by your spirit gaze, one of the dream unicorns lowers its head and charges fiercely toward/, + 'Tonis' => /^Accompanied by a particularly impressive gust of wind, a fleeting golden blur flashes past/, + 'Gosaena' => /^An ethereal pair of feathered white wings materializes from midair and closes around/, + 'Zelia' => /^You notice .*? nearby\. How marvelous!/, + 'Eorgina' => /^Shimmering black flames lash out toward/, + 'Fash\'lo\'nae' => /^A matte grey scalpel appears from midair, and it moves with evident purpose to take a deliberate, methodical slice at/, + 'Luukos' => /^Long, spectral talons materialize from midair to tear viciously at the body of/, + 'Marlu' => /^A tendril of black mist suddenly senses the proximity of/, + 'Mularos' => /^The ethereal barbed whip that lies loosely coiled around you uncoils at terrifying speed\. It snaps out toward/, + 'Sheru' => /^Suddenly, .*? tries to bolt away, but instead smashes into a wall of spectral force hidden within the shadows!/, + 'V\'tull' => /^Divine will surges through you, and you command the scimitar to strike at/, + 'the Huntress' => /^A silver-bladed scythe materializes from thin air, spinning end over end as it hurtles toward/, + 'Laethe' => /^A shadowy black rose touches/, + 'Leya' => /^A dagger of ivory light suddenly flashes away from the aura surrounding you to strike at/, + 'Niima' => /^As the song from the pillar of water crescendos, it reaches a pitch that normally only trained bards can achieve, and the intense waves of elegant sound focus upon/, + 'Voaris' => /^A glowing golden rose touches/, + # fixme: missing Kai, Oleani, Phoen, Andelas, Ivas, Aeia, Amasalen, Arachne, Jaston, Kuon, Onar, Tilamaire, Voln } spell_circle_list = [ 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 16 ] add_commas = proc { |num| - num.to_s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse -} - -globe_offset = proc { - if XMLData.level > 42 and XMLData.level < 100 - guessed_globe = true - else - guessed_globe = false - end - ([[(XMLData.level-30),0].max, 68].min/4.0).ceil + ([([XMLData.level,30].min-10),0].max/5.0).ceil + num.to_s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse } subtract_favor = proc { |symbol_factor| - if XMLData.level > 42 and XMLData.level < 100 - guessed_str = ' (guessed)' - else - guessed_str = String.new - end - cost = ((-3.5582503162159274e-001 * XMLData.level**0 + 2.2957964748856852e-001 * XMLData.level**1 + 1.1029166002049873e-001 * XMLData.level**2 + -3.6503722958574330e-003 * XMLData.level**3 + 7.3012042689120181e-005 * XMLData.level**4 + -7.6807923677936175e-007 * XMLData.level**5 + 3.1218083213686857e-009 * XMLData.level**6) * symbol_factor).ceil - $favor[:symbol] -= cost - echo "- #{cost}#{guessed_str} = #{add_commas.call($favor[:symbol])}" + if level_factor[XMLData.level] + cost = (level_factor[XMLData.level] * symbol_factor).ceil + $favor[:symbol] -= cost + favor_used += cost + output = "- #{cost} = #{add_commas.call($favor[:symbol])}" + if $favor[:symbol_error] > 0 + output.concat " (+/- #{add_commas.call($favor[:symbol_error])})" + end + echo output + else + echo "error: out of cheese" + exit + end } favor_to_step = proc { - # (Society.rank*100)+((Society.rank/3.0).ceil*15) # formula for level 3 - # (Society.rank*100)+((Society.rank/3.0).ceil*(XMLData.level*1.291)**2).floor # good for level 3 and 40 - - (Society.rank*100) + (((XMLData.level**2)*(((Society.rank+2)/3)*5))/3) + (Society.rank*100) + (((XMLData.level**2)*(((Society.rank+2)/3)*5))/3) } fix_name = proc { |name| - if name == 'moor wight' - if get =~ /greater/ - name = 'greater moor wight' - else - name = 'lesser moor wight' - end - elsif name == 'ghoul master' - next_line = get - if next_line =~ /ancient/ - name = 'ancient ghoul master' - elsif next_line =~ /elder/ - name = 'elder ghoul master' - end - end - name + if name == 'moor wight' + if get =~ /greater/ + name = 'greater moor wight' + else + name = 'lesser moor wight' + end + elsif name == 'ghoul master' + next_line = get + if next_line =~ /ancient/ + name = 'ancient ghoul master' + elsif next_line =~ /elder/ + name = 'elder ghoul master' + end + end + name +} + +globe_adjust_favor = proc { |globe_low, globe_high| + unless (UserVars.globe_sets_favor == 'no' or UserVars.globe_sets_favor == 'false') + orig_symbol = $favor[:symbol] + orig_error = $favor[:symbol_error] + favor_high = [[($favor[:symbol] + $favor[:symbol_error]), globe_high].min, globe_low].max + favor_low = [[($favor[:symbol] - $favor[:symbol_error]), globe_low].max, globe_high].min + $favor[:symbol] = (favor_high + favor_low)/2 + $favor[:symbol_error] = ((favor_high - favor_low)/2.0).ceil + if $favor[:symbol] > orig_symbol + echo "symbol favor + #{$favor[:symbol] - orig_symbol} = #{add_commas.call($favor[:symbol])}" + elsif $favor[:symbol] < orig_symbol + echo "symbol favor - #{orig_symbol - $favor[:symbol]} = #{add_commas.call($favor[:symbol])}" + end + if $favor[:symbol_error] > orig_error + echo "symbol favor error + #{$favor[:symbol_error] - orig_error} = #{add_commas.call($favor[:symbol_error])}" + elsif $favor[:symbol_error] < orig_error + echo "symbol favor error - #{orig_error - $favor[:symbol_error]} = #{add_commas.call($favor[:symbol_error])}" + end + end } hook_proc = proc { |client_string| - begin - if client_string =~ /^(?:)?favor(.*)/i - cmd = $1 - if cmd.downcase.strip == 'clear' - $favor[:symbol] = 0 - elsif cmd =~ /^\s+set\s+([0-9]+)\s*$/i - $favor[:symbol] = $1.to_i - elsif not cmd.empty? - output = "\n" - output.concat "Usage:\n" - output.concat "\n" - output.concat " favor show current favors\n" - output.concat " favor clear set current favor to zero\n" - output.concat " favor set set current favor to the given amount\n" - output.concat "\n" - respond output - end - output = "Symbol Favor: #{add_commas.call($favor[:symbol])}" - if Society.rank < 26 - output.concat " Step Favor: #{add_commas.call($favor[:step])}/#{add_commas.call(favor_to_step.call)} (#{($favor[:step]*100)/favor_to_step.call}%) (#{add_commas.call((($favor[:step] - start_step_favor)/((Time.now - start_time)/3600.0)).round)} f/h in #{((Time.now - start_time)/60.0).as_time})" - else - output.concat " (#{add_commas.call((($favor[:symbol] - start_symbol_favor)/((Time.now - start_time)/3600.0)).round)} f/h in #{((Time.now - start_time)/60.0).as_time})" - end - respond output - nil - else - client_string - end - rescue - UpstreamHook.remove('sexual-favors') - client_string - end + begin + if client_string =~ /^(?:)?favor(.*)/i + cmd = $1 + if cmd.downcase.strip == 'clear' + $favor[:symbol] = 0 + $favor[:symbol_error] = 0 + script_start = Time.now - 1 + symbol_favor_gained = 0 + favor_used = 0 + elsif cmd =~ /^\s+set\s+([0-9]+)\s*$/i + $favor[:symbol] = $1.to_i + script_start = Time.now - 1 + symbol_favor_gained = 0 + favor_used = 0 + elsif not cmd.empty? + output = "\n" + output.concat "Usage:\n" + output.concat "\n" + output.concat " favor show current favors\n" + output.concat " favor clear set current favor to zero\n" + output.concat " favor set set current favor to the given amount\n" + output.concat "\n" + respond output + end + output = "Symbol Favor: #{add_commas.call($favor[:symbol])}" + if $favor[:symbol_error] > 0 + output.concat " (+/- #{add_commas.call($favor[:symbol_error])})\n" + else + output.concat "\n" + end + output.concat " gained: #{symbol_favor_gained} favor in #{((Time.now - script_start)/60.0).as_time} (#{(symbol_favor_gained/((Time.now - script_start)/3600.0)).round} f/h)\n" + output.concat " used: #{favor_used} favor in #{((Time.now - script_start)/60.0).as_time} (#{(favor_used/((Time.now - script_start)/3600.0)).round} f/h)\n" + output.concat " net gain: #{(symbol_favor_gained - favor_used)} favor in #{((Time.now - script_start)/60.0).as_time} (#{((symbol_favor_gained - favor_used)/((Time.now - script_start)/3600.0)).round} f/h)\n\n" + if Society.rank < 26 + output.concat "Step Favor: #{add_commas.call($favor[:step])}" + if $favor[:step_error] > 0 + output.concat "(+/- #{add_commas.call($favor[:step_error])})" + end + output.concat "/#{add_commas.call(favor_to_step.call)}" + if favor_to_step.call > 0 + output.concat " (#{($favor[:step]/favor_to_step.call.to_f*100).floor}%)" + end + output.concat "\n" + output.concat " gained: #{step_favor_gained} favor in #{((Time.now - step_start)/60.0).as_time} (#{(step_favor_gained/((Time.now - step_start)/3600.0)).round} f/h)\n" + end + respond output + nil + else + client_string + end + rescue + respond $! + respond $!.backtrace + UpstreamHook.remove('sexual-favors') + client_string + end } before_dying { UpstreamHook.remove('sexual-favors') } UpstreamHook.add('sexual-favors', hook_proc) while (line = get) - # fixme: open implode - if line =~ /^The glow fades from .*?exist="(.*?)"/ - banshee_defence.delete($1) - elsif (line =~ /You (?:swing|gesture|sing|weave another verse|continue to sing|channel|fire|wave|tap|rub|hurl|thrust|slash|throw|punch|attempt to punch|attempt to kick|attempt to throw|quickly dart behind .*? and try to hamstring|mentally attempt to locate your implanted essence|rush forward)|You .*?attempt to (?:kick|punch|jab|grapple)|A wave of power flows out of you and toward .+ bursts into flames|Your (?:<.*?>)?raging sandstorm(?:<.*?>)? swirls around|^The flames surrounding an? .*?<\/a> flare up violently\.\.\.|A .*? leaps from a .*?<\/a> .*?.*?<\/a> is wielding\.|^(?:Brilliant flashes of lightning surround|Large hailstones pound relentlessly on|Violent winds tighten around) .*?.*?<\/a>\.|Suddenly a lightning bolt explodes from the small thundercloud and strikes .*?.*?<\/a> with a brilliant flash!|^Holy water continues to burn away at .*?exist="(?:#{holy_bolted.join('|')})"/) or (divine_wrath_active and divine_wrath_message[deity] and line =~ divine_wrath_message[deity]) - # symbol of holiness - if line =~ /^A wave of power flows out of you and toward .+ bursts into flames/ - subtract_favor.call(3) - end - if line =~ /You gesture at.*?exist=['"](.*?)['"]/ - target_npc_id = $1 - else - target_npc_id = nil - end - possible_holy_bolted = nil - while (line = get) and (line !~ /= 30) and (line =~ /You hurl a stream of holy water at .*?.*?<\/a>!/) - possible_holy_bolted = $1 - elsif line =~ /Wisps of black smoke swirl around .*?.*?<\/a> and s?he bursts into flame!/ - immolated.push($1) unless immolated.include?($1) - elsif line =~ /You successfully hit .*?.*?<\/a> .*?<\/a> with the spell\./ - weapon_fired.push($1) unless weapon_fired.include?($1) - elsif line =~ /A stiff breeze begins to swirl around .*?.*?<\/a>\./ - maelstromed.push($1) unless maelstromed.include?($1) - elsif line =~ /You notice a small cloud form above .*?.*?<\/a>\./ - lightning_called.push($1) - elsif line =~ /^As you pour your soul into an appeal to (.*?), / - deity = $1 - divine_wrath_active = true - elsif line =~ /^A final rumble of thunder rolls through the area, and, as its last echoes fade away, your skin ceases to tingle as your connection to Charl lessens\.|^Your connection to Cholen lessens\. The airy, brisk trill of a well-played fife and a quick cymbal crash heralds the departure of the spirit jesters\.|^The ruddy haze near you dissipates, and the sound of the forging hammer dies away\. As the forge-fire's heat leaves your skin, your connection to Eonak lessens\.|^You sense the last of the spirit animals running away unseen, and the aroma of forest loam fades as your connection to Imaera lessens\.|^The iridescent lights surrounding you pop like soap bubbles, one by one, until the last one bursts in a small flare of starry radiance and is gone\. Your connection to Jastev lessens\.|^Your connection to Koar lessens, and the divine light fades around you\. The ground shudders one last time before falling still\.|^As your connection to Lorminstra lessens, the snowflakes stop falling, and the few that still cling to you melt away\. The icy cold gradually lifts from your body\.|^As your connection to Lumnis lessens, the world of divine insight slips away from you, destroying the subtle understanding that you so briefly managed to grasp\.|^You lose sight of the dream unicorns and the barren plain upon which they run as your connection to Ronan lessens\. The waking world seems brighter again as the sense of dreamlike lassitude leaves you\.|^You glimpse the golden blur one last time, but then you lose track of it entirely as your connection to Tonis lessens\. The wind's force lessens as well, and then the air falls still\.|^You realize that you had ceased to hear the sound of your own heartbeat only when you become aware of it again, and other sounds filter back into your awareness as well\. Warmth returns to your body as your connection to Gosaena lessens\.|^Suddenly, the important insights slip away, leaving you drained and exhausted as you plummet back to a more mundane state of mind\. Your throat and sides are slightly sore, and your cheeks are wet with tears\. Your connection to Zelia has lessened\.|^Your connection to Eorgina lessens, and the black flames instantly vanish, leaving you stranded and bereft of the presence of the Arkati's power\.|^Your connection to Fash'lo'nae lessens\. The quiet sound of a blade being honed persists a moment longer before fading away into silence\.|^A spectral howl echoes through the air, resonant with pain and anguish\. Your skin prickles again as your connection to Luukos lessens\.|^As your connection to Mularos lessens, the cold, invisible collar locked about your throat fades into a compassionate caress, and a similar caress traces its way across the side of your cheek\. Beneath that gentle touch, the wounds upon your face heal immediately\. The ethereal barbed whip twitches one last time before dissolving back into air\.|^Your connection to Sheru lessens, and the murky shadows brought by your appeal fade away, yet the feeling of being watched does not\. On any night, in any dream or nightmare, those amber eyes will follow you endlessly\.\.\. but such is the prize and the price of your devotion\.|^As your connection to the Huntress lessens, the foreign anger that lent you strength passes from your body as well, and your heartbeat returns to its regular pace\.|^You feel the kiss of benediction once more upon your brow, and then your connection to Laethe lessens\. The shadowy black roses dissolve into tendrils of black, rose-scented smoke that dissipate rapidly\.|^The ivory light around you fades and glimmers out, and the strength and control of your movements lessens along with your connection to Leya\.|^The singing from the watery pillar begins to fade as your connection to Niima lessens\. The pillar thins, then suddenly drops with a great splash! You are utterly drenched in water\.|^You feel the kiss of benediction once more upon your brow, and then your connection to Voaris lessens\. One of the glowing golden roses lights with scarlet flame, and the fire spreads rapidly down the vine until every rose is burning\. The flames consume the roses swiftly and without smoke, until, in less than a second, the roses are gone entirely\./ - # fixme: missing Kai, Oleani, Phoen, Andelas, Ivas, Marlu, V'tull, Aeia, Amasalen, Arachne, Jaston, Kuon, Onar, Tilamaire, Voln - divine_wrath_active = false - elsif line =~ /^The .*?exist="(.*?)".*? eyes grow wide as .*? watches your gestures! Suddenly .*? makes hurried movements as .*? recognizes that .*? is about to be attacked by magic!/ - banshee_defence.push($1) - elsif line =~ /^\s*AS\: [\+\-][0-9]+ vs DS\: [\+\-][0-9]+ with AvD\: [\+\-][0-9]+ \+ d100 roll\: \+[0-9]+ = ([\+\-])([0-9]+)/ - if possible_holy_bolted and ($1 == '+') and ($2.to_i > 100) - holy_bolted.push(possible_holy_bolted) unless holy_bolted.include?(possible_holy_bolted) - end - elsif line =~ /^\s*CS\: [\+\-][0-9]+ \- TD\: \+([0-9]+) \+ CvA\: [\+\-][0-9]+ \+ d100\: \+[0-9]+ == [\+\-][0-9]+/ - td = $1.to_i - unless target_npc_id.nil? - if line = $_SERVERBUFFER_.reverse.find { |l| l =~ /]*>(?!None)/ } - spell_name = line.match(/(.*?)<\/spell>/).captures.first - if spell_circle = Spell[spell_name].circle - unless info = npc_td.find { |foo| foo['id'] == target_npc_id } - info = { 'id' => target_npc_id } - npc_td.push(info) - end - td -= 75 if banshee_defence.include?(target_npc_id) - info[spell_circle.to_i] = td - end - end - end - elsif line =~ /^You hear a sound like a weeping child as a white glow separates itself from the <.*exist=['"](.*?)['"].*>(.+)'s<.*?> body/ - npc_id = $1 - if GameObj.npcs.find { |n| n.id == npc_id }.name == 'elder tree spirit' - npc_name = 'elder tree spirit' - else - npc_name = fix_name.call($2) - end - sleep 0.1 - if $sexual_favors_debug - echo "npc_name: #{npc_name.inspect}" - echo "npc[npc_name][:lvl]: #{npc[npc_name][:lvl].inspect}" - end - if level = npc[npc_name][:lvl] - echo "level: #{level.inspect}" if $sexual_favors_debug - if level > 19 - level_variation = [(level/10), 5].min - if spell_circle = spell_circle_list.find { |c| npc[npc_name][:td_mod][c] and npc_td.any? { |foo| (foo['id'] == npc_id) and foo[c] } } - echo "spell_circle: #{spell_circle}" if $sexual_favors_debug - offset = npc[npc_name][:td_mod][spell_circle] - echo "offset: #{offset}" if $sexual_favors_debug - td = npc_td.find { |foo| foo['id'] == npc_id }[spell_circle] - echo "td: #{td}" if $sexual_favors_debug - while (line = get) - if line =~ /exist=['"]#{npc_id}['"]/ - for message,bonus in spell_bonus - if line =~ message - echo "td - #{bonus[spell_circle]} = #{td - bonus[spell_circle]}" if $sexual_favors_debug - td -= bonus[spell_circle] - break - end - end - else - script.downstream_buffer.unshift(line) - break - end - end - if ((td - offset) % 3 == 0) and (exact_level = (td - offset) / 3) and (exact_level <= (level + level_variation)) and (exact_level >= (level - level_variation)) - favor_gain = (exact_level*XMLData.level/15.0).ceil - favor_range = " (level #{exact_level})" - else - favor_gain = (level*XMLData.level/15.0).ceil - favor_range = " (+/- #{[(favor_gain - ((level-level_variation)*XMLData.level/15.0).ceil), (((level+level_variation)*XMLData.level/15.0).ceil - favor_gain)].max})" - end - else - favor_gain = (level*XMLData.level/15.0).ceil - favor_range = " (+/- #{[(favor_gain - ((level-level_variation)*XMLData.level/15.0).ceil), (((level+level_variation)*XMLData.level/15.0).ceil - favor_gain)].max})" - end - else - favor_range = String.new - favor_gain = (level*XMLData.level/15.0).ceil - end - $favor[:symbol] += favor_gain - $favor[:step] += favor_gain - output = "+ #{favor_gain}#{favor_range} = #{add_commas.call($favor[:symbol])}" - if Society.rank < 26 - output.concat " step favor: #{add_commas.call($favor[:step])}/#{add_commas.call(favor_to_step.call)} (#{($favor[:step]*100)/favor_to_step.call}%)" - end - echo output - npc_td.delete_if { |foo| foo['id'] == npc_id } - else - echo "unknown level for #{npc_name}" - end - end - end - elsif line =~ /^You hear a sound like a weeping child as a white glow separates itself from the <.*exist=['"](.*?)['"].*>(.+)'s<.*?> body/ - npc_id = $1 - if GameObj.npcs.find { |n| n.id == npc_id }.name == 'elder tree spirit' - npc_name = 'elder tree spirit' - else - npc_name = fix_name.call($2) - end - sleep 0.1 - if level = npc[npc_name][:lvl] - if level > 19 - level_variation = [(level/10), 5].min - if spell_circle = spell_circle_list.find { |c| npc[npc_name][:td_mod][c] and npc_td.any? { |foo| (foo['id'] == npc_id) and foo[c] } } - echo "spell_circle: #{spell_circle}" if $sexual_favors_debug - offset = npc[npc_name][:td_mod][spell_circle] - td = npc_td.find { |foo| foo['id'] == npc_id }[spell_circle] - while (line = get) - if line =~ /exist=['"]#{npc_id}['"]/ - for message,bonus in spell_bonus - if line =~ message - echo "td -= #{bonus[spell_circle]}" if $sexual_favors_debug - td -= bonus[spell_circle] - break - end - end - else - script.downstream_buffer.unshift(line) - break - end - end - if ((td - offset) % 3 == 0) and (exact_level = (td - offset) / 3) and (exact_level <= (level + level_variation)) and (exact_level >= (level - level_variation)) - favor_gain = (([exact_level, XMLData.level].min*XMLData.level/15.0).ceil/3.0).ceil - favor_range = " (level #{exact_level})" - else - favor_gain = (([level, XMLData.level].min*XMLData.level/15.0).ceil/3.0).ceil - favor_range = " (+/- #{[ favor_gain - (([level-level_variation, XMLData.level].min*XMLData.level/15.0).ceil/3.0).ceil, (([level+level_variation, XMLData.level].min*XMLData.level/15.0).ceil/3.0).ceil - favor_gain ].max})" - end - else - favor_gain = (([level, XMLData.level].min*XMLData.level/15.0).ceil/3.0).ceil - favor_range = " (+/- #{[ favor_gain - (([level-level_variation, XMLData.level].min*XMLData.level/15.0).ceil/3.0).ceil, (([level+level_variation, XMLData.level].min*XMLData.level/15.0).ceil/3.0).ceil - favor_gain ].max})" - end - else - favor_range = String.new - favor_gain = (([level, XMLData.level].min*XMLData.level/15.0).ceil/3.0).ceil - end - $favor[:symbol] += favor_gain - $favor[:step] += favor_gain - output = "+ #{favor_gain}#{favor_range} (spectator) = #{add_commas.call($favor[:symbol])}" - if Society.rank < 26 - output.concat " step favor: #{add_commas.call($favor[:step])}/#{add_commas.call(favor_to_step.call)} (#{($favor[:step]*100)/favor_to_step.call}%)" - end - echo output - else - echo "unknown level for #{npc_name}" - end - elsif line =~ /^(?:<.*?>)?The (?:<.*?>)?monk(?:<.*?>)? concludes ceremoniously.*Go now and continue your work\./ - $favor[:step] = 0 - start_time = Time.now - start_step_favor = 0 - - # - # symbol of blessing - # - elsif line =~ /^A wave of power flows outward from you towards/ - sleep 0.1 - if next_line = get? -# if (next_line =~ /^A soft white glow surrounds|^A brilliant white light wraps around/) and (next_line !~ /gently dissipates|returns to its original color/) - if (next_line =~ /^A brilliant white light wraps around/) and (next_line !~ /returns to its original color/) - # fixme: find a more accurate way to tell if the weapon is magical - if line =~ /(?:carmiln|deringo|faewood|fireleaf|glowbark|hoarbeam|ilthorn|ipantor|kakore|lor|mesille|mossbark|orase|rowan|ruic|sephwir|villswood|witchwood|wyrwood|yew|coraesine|drakar|eahnor|eonake|faenor|glaes|mein|golvern|gornar|imflass|kelyn|krodera|mithglin|mithril|ora|razern|rhimar|rolaren|urglaes|urnon|vaalorn|veil iron|vultite|zorchar)[^\-]/ - # if line =~ /^A wave of power flows outward from you towards an? (?:<.*?>)?[A-z\-]+ .+(?:<.*?>)?\.$/ - subtract_favor.call(2) - else - subtract_favor.call(0.4) - end - end - end - # - # symbol of thought - # - elsif line =~ /^You concentrate on the Symbol of Thought/ - sleep 0.1 - unless get? =~ /^You strain/ - if thought = $_CLIENTBUFFER_.reverse.find { |line| line =~ /^(?:\[.+?\]>)?(?:)?sym(?:b|bo|bol)?\s+(?:of\s+)?th(?:o|ou|oug|ough|ought)?/ } - if thought =~ /^(?:\[.+?\]>)?(?:)?sym(?:b|bo|bol)?\s+(?:of\s+)?th(?:o|ou|oug|ough|ought)?\s+(.*)/ - message = $1 - this_favor = [((message.length-1)/3.0).ceil, 83].min - $favor[:symbol] = ($favor[:symbol] - this_favor).to_i - echo "- #{this_favor} = #{add_commas.call($favor[:symbol])}" - end - end - end - - elsif line =~ /^You draw a glowing pattern in the air before/ - sleep 0.1 - next_line = get? - - # - # symbol of diminishment - # - if next_line =~ /^(?:<.*?>)?(?:The|A|An) .*? (?:appears diminished|is unaffected)!$/ - subtract_favor.call(3) - - # - # symbol of sleep - # - elsif next_line =~ /eyes roll up into|eyes glass over as a distant look takes over|is unaffected by your Symbol of Sleep/ - subtract_favor.call(2) - - # - # symbol of turning - # - elsif next_line =~ /lets out a blood curdling scream/ - # fixme: more messages maybe - subtract_favor.call(3) - - end - - # - # symbol of courage - # - elsif line =~ /^You feel more courageous/ - subtract_favor.call(1) - - # - # protection - # - elsif line =~ /^You feel a layer of protection surround you/ - subtract_favor.call(1) - - # - # symbol of submission - # - elsif line =~ /^You feel the power of the symbol project toward/ - subtract_favor.call(3) - - # - # symbol of holiness: moved up to kill tracking - # - - # - # symbol of recall - # - elsif line =~ /^You focus on recalling magical assistance that will be of use when you rise again, and feel the power of Lorminstra suffusing your spirit\./ - subtract_favor.call(4) - - # - # symbol of transcendence - # - elsif line =~ /^You step into the space between the corporeal and ethereal realms\.|^With difficulty, you manage to will yourself into the space between the corporeal and ethereal realms\./ - subtract_favor.call(6) - - # - # symbol of mana - # - elsif line =~ /^(?:<.*?>)?You feel a surge of mana flow through you/ - subtract_favor.call(3) - - # - # symbol of sight - # - elsif line =~ /^You concentrate on establishing the link and suddenly you see/ - subtract_favor.call(3) - - # - # symbol of retribution (alive) - # - elsif line =~ /^You feel an aura of righteous wrath surround you\./ - subtract_favor.call(3) - - # - # symbol of retribution (dead) - # - elsif line =~ /^You sense deep within your soul, a rage that burns upward and out of your lips in a terrible scream of rage against the undead!/ - subtract_favor.call(0.4) - - # - # symbol of supremacy - # - elsif line =~ /^You feel infused with a collective knowledge on the undead and their weaknesses\./ - subtract_favor.call(5) - - # - # restoration - # - elsif line =~ /^(?:<.*?>)?You feel the power of the symbol course through your body/ - subtract_favor.call(4) - - # - # symbol of need - # - elsif line =~ /^You concentrate on the Symbol of Need\./ - subtract_favor.call(4) - - # symbol of renewal - # - elsif line =~ /^(?:<.*?>)?You feel a surge of life flow through you\./ # fixme: test xml - subtract_favor.call(5) # fixme: test - - # - # symbol of disruption - # - elsif line =~ /^A churning spectral aura surrounds you/ - # fixme: extra cost for group members - subtract_favor.call(3) # fixme: test - - # - # symbol of preservation - # - elsif line =~ /^You concentrate and sense the power of the Symbol of Preservation well up within you|^You send a wave of energy toward .*?\. It coalesces around .*? body and then seeps in leaving a glow that strengthens the bond between body and spirit\./ - subtract_favor.call(6) - - # - # symbol of dreams - # - elsif line =~ /^(?:<.*?>)?You feel suddenly tired and lie down for a nap\./ - subtract_favor.call(6) # fixme: test - - # - # symbol of return - # - elsif line =~ /^Your surroundings blur into a white fog \. \. \./ - if symbol = $_CLIENTBUFFER_[[-10,0-$_CLIENTBUFFER_.length].max..-1].reverse.find { |cmd| cmd =~ /^(?:\[.*?\]>)?(?:)?(?:sy|sym|symb|symbo|symbol)\s+(?:of\s+)?(?:retu|see)/i } - unless symbol =~ /\(checked\)$/ - symbol.concat ' (checked)' - if symbol =~ /^(?:\[.*?\]>)?(?:)?(?:sy|sym|symb|symbo|symbol)\s+(?:of\s+)?retu/i - subtract_favor.call(10) - end - end - end - - # fixme: need River's Rest messages - elsif line =~ /^After a few moments of prayer and reflection you see a vision of a flower that has not yet begun to open\./ - echo '0-10%' - elsif line =~ /^After a few moments of prayer and reflection you see a vision of a baby eagle barely hatched from its egg\./ - echo '10-20%' - elsif line =~ /^After a few moments of prayer and reflection you see a vision of a butterfly drying its wings on a leaf\./ - echo '20-30%' - elsif line =~ /^After a few moments of prayer and reflection you see a vision of the headwaters of a mighty river\.\s? Here it has joined with several other streams and is growing quickly\./ - echo '30-40%' - elsif line =~ /^After a few moments of prayer and reflection you see a vision of a weaver on a loom, nearly half way in the creation of an intricate tapestry\./ - echo '40-50%' - elsif line =~ /^After a few moments of prayer and reflection you see a brief vision of twin bowls of wine\.\s? You reach out and empty the contents of one into the other filling it up\.\s? You have a sudden desire to fill up the empty bowl too\./ - echo '50-60%' - elsif line =~ /^After a few moments of prayer and reflection you see a vision of a hiker as he clears the peak of a hill and begins to descend the other side\./ - echo '60-70%' - elsif line =~ /^After a few moments of prayer and reflection you see a vision of a lute, finely crafted, but missing a third of its strings\./ - echo '70-80%' - elsif line =~ /^After a few moments of prayer and reflection you see a vision of a rainbow forming as a thunder storm begins to abate\./ - echo '80-90%' - elsif line =~ /^After a few moments of prayer and reflection you see a vision of a path as it winds its way through a forest and to the edge of a clear pool\.\s? You have a sudden desire to jump in but cannot\./ - echo '90-100%' - elsif line =~ /^After a few moments of prayer and reflection you see a vision of a pool of clear water\.\s? You dive in and swim to the bottom where you find a gold coin engraved with the image of Voln\.\s? An overwhelming feeling makes you realize that you are indeed ready to take the next step along the Path to Enlightenment\./ - echo '100%' - elsif line =~ /^The (?:<.*?>)?globe(?:<.*?>)? feels cold beneath your touch\./ - high = 999 - globe_offset.call - low = 0 - echo "0 revolutions = 0 to #{high} favor#{' (+/- 15)' if guessed_globe}" - if globe_sets_favor - if $favor[:symbol] > high - diff = $favor[:symbol] - high - $favor[:symbol] = high - echo "symbol favor - #{diff} = #{add_commas.call($favor[:symbol])}" - elsif $favor[:symbol] < low - diff = low - $favor[:symbol] - $favor[:symbol] = low - echo "symbol favor + #{diff} = #{add_commas.call($favor[:symbol])}" - end - end - elsif line =~ /^The (?:<.*?>)?globe(?:<.*?>)? hums and turns slowly once under your fingers\./ - high = 1999 - globe_offset.call - low = 1000 - globe_offset.call - echo "1 revolution = #{add_commas.call(low)} to #{add_commas.call(high)} favor#{' (+/- 15)' if guessed_globe}" - if globe_sets_favor - if $favor[:symbol] > high - diff = $favor[:symbol] - high - $favor[:symbol] = high - echo "symbol favor - #{diff} = #{add_commas.call($favor[:symbol])}" - elsif $favor[:symbol] < low - diff = low - $favor[:symbol] - $favor[:symbol] = low - echo "symbol favor + #{diff} = #{add_commas.call($favor[:symbol])}" - end - end - elsif line =~ /^You try to count the number of spins and (?:are certain it was|figure it was around|figure it was at least) ([0-9]+) revolutions\./ - count = $1.to_i - if count < 10 - high = (count*1000) + 999 - globe_offset.call - low = (count*1000) - globe_offset.call - elsif count < 100 - high = (count*1000) + 9999 - globe_offset.call - low = (count*1000) - globe_offset.call - else - high = (count*1000) + 49999 - globe_offset.call - low = (count*1000) - globe_offset.call - end - echo "#{count} revolutions = #{add_commas.call(low)} to #{add_commas.call(high)} favor#{' (+/- 15)' if guessed_globe}" - if globe_sets_favor - if $favor[:symbol] > high - diff = $favor[:symbol] - high - $favor[:symbol] = high - echo "symbol favor - #{diff} = #{add_commas.call($favor[:symbol])}" - elsif $favor[:symbol] < low - diff = low - $favor[:symbol] - $favor[:symbol] = low - echo "symbol favor + #{diff} = #{add_commas.call($favor[:symbol])}" - end - end - end + # fixme: open implode + if line =~ /^The glow fades from .*?exist="(.*?)"/ + banshee_defense.delete($1) + elsif (line =~ /You (?:swing|gesture|sing|weave another verse|continue to sing|channel|fire|wave|tap|rub|hurl|thrust|slash|throw|punch|attempt to punch|attempt to kick|attempt to throw|quickly dart behind .*? and try to hamstring|mentally attempt to locate your implanted essence|rush forward|exhale a virulent green mist toward)|You .*?attempt to (?:kick|punch|jab|grapple)|A wave of power flows out of you and toward .+ bursts into flames|Your (?:<.*?>)?raging sandstorm(?:<.*?>)? swirls around|^The flames surrounding an? .*?<\/a> flare up violently\.\.\.|^An? .*?<\/a> (?:.*? as virulent green mist passes through|convulses with a crippling affliction|skin necrotizes and falls away as an indiscernible mass|skin hardens into a black rot and begins to crumble causing)|^(?:The sickly green miasma around|Light and dark pockmarks appear on|A spiritual malady wracks|Pus-filled sores erupt on|Pustules break out all over|Painful, pus-filled bumps begin to appear on) an? .*?<\/a> (?:flares|causing)|A .*? leaps from a .*?<\/a> .*?.*?<\/a> is wielding\.|^(?:Brilliant flashes of lightning surround|Large hailstones pound relentlessly on|Violent winds tighten around|Large rocks swirl around) .*?.*?<\/a>\.|Suddenly a lightning bolt explodes from the small thundercloud and strikes .*?.*?<\/a> with a brilliant flash!|^Holy water continues to burn away at .*?exist="(?:#{holy_bolted.join('|')})"/) or (divine_wrath_active and divine_wrath_message[deity] and line =~ divine_wrath_message[deity]) + next if line =~ /You gesture sharply/ + # symbol of holiness + if line =~ /^A wave of power flows out of you and toward .+ bursts into flames/ + subtract_favor.call(3) + end + if line =~ /You exhale a virulent green mist toward .*?.*?<\/a>, instantly infecting/ + pestilenced.push($1) unless pestilenced.include?($1) + end + if line =~ /You gesture at.*?exist=['"](.*?)['"]/ + target_npc_id = $1 + else + target_npc_id = nil + end + possible_holy_bolted = nil + while (line = get) and (line !~ /= 30) and (line =~ /You hurl a stream of holy water at .*?.*?<\/a>!/) + possible_holy_bolted = $1 + elsif line =~ /Wisps of black smoke swirl around .*?.*?<\/a> and s?he bursts into flame!/ + immolated.push($1) unless immolated.include?($1) + elsif line =~ /You exhale a virulent green mist toward .*?.*?<\/a>, instantly infecting/ + pestilenced.push($1) unless pestilenced.include?($1) + elsif line =~ /You successfully hit .*?.*?<\/a> .*?<\/a> with the spell\./ + weapon_fired.push($1) unless weapon_fired.include?($1) + elsif line =~ /A stiff breeze begins to swirl around .*?.*?<\/a>\./ + maelstromed.push($1) unless maelstromed.include?($1) + elsif line =~ /You notice a small cloud form above .*?.*?<\/a>\./ + lightning_called.push($1) + elsif line =~ /^As you pour your soul into an appeal to (.*?), / + deity = $1 + divine_wrath_active = true + elsif line =~ /^A final rumble of thunder rolls through the area, and, as its last echoes fade away, your skin ceases to tingle as your connection to Charl lessens\.|^Your connection to Cholen lessens\. The airy, brisk trill of a well-played fife and a quick cymbal crash heralds the departure of the spirit jesters\.|^The ruddy haze near you dissipates, and the sound of the forging hammer dies away\. As the forge-fire's heat leaves your skin, your connection to Eonak lessens\.|^You sense the last of the spirit animals running away unseen, and the aroma of forest loam fades as your connection to Imaera lessens\.|^The iridescent lights surrounding you pop like soap bubbles, one by one, until the last one bursts in a small flare of starry radiance and is gone\. Your connection to Jastev lessens\.|^Your connection to Koar lessens, and the divine light fades around you\. The ground shudders one last time before falling still\.|^As your connection to Lorminstra lessens, the snowflakes stop falling, and the few that still cling to you melt away\. The icy cold gradually lifts from your body\.|^As your connection to Lumnis lessens, the world of divine insight slips away from you, destroying the subtle understanding that you so briefly managed to grasp\.|^You lose sight of the dream unicorns and the barren plain upon which they run as your connection to Ronan lessens\. The waking world seems brighter again as the sense of dreamlike lassitude leaves you\.|^You glimpse the golden blur one last time, but then you lose track of it entirely as your connection to Tonis lessens\. The wind's force lessens as well, and then the air falls still\.|^You realize that you had ceased to hear the sound of your own heartbeat only when you become aware of it again, and other sounds filter back into your awareness as well\. Warmth returns to your body as your connection to Gosaena lessens\.|^Suddenly, the important insights slip away, leaving you drained and exhausted as you plummet back to a more mundane state of mind\. Your throat and sides are slightly sore, and your cheeks are wet with tears\. Your connection to Zelia has lessened\.|^Your connection to Eorgina lessens, and the black flames instantly vanish, leaving you stranded and bereft of the presence of the Arkati's power\.|^Your connection to Fash'lo'nae lessens\. The quiet sound of a blade being honed persists a moment longer before fading away into silence\.|^A spectral howl echoes through the air, resonant with pain and anguish\. Your skin prickles again as your connection to Luukos lessens\.|^As your connection to Mularos lessens, the cold, invisible collar locked about your throat fades into a compassionate caress, and a similar caress traces its way across the side of your cheek\. Beneath that gentle touch, the wounds upon your face heal immediately\. The ethereal barbed whip twitches one last time before dissolving back into air\.|^Your connection to Sheru lessens, and the murky shadows brought by your appeal fade away, yet the feeling of being watched does not\. On any night, in any dream or nightmare, those amber eyes will follow you endlessly\.\.\. but such is the prize and the price of your devotion\.|^As your connection to the Huntress lessens, the foreign anger that lent you strength passes from your body as well, and your heartbeat returns to its regular pace\.|^You feel the kiss of benediction once more upon your brow, and then your connection to Laethe lessens\. The shadowy black roses dissolve into tendrils of black, rose-scented smoke that dissipate rapidly\.|^The ivory light around you fades and glimmers out, and the strength and control of your movements lessens along with your connection to Leya\.|^The singing from the watery pillar begins to fade as your connection to Niima lessens\. The pillar thins, then suddenly drops with a great splash! You are utterly drenched in water\.|^You feel the kiss of benediction once more upon your brow, and then your connection to Voaris lessens\. One of the glowing golden roses lights with scarlet flame, and the fire spreads rapidly down the vine until every rose is burning\. The flames consume the roses swiftly and without smoke, until, in less than a second, the roses are gone entirely\./ + # fixme: missing Kai, Oleani, Phoen, Andelas, Ivas, Marlu, V'tull, Aeia, Amasalen, Arachne, Jaston, Kuon, Onar, Tilamaire, Voln + divine_wrath_active = false + elsif line =~ /^The .*?exist="(.*?)".*? eyes grow wide as .*? watches your gestures! Suddenly .*? makes hurried movements as .*? recognizes that .*? is about to be attacked by magic!/ + banshee_defense.push($1) + elsif line =~ /^\s*AS\: [\+\-][0-9]+ vs DS\: [\+\-][0-9]+ with AvD\: [\+\-][0-9]+ \+ d100 roll\: \+[0-9]+ = ([\+\-])([0-9]+)/ + if possible_holy_bolted and ($1 == '+') and ($2.to_i > 100) + holy_bolted.push(possible_holy_bolted) unless holy_bolted.include?(possible_holy_bolted) + end + elsif line =~ /^\s*CS\: [\+\-][0-9]+ \- TD\: \+([0-9]+) \+ CvA\: [\+\-][0-9]+ \+ d100\: \+[0-9]+ == [\+\-][0-9]+/ + td = $1.to_i + unless target_npc_id.nil? + if line = $_SERVERBUFFER_.reverse.find { |l| l =~ /]*>(?!None)/ } + spell_name = line.match(/(.*?)<\/spell>/).captures.first + if (spell_name != 'Corrupt Essence') and (spell_circle = Spell[spell_name].circle) # corrupt essence td pushdown is critter level based and not helpful + if spell_name == 'Arcane Blast' + spell_circle = { 'Sorcerer' => 7, 'Wizard' => 9, 'Cleric' => 3, 'Empath' => 11 }[Char.prof] + end + unless info = npc_td.find { |foo| foo['id'] == target_npc_id } + info = { 'id' => target_npc_id } + npc_td.push(info) + end + td -= 75 if banshee_defense.include?(target_npc_id) + info[spell_circle.to_i] = td + echo "npc id: #{target_npc_id}, spell: #{spell_name}, circle: #{spell_circle}, td: #{td}" if $sexual_favors_debug + end + end + end + elsif line =~ /^(?:The internal skeletal structure of .*? implodes inward upon .*?, leaving behind no support for .*? body or life\. )?You hear a sound like a weeping child as a white glow separates itself from the <.*exist=['"](.*?)['"].*>(.+)'s<.*?> body/ + npc_id = $1 + if GameObj.npcs.find { |n| n.id == npc_id }.name == 'elder tree spirit' + npc_name = 'elder tree spirit' + else + npc_name = fix_name.call($2) + end + sleep 0.1 + if $sexual_favors_debug + echo "npc_name: #{npc_name.inspect}" + echo "npc[npc_name][:lvl]: #{npc[npc_name][:lvl].inspect}" + end + if level = npc[npc_name][:lvl] + calculated_level = nil + echo "level: #{level.inspect}" if $sexual_favors_debug + if level > 19 + level_variation = [(level/10), 5].min + if spell_circle = spell_circle_list.find { |c| npc[npc_name][:td_mod][c] and npc_td.any? { |foo| (foo['id'] == npc_id) and foo[c] } } + echo "spell_circle: #{spell_circle}" if $sexual_favors_debug + offset = npc[npc_name][:td_mod][spell_circle] + echo "offset: #{offset}" if $sexual_favors_debug + td = npc_td.find { |foo| foo['id'] == npc_id }[spell_circle] + echo "td: #{td}" if $sexual_favors_debug + while (line = get) + if line =~ /exist=['"]#{npc_id}['"]/ + for message,bonus in spell_bonus + if line =~ message + echo "td - #{bonus[spell_circle]} = #{td - bonus[spell_circle]}" if $sexual_favors_debug + td -= bonus[spell_circle] + break + end + end + else + script.downstream_buffer.unshift(line) + break + end + end + if ((td - offset) % 3 == 0) and (clvl = (td - offset) / 3) and (clvl <= (level + level_variation)) and (clvl >= (level - level_variation)) + favor_gain = (clvl*XMLData.level/15.0).ceil + favor_error = 0 + calculated_level = clvl + else + favor_gain = (level*XMLData.level/15.0).ceil + favor_error = [(favor_gain - ((level-level_variation)*XMLData.level/15.0).ceil), (((level+level_variation)*XMLData.level/15.0).ceil - favor_gain)].max + end + else + favor_gain = (level*XMLData.level/15.0).ceil + favor_error = [(favor_gain - ((level-level_variation)*XMLData.level/15.0).ceil), (((level+level_variation)*XMLData.level/15.0).ceil - favor_gain)].max + end + else + favor_error = 0 + favor_gain = (level*XMLData.level/15.0).ceil + end + $favor[:symbol] += favor_gain + $favor[:symbol_error] += favor_error + $favor[:step] += favor_gain + $favor[:step_error] += favor_error + symbol_favor_gained += favor_gain + step_favor_gained += favor_gain + if favor_error > 0 + output = "+ #{favor_gain} (+/- #{add_commas.call(favor_error)}) = #{add_commas.call($favor[:symbol])} (+/- #{add_commas.call($favor[:symbol_error])})" + elsif calculated_level + output = "+ #{favor_gain} (lvl #{calculated_level}) = #{add_commas.call($favor[:symbol])}" + if $favor[:symbol_error] > 0 + output.concat " (+/- #{add_commas.call($favor[:symbol_error])})" + end + else + output = "+ #{favor_gain} = #{add_commas.call($favor[:symbol])}" + if $favor[:symbol_error] > 0 + output.concat " (+/- #{add_commas.call($favor[:symbol_error])})" + end + end + if Society.rank < 26 + output.concat " step favor: #{add_commas.call($favor[:step])}/#{add_commas.call(favor_to_step.call)}" + if favor_to_step.call > 0 + output.concat " (#{($favor[:step]*100)/favor_to_step.call}%)" + end + end + echo output + npc_td.delete_if { |foo| foo['id'] == npc_id } + else + echo "unknown level for #{npc_name}" + end + end + end + elsif line =~ /^(?:The internal skeletal structure of .*? implodes inward upon .*?, leaving behind no support for .*? body or life\. )?You hear a sound like a weeping child as a white glow separates itself from the <.*exist=['"](.*?)['"].*>(.+)'s<.*?> body/ + npc_id = $1 + if GameObj.npcs.find { |n| n.id == npc_id }.name == 'elder tree spirit' + npc_name = 'elder tree spirit' + else + npc_name = fix_name.call($2) + end + sleep 0.1 + if level = npc[npc_name][:lvl] + calculated_level = nil + if level > 19 + level_variation = [(level/10), 5].min + if spell_circle = spell_circle_list.find { |c| npc[npc_name][:td_mod][c] and npc_td.any? { |foo| (foo['id'] == npc_id) and foo[c] } } + echo "spell_circle: #{spell_circle}" if $sexual_favors_debug + offset = npc[npc_name][:td_mod][spell_circle] + td = npc_td.find { |foo| foo['id'] == npc_id }[spell_circle] + while (line = get) + if line =~ /exist=['"]#{npc_id}['"]/ + for message,bonus in spell_bonus + if line =~ message + echo "td -= #{bonus[spell_circle]}" if $sexual_favors_debug + td -= bonus[spell_circle] + break + end + end + else + script.downstream_buffer.unshift(line) + break + end + end + if ((td - offset) % 3 == 0) and (clvl = (td - offset) / 3) and (clvl <= (level + level_variation)) and (clvl >= (level - level_variation)) + favor_gain = (([clvl, XMLData.level].min*XMLData.level/15.0).ceil/3.0).ceil + favor_error = 0 + calculated_level = clvl + else + favor_gain = (([level, XMLData.level].min*XMLData.level/15.0).ceil/3.0).ceil + favor_error = [ favor_gain - (([level-level_variation, XMLData.level].min*XMLData.level/15.0).ceil/3.0).ceil, ((([level+level_variation, XMLData.level].min*XMLData.level/15.0).ceil/3.0).ceil - favor_gain) ].max + end + else + favor_gain = (([level, XMLData.level].min*XMLData.level/15.0).ceil/3.0).ceil + favor_error = [ favor_gain - (([(level - level_variation), XMLData.level].min * XMLData.level / 15.0).ceil / 3.0).ceil, ((([(level + level_variation), XMLData.level].min * XMLData.level / 15.0).ceil / 3.0).ceil - favor_gain) ].max + end + else + favor_error = 0 + favor_gain = (([level, XMLData.level].min*XMLData.level/15.0).ceil/3.0).ceil + end + $favor[:symbol] += favor_gain + $favor[:symbol_error] += favor_error + $favor[:step] += favor_gain + $favor[:step_error] += favor_error + symbol_favor_gained += favor_gain + step_favor_gained += favor_gain + if favor_error > 0 + output = "+ #{favor_gain} (+/- #{add_commas.call(favor_error)}) (spectator) = #{add_commas.call($favor[:symbol])} (+/- #{add_commas.call($favor[:symbol_error])})" + elsif calculated_level + output = "+ #{favor_gain} (lvl #{calculated_level}) (spectator) = #{add_commas.call($favor[:symbol])}" + if $favor[:symbol_error] > 0 + output.concat " (+/- #{add_commas.call($favor[:symbol_error])})" + end + else + output = "+ #{favor_gain} (spectator) = #{add_commas.call($favor[:symbol])}" + if $favor[:symbol_error] > 0 + output.concat " (+/- #{add_commas.call($favor[:symbol_error])})" + end + end + if Society.rank < 26 + output.concat " step favor: #{add_commas.call($favor[:step])}" + if $favor[:step_error] > 0 + output.concat "(+/- #{add_commas.call($favor[:step_error])})" + end + output.concat "/#{add_commas.call(favor_to_step.call)}" + if favor_to_step.call > 0 + output.concat " (#{($favor[:step]*100)/favor_to_step.call}%)" + end + end + echo output + else + echo "unknown level for #{npc_name}" + end + elsif line =~ /^(?:<.*?>)?The (?:<.*?>)?monk(?:<.*?>)? concludes ceremoniously.*Go now and continue your work\./ + $favor[:step] = 0 + step_favor_gained = 0 + step_start = Time.now + + # + # symbol of blessing + # + elsif line =~ /^A wave of power flows outward from you towards/ + sleep 0.1 + if next_line = get? + # if (next_line =~ /^A soft white glow surrounds|^A brilliant white light wraps around/) and (next_line !~ /gently dissipates|returns to its original color/) + if (next_line =~ /^A brilliant white light (?:streaked with silvery wisps )?wraps around/) and (next_line !~ /returns to its original color/) + # fixme: find a more accurate way to tell if the weapon is magical + if line =~ /(?:carmiln|deringo|faewood|fireleaf|glowbark|hoarbeam|ilthorn|ipantor|kakore|lor|mesille|mossbark|orase|rowan|ruic|sephwir|villswood|witchwood|wyrwood|yew|coraesine|drakar|eahnor|eonake|faenor|glaes|mein|golvern|gornar|imflass|kelyn|krodera|mithglin|mithril|ora|razern|rhimar|rolaren|urglaes|urnon|vaalorn|veil iron|vultite|zorchar)[^\-]/ + subtract_favor.call(2) + elsif item = [GameObj.right_hand, GameObj.left_hand].find { |o| line =~ /#{o.noun}/ } + # fixme + result = dothistimeout "look ##{item.id}", 3, /^You see nothing unusual/ + if result =~ /except for a small enchanter's glyph/ + subtract_favor.call(2) + else + subtract_favor.call(0.4) + end + else + subtract_favor.call(0.4) + end + end + end + # + # symbol of thought + # + elsif line =~ /^You concentrate on the Symbol of Thought/ + sleep 0.1 + unless get? =~ /^You strain/ + if thought = $_CLIENTBUFFER_.reverse.find { |line| line =~ /^(?:\[.+?\]>)?(?:)?sym(?:b|bo|bol)?\s+(?:of\s+)?th(?:o|ou|oug|ough|ought)?/ } + if thought =~ /^(?:\[.+?\]>)?(?:)?sym(?:b|bo|bol)?\s+(?:of\s+)?th(?:o|ou|oug|ough|ought)?\s+(.*)/ + message = $1 + this_favor = [((message.length-1)/3.0).ceil, 83].min + $favor[:symbol] = ($favor[:symbol] - this_favor).to_i + favor_used += this_favor.to_i + echo "- #{this_favor} = #{add_commas.call($favor[:symbol])}" + end + end + end + + elsif line =~ /^You draw a glowing pattern in the air before/ + sleep 0.1 + next_line = get? + + # + # symbol of diminishment + # + if next_line =~ /^(?:<.*?>)?(?:The|A|An) .*? (?:appears diminished|is unaffected)!$/ + subtract_favor.call(3) + + # + # symbol of sleep + # + elsif next_line =~ /eyes roll up into|eyes glass over as a distant look takes over|is unaffected by your Symbol of Sleep/ + subtract_favor.call(2) + + # + # symbol of turning + # + elsif next_line =~ /lets out a blood curdling scream|lets out a scream of terror|backs away from the pattern for a few moments/ + # fixme: more messages maybe + subtract_favor.call(3) + + end + + # + # symbol of courage + # + elsif line =~ /^You feel more courageous/ + subtract_favor.call(1) + + # + # protection + # + elsif line =~ /^You feel a layer of protection surround you/ + subtract_favor.call(1) + + # + # symbol of submission + # + elsif line =~ /^You feel the power of the symbol project toward/ + subtract_favor.call(3) + + # + # symbol of holiness: moved up to kill tracking + # + + # + # symbol of recall + # + elsif line =~ /^You focus on recalling magical assistance that will be of use when you rise again, and feel the power of Lorminstra suffusing your spirit\./ + subtract_favor.call(4) + + # + # symbol of transcendence + # + elsif line =~ /^You step into the space between the corporeal and ethereal realms\.|^With difficulty, you manage to will yourself into the space between the corporeal and ethereal realms\./ + subtract_favor.call(6) + + # + # symbol of mana + # + elsif line =~ /^(?:<.*?>)?You feel a surge of mana flow through you/ + subtract_favor.call(3) + + # + # symbol of sight + # + elsif line =~ /^You concentrate on establishing the link and suddenly you see/ + subtract_favor.call(3) + + # + # symbol of retribution (alive) + # + elsif line =~ /^You feel an aura of righteous wrath surround you\./ + subtract_favor.call(3) + + # + # symbol of retribution (dead) + # + elsif line =~ /^You sense deep within your soul, a rage that burns upward and out of your lips in a terrible scream of rage against the undead!/ + subtract_favor.call(0.4) + + # + # symbol of supremacy + # + elsif line =~ /^You feel infused with a collective knowledge on the undead and their weaknesses\./ + subtract_favor.call(5) + + # + # restoration + # + elsif line =~ /^(?:<.*?>)?You feel the power of the symbol course through your body/ + subtract_favor.call(4) + + # + # symbol of need + # + elsif line =~ /^You concentrate on the Symbol of Need\./ + subtract_favor.call(4) + + # symbol of renewal + # + elsif line =~ /^(?:<.*?>)?You feel a surge of life flow through you\./ + subtract_favor.call(5) # fixme: test + + # + # symbol of disruption + # + elsif line =~ /^A churning spectral aura surrounds you/ + # fixme: extra cost for group members + subtract_favor.call(3) # fixme: test + + # + # symbol of preservation + # + elsif line =~ /^You concentrate and sense the power of the Symbol of Preservation well up within you|^You send a wave of energy toward .*?\. It coalesces around .*? body and then seeps in leaving a glow that strengthens the bond between body and spirit\./ + subtract_favor.call(6) + + # + # symbol of dreams + # + elsif line =~ /^(?:<.*?>)?You feel suddenly tired and lie down for a nap\./ + subtract_favor.call(6) # fixme: test + + # + # symbol of return + # + elsif line =~ /^Your surroundings blur into a white fog \. \. \./ + if symbol = $_CLIENTBUFFER_[[-10,0-$_CLIENTBUFFER_.length].max..-1].reverse.find { |cmd| cmd =~ /^(?:\[.*?\]>)?(?:)?(?:sy|sym|symb|symbo|symbol)\s+(?:of\s+)?(?:retu|see)/i } + unless symbol =~ /\(checked\)$/ + symbol.concat ' (checked)' + if symbol =~ /^(?:\[.*?\]>)?(?:)?(?:sy|sym|symb|symbo|symbol)\s+(?:of\s+)?retu/i + subtract_favor.call(10) + end + end + end + + # fixme: need River's Rest messages + elsif line =~ /^After a few moments of prayer and reflection you see a vision of a flower that has not yet begun to open\./ + echo '0-10%' + elsif line =~ /^After a few moments of prayer and reflection you see a vision of a baby eagle barely hatched from its egg\./ + echo '10-20%' + elsif line =~ /^After a few moments of prayer and reflection you see a vision of a butterfly drying its wings on a leaf\./ + echo '20-30%' + elsif line =~ /^After a few moments of prayer and reflection you see a vision of the headwaters of a mighty river\.\s? Here it has joined with several other streams and is growing quickly\./ + echo '30-40%' + elsif line =~ /^After a few moments of prayer and reflection you see a vision of a weaver on a loom, nearly half way in the creation of an intricate tapestry\./ + echo '40-50%' + elsif line =~ /^After a few moments of prayer and reflection you see a brief vision of twin bowls of wine\.\s? You reach out and empty the contents of one into the other filling it up\.\s? You have a sudden desire to fill up the empty bowl too\./ + echo '50-60%' + elsif line =~ /^After a few moments of prayer and reflection you see a vision of a hiker as he clears the peak of a hill and begins to descend the other side\./ + echo '60-70%' + elsif line =~ /^After a few moments of prayer and reflection you see a vision of a lute, finely crafted, but missing a third of its strings\./ + echo '70-80%' + elsif line =~ /^After a few moments of prayer and reflection you see a vision of a rainbow forming as a thunder storm begins to abate\./ + echo '80-90%' + elsif line =~ /^After a few moments of prayer and reflection you see a vision of a path as it winds its way through a forest and to the edge of a clear pool\.\s? You have a sudden desire to jump in but cannot\./ + echo '90-100%' + elsif line =~ /^After a few moments of prayer and reflection you see a vision of a pool of clear water\.\s? You dive in and swim to the bottom where you find a gold coin engraved with the image of Voln\.\s? An overwhelming feeling makes you realize that you are indeed ready to take the next step along the Path to Enlightenment\./ + echo '100%' + elsif line =~ /^The (?:<.*?>)?globe(?:<.*?>)? feels cold beneath your touch\./ + high = 999 - globe_offset[XMLData.level] + low = 0 + echo "0 revolutions = 0 to #{high} favor" + globe_adjust_favor.call(low, high) + elsif line =~ /^The (?:<.*?>)?globe(?:<.*?>)? hums and turns slowly once under your fingers\./ + high = 1999 - globe_offset[XMLData.level] + low = 1000 - globe_offset[XMLData.level] + echo "1 revolution = #{add_commas.call(low)} to #{add_commas.call(high)} favor" + globe_adjust_favor.call(low, high) + elsif line =~ /^You try to count the number of spins and (?:are certain it was|figure it was around|figure it was at least) ([0-9]+) revolutions\./ + count = $1.to_i + if count < 10 + high = (count*1000) + 999 - globe_offset[XMLData.level] + low = (count*1000) - globe_offset[XMLData.level] + elsif count < 100 + high = (count*1000) + 9999 - globe_offset[XMLData.level] + low = (count*1000) - globe_offset[XMLData.level] + else + high = (count*1000) + 49999 - globe_offset[XMLData.level] + low = (count*1000) - globe_offset[XMLData.level] + end + echo "#{count} revolutions = #{add_commas.call(low)} to #{add_commas.call(high)} favor" + globe_adjust_favor.call(low, high) + end end =begin - - favor to step - - - - level 3 - (accurate) - - rank 1: 115 - rank 2: 215 - rank 3: 315 - rank 4: 430 - rank 5: 530 - rank 6: 630 - rank 7: 745 - rank 8: 845 - rank 9: 945 - rank 10: 1060 - rank 11: 1160 - rank 12: 1260 - rank 13: 1375 - rank 14: 1475 - rank 15: 1575 - rank 16: 1690 - rank 17: 1790 - rank 18: 1890 - rank 19: 2005 - rank 20: 2105 - rank 21: 2205 - rank 22: 2320 - rank 23: 2420 - rank 24: 2520 - rank 25: 2635 - - - level 40 - (accurate) - - rank 1: 2766 - rank 2: 2866 - rank 3: 2966 - rank 4: 5733 - rank 5: 5833 - - - level 77 - (inaccurate by undead level variance) - - step 2: 8,237 - 9,268 - step 4: 19,060 - 21,443 - step 5: 0 - 30,285 - step 6: 0 - 31,412 - step 7: 30,100 - 33,099 - step 8: 30,154 - 33,237 - - - level 78 - (inaccurate by undead level variance) - - step 2: 0 - 12,290 - step 6: 0 - 31,426 - step 7: 30,731 - 31,300 - step 8: 29,983 - 31,359 - - - level 100 - (inaccurate by undead level variance) - - step 17: 101,615 - 103,877 - step 18: 101,956 - 110,905 - step 19: 118,054 - 120,246 - step 20: 117,190 - 118,835 - step 21: 118,046 - 119,890 - step 22: 133,376 - 136,375 - step 23: 134,386 - 137,352 - step 24: 135,500 - 137,673 - - - -=end - -=begin - - - level 100 globe - - - favor message - ----- ------- - 0- 978 The globe feels cold beneath your touch. - 979- 1978 The globe hums and turns slowly once under your fingers. - 1979- 2978 You try to count the number of spins and are certain it was 2 revolutions. - 2979- 3978 You try to count the number of spins and are certain it was 3 revolutions. - 3979- 4978 You try to count the number of spins and are certain it was 4 revolutions. - 4979- 5978 You try to count the number of spins and are certain it was 5 revolutions. - 5979- 6978 You try to count the number of spins and are certain it was 6 revolutions. - 6979- 7978 You try to count the number of spins and are certain it was 7 revolutions. - 7979- 8978 You try to count the number of spins and are certain it was 8 revolutions. - 8979- 9978 You try to count the number of spins and are certain it was 9 revolutions. - 9979- 19978 You try to count the number of spins and figure it was around 10 revolutions. - 19979- 29978 You try to count the number of spins and figure it was around 20 revolutions. - 29979- 39978 You try to count the number of spins and figure it was around 30 revolutions. - 39979- 49978 You try to count the number of spins and figure it was around 40 revolutions. - 49979- You try to count the number of spins and figure it was around 50 revolutions. - - -392316 You try to count the number of spins and figure it was at least 350 revolutions. - - - - level 3-10 globe - - - favor message - ----- ------- - 0- 999 The globe feels cold beneath your touch. - 1000- 1999 The globe hums and turns slowly once under your fingers. - 2000- You try to count the number of spins and are certain it was 2 revolutions. - - - level 11-15 globe - - - favor message - ----- ------- - 0- 998 The globe feels cold beneath your touch. - 999- 1998 The globe hums and turns slowly once under your fingers. - 1999- You try to count the number of spins and are certain it was 2 revolutions. - - - level 16-20 globe - - - favor message - ----- ------- - 0- 997 The globe feels cold beneath your touch. - 998- 1997 The globe hums and turns slowly once under your fingers. - 1998- You try to count the number of spins and are certain it was 2 revolutions. - - - level 21-25 globe - - - favor message - ----- ------- - 0- 996 The globe feels cold beneath your touch. - 997- 1996 The globe hums and turns slowly once under your fingers. - 1997- You try to count the number of spins and are certain it was 2 revolutions. - - - level 26-30 globe - - - favor message - ----- ------- - 0- 995 The globe feels cold beneath your touch. - 996- 1995 The globe hums and turns slowly once under your fingers. - 1996- You try to count the number of spins and are certain it was 2 revolutions. - - - level 31-34 globe - - - favor message - ----- ------- - 0- 994 The globe feels cold beneath your touch. - 995- 1994 The globe hums and turns slowly once under your fingers. - 1995- You try to count the number of spins and are certain it was 2 revolutions. - - - level 35-38 globe - - - favor message - ----- ------- - 0- 993 The globe feels cold beneath your touch. - 994- 1993 The globe hums and turns slowly once under your fingers. - 1994- You try to count the number of spins and are certain it was 2 revolutions. - - - level 39-42 globe - - - favor message - ----- ------- - 0- 992 The globe feels cold beneath your touch. - 993- 1992 The globe hums and turns slowly once under your fingers. - 1993- You try to count the number of spins and are certain it was 2 revolutions. - -=end - -=begin - - - level 3 - - - level 1- 5 kill = 1 favor - level 6-10 kill = 2 favor - level 13-15 kill = 3 favor - level 16-20 kill = 4 favor - level 23 kill = 5 favor - - level 1-41 spectator = 1 favor - - sym bless = 1 favor - sym courage = 2 favor - sym sleep = 3 favor - sym dimin = 4 favor - sym need = 5 favor - sym suprem = 7 favor - sym transen = 8 favor - sym return = 13 favor - - - level 4 - - - level 1- 3 kill = 1 favor - level 4- 6 kill = 2 favor - level 8-10 kill = 3 favor - level 13-15 kill = 4 favor - level 16 kill = 5 favor - level 20 kill = 6 favor - - level 1-20 spectator = 1 favor - - sym bless = 1 favor - sym courage = 3 favor - sym sleep = 5 favor - sym dimin = 7 favor - sym need = 9 favor - sym suprem = 11 favor - sym transen = 13 favor - sym return = 22 favor - - - level 5 - - - sym bless = 2 favor - sym courage = 4 favor - sym sleep = 7 favor - sym dimin = 10 favor - sym need = 13 favor - sym suprem = 16 favor - sym transen = 19 favor - sym return = 32 favor - - level 1- 3 kill = 1 favor - level 6 kill = 2 favor - level 9 kill = 3 favor - level 15 kill = 5 favor - level 16 kill = 6 favor - - level 16 spectator = 1 favor - - - level 6 - - - level 3 kill = 2 favor - level 6 kill = 3 favor - level 16 kill = 7 favor - level 20 kill = 8 favor - level 24 kill = 10 favor - - level 1-2 spectator = 1 favor - - sym bless = 2 favor - sym courage = 5 favor - sym sleep = 9 favor - sym dimin = 13 favor - sym need = 18 favor - sym suprem = 22 favor - sym transen = 26 favor - sym return = 43 favor - - - level 7 - - - checked kill: 3, 9, 16, 20, 24 - checked spectator: 9, 16, 20 - - sym bless = 3 favor - sym courage = 6 favor - sym sleep = 12 favor - sym dimin = 17 favor - sym need = 23 favor - sym suprem = 28 favor - sym transen = 34 favor - sym return = 56 favor - - - level 8 - - - checked kill: 1, 2, 6, 16, 24 - checked spectator: 1, 2, 6, 16, 24 - - sym bless = 3 favor - sym courage = 7 favor - sym sleep = 14 favor - sym dimin = 21 favor - sym need = 28 favor - sym suprem = 35 favor - sym transen = 42 favor - sym return = 70 favor - - - level 9 - - - checked kill: 1, 2 - - sym bless = 4 favor - sym courage = 9 favor - sym sleep = 17 favor - sym dimin = 26 favor - sym need = 34 favor - sym suprem = 43 favor - sym transen = 51 favor - sym return = 85 favor - - - - level 10 - - - checked kill: 1, 2 - - sym bless = 4 favor - sym courage = 10 favor - sym sleep = 20 favor - sym dimin = 30 favor - sym need = 40 favor - sym suprem = 50 favor - sym transen = 60 favor - sym return = 100 favor - - - level 11 - - - checked kill: 1, 2, 6 - - sym bless = 5 favor - sym courage = 12 favor - sym sleep = 24 favor - sym dimin = 35 favor - sym need = 47 favor - sym suprem = 59 favor - sym transen = 70 favor - sym return = 117 favor - - - level 12 - - - checked kill: 1, 2, 6 - - sym bless = 6 favor - sym courage = 14 favor - sym sleep = 27 favor - sym dimin = 40 favor - sym need = 54 favor - sym suprem = 67 favor - sym transen = 80 favor - sym return = 134 favor - - - level 13 - - - checked kill: 1, 2, 3, 6, 9 - - sym bless = 7 favor - sym courage = 16 favor - sym sleep = 31 favor - sym dimin = 46 favor - sym need = 61 favor - sym suprem = 76 favor - sym transen = 91 favor - sym return = 151 favor - - - level 14 - - - checked kill: 1, 2, 3, 9 - checked spectator: 1, 2 - - sym bless = 7 favor - sym courage = 17 favor - sym sleep = 34 favor - sym dimin = 51 favor - sym need = 68 favor - sym suprem = 85 favor - sym transen = 102 favor - sym return = 169 favor - - - level 15 - - - checked kill: 1, 2, 15 - checked spectator: 1, 2 - - sym bless = 8 favor - sym courage = 19 favor - sym sleep = 38 favor - sym dimin = 57 favor - sym need = 75 favor - sym suprem = 94 favor - sym transen = 113 favor - sym return = 188 favor - - - - level 16 - - - checked kill: 1, 2 - checked spectator: - - sym bless = 9 favor - sym courage = 21 favor - sym sleep = 42 favor - sym dimin = 62 favor - sym need = 83 favor - sym suprem = 104 favor - sym transen = 124 favor - sym return = 207 favor - - - level 17 - - - checked kill: 1, 2, 15 - checked spectator: - - sym bless = 10 favor - sym courage = 23 favor - sym sleep = 46 favor - sym dimin = 68 favor - sym need = 91 favor - sym suprem = 113 favor - sym transen = 136 favor - sym return = 226 favor - - - level 18 - - - checked kill: 1, 2, 15 - checked spectator: - - sym bless = 10 favor - sym courage = 25 favor - sym sleep = 50 favor - sym dimin = 74 favor - sym need = 99 favor - sym suprem = 123 favor - sym transen = 148 favor - sym return = 246 favor - - - level 19 - - - checked kill: 1, 2, 15 - checked spectator: - - sym bless = 11 favor - sym courage = 27 favor - sym sleep = 54 favor - sym dimin = 80 favor - sym need = 107 favor - sym suprem = 133 favor - sym transen = 160 favor - sym return = 266 favor - - - level 20 - - - checked kill: 1, 2, 15 - checked spectator: - - sym bless = 12 favor - sym courage = 29 favor - sym sleep = 58 favor - sym dimin = 86 favor - sym need = 115 favor - sym suprem = 143 favor - sym transen = 172 favor - sym return = 286 favor - - - level 21 - - - checked kill: 1, 15 - checked spectator: - - sym bless = 13 favor - sym courage = 31 favor - sym sleep = 62 favor - sym dimin = 92 favor - sym need = 123 favor - sym suprem = 154 favor - sym transen = 184 favor - sym return = 307 favor - - - level 22 - - - checked kill: 15 - checked spectator: - - sym bless = 14 favor - sym courage = 33 favor - sym sleep = 66 favor - sym dimin = 99 favor - sym need = 131 favor - sym suprem = 164 favor - sym transen = 197 favor - sym return = 328 favor - - - level 23 - - - checked kill: 15, 23 - checked spectator: - - sym bless = 14 favor - sym courage = 35 favor - sym sleep = 70 favor - sym dimin = 105 favor - sym need = 140 favor - sym suprem = 175 favor - sym transen = 209 favor - sym return = 349 favor - - - level 24 - - - checked kill: 15 - checked spectator: - - sym bless = 15 favor - sym courage = 37 favor - sym sleep = 74 favor - sym dimin = 111 favor - sym need = 148 favor - sym suprem = 185 favor - sym transen = 222 favor - sym return = 370 favor - - - level 25 - - - checked kill: 15 - checked spectator: - - sym bless = 16 favor - sym courage = 40 favor - sym sleep = 79 favor - sym dimin = 118 favor - sym need = 157 favor - sym suprem = 196 favor - sym transen = 235 favor - sym return = 391 favor - - - level 26 - - - checked kill: - checked spectator: - - sym bless = 17 favor - sym courage = 42 favor - sym sleep = 83 favor - sym dimin = 124 favor - sym need = 165 favor - sym suprem = 207 favor - sym transen = 248 favor - sym return = 413 favor - - - level 27 - - - sym bless = 18 favor - sym courage = 44 favor - sym sleep = 87 favor - sym dimin = 131 favor - sym need = 174 favor - sym suprem = 217 favor - sym transen = 261 favor - sym return = 434 favor - - - level 28 - - - sym bless = 19 favor - sym courage = 46 favor - sym sleep = 92 favor - sym dimin = 137 favor - sym need = 183 favor - sym suprem = 228 favor - sym transen = 274 favor - sym return = 456 favor - - - level 29 - - - sym bless = 20 favor - sym courage = 48 favor - sym sleep = 96 favor - sym dimin = 144 favor - sym need = 192 favor - sym suprem = 239 favor - sym transen = 287 favor - sym return = 478 favor - - - level 30 - - - sym bless = 20 favor - sym courage = 50 favor - sym sleep = 100 favor - sym dimin = 150 favor - sym need = 200 favor - sym suprem = 250 favor - sym transen = 300 favor - sym return = 500 favor - - - level 31 - - - level 15 kill: 31 favor - (undead_level * (XMLData.level / 15.0)).ceil = wrong - (undead_level * XMLData.level / 15.0).ceil = right - - sym bless = 21 favor - sym courage = 53 favor - sym sleep = 105 favor - sym dimin = 157 favor - sym need = 209 favor - sym suprem = 262 favor - sym transen = 314 favor - sym return = 523 favor - - - level 32 - - - sym bless = 22 favor - sym courage = 55 favor - sym sleep = 109 favor - sym dimin = 164 favor - sym need = 218 favor - sym suprem = 273 favor - sym transen = 327 favor - sym return = 545 favor - - - level 33 - - - sym bless = 23 favor - sym courage = 57 favor - sym sleep = 114 favor - sym dimin = 171 favor - sym need = 227 favor - sym suprem = 284 favor - sym transen = 341 favor - sym return = 568 favor - - - level 34 - - - sym bless = 24 favor - sym courage = 59 favor - sym sleep = 118 favor - sym dimin = 177 favor - sym need = 236 favor - sym suprem = 295 favor - sym transen = 354 favor - sym return = 590 favor - - - level 35 - - - sym bless = 25 favor - sym courage = 62 favor - sym sleep = 123 favor - sym dimin = 184 favor - sym need = 245 favor - sym suprem = 307 favor - sym transen = 368 favor - sym return = 613 favor - - - level 36 - - - sym bless = 26 favor - sym courage = 64 favor - sym sleep = 128 favor - sym dimin = 191 favor - sym need = 255 favor - sym suprem = 318 favor - sym transen = 382 favor - sym return = 636 favor - - - level 37 - - - sym bless = 27 favor - sym courage = 66 favor - sym sleep = 132 favor - sym dimin = 198 favor - sym need = 264 favor - sym suprem = 330 favor - sym transen = 395 favor - sym return = 659 favor - - - level 38 - - - sym bless = 28 favor - sym courage = 69 favor - sym sleep = 137 favor - sym dimin = 205 favor - sym need = 273 favor - sym suprem = 341 favor - sym transen = 409 favor - sym return = 682 favor - - - level 39 - - - sym bless = 29 favor - sym courage = 71 favor - sym sleep = 141 favor - sym dimin = 212 favor - sym need = 282 favor - sym suprem = 353 favor - sym transen = 423 favor - sym return = 705 favor - - - level 40 - - - sym bless = 30 favor - sym courage = 73 favor - sym sleep = 146 favor - sym dimin = 219 favor - sym need = 291 favor (wrong on krakii) - sym suprem = 364 favor - sym transen = 437 favor - sym return = 728 favor - - - level 41 - - - sym bless = 31 favor - sym courage = 76 favor - sym sleep = 151 favor - sym dimin = 226 favor - sym need = 301 favor - sym suprem = 376 favor - sym transen = 451 favor - sym return = 751 favor - - - level 42 - - - sym bless = 31 favor - sym courage = 78 favor - sym sleep = 155 favor - sym dimin = 233 favor - sym need = 310 favor - sym suprem = 387 favor - sym transen = 465 favor - sym return = 774 favor - - - level 43 - - - sym bless = 32 favor - sym courage = 80 favor - sym sleep = 160 favor - sym dimin = 240 favor (formula says 239) - sym need = 319 favor - sym suprem = 399 favor - sym transen = 479 favor (formula says 478) - sym return = 797 favor - + ---------- symbol favor cost (as measured) ---------- globe +level 0.4x 1x 2x 3x 4x 5x 6x 10x offset +----- ---- ---- ---- ---- ---- ---- ---- ---- ------ + 3 1 2 3 4 5 7 8 13 0 + 4 1 3 5 7 9 11 13 22 0 + 5 2 4 7 10 13 16 19 32 0 + 6 2 5 9 13 18 22 26 43 0 + 7 3 6 12 17 23 28 34 56 0 + 8 3 7 14 21 28 35 42 70 0 + 9 4 9 17 26 34 43 51 85 0 + 10 4 10 20 30 40 50 60 100 0 + 11 5 12 24 35 47 59 70 117 1 + 12 6 14 27 40 54 67 80 134 1 + 13 7 16 31 46 61 76 91 151 1 + 14 7 17 34 51 68 85 102 169 1 + 15 8 19 38 57 75 94 113 188 1 + 16 9 21 42 62 83 104 124 207 2 + 17 10 23 46 68 91 113 136 226 2 + 18 10 25 50 74 99 123 148 246 2 + 19 11 27 54 80 107 133 160 266 2 + 20 12 29 58 86 115 143 172 286 2 + 21 13 31 62 92 123 154 184 307 3 + 22 14 33 66 99 131 164 197 328 3 + 23 14 35 70 105 140 175 209 349 3 + 24 15 37 74 111 148 185 222 370 3 + 25 16 40 79 118 157 196 235 391 3 + 26 17 42 83 124 165 207 248 413 4 + 27 18 44 87 131 174 217 261 434 4 + 28 19 46 92 137 183 228 274 456 4 + 29 20 48 96 144 192 239 287 478 4 + 30 20 50 100 150 200 250 300 500 4 + 31 21 53 105 157 209 262 314 523 5 + 32 22 55 109 164 218 273 327 545 5 + 33 23 57 114 171 227 284 341 568 5 + 34 24 59 118 177 236 295 354 590 5 + 35 25 62 123 184 245 307 368 613 6 + 36 26 64 128 191 255 318 382 636 6 + 37 27 66 132 198 264 330 395 659 6 + 38 28 69 137 205 273 341 409 682 6 + 39 29 71 141 212 282 353 423 705 7 + 40 30 73 146 219 291 364 437 728 7 + 41 31 76 151 226 301 376 451 751 7 + 42 31 78 155 233 310 387 465 774 7 + 43 32 80 160 240 319 399 479 797 7 + 44 33 83 165 247 329 411 493 821 8 + 45 34 85 169 254 338 422 507 844 8 + 46 35 87 174 261 347 434 521 868 8 + 47 36 90 179 268 357 446 535 891 8 + 48 37 92 183 275 366 458 549 915 9 + 49 38 94 188 282 376 469 563 938 9 + 50 39 97 193 289 385 481 577 962 9 + 51 40 99 198 296 395 493 592 986 10 (fixme: retest globe offset) + 52 41 101 202 303 404 505 606 1009 10 + 53 42 104 207 310 414 517 620 1033 10 + 54 43 106 212 317 423 529 634 1057 10 + 55 44 109 217 325 433 541 649 1081 10 + 56 45 111 221 332 442 553 663 1105 11 + 57 46 113 226 339 452 565 677 1129 11 + 58 47 116 231 346 461 577 692 1153 11 + 59 48 118 236 353 471 589 706 1177 11 + 60 48 120 240 360 480 600 729 1200 11 + 61 49 123 245 368 490 613 735 1225 12 + 62 50 125 250 375 500 625 749 1249 12 + 63 51 128 255 382 509 637 764 1273 12 + 64 52 130 260 389 519 649 778 1297 12 + 65 53 133 265 397 529 661 793 1321 13 + 66 54 135 269 404 538 673 807 1345 13 + 67 55 137 274 411 548 685 822 1369 13 + 68 56 140 279 418 558 697 836 1393 13 + 69 57 142 284 426 567 709 851 1417 14 + 70 58 145 289 433 577 721 865 1442 14 + 71 59 147 294 440 587 733 880 1466 14 + 72 60 149 298 447 596 750 894 1490 14 + 73 61 152 303 455 606 757 909 1514 15 + 74 62 154 308 462 616 770 923 1539 15 + 75 63 157 313 469 625 782 938 1563 15 + 76 64 159 318 477 635 794 953 1587 15 + 77 65 162 323 484 645 806 967 1612 16 + 78 66 164 328 491 655 818 982 1636 16 + 79 67 166 332 498 664 830 996 1660 16 + 80 68 169 337 506 674 843 1011 1685 16 + 81 69 171 342 513 684 855 1026 1709 17 + 82 70 174 347 520 694 867 1040 1733 17 + 83 71 176 352 528 703 879 1055 1758 17 + 84 72 179 357 535 713 891 1070 1782 17 + 85 73 181 362 542 723 904 1084 1807 17 + 86 74 184 367 550 733 916 1099 1831 18 + 87 75 186 372 557 743 928 1114 1856 18 + 88 76 188 376 564 752 940 1128 1880 18 + 89 77 191 381 572 762 953 1143 1905 19 + 90 78 193 386 579 772 965 1158 1929 19 + 91 79 196 391 586 782 977 1172 1954 19 + 92 80 198 396 594 792 989 1187 1978 19 + 93 81 201 401 601 801 1002 1202 2003 20 + 94 82 203 406 608 811 1014 1216 2027 20 + 95 83 206 411 616 821 1026 1231 2052 20 + 96 84 208 416 623 831 1038 1246 2076 20 + 97 85 211 421 631 841 1051 1261 2101 21 + 98 85 213 425 638 850 1063 1275 2125 21 + 99 86 215 430 645 860 1075 1290 2150 21 + 100 87 218 435 653 870 1087 1305 2174 21 + +globe offset: + The globe feels cold beneath your touch. = 0 to (999 - offset) favor + The globe hums and turns slowly once under your fingers. = (1000 - offset) to (1999 - offset) favor =end =begin - # stupid fame only works some of the time for various reasons + # stupid fame only works some of the time for various reasons check_fame = proc { - fame = nil - started = false - hook_proc = proc { |server_string| - if started - if server_string =~ /^\s*Mental TPs: [0-9]+\s+Fame\: ([0-9]+)/ - fame = $1.to_i - nil - elsif server_string =~ /Your spell is ready\.<\/a>/ + nil + elsif rt_string.nil? if (server_string =~ /^(?:<.+>)?Roundtime\: ([0-9]+) sec\./) and (XMLData.active_spells['Haste'] or XMLData.active_spells['506']) orig_rt = $1 rt_string = server_string @@ -35,6 +43,10 @@ hook_proc = proc { |server_string| new_server_string end } -DownstreamHook.add('short_haste_message', hook_proc) -loop { sleep 1 } +begin + DownstreamHook.add('short_haste_message', hook_proc) + loop { sleep 1 } +ensure + DownstreamHook.remove('short_haste_message') +end diff --git a/sorter.lic b/sorter.lic index 9d02ebc..4e0aa0d 100644 --- a/sorter.lic +++ b/sorter.lic @@ -6,7 +6,32 @@ ;sorter width= to display contents in columns ;sorter width=nil to stop using columns - tillmen@lichproject.org + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: cosmetic + version: 0.9 + + changelog: + 0.9 (2016-08-17): + fix for the last fix + 0.8 (2016-08-07): + fix for containers that give XML of what's inside the container when you look on the container + 0.7 (2015-04-16): + fix display of broken containers on WizardFE + +=end +=begin + + 0.6 (2015-02-17): + fix the fix for squelching containers that can't be sorted + 0.5 (2015-02-17): + another fix for squelching containers that can't be sorted + 0.4 (2014-11-21): + fix for squelching containers that can't be sorted + 0.3 (2014-11-21): + testing fix for squelching containers that can't be sorted + 0.2 (2014-11-10): + don't display container contents twice on Lich 4.6 =end @@ -73,19 +98,28 @@ best_column_count = proc { |list| } begin - action = proc { |server_string| - if server_string =~ /^(|)(?:[IO]n the .*?exist=".*?".*? you see |Peering into the .*?, you see .*?(?:, | and )(?:a|an|some) <).*\./ - $1 + action = proc { |s| + if s =~ /^(<(?:c|clearC|exposeC)ontainer.+>)?(?:[IO]n the .*? you see |Peering into the .*?, you see .*?(?:, | and )(?:a|an|some) <)/ + xml_only = $1 + if s =~ /In the/ and s =~ /On the/ + s + elsif s =~ /^(?:||)(?:(?:[IO]n the .*?) you see .*\.|(?:Peering into the .*?, you see .*?)(?:, | and )(?:a|an|some) <.*\.)/ + xml_only + else + s + end else - server_string + s end } DownstreamHook.add('sorter', action) while (line = get) - if line =~ /^(?:|)([IO]n the .*?) you see .*\./ + if line =~ /^(?:||)([IO]n the .*?) you see .*\./ container = $1 - elsif line =~ /^(?:|)(Peering into the .*?, you see .*?)(?:, | and )(?:a|an|some) <.*\./ + next if line =~ /In the/ and line =~ /On the/ + elsif line =~ /^(?:||)(Peering into the .*?, you see .*?)(?:, | and )(?:a|an|some) <.*\./ container = $1.concat ' and' + next if line =~ /In the/ and line =~ /On the/ else next end diff --git a/staminabar.lic b/staminabar.lic index 47b0a2b..40334c2 100644 --- a/staminabar.lic +++ b/staminabar.lic @@ -2,7 +2,10 @@ Quick script to show your stamina in a progress bar - tillmen@lichproject.org + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: cosmetic + version: 0.1 =end diff --git a/trollhear.lic b/trollhear.lic index cc686d5..5bc50df 100644 --- a/trollhear.lic +++ b/trollhear.lic @@ -6,7 +6,10 @@ Start the script with some trollspeak to translate it. Start the script with no variables and it will attempt to find and translate any trollspeak that shows up in the game. - tillmen@lichproject.org + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: speech + version: 0.1 =end @@ -101,6 +104,8 @@ loop { if line =~ /\[(General|LNet|Merchant|Guild|House|Shattered)\]/ if $frontend == 'stormfront' puts '[trollhear: ' + to_common(troll) + ']' + elsif $frontend == 'profanity' + _respond '[trollhear: ' + to_common(troll) + ']' else respond "You hear the faint thoughts of [trollhear echo in your mind:\n" + to_common(troll) + "]" end diff --git a/trollspeak.lic b/trollspeak.lic index 7c4258e..56ebebc 100644 --- a/trollspeak.lic +++ b/trollspeak.lic @@ -4,7 +4,10 @@ ;trollspeak - tillmen@lichproject.org + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: speech + version: 0.1 =end diff --git a/useherbs.lic b/useherbs.lic index e5ec045..6ae179c 100644 --- a/useherbs.lic +++ b/useherbs.lic @@ -4,226 +4,271 @@ Will use herbs in your herbsack, or on a bench or something. Works with any combination of herbs from any town. - Herbsack must be set. ( unless using bench mode, ;set change herbsack ) - Might heal your Adventurer's Guild escort. ( ;useherbs escort ) - Will buy missing herbs. ( ;useherbs buy=on ) + Can buy herbs. + Might heal your traveller. - https://github.com/matt-lowe/lich-scripts - tillmen@lichproject.org + ;useherbs help + + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: healing + version: 0.10 + requried: Lich >= 4.6.0 + + changelog: + 0.10 (2017-09-30): + add feature to fill your herbsack with herbs (;useherbs stock herbs) + 0.9 (2017-03-04): + remove 506 from the script, since it doesn't affect eating herbs anymore + 0.8 (2017-01-14): + withdraw silvers first when using the "stock potions" command + 0.7 (2015-04-26): + fix for working with hidden containers, like the basket in Ta'Vaalor =end +=begin -unless defined?(dothis) and defined?(GameObj) - echo 'Your version of Lich is too old for this script.' - exit -end + 0.6 (2015-03-28): + remember to look on/under/behind a container instead of "in" if a second look is required + fix bug with finding a herbsack given on the command line + 0.5 (2015-02-23): + better method of finding container from herbsack setting + 0.4 (2014-12-12): + make "stock potions" track potion use instead of measuring every time + 0.3 (2014-11-14): + set herbsack with ;useherbs set herbsack + +=end # fixme: garland of sovyn cloves # fixme: skip more better # fixme: buy herbs/right hand full # fixme: use bank note -known_herbs = [ - { :name=>"some acantha leaf", :type=>"blood", :store_doses=>10 }, - { :name=>"some spicy acantha leaf", :type=>"blood", :store_doses=>10 }, - { :name=>"tincture of acantha", :type=>"blood" }, - { :name=>"tincture of yabathilium", :type=>"blood" }, - { :name=>"yabathilium fruit", :type=>"blood" }, - { :name=>"iceberry tart", :type=>"blood", :store_doses=>10 }, - { :name=>"some acantha leaf tea", :type=>"blood" }, - { :name=>"grey mushroom potion", :type=>"blood" }, - { :name=>"flagon of Olak's Ol'style ale", :type=>"blood" }, - { :name=>"barrel of Olak's Ol'style ale", :type=>"blood" }, - { :name=>"flagon of Bloody Krolvin ale", :type=>"blood" }, - { :name=>"barrel of Bloody Krolvin ale", :type=>"blood" }, - { :name=>"some aloeas stem", :type=>"major head wound", :store_doses=>2 }, - { :name=>"some withered aloeas stem", :type=>"major head wound", :store_doses=>2 }, - { :name=>"tincture of aloeas", :type=>"major head wound" }, - { :name=>"some ram's bladder", :type=>"major head wound", :store_doses=>2 }, - { :name=>"feverfew potion", :type=>"major head wound" }, - { :name=>"sticky lichen tea", :type=>"major head wound" }, - { :name=>"flagon of Dark Swampwater ale", :type=>"major head wound" }, - { :name=>"barrel of Dark Swampwater ale", :type=>"major head wound" }, - { :name=>"rose-marrow potion", :type=>"minor head wound", :store_doses=>4 }, - { :name=>"crystalline rose-marrow elixir", :type=>"minor head wound" }, - { :name=>"tincture of rose-marrow", :type=>"minor head wound" }, - { :name=>"elk horn potion", :type=>"minor head wound", :store_doses=>4 }, - { :name=>"some feverfew tea", :type=>"minor head wound" }, - { :name=>"rusty red ale", :type=>"minor head wound" }, - { :name=>"flagon of Semak's Smooth ale", :type=>"minor head wound" }, - { :name=>"barrel of Semak's Smooth ale", :type=>"minor head wound" }, - { :name=>"brostheras potion", :type=>"major head scar", :store_doses=>2 }, - { :name=>"crystalline brostheras elixir", :type=>"major head scar" }, - { :name=>"tincture of brostheras", :type=>"major head scar" }, - { :name=>"some polar bear fat soup", :type=>"major head scar", :store_doses=>2 }, - { :name=>"pennyroyal potion", :type=>"major head scar" }, - { :name=>"stone soot brew", :type=>"major head scar" }, - { :name=>"flagon of Reaper's Red ale", :type=>"major head scar" }, - { :name=>"barrel of Reaper's Red ale", :type=>"major head scar" }, - { :name=>"some haphip root", :type=>"minor head scar", :store_doses=>4 }, - { :name=>"some dirty haphip root", :type=>"minor head scar", :store_doses=>4 }, - { :name=>"tincture of haphip", :type=>"minor head scar" }, - { :name=>"sparrowhawk pie", :type=>"minor head scar", :store_doses=>4 }, - { :name=>"pennyroyal tea", :type=>"minor head scar" }, - { :name=>"dull crimson ale", :type=>"minor head scar" }, - { :name=>"flagon of Agrak's Amber ale", :type=>"minor head scar" }, - { :name=>"barrel of Agrak's Amber ale", :type=>"minor head scar" }, - { :name=>"some pothinir grass", :type=>"major organ wound", :store_doses=>2 }, - { :name=>"some bright green pothinir grass", :type=>"major organ wound", :store_doses=>2 }, - { :name=>"tincture of pothinir", :type=>"major organ wound" }, - { :name=>"musk ox tart", :type=>"major organ wound", :store_doses=>2 }, - { :name=>"ginkgo nut potion", :type=>"major organ wound" }, - { :name=>"roasted ratweed tea", :type=>"major organ wound" }, - { :name=>"flagon of Aged Schooner ale", :type=>"major organ wound" }, - { :name=>"barrel of Aged Schooner ale", :type=>"major organ wound" }, - { :name=>"some basal moss", :type=>"minor organ wound", :store_doses=>4 }, - { :name=>"tincture of moss", :type=>"minor organ wound" }, - { :name=>"sticky ball of basal moss", :type=>"minor organ wound", :store_doses=>4 }, - { :name=>"tincture of basal", :type=>"minor organ wound" }, - { :name=>"some tundra grass", :type=>"minor organ wound", :store_doses=>4 }, - { :name=>"some ginkgo nut tea", :type=>"minor organ wound" }, - { :name=>"chunky black ale", :type=>"minor organ wound" }, - { :name=>"flagon of Mama Dwarf's ale", :type=>"minor organ wound" }, - { :name=>"barrel of Mama Dwarf's ale", :type=>"minor organ wound" }, - { :name=>"wingstem potion", :type=>"major organ scar", :store_doses=>2 }, - { :name=>"crystalline wingstem elixir", :type=>"major organ scar" }, - { :name=>"tincture of wingstem", :type=>"major organ scar" }, - { :name=>"earthworm potion", :type=>"major organ scar", :store_doses=>2 }, - { :name=>"wyrmwood root potion", :type=>"major organ scar" }, - { :name=>"dirty crevice brew", :type=>"major organ scar" }, - { :name=>"flagon of Wort's Winter ale", :type=>"major organ scar" }, - { :name=>"barrel of Wort's Winter ale", :type=>"major organ scar" }, - { :name=>"talneo potion", :type=>"minor organ scar", :store_doses=>4 }, - { :name=>"crystalline talneo elixir", :type=>"minor organ scar" }, - { :name=>"tincture of talneo", :type=>"minor organ scar" }, - { :name=>"rock lizard potion", :type=>"minor organ scar", :store_doses=>4 }, - { :name=>"wyrmwood root tea", :type=>"minor organ scar" }, - { :name=>"brown weedroot ale", :type=>"minor organ scar" }, - { :name=>"flagon of Gert's Homemade ale", :type=>"minor organ scar" }, - { :name=>"barrel of Gert's Homemade ale", :type=>"minor organ scar" }, - { :name=>"bur-clover potion", :type=>"missing eye", :store_doses=>1 }, - { :name=>"crystalline bur-clover elixir", :type=>"missing eye", }, - { :name=>"tincture of bur-clover", :type=>"missing eye" }, - { :name=>"starfish potion", :type=>"missing eye", :store_doses=>1 }, - { :name=>"daggit root potion", :type=>"missing eye" }, - { :name=>"dirty rat fur potion", :type=>"missing eye" }, - { :name=>"flagon of Volcano Vision ale", :type=>"missing eye" }, - { :name=>"barrel of Volcano Vision ale", :type=>"missing eye" }, - { :name=>"some ephlox moss", :type=>"major limb wound", :store_doses=>4 }, - { :name=>"gooey ball of ephlox moss", :type=>"major limb wound" }, - { :name=>"tincture of ephlox", :type=>"major limb wound" }, - { :name=>"some frog's bone porridge", :type=>"major limb wound", :store_doses=>4 }, - { :name=>"sweetfern potion", :type=>"major limb wound" }, - { :name=>"crushed cavegrass tea", :type=>"major limb wound" }, - { :name=>"flagon of Golden Goose ale", :type=>"major limb wound" }, - { :name=>"barrel of Golden Goose ale", :type=>"major limb wound" }, - { :name=>"some ambrominas leaf", :type=>"minor limb wound", :store_doses=>4 }, - { :name=>"some sugary ambrominas leaf", :type=>"minor limb wound", }, - { :name=>"tincture of ambrominas", :type=>"minor limb wound" }, - { :name=>"Dabbings Family special tart", :type=>"minor limb wound", :store_doses=>4 }, - { :name=>"some sweetfern tea", :type=>"minor limb wound" }, - { :name=>"bubbling brown ale", :type=>"minor limb wound" }, - { :name=>"flagon of Lost Dogwater ale", :type=>"minor limb wound" }, - { :name=>"barrel of Lost Dogwater ale", :type=>"minor limb wound" }, - { :name=>"some calamia fruit", :type=>"major limb scar", :store_doses=>2 }, - { :name=>"some ripe calamia fruit", :type=>"major limb scar" }, - { :name=>"tincture of calamia", :type=>"major limb scar" }, - { :name=>"some walrus blubber", :type=>"major limb scar", :store_doses=>2 }, - { :name=>"manroot potion", :type=>"major limb scar" }, - { :name=>"stalactite brew", :type=>"major limb scar" }, - { :name=>"flagon of Mad Mutt Frothy ale", :type=>"major limb scar" }, - { :name=>"barrel of Mad Mutt Frothy ale", :type=>"major limb scar" }, - { :name=>"some cactacae spine", :type=>"minor limb scar", :store_doses=>4 }, - { :name=>"some prickly cactacae spine", :type=>"minor limb scar" }, - { :name=>"tincture of cactacae", :type=>"minor limb scar" }, - { :name=>"some elk fat gel", :type=>"minor limb scar", :store_doses=>4 }, - { :name=>"manroot tea", :type=>"minor limb scar" }, - { :name=>"spotted toadstool ale", :type=>"minor limb scar" }, - { :name=>"flagon of Bearded Ladies' ale", :type=>"minor limb scar" }, - { :name=>"barrel of Bearded Ladies' ale", :type=>"minor limb scar" }, - { :name=>"some sovyn clove", :type=>"severed limb", :store_doses=>1 }, - { :name=>"sovyn clove", :type=>"severed limb" }, - { :name=>"tincture of sovyn", :type=>"severed limb" }, - { :name=>"some rock ptarmigan feathers", :type=>"severed limb", :store_doses=>1 }, - { :name=>"angelica root potion", :type=>"severed limb" }, - { :name=>"grainy black potion", :type=>"severed limb" }, - { :name=>"flagon of Captn' Pegleg's ale", :type=>"severed limb" }, - { :name=>"barrel of Captn' Pegleg's ale", :type=>"severed limb" }, - { :name=>"bolmara potion", :type=>"major nerve wound", :store_doses=>4 }, - { :name=>"crystalline bolmara elixir", :type=>"major nerve wound" }, - { :name=>"tincture of bolmara", :type=>"major nerve wound" }, - { :name=>"snowflake elixir", :type=>"major nerve wound", :store_doses=>4 }, - { :name=>"red lichen potion", :type=>"major nerve wound" }, - { :name=>"glowing mold tea", :type=>"major nerve wound" }, - { :name=>"flagon of Kenar's Dropjaw ale", :type=>"major nerve wound" }, - { :name=>"barrel of Kenar's Dropjaw ale", :type=>"major nerve wound" }, - { :name=>"some wolifrew lichen", :type=>"minor nerve wound", :store_doses=>4 }, - { :name=>"some dry wolifrew lichen", :type=>"minor nerve wound", }, - { :name=>"tincture of wolifrew", :type=>"minor nerve wound" }, - { :name=>"Leaftoe's lichen tart", :type=>"minor nerve wound", :store_doses=>4 }, - { :name=>"some red lichen tea", :type=>"minor nerve wound" }, - { :name=>"thick foggy ale", :type=>"minor nerve wound" }, - { :name=>"flagon of Orc's Head ale", :type=>"minor nerve wound" }, - { :name=>"barrel of Orc's Head ale", :type=>"minor nerve wound" }, - { :name=>"some woth flower", :type=>"major nerve scar", :store_doses=>2 }, - { :name=>"some fragrant woth flower", :type=>"major nerve scar" }, - { :name=>"tincture of woth", :type=>"major nerve scar" }, - { :name=>"flower-shaped tart", :type=>"major nerve scar", :store_doses=>2 }, - { :name=>"valerian root potion", :type=>"major nerve scar" }, - { :name=>"stalagmite brew", :type=>"major nerve scar" }, - { :name=>"flagon of Dacra's Dream ale", :type=>"major nerve scar" }, - { :name=>"barrel of Dacra's Dream ale", :type=>"major nerve scar" }, - { :name=>"some torban leaf", :type=>"minor nerve scar", :store_doses=>3 }, - { :name=>"some fresh torban leaf", :type=>"minor nerve scar" }, - { :name=>"tincture of torban", :type=>"minor nerve scar" }, - { :name=>"Ma Leaftoe's spiced torban tart", :type=>"minor nerve scar", :store_doses=>4 }, - { :name=>"valerian root tea", :type=>"minor nerve scar" }, - { :name=>"dark frothing ale", :type=>"minor nerve scar" }, - { :name=>"flagon of Miner's Muddy ale", :type=>"minor nerve scar" }, - { :name=>"barrel of Miner's Muddy ale", :type=>"minor nerve scar" }, - { :name=>"dimly glowing sky-blue potion", :type=>"disease" }, - { :name=>"dimly glowing sea-green potion", :type=>"poison" }, +$known_herbs = [ + { :name=>"some acantha leaf", :type=>"blood", :short_name => "acantha leaf", :store_doses=>10 }, + { :name=>"some spicy acantha leaf", :type=>"blood", :short_name => "spicy acantha leaf", :store_doses=>10 }, + { :name=>"tincture of acantha", :type=>"blood", }, + { :name=>"tincture of yabathilium", :type=>"blood", }, + { :name=>"yabathilium fruit", :type=>"blood", }, + { :name=>"iceberry tart", :type=>"blood", :store_doses=>10 }, + { :name=>"some acantha leaf tea", :type=>"blood", :short_name => "acantha leaf tea" }, + { :name=>"grey mushroom potion", :type=>"blood", }, + { :name=>"flagon of Olak's Ol'style ale", :type=>"blood", :short_name => "Olak's Ol'style ale" }, + { :name=>"barrel of Olak's Ol'style ale", :type=>"blood", :short_name => "Olak's Ol'style ale" }, + { :name=>"flagon of Bloody Krolvin ale", :type=>"blood", :short_name => "Bloody Krolvin ale" }, + { :name=>"barrel of Bloody Krolvin ale", :type=>"blood", :short_name => "Bloody Krolvin ale" }, + { :name=>"some aloeas stem", :type=>"major head wound", :short_name => "aloeas stem", :store_doses=>2 }, + { :name=>"some withered aloeas stem", :type=>"major head wound", :short_name => "withered aloeas stem", :store_doses=>2 }, + { :name=>"tincture of aloeas", :type=>"major head wound", }, + { :name=>"tiny ram's bladder tart", :type=>"major head wound", :short_name => "ram's bladder tart", :store_doses=>2 }, + { :name=>"feverfew potion", :type=>"major head wound", }, + { :name=>"sticky lichen tea", :type=>"major head wound", }, + { :name=>"flagon of Dark Swampwater ale", :type=>"major head wound", :short_name => "Dark Swampwater ale" }, + { :name=>"barrel of Dark Swampwater ale", :type=>"major head wound", :short_name => "Dark Swampwater ale" }, + { :name=>"rose-marrow potion", :type=>"minor head wound", :store_doses=>4 }, + { :name=>"crystalline rose-marrow elixir", :type=>"minor head wound", }, + { :name=>"tincture of rose-marrow", :type=>"minor head wound", }, + { :name=>"elk horn potion", :type=>"minor head wound", :store_doses=>4 }, + { :name=>"some feverfew tea", :type=>"minor head wound", :short_name => "feverfew tea" }, + { :name=>"rusty red ale", :type=>"minor head wound", }, + { :name=>"flagon of Semak's Smooth ale", :type=>"minor head wound", :short_name => "Semak's Smooth ale" }, + { :name=>"barrel of Semak's Smooth ale", :type=>"minor head wound", :short_name => "Semak's Smooth ale" }, + { :name=>"brostheras potion", :type=>"major head scar", :store_doses=>2 }, + { :name=>"crystalline brostheras elixir", :type=>"major head scar", }, + { :name=>"tincture of brostheras", :type=>"major head scar", }, + { :name=>"tiny cup of polar bear fat soup", :type=>"major head scar", :store_doses=>2, :short_name => 'polar bear fat soup' }, + { :name=>"pennyroyal potion", :type=>"major head scar", }, + { :name=>"stone soot brew", :type=>"major head scar", }, + { :name=>"flagon of Reaper's Red ale", :type=>"major head scar", :short_name => "Reaper's Red ale" }, + { :name=>"barrel of Reaper's Red ale", :type=>"major head scar", :short_name => "Reaper's Red ale" }, + { :name=>"some haphip root", :type=>"minor head scar", :short_name => "haphip root", :store_doses=>4 }, + { :name=>"some dirty haphip root", :type=>"minor head scar", :short_name => "dirty haphip root", :store_doses=>4 }, + { :name=>"tincture of haphip", :type=>"minor head scar", }, + { :name=>"slice of sparrowhawk pie", :type=>"minor head scar", :store_doses=>5, :short_name => 'sparrowhawk pie' }, + { :name=>"pennyroyal tea", :type=>"minor head scar", }, + { :name=>"dull crimson ale", :type=>"minor head scar", }, + { :name=>"flagon of Agrak's Amber ale", :type=>"minor head scar", :short_name => "Agrak's Amber ale" }, + { :name=>"barrel of Agrak's Amber ale", :type=>"minor head scar", :short_name => "Agrak's Amber ale" }, + { :name=>"some pothinir grass", :type=>"major organ wound", :short_name => "pothinir grass", :store_doses=>2 }, + { :name=>"some bright green pothinir grass", :type=>"major organ wound", :short_name => "pothinir grass", :store_doses=>2 }, + { :name=>"tincture of pothinir", :type=>"major organ wound", }, + { :name=>"tiny musk ox tart", :type=>"major organ wound", :short_name => 'musk ox tart', :store_doses=>2 }, + { :name=>"ginkgo nut potion", :type=>"major organ wound", }, + { :name=>"roasted ratweed tea", :type=>"major organ wound", }, + { :name=>"flagon of Aged Schooner ale", :type=>"major organ wound", :short_name => "Aged Schooner ale" }, + { :name=>"barrel of Aged Schooner ale", :type=>"major organ wound", :short_name => "Aged Schooner ale" }, + { :name=>"some basal moss", :type=>"minor organ wound", :short_name => "basal moss", :store_doses=>4 }, + { :name=>"tincture of moss", :type=>"minor organ wound", }, + { :name=>"sticky ball of basal moss", :type=>"minor organ wound", :store_doses=>4 }, + { :name=>"tincture of basal", :type=>"minor organ wound", }, + { :name=>"small egg and tundra grass tart", :type=>"minor organ wound", :store_doses=>5, :short_name => 'tundra grass tart' }, + { :name=>"some ginkgo nut tea", :type=>"minor organ wound", :short_name => "ginkgo nut tea" }, + { :name=>"chunky black ale", :type=>"minor organ wound", }, + { :name=>"flagon of Mama Dwarf's ale", :type=>"minor organ wound", :short_name => "Mama Dwarf's ale" }, + { :name=>"barrel of Mama Dwarf's ale", :type=>"minor organ wound", :short_name => "Mama Dwarf's ale" }, + { :name=>"wingstem potion", :type=>"major organ scar", :store_doses=>2 }, + { :name=>"crystalline wingstem elixir", :type=>"major organ scar", }, + { :name=>"tincture of wingstem", :type=>"major organ scar", }, + { :name=>"earthworm potion", :type=>"major organ scar", :store_doses=>2 }, + { :name=>"wyrmwood root potion", :type=>"major organ scar", }, + { :name=>"dirty crevice brew", :type=>"major organ scar", }, + { :name=>"flagon of Wort's Winter ale", :type=>"major organ scar", :short_name => "Wort's Winter ale" }, + { :name=>"barrel of Wort's Winter ale", :type=>"major organ scar", :short_name => "Wort's Winter ale" }, + { :name=>"talneo potion", :type=>"minor organ scar", :store_doses=>4 }, + { :name=>"crystalline talneo elixir", :type=>"minor organ scar", }, + { :name=>"tincture of talneo", :type=>"minor organ scar", }, + { :name=>"rock lizard potion", :type=>"minor organ scar", :store_doses=>4 }, + { :name=>"wyrmwood root tea", :type=>"minor organ scar", }, + { :name=>"brown weedroot ale", :type=>"minor organ scar", }, + { :name=>"flagon of Gert's Homemade ale", :type=>"minor organ scar", :short_name => "Gert's Homemade ale" }, + { :name=>"barrel of Gert's Homemade ale", :type=>"minor organ scar", :short_name => "Gert's Homemade ale" }, + { :name=>"bur-clover potion", :type=>"missing eye", :store_doses=>1 }, + { :name=>"crystalline bur-clover elixir", :type=>"missing eye", }, + { :name=>"tincture of bur-clover", :type=>"missing eye", }, + { :name=>"starfish potion", :type=>"missing eye", :store_doses=>1 }, + { :name=>"daggit root potion", :type=>"missing eye", }, + { :name=>"dirty rat fur potion", :type=>"missing eye", }, + { :name=>"flagon of Volcano Vision ale", :type=>"missing eye", :short_name => "Volcano Vision ale" }, + { :name=>"barrel of Volcano Vision ale", :type=>"missing eye", :short_name => "Volcano Vision ale" }, + { :name=>"some ephlox moss", :type=>"major limb wound", :short_name => "ephlox moss", :store_doses=>4 }, + { :name=>"gooey ball of ephlox moss", :type=>"major limb wound", }, + { :name=>"tincture of ephlox", :type=>"major limb wound", }, + { :name=>"some frog's bone porridge", :type=>"major limb wound", :store_doses=>4, :short_name => "frog's bone porridge" }, + { :name=>"sweetfern potion", :type=>"major limb wound", }, + { :name=>"crushed cavegrass tea", :type=>"major limb wound", }, + { :name=>"flagon of Golden Goose ale", :type=>"major limb wound", :short_name => "Golden Goose ale" }, + { :name=>"barrel of Golden Goose ale", :type=>"major limb wound", :short_name => "Golden Goose ale" }, + { :name=>"some ambrominas leaf", :type=>"minor limb wound", :short_name => "ambrominas leaf", :store_doses=>4 }, + { :name=>"some sugary ambrominas leaf", :type=>"minor limb wound", :short_name => "sugary ambrominas leaf" }, + { :name=>"tincture of ambrominas", :type=>"minor limb wound", }, + { :name=>"Dabbings Family special tart", :type=>"minor limb wound", :store_doses=>4, :short_name => 'Family special tart' }, + { :name=>"some sweetfern tea", :type=>"minor limb wound", :short_name => "sweetfern tea" }, + { :name=>"bubbling brown ale", :type=>"minor limb wound", }, + { :name=>"flagon of Lost Dogwater ale", :type=>"minor limb wound", :short_name => "Lost Dogwater ale" }, + { :name=>"barrel of Lost Dogwater ale", :type=>"minor limb wound", :short_name => "Lost Dogwater ale" }, + { :name=>"some calamia fruit", :type=>"major limb scar", :short_name => "calamia fruit", :store_doses=>2 }, + { :name=>"some ripe calamia fruit", :type=>"major limb scar", :short_name => "ripe calamia fruit" }, + { :name=>"tincture of calamia", :type=>"major limb scar", }, + { :name=>"slice of pickled walrus blubber", :type=>"major limb scar", :store_doses=>2, :short_name => 'pickled walrus blubber' }, + { :name=>"manroot potion", :type=>"major limb scar", }, + { :name=>"stalactite brew", :type=>"major limb scar", }, + { :name=>"flagon of Mad Mutt Frothy ale", :type=>"major limb scar", :short_name => "Mad Mutt Frothy ale" }, + { :name=>"barrel of Mad Mutt Frothy ale", :type=>"major limb scar", :short_name => "Mad Mutt Frothy ale" }, + { :name=>"some cactacae spine", :type=>"minor limb scar", :short_name => "cactacae spine", :store_doses=>4 }, + { :name=>"some prickly cactacae spine", :type=>"minor limb scar", :short_name => "prickly cactacae spine" }, + { :name=>"tincture of cactacae", :type=>"minor limb scar", }, + { :name=>"gelatinous elk fat tart", :type=>"minor limb scar", :short_name => 'elk fat tart', :store_doses=>10 }, + { :name=>"manroot tea", :type=>"minor limb scar", }, + { :name=>"spotted toadstool ale", :type=>"minor limb scar", }, + { :name=>"flagon of Bearded Ladies' ale", :type=>"minor limb scar", :short_name => "Bearded Ladies' ale" }, + { :name=>"barrel of Bearded Ladies' ale", :type=>"minor limb scar", :short_name => "Bearded Ladies' ale" }, + # fixme + { :name=>"some sovyn clove", :type=>"severed limb", :short_name => "sovyn clove", :store_doses=>1 }, + { :name=>"sovyn clove", :type=>"severed limb", }, + { :name=>"tincture of sovyn", :type=>"severed limb", }, + { :name=>"candied ptarmigan feather", :type=>"severed limb", :short_name => 'ptarmigan feather', :store_doses=>1 }, + { :name=>"angelica root potion", :type=>"severed limb", }, + { :name=>"grainy black potion", :type=>"severed limb", }, + { :name=>"flagon of Captn' Pegleg's ale", :type=>"severed limb", :short_name => "Captn' Pegleg's ale" }, + { :name=>"barrel of Captn' Pegleg's ale", :type=>"severed limb", :short_name => "Captn' Pegleg's ale" }, + { :name=>"bolmara potion", :type=>"major nerve wound", :store_doses=>4 }, + { :name=>"crystalline bolmara elixir", :type=>"major nerve wound", }, + { :name=>"tincture of bolmara", :type=>"major nerve wound", }, + { :name=>"snowflake elixir", :type=>"major nerve wound", :store_doses=>4 }, + { :name=>"red lichen potion", :type=>"major nerve wound", }, + { :name=>"glowing mold tea", :type=>"major nerve wound", }, + { :name=>"flagon of Kenar's Dropjaw ale", :type=>"major nerve wound", :short_name => "Kenar's Dropjaw ale" }, + { :name=>"barrel of Kenar's Dropjaw ale", :type=>"major nerve wound", :short_name => "Kenar's Dropjaw ale" }, + { :name=>"some wolifrew lichen", :type=>"minor nerve wound", :short_name => "wolifrew lichen", :store_doses=>4 }, + { :name=>"some dry wolifrew lichen", :type=>"minor nerve wound", :short_name => "dry wolifrew lichen", }, + { :name=>"tincture of wolifrew", :type=>"minor nerve wound", }, + { :name=>"Leaftoe's lichen tart", :type=>"minor nerve wound", :store_doses=>4, :short_name => 'lichen tart' }, + { :name=>"some red lichen tea", :type=>"minor nerve wound", :short_name => "red lichen tea" }, + { :name=>"thick foggy ale", :type=>"minor nerve wound", }, + { :name=>"flagon of Orc's Head ale", :type=>"minor nerve wound", :short_name => "Orc's Head ale" }, + { :name=>"barrel of Orc's Head ale", :type=>"minor nerve wound", :short_name => "Orc's Head ale" }, + { :name=>"some woth flower", :type=>"major nerve scar", :short_name => "woth flower", :store_doses=>2 }, + { :name=>"some fragrant woth flower", :type=>"major nerve scar", :short_name => "fragrant woth flower" }, + { :name=>"tincture of woth", :type=>"major nerve scar", }, + { :name=>"tiny flower-shaped tart", :type=>"major nerve scar", :store_doses=>2, :short_name => 'flower-shaped tart' }, + { :name=>"valerian root potion", :type=>"major nerve scar", }, + { :name=>"stalagmite brew", :type=>"major nerve scar", }, + { :name=>"flagon of Dacra's Dream ale", :type=>"major nerve scar", :short_name => "Dacra's Dream ale" }, + { :name=>"barrel of Dacra's Dream ale", :type=>"major nerve scar", :short_name => "Dacra's Dream ale" }, + { :name=>"some torban leaf", :type=>"minor nerve scar", :short_name => "torban leaf", :store_doses=>3 }, + { :name=>"some fresh torban leaf", :type=>"minor nerve scar", :short_name => "fresh torban leaf" }, + { :name=>"tincture of torban", :type=>"minor nerve scar", }, + { :name=>"slice of Ma Leaftoe's Special", :type=>"minor nerve scar", :store_doses=>5, :short_name => "Ma Leaftoe's Special" }, + { :name=>"valerian root tea", :type=>"minor nerve scar", }, + { :name=>"dark frothing ale", :type=>"minor nerve scar", }, + { :name=>"flagon of Miner's Muddy ale", :type=>"minor nerve scar", :short_name => "Miner's Muddy ale" }, + { :name=>"barrel of Miner's Muddy ale", :type=>"minor nerve scar", :short_name => "Miner's Muddy ale" }, + { :name=>"dimly glowing sky-blue potion", :type=>"disease", }, + { :name=>"dimly glowing sea-green potion", :type=>"poison", }, ] -silence_me +#silence_me drinkable = /potion|tea|elixir|brew|tincture|ale|soup/ skippable = Array.new close_herbsack = false -stow_container_id = nil preposition = 'in' return_to_stow = false herb_container = nil right_hand_save = nil left_hand_save = nil buy_missing = CharSettings['buy_missing'] +use_mending = CharSettings['use-mending'] start_room = Room.current herb_shop_menu = nil silvers = nil withdraw_amount = 8000 -deposit_silvers = false +should_deposit = false used_herbs = Array.new +open_regex = /^You open|^That is already open\.$|^There doesn't seem to be any way to do that\.$|^What were you referring to\?|^I could not find what you were referring to\./ +close_regex = /^You close|^That is already closed\.$/ +put_regex = /^You (?:attempt to shield .*? from view as you |discreetly |carefully |absent-mindedly )?(?:put|place|slip|tuck|add|hang|drop|untie your|find an incomplete bundle|wipe off .*? and sheathe)|^A sigh of grateful pleasure can be heard as you feed .*? to your|^As you place|^I could not find what you were referring to\.$|^Your bundle would be too large|^The .+ is too large to be bundled\.|^As you place your|^The .*? is already a bundle|^Your .*? won't fit in .*?\.$|^You can't .+ It's closed!$/ +put_fail_regex = /^Your .*? won't fit in .*?\.$|^You can't .+ It's closed!$||^I could not find what you were referring to\.$/ +get_regex = /^You (?:shield the opening of .*? from view as you |discreetly |carefully |deftly )?(?:remove|draw|grab|reach|slip|tuck|retrieve|already have|unsheathe|detach)|^Get what\?$|^Why don't you leave some for others\?$|^You need a free hand|^You already have that/ +get_from = nil -=begin -if script.vars[1].downcase == 'set' - if script.vars[2].downcase == 'buy-missing' - CharSettings['buy-missing'] = nil - if script.vars[2].downcase == 'fill-missing' - CharSettings['fill-missing'] = nil - elsif script.vars[2].downcase == 'use-haste' - - elsif script.vars[2].downcase == 'use-mending' - - else - echo 'unknown setting' +min_stock_doses = { + 'major head scar' => 13, + 'minor head wound' => 11, + 'major nerve wound' => 11, + 'minor organ scar' => 11, + 'major organ scar' => 13, + 'missing eye' => 7, +} + +check_silvers = proc { + action = proc { |server_string| + if server_string =~ /^\s*Name\:|^\s*Gender\:|^\s*Normal \(Bonus\)|^\s*Strength \(STR\)\:|^\s*Constitution \(CON\)\:|^\s*Dexterity \(DEX\)\:|^\s*Agility \(AGI\)\:|^\s*Discipline \(DIS\)\:|^\s*Aura \(AUR\)\:|^\s*Logic \(LOG\)\:|^\s*Intuition \(INT\)\:|^\s*Wisdom \(WIS\)\:|^\s*Influence \(INF\)\:/ + nil + elsif server_string =~ /^\s*Mana\:\s+\-?[0-9]+\s+Silver\:\s+[0-9]+/ + DownstreamHook.remove("#{script.name}_check_silvers") + nil + else + server_string + end + } + DownstreamHook.add("#{script.name}_check_silvers", action) + silence_me unless undo_silence = silence_me + clear + put 'info' + silence_me if undo_silence + while line = get + if line =~ /^\s*Mana\:\s+\-?[0-9]+\s+Silver\:\s+([0-9]+)/ + silvers = $1.to_i + break + end end - exit -end -=end + silvers +} withdraw = proc { - start_script 'go2', [ 'bank', '_disable_confirm_' ] - wait_while { running?('go2') } + Script.run('go2', 'bank --disable-confirm') fput 'unhide' if invisible? if XMLData.room_title == '[Pinefar, Depository]' if GameObj.npcs.any? { |npc| npc.noun == 'banker' } @@ -232,8 +277,7 @@ withdraw = proc { # The banker looks at you suspiciously and says, "Hmm, I don't think ye be havin' enough in ye account to cover that and my fee. Ye tryin' to pull one over on me?" else if icemule_bank = Room.list.find { |room| room.location == 'Icemule Trace' and room.tags.include?('bank') } - start_script 'go2', [ icemule_bank.id.to_s ] - wait_while { running?('go2') } + Script.run('go2', icemule_bank.id.to_s) result = dothistimeout "withdraw #{withdraw_amount} silvers", 1, /debt collector/ if result =~ /debt collector/ fput "withdraw #{withdraw_amount} silvers" @@ -251,7 +295,20 @@ withdraw = proc { end end silvers += withdraw_amount - deposit_silvers = true + should_deposit = true +} + +deposit = proc { + if should_deposit + Script.run('go2', 'bank --disable-confirm') + if XMLData.room_title == '[Pinefar, Depository]' + if GameObj.npcs.any? { |npc| npc.noun == 'banker' } + fput "give banker #{check_silvers.call} silvers" + end + else + fput "deposit #{check_silvers.call}" + end + end } too_wounded_to_cast = proc { @@ -260,11 +317,10 @@ too_wounded_to_cast = proc { go_to_herbalist = proc { if working_herbalist = Room.current.find_nearest(Room.list.find_all { |room| room.tags.include?('herbalist') and not room.title.any? { |t| t =~ /Valina's Herbs and Tinctures|Marroux and Haert, Chirurgeons/ } }) - start_script 'go2', [ working_herbalist.to_s ] + Script.run('go2', working_herbalist.to_s) else - start_script 'go2', [ 'herbalist', '--disable-confirm' ] + Script.run('go2', 'herbalist --disable-confirm') end - wait_while { running?('go2') } } next_herb_type = proc { @@ -344,20 +400,15 @@ next_herb_type = proc { stow_herb = proc { if return_to_stow and (Room.current.id != start_room.id) - start_script 'go2', [ start_room.id.to_s ] - wait_while { running?('go2') } + Script.run('go2', start_room.id.to_s) end if used_herbs.include?(GameObj.right_hand.id) - result = dothistimeout "put ##{GameObj.right_hand.id} #{preposition} ##{herb_container.id}", 10, /^You put|^You slip|^You carefully add|^A sigh of grateful pleasure can be heard as you feed .*? to your|^I could not find what you were referring to\.$/ - if result =~ /^I could not find what you were referring to\./ - dothistimeout "drop ##{GameObj.right_hand.id}", 10, /^You drop/ - end + dothistimeout "put ##{GameObj.right_hand.id} #{preposition} ##{herb_container.id}", 10, put_regex + fput('stow right') if checkright end if used_herbs.include?(GameObj.left_hand.id) - dothistimeout "put ##{GameObj.left_hand.id} #{preposition} ##{herb_container.id}", 10, /^You put|^You slip|^You carefully add|^A sigh of grateful pleasure can be heard as you feed .*? to your|^I could not find what you were referring to\.$/ - if result =~ /^I could not find what you were referring to\./ - dothistimeout "drop ##{GameObj.right_hand.id}", 10, /^You drop/ - end + dothistimeout "put ##{GameObj.left_hand.id} #{preposition} ##{herb_container.id}", 10, put_regex + fput('stow left') if checkleft end } @@ -377,27 +428,6 @@ read_menu = proc { menu } -check_silvers = proc { - silvers = nil - action = proc { |server_string| - if server_string =~ /^\s*Name\:|^\s*Gender\:|^\s*Normal \(Bonus\)|^\s*Strength \(STR\)\:|^\s*Constitution \(CON\)\:|^\s*Dexterity \(DEX\)\:|^\s*Agility \(AGI\)\:|^\s*Discipline \(DIS\)\:|^\s*Aura \(AUR\)\:|^\s*Logic \(LOG\)\:|^\s*Intuition \(INT\)\:|^\s*Wisdom \(WIS\)\:|^\s*Influence \(INF\)\:/ - nil - elsif server_string =~ /^\s*Mana\:\s+\-?[0-9]+\s+Silver\:\s+([0-9]+)/ - silvers = $1.to_i - DownstreamHook.remove("#{script.name}_check_silvers") - nil - else - server_string - end - } - DownstreamHook.add("#{script.name}_check_silvers", action) - silence_me unless undo_silence = silence_me - put 'info' - silence_me if undo_silence - wait_until { silvers } - silvers -} - buy_herb = proc { |herb_type| unless silvers silvers = check_silvers.call @@ -405,7 +435,7 @@ buy_herb = proc { |herb_type| unless herb_shop_menu herb_shop_menu = read_menu.call end - herb_name = herb_shop_menu.keys.find { |name| known_herbs.any? { |h| (h[:type] == herb_type) and (name =~ /#{h[:name]}/ or name =~ /#{h[:name].sub(/sticky |gooey | green| fragrant| shiny| dirty/, '')}/) } } + herb_name = herb_shop_menu.keys.find { |name| $known_herbs.any? { |h| (h[:type] == herb_type) and (name =~ /#{h[:name]}/ or name =~ /#{h[:name].sub(/sticky |gooey | green| fragrant| shiny| dirty/, '')}/) } } unless order_number = herb_shop_menu[herb_name] echo "error: failed to find a herb for #{herb_type} in the menu" exit @@ -430,9 +460,7 @@ buy_herb = proc { |herb_type| if script.vars[0] =~ /help/i respond - respond 'To use the herbs in your herbsack:' - respond - respond ' ;setting change herbsack ' + respond 'To use the herbs in your herbsack (see below for setting your herbsack):' respond respond ' ;useherbs' respond @@ -442,9 +470,9 @@ if script.vars[0] =~ /help/i respond respond ' ;useherbs behind altar' respond - respond 'To use the herbs on a bench without picking up the eatables:' + respond 'To use the herbs on a bench without picking up the edible herbs:' respond - respond ' ;useherbs on bench noget' + respond ' ;useherbs on bench --no-get' respond respond 'To look up what herbs heal what:' respond @@ -456,15 +484,21 @@ if script.vars[0] =~ /help/i respond respond ' ;useherbs escort' respond - respond 'Other options:' + respond 'Options (add these to the end of the command; these override default options):' respond - respond ' ;useherbs buy= Buy missing herbs or not in the future.' - respond ' ;useherbs haste= Use haste before healing.' - respond ' ;useherbs mending= Use sigil of mending before healing.' - respond ' ;useherbs --buy-missing= Buy missing herbs or not for this run only.' + respond ' --buy= Go to the herbalist to buy herbs if needed' + respond ' --mending= Use sigil of mending before using herbs' + respond + respond "Change default options (so you don't have to specify the option every time):" + respond + respond ' ;useherbs set buy same as above' + respond ' ;useherbs set mending same as above' + respond " ;useherbs set herbsack sets which container you use if one isn't" + respond ' specified on the command line' respond exit elsif script.vars[1] =~ /^list$/i + known_herbs = $known_herbs.dup if (script.vars[0] =~ /major|severed|missing/i) and (script.vars[0] !~ /minor/i) known_herbs.delete_if { |herb| herb[:type] !~ /major|severed|missing/i } elsif (script.vars[0] =~ /minor/i) and (script.vars[0] !~ /major|severed|missing/i) @@ -485,7 +519,7 @@ elsif script.vars[1] =~ /^list$/i known_herbs.delete_if { |herb| herb[:type] =~ /disease/ } unless script.vars[0] =~ /disease/ end list = Hash.new - for herb in known_herbs + for herb in $known_herbs list[herb[:type]] ||= Array.new list[herb[:type]].push(herb[:name]) end @@ -500,17 +534,61 @@ elsif script.vars[1] =~ /^list$/i puts output end exit -elsif script.vars[1] =~ /^buy=(on|off|true|false|yes|no)$/ - fix_option = { 'on' => true, 'true' => true, 'yes' => true, 'off' => false, 'false' => false, 'no' => false } - CharSettings['buy_missing'] = fix_option[$1] - echo 'setting saved' +elsif script.vars[1] == 'set' + if script.vars[2] == 'buy' + if script.vars[3] =~ /^(?:on|true|yes)$/ + CharSettings['buy_missing'] = true + echo 'setting saved' + elsif script.vars[3] =~ /^(?:off|false|no)$/ + CharSettings['buy_missing'] = false + echo 'setting saved' + else + echo "error: bad setting value: #{script.vars[3]}" + end + elsif script.vars[2] == 'mending' + if script.vars[3] =~ /^(?:on|true|yes)$/ + CharSettings['use-mending'] = true + echo 'setting saved' + elsif script.vars[3] =~ /^(?:off|false|no)$/ + CharSettings['use-mending'] = false + echo 'setting saved' + else + echo "error: bad setting value: #{script.vars[3]}" + end + elsif script.vars[2] == 'herbsack' + if script.vars[3] + name = script.vars[3..-1].join(' ') + obj_list = GameObj.inv.find_all { |obj| obj.noun == name } + if obj_list.empty? + obj_list = GameObj.inv.find_all { |obj| obj.name == name } + end + if obj_list.empty? + obj_list = GameObj.inv.find_all { |obj| obj.name =~ /\b#{Regexp.escape(name)}$/i } + end + if obj_list.empty? + obj_list = GameObj.inv.find_all { |obj| obj.name =~ /\b#{name.split(' ').collect { |n| Regexp.escape(n) }.join(".*\\b")}/i } + end + if obj_list.empty? + echo "error: failed to find a container in your inventory by the name of \"#{name}\"" + elsif obj_list.length > 1 + echo "error: multiple containers in your inventory match the name \"#{name}\"" + else + UserVars.herbsack = name + echo 'setting saved' + end + else + echo 'error: no container name given' + end + else + echo "error: unknown setting: #{script.vars[2]}" + end exit -elsif script.vars[1] =~ /^haste=(on|off|true|false|yes|no)$/ +elsif script.vars[1] =~ /^buy=(on|off|true|false|yes|no)$/ # depreciated fix_option = { 'on' => true, 'true' => true, 'yes' => true, 'off' => false, 'false' => false, 'no' => false } - CharSettings['use-haste'] = fix_option[$1] + CharSettings['buy_missing'] = fix_option[$1] echo 'setting saved' exit -elsif script.vars[1] =~ /^mending=(on|off|true|false|yes|no)$/ +elsif script.vars[1] =~ /^mending=(on|off|true|false|yes|no)$/ # depreciated fix_option = { 'on' => true, 'true' => true, 'yes' => true, 'off' => false, 'false' => false, 'no' => false } CharSettings['use-mending'] = fix_option[$1] echo 'setting saved' @@ -520,18 +598,17 @@ elsif script.vars[1].downcase == 'fill' # 3-4 doses: There is a small amount in the rose-marrow potion. # 1-2 doses: There is just a little left in the rose-marrow potion. - start_room = Room.current if UserVars.herbsack.nil? or UserVars.herbsack.empty? - echo 'herbsack is not set (;set change herbsack )' + echo 'herbsack is not set (;useherbs set herbsack )' exit end - unless herb_container = GameObj.inv.find { |obj| obj.name =~ /#{Regexp.escape(UserVars.herbsack.strip)}/i } || GameObj.inv.find { |obj| obj.name =~ /#{Regexp.escape(UserVars.herbsack).sub(' ', ' .*')}/i } + unless herb_container = (GameObj.inv.find { |obj| obj.noun == UserVars.herbsack } || GameObj.inv.find { |obj| obj.name == UserVars.herbsack } || GameObj.inv.find { |obj| obj.name =~ /\b#{Regexp.escape(UserVars.herbsack)}$/i } || GameObj.inv.find { |obj| obj.name =~ /\b#{UserVars.herbsack.split(' ').collect { |n| Regexp.escape(n) }.join(".*\\b")}/i }) echo "error: unable to find container \"#{UserVars.herbsack}\" in your inventory." exit end close_herbsack = false if herb_container.contents.nil? - open_result = dothistimeout "open ##{herb_container.id}", 10, /^You open|^That is already open\.$|^There doesn't seem to be any way to do that\./ + open_result = dothistimeout "open ##{herb_container.id}", 10, open_regex if open_result =~ /^You open/ close_herbsack = true else @@ -548,13 +625,12 @@ elsif script.vars[1].downcase == 'fill' unless silvers > 4000 withdraw.call end - start_script 'go2', [ '325' ] - wait_while { running?('go2') } + Script.run('go2', '325') herb_shop_menu = read_menu.call for herb_type in [ 'blood', 'major head wound', 'minor head wound', 'major head scar', 'minor head scar', 'major organ wound', 'minor organ wound', 'major organ scar', 'minor organ scar', 'missing eye', 'major limb wound', 'minor limb wound', 'major limb scar', 'minor limb scar', 'severed limb', 'major nerve wound', 'minor nerve wound', 'major nerve scar', 'minor nerve scar' ] - unless herb_container.contents.any? { |obj| known_herbs.any? { |herb| (herb[:name] == obj.name) and herb[:type] == herb_type } } + unless herb_container.contents.any? { |obj| $known_herbs.any? { |herb| (herb[:name] == obj.name) and herb[:type] == herb_type } } #echo "no herb for #{herb_type}" - herb_name = herb_shop_menu.keys.find { |name| known_herbs.any? { |h| (h[:type] == herb_type) and (name =~ /#{h[:name]}/ or name =~ /#{h[:name].sub(/sticky |gooey | green| fragrant| shiny| dirty/, '')}/) } } + herb_name = herb_shop_menu.keys.find { |name| $known_herbs.any? { |h| (h[:type] == herb_type) and (name =~ /#{h[:name]}/ or name =~ /#{h[:name].sub(/sticky |gooey | green| fragrant| shiny| dirty/, '')}/) } } unless order_number = herb_shop_menu[herb_name] echo "error: failed to find a herb for #{herb_type} in the menu" exit @@ -572,51 +648,48 @@ elsif script.vars[1].downcase == 'fill' end if checkright herb = GameObj.right_hand - dothistimeout "put ##{herb.id} #{preposition} ##{herb_container.id}", 10, /^You put|^You slip|^You carefully add|^A sigh of grateful pleasure can be heard as you feed .*? to your|^I could not find what you were referring to\.$/ - if herb_info = known_herbs.find { |h| h[:name] =~ /#{herb.name}$/ } + dothistimeout "put ##{herb.id} #{preposition} ##{herb_container.id}", 10, put_regex + if herb_info = $known_herbs.find { |h| h[:name] =~ /#{herb.name}$/ } $count_herbs[herb.id] = herb_info[:store_doses] end end end end fput "close ##{herb_container.id}" if close_herbsack - start_script 'go2', [ start_room.id.to_s ] - wait_while { running?('go2') } + Script.run('go2', start_room.id.to_s) exit elsif script.vars[1].downcase == 'escort' + if script.vars[2] + unless escort = GameObj.npcs.find { |npc| (npc.id == script.vars[2]) or (npc.noun == script.vars[2]) } + echo "Failed to find an npc with id or noun #{script.vars[2]}." + exit + end + else + unless escort = GameObj.npcs.find { |npc| npc.type =~ /escort/ } + echo "Failed to find an escort." + exit + end + end close_herbsack = false - unless herb_container = GameObj.inv.find { |obj| obj.name =~ /#{Regexp.escape(UserVars.herbsack.strip)}/i } || GameObj.inv.find { |obj| obj.name =~ /#{Regexp.escape(UserVars.herbsack).sub(' ', ' .*')}/i } + unless herb_container = (GameObj.inv.find { |obj| obj.noun == UserVars.herbsack } || GameObj.inv.find { |obj| obj.name == UserVars.herbsack } || GameObj.inv.find { |obj| obj.name =~ /\b#{Regexp.escape(UserVars.herbsack)}$/i } || GameObj.inv.find { |obj| obj.name =~ /\b#{UserVars.herbsack.split(' ').collect { |n| Regexp.escape(n) }.join(".*\\b")}/i }) echo "error: unable to find container \"#{UserVars.herbsack}\" in your inventory." exit end if herb_container.contents.nil? - open_result = dothistimeout "open ##{herb_container.id}", 10, /^You open|^That is already open\.$|^There doesn't seem to be any way to do that\./ + open_result = dothistimeout "open ##{herb_container.id}", 10, open_regex if open_result =~ /^You open/ close_herbsack = true else dothistimeout "look in ##{herb_container.id}", 10, /In the .*? you see/ if herb_container.contents.nil? - echo 'fixme 2' + echo "error: failed to find herb container contents (#{herb_container.name}, #{herb_container.id})" exit end end end - if script.vars[2] - unless escort = GameObj.npcs.find { |npc| npc.id == script.vars[2] } - echo "Failed to find an npc with id #{script.vars[2]}." - dothistimeout "close ##{herb_container.id}", 5, /^You close|^That is already closed\.$/ if close_herbsack - exit - end - else - unless escort = GameObj.npcs.find { |npc| npc.type =~ /escort/ } - echo "Failed to find an escort." - dothistimeout "close ##{herb_container.id}", 5, /^You close|^That is already closed\.$/ if close_herbsack - exit - end - end - look_result = dothistimeout "look ##{escort.id}", 5, /^(?:She|He) appears to be in good shape\.|^(?:She|He) has|^I could not find what you were referring to\./ + look_result = dothistimeout "look ##{escort.id}", 10, /^(?:She|He) appears to be in good shape\.|^(?:She|He) has|^I could not find what you were referring to\./ if look_result.nil? - echo 'error: timed out' + echo "error: timeout while trying to look at escort (#{escort.name}, #{escort.id})" elsif look_result =~ /^I could not find what you were referring to\./ echo "error: can't see escort" elsif look_result =~ /^(?:She|He) appears to be in good shape\./ @@ -626,91 +699,129 @@ elsif script.vars[1].downcase == 'escort' if look_result =~ /severe head trauma and bleeding from the ears/ escort_injuries.push('major head wound') escort_injuries.push('major head wound') + escort_injuries.push('minor head wound') end if look_result =~ /minor lacerations about the head and a possible mild concussion/ escort_injuries.push('major head wound') + escort_injuries.push('minor head wound') end if look_result =~ /snapped bones and serious bleeding from the neck/ escort_injuries.push('major head wound') escort_injuries.push('major head wound') + escort_injuries.push('minor head wound') end if look_result =~ /moderate bleeding from (?:his|her) neck/ escort_injuries.push('major head wound') + escort_injuries.push('minor head wound') end if look_result =~ /deep gashes and serious bleeding from (?:his|her) chest/ escort_injuries.push('major organ wound') escort_injuries.push('major organ wound') + escort_injuries.push('minor organ wound') end if look_result =~ /deep lacerations across (?:his|her) chest/ escort_injuries.push('major organ wound') + escort_injuries.push('minor organ wound') end if look_result =~ /deep gashes and serious bleeding from (?:his|her) abdomen/ escort_injuries.push('major organ wound') escort_injuries.push('major organ wound') + escort_injuries.push('minor organ wound') end if look_result =~ /deep lacerations across (?:his|her) abdomen/ escort_injuries.push('major organ wound') + escort_injuries.push('minor organ wound') end if look_result =~ /deep gashes and serious bleeding from (?:his|her) back/ escort_injuries.push('major organ wound') escort_injuries.push('major organ wound') + escort_injuries.push('minor organ wound') end if look_result =~ /deep lacerations across (?:his|her) back/ escort_injuries.push('major organ wound') + escort_injuries.push('minor organ wound') end if look_result =~ /a blinded right eye/ - escort_injuries.push('missing eye') +# escort_injuries.push('missing eye') + escort_injuries.push('major organ wound') + escort_injuries.push('major organ wound') + escort_injuries.push('minor organ wound') end if look_result =~ /a blinded left eye/ - escort_injuries.push('missing eye') +# escort_injuries.push('missing eye') + escort_injuries.push('major organ wound') + escort_injuries.push('major organ wound') + escort_injuries.push('minor organ wound') end if look_result =~ /a swollen right eye/ escort_injuries.push('major organ wound') + escort_injuries.push('minor organ wound') end if look_result =~ /a swollen left eye/ escort_injuries.push('major organ wound') + escort_injuries.push('minor organ wound') end if look_result =~ /a completely severed right leg/ - escort_injuries.push('severed limb') + escort_injuries.push('major limb wound') + escort_injuries.push('major limb wound') + escort_injuries.push('minor limb wound') end if look_result =~ /a completely severed left leg/ - escort_injuries.push('severed limb') + escort_injuries.push('major limb wound') + escort_injuries.push('major limb wound') + escort_injuries.push('minor limb wound') end if look_result =~ /a completely severed right arm/ - escort_injuries.push('severed limb') + escort_injuries.push('major limb wound') + escort_injuries.push('major limb wound') + escort_injuries.push('minor limb wound') end if look_result =~ /a completely severed left arm/ - escort_injuries.push('severed limb') + escort_injuries.push('major limb wound') + escort_injuries.push('major limb wound') + escort_injuries.push('minor limb wound') end if look_result =~ /a completely severed right hand/ - escort_injuries.push('severed limb') + escort_injuries.push('major limb wound') + escort_injuries.push('major limb wound') + escort_injuries.push('minor limb wound') end if look_result =~ /a completely severed left hand/ - escort_injuries.push('severed limb') + escort_injuries.push('major limb wound') + escort_injuries.push('major limb wound') + escort_injuries.push('minor limb wound') end if look_result =~ /a fractured and bleeding right leg/ escort_injuries.push('major limb wound') + escort_injuries.push('minor limb wound') end if look_result =~ /a fractured and bleeding left leg/ escort_injuries.push('major limb wound') + escort_injuries.push('minor limb wound') end if look_result =~ /a fractured and bleeding right arm/ escort_injuries.push('major limb wound') + escort_injuries.push('minor limb wound') end if look_result =~ /a fractured and bleeding left arm/ escort_injuries.push('major limb wound') + escort_injuries.push('minor limb wound') end if look_result =~ /a fractured and bleeding right hand/ escort_injuries.push('major limb wound') + escort_injuries.push('minor limb wound') end if look_result =~ /a fractured and bleeding left hand/ escort_injuries.push('major limb wound') + escort_injuries.push('minor limb wound') end if look_result =~ /a case of uncontrollable convulsions/ escort_injuries.push('major nerve wound') + escort_injuries.push('minor nerve wound') end if look_result =~ /a case of sporadic convulsions/ escort_injuries.push('major nerve wound') + escort_injuries.push('minor nerve wound') end if look_result =~ /minor bruises about the head/ escort_injuries.push('minor head wound') @@ -758,131 +869,308 @@ elsif script.vars[1].downcase == 'escort' empty_right_hand for herb_type in escort_injuries herb = nil - if known_herbs.any? { |h| (h[:name].sub(/^(?:some|flagon of|barrel of) /, '') == GameObj.right_hand.name) and (h[:type] == herb_type) } + if $known_herbs.any? { |h| h[:type] == herb_type and (h[:name] == GameObj.right_hand.name or (h[:short_name] and h[:short_name] == GameObj.right_hand.name)) } herb = GameObj.right_hand - elsif known_herbs.any? { |h| (h[:name].sub(/^(?:some|flagon of|barrel of) /, '') == GameObj.left_hand.name) and (h[:type] == herb_type) } + elsif $known_herbs.any? { |h| h[:type] == herb_type and (h[:name] == GameObj.left_hand.name or (h[:short_name] and h[:short_name] == GameObj.left_hand.name)) } herb = GameObj.left_hand else - if herb = herb_container.contents.find { |i| known_herbs.find { |h| (h[:name] == i.name) and h[:type] == herb_type } } - stow_herb.call - get_result = dothistimeout "get ##{herb.id}", 5, /^You (?:carefully )?(?:remove|grab|reach|slip|tuck)|^Get what\?|^You need a free hand for that\./ + stow_herb.call + if herb = herb_container.contents.find { |i| $known_herbs.find { |h| (h[:name] == i.name) and h[:type] == herb_type } } + used_herbs.push(herb.id) unless used_herbs.include?(herb.id) + get_result = dothistimeout "get ##{herb.id}", 5, get_regex if get_result.nil? or (get_result =~ /^Get what\?/) - echo 'fixme 44235' - dothistimeout "close ##{herb_container.id}", 5, /^You close|^That is already closed\.$/ if close_herbsack + echo "error: timeout while trying to get herb (#{herb.name}, #{herb.id})" + dothistimeout "close ##{herb_container.id}", 5, close_regex if close_herbsack exit elsif get_result =~ /^You need a free hand for that\./ echo 'fixme 28382' - dothistimeout "close ##{herb_container.id}", 5, /^You close|^That is already closed\.$/ if close_herbsack + dothistimeout "close ##{herb_container.id}", 5, close_regex if close_herbsack exit end end end if herb - haste = Spell[506] - haste.cast if haste.known? and haste.affordable? and not haste.active? - dothistimeout "give ##{escort.id}", 5, /fuck/ + dothistimeout "give ##{escort.id}", 10, /accepts your .* hands it back to you|ignores your offer/ end end stow_herb.call fill_right_hand end if close_herbsack - dothistimeout "close ##{herb_container.id}", 5, /^You close|^That is already closed\.$/ + dothistimeout "close ##{herb_container.id}", 5, close_regex end exit elsif script.vars[1].downcase == 'stock' - start_room = Room.current close_herbsack = false if UserVars.herbsack.nil? or UserVars.herbsack.empty? - echo 'herbsack is not set (;set change herbsack )' + echo 'herbsack is not set (;useherbs set herbsack )' exit end - unless herb_container = GameObj.inv.find { |obj| obj.name =~ /#{Regexp.escape(UserVars.herbsack.strip)}/i } || GameObj.inv.find { |obj| obj.name =~ /#{Regexp.escape(UserVars.herbsack).sub(' ', ' .*')}/i } + unless herb_container = (GameObj.inv.find { |obj| obj.noun == UserVars.herbsack } || GameObj.inv.find { |obj| obj.name == UserVars.herbsack } || GameObj.inv.find { |obj| obj.name =~ /\b#{Regexp.escape(UserVars.herbsack)}$/i } || GameObj.inv.find { |obj| obj.name =~ /\b#{UserVars.herbsack.split(' ').collect { |n| Regexp.escape(n) }.join(".*\\b")}/i }) echo "error: unable to find container \"#{UserVars.herbsack}\" in your inventory." exit end if herb_container.contents.nil? - open_result = dothistimeout "open ##{herb_container.id}", 10, /^You open|^That is already open\.$|^There doesn't seem to be any way to do that\./ + open_result = dothistimeout "open ##{herb_container.id}", 10, open_regex if open_result =~ /^You open/ close_herbsack = true else dothistimeout "look in ##{herb_container.id}", 10, /In the .*? you see/ if herb_container.contents.nil? - echo 'fixme 2' + echo "error: timeout while trying to look in herb container (#{herb_container.name}, #{herb_container.id})" exit end end end - if script.vars[2].downcase == 'potions' + + if $useherbs_measure.nil? + exec_string = " + hide_me + status_tags + $useherbs_measure = Hash.new + using = nil + last_left_hand_id = nil + begin + while line = get + if line =~ / 10) + $useherbs_measure[$1] = 7 + end + elsif line =~ /^The .*? exist=\"([0-9]+)\" .*? has a few doses left\\./ + if $useherbs_measure[$1].nil? or ($useherbs_measure[$1] < 3) or ($useherbs_measure[$1] > 4) + $useherbs_measure[$1] = 4 + end + elsif line =~ /^The .*? exist=\"([0-9]+)\" .*? has 2 doses left\\./ + $useherbs_measure[$1] = 2 + elsif line =~ /^The .*? exist=\"([0-9]+)\" .*? has 1 dose left\\./ + $useherbs_measure[$1] = 1 + elsif line =~ /^You can't tell exactly, but .*? exist=\"(.*?)\" .*? seems to have plenty of bites left\\.$/ + if $useherbs_measure[$1].nil? or ($useherbs_measure[$1] < 11) or ($useherbs_measure[$1] > 50) + $useherbs_measure[$1] = 50 + end + elsif line =~ /^The .*? exist=\"(.*?)\" .*? looks like it has several bites left\\.$/ + if $useherbs_measure[$1].nil? or ($useherbs_measure[$1] < 5) or ($useherbs_measure[$1] > 10) + $useherbs_measure[$1] = 10 + end + elsif line =~ /^The .*? exist=\"(.*?)\" .*? looks like it has a few bites left\\.$/ + if $useherbs_measure[$1].nil? or ($useherbs_measure[$1] < 3) or ($useherbs_measure[$1] > 4) + $useherbs_measure[$1] = 4 + end + elsif line =~ /^The .*? exist=\"(.*?)\" .*? has 2 bites left\\.$/ + $useherbs_measure[$1] = 2 + elsif line =~ /^The .*? exist=\"(.*?)\" .*? has one bite left\\.$/ + $useherbs_measure[$1] = 1 + elsif line =~ /^He hands you (#{$known_herbs.collect { |h| h[:name] }.join('|')})<\\/a> and says, \"Here's your purchase./o + doses = $known_herbs.find { |h| h[:name] == $2 }[:store_doses] + if doses.nil? + echo \"warning: no store_doses entry for \#{$2}\" + doses = 4 + end + $useherbs_measure[$1] = doses + elsif line =~ /^Carefully, you combine all your 10) or ($useherbs_measure[last_left_hand_id] and $useherbs_measure[last_left_hand_id] > 10) + # bundle has 11 - 50 bytes + # overestimate so that we don't buy more than we can bundle + # exact count will be found if the herb is used + $useherbs_measure[$1] = 50 + $useherbs_measure.delete(last_left_hand_id) + else + # bundle has 2-50 bytes + # clear count so the bundle gets measured + $useherbs_measure.delete($1) + $useherbs_measure.delete(last_left_hand_id) + end + elsif line =~ /^You carefully remove one dose from your true }) + end +#exit + if script.vars[2].nil? or (script.vars[2].downcase == 'potions') herb_type_list = [ 'major head scar', 'minor head wound', 'major nerve wound', 'minor organ scar', 'major organ scar', 'missing eye' ] - for herb_type in herb_type_list - doses = Hash.new - herb_list = herb_container.contents.find_all { |obj| known_herbs.find { |h| (h[:name] == obj.name) and h[:type] == herb_type } } - if herb_type == 'missing eye' - num_wanted = 1 - else - num_wanted = 2 + done_empty_hand = false + herb_container.contents.each { |obj| + if $known_herbs.any? { |h| herb_type_list.include?(h[:type]) and (h[:name] == obj.name) } and $useherbs_measure[obj.id].nil? + if obj.noun == 'potion' + result = dothistimeout "look in ##{obj.id}", 5, /^There is (?:a good|a small|just a little)/ + if result =~ /good/ # 5-7 doses + $useherbs_measure[obj.id] = 7 + elsif result =~ /small/ # 3-4 doses + $useherbs_measure[obj.id] = 4 + elsif result =~ /little/ # 1-2 doses + $useherbs_measure[obj.id] = 2 + else + echo 'fixme 293823' + end + else + unless done_empty_hand + empty_hand + done_empty_hand = true + end + dothistimeout "get ##{obj.id}", 10, get_regex + dothistimeout "measure ##{obj.id}", 10, /^The .*? left/ + dothistimeout "put ##{obj.id} in ##{herb_container.id}", 10, put_regex + end end - done_gone_to_herbalist = false - (num_wanted - herb_list.length).times { + } + done_gone_to_herbalist = false + for herb_type in herb_type_list + last_total_doses = -1 + loop { + herb_list = herb_container.contents.find_all { |obj| $known_herbs.find { |h| (h[:name] == obj.name) and h[:type] == herb_type } } + total_doses = 0; herb_list.each { |h| total_doses += $useherbs_measure[h.id].to_i } + echo "#{herb_type}: #{total_doses}" + break unless total_doses < min_stock_doses[herb_type] + break unless total_doses > last_total_doses + last_total_doses = total_doses + echo "need more #{herb_type}" unless done_gone_to_herbalist + if check_silvers.call < 1500 + withdraw.call + end go_to_herbalist.call done_gone_to_herbalist = true end - if herb = buy_herb.call(herb_type) - dothistimeout "_drag ##{herb.id} ##{herb_container.id}", 10, /^You put|^You slip|^You carefully add|^A sigh of grateful pleasure can be heard as you feed .*? to your|^I could not find what you were referring to\.$/ + if new_herb = buy_herb.call(herb_type) + if (herb_info = $known_herbs.find { |h| h[:short_name] == new_herb.name }) and (store_doses = herb_info[:store_doses]) + $useherbs_measure[new_herb.id] = store_doses + end + for old_herb in herb_list + 10.times { + if (GameObj.right_hand.id == new_herb.id) or (GameObj.left_hand.id == new_herb.id) + result = dothistimeout "pour ##{new_herb.id} in ##{old_herb.id}", 5, /^You carefully pour|^You can't pour|^I can't find that|^I could not find what you were referring to/ + if result =~ /^You can't pour any more in there without spilling it\./ + $useherbs_measure[old_herb.id] = 7 # fixme: barrels hold 10 + break + elsif result =~ /^You can't pour|^I can't find that|^I could not find what you were referring to/ + break + end + else + break + end + } + end + if (GameObj.right_hand.id == new_herb.id) or (GameObj.left_hand.id == new_herb.id) + dothistimeout "_drag ##{new_herb.id} ##{herb_container.id}", 10, put_regex + end end } - herb_list = herb_container.contents.find_all { |obj| known_herbs.find { |h| (h[:name] == obj.name) and h[:type] == herb_type } } - for herb in herb_list - result = dothistimeout "look in ##{herb.id}", 5, /^There is (?:a good|a small|just a little)/ - if result =~ /good/ # 5-7 doses - doses[herb.id] = [5,7] - elsif result =~ /small/ # 3-4 doses - doses[herb.id] = [3,4] - elsif result =~ /little/ # 1-2 doses - doses[herb.id] = [1,2] + end + fill_hand if done_empty_hand + end + if script.vars[2].nil? or (script.vars[2].downcase == 'herbs') + done_empty_hands = false + nearest_herbalist_id = Room.current.find_nearest_by_tag('herbalist') + nearest_herbalist_id or raise "can't find a path to a herbalist from here" + unless Room[nearest_herbalist_id].location =~ /Wehnimer's|Solhaven/ + echo "stocking herbs is only supported in Wehnimer's and Solhaven (they sell herbs that can be bundled)" + exit # fixme: go back to start room? + end + shopping_list = Array.new + for herb in [ "some acantha leaf", "some aloeas stem", "some haphip root", "some pothinir grass", "some basal moss", "some ephlox moss", "some ambrominas leaf", "some calamia fruit", "some cactacae spine", "some sovyn clove", "some wolifrew lichen", "some woth flower", "some torban leaf" ] + herb_list = herb_container.contents.find_all { |o| o.name == herb } + total_doses = 0; herb_list.each { |h| total_doses += $useherbs_measure[h.id].to_i } + if herb_list.any? { |h| $useherbs_measure[h.id].nil? } # assume any herb with an unkown count is good enough + if total_doses > 0 + respond "#{herb.rjust(25)}: found (#{total_doses}+)" + else + respond "#{herb.rjust(25)}: found" end + next + end + unless store_doses = $known_herbs.find { |h| h[:name] == herb }[:store_doses] + echo "error: missing store_doses for #{herb}" + next end - while doses.values.any? { |dose| dose.max < 7 } + if herb_list.empty? + respond "#{herb.rjust(25)}: missing" + else + respond "#{herb.rjust(25)}: found (#{total_doses})" + if (total_doses + store_doses) > 50 + next + end + end + shopping_list.push(:herb_name => herb, :herb_list => herb_list, :needed => ((50-total_doses)/store_doses)) + end + unless shopping_list.empty? + respond + respond "shopping list:" + for thing in shopping_list + respond "#{thing[:herb_name].rjust(25)} (#{thing[:needed]})" + end + respond + sleep 2 + for thing in shopping_list unless done_gone_to_herbalist + if check_silvers.call < 1500 + withdraw.call + end go_to_herbalist.call done_gone_to_herbalist = true end - new_herb = buy_herb.call(herb_type) - while doses.values.any? { |dose| dose.min < 7 } and ((GameObj.right_hand.id == new_herb.id) or (GameObj.left_hand.id == new_herb.id)) - for herb in herb_list - result = dothistimeout "pour ##{new_herb.id} in ##{herb.id}", 5, /^You carefully pour|You can't pour|^I can't find that|^I could not find what you were referring to/ - if result =~ /^You carefully pour/ - doses[herb.id].collect! { |num| num + 1 } - elsif result =~ /^You can't pour/ - doses[herb.id] = [7,7] - else - break - end - unless doses.values.any? { |dose| dose.min < 7 } and ((GameObj.right_hand.id == new_herb.id) or (GameObj.left_hand.id == new_herb.id)) - dothistimeout "_drag ##{new_herb.id} drop", 5, /^You drop|^^I could not find what you were referring to/ - break - end + unless done_empty_hands + empty_hands + done_empty_hands = true + end + while old_herb = thing[:herb_list].shift + dothistimeout "get ##{old_herb.id}", 5, get_regex + if checkleft and checkright + bundle_result = dothistimeout 'bundle', 5, /^Carefully, you combine|^If you add anything more to this bundle|^You do not have anything to bundle!$/ end end + herb_type = $known_herbs.find { |h| h[:name] == thing[:herb_name] }[:type] + thing[:needed].times { + if buy_herb.call(herb_type) + if checkleft and checkright + bundle_result = dothistimeout 'bundle', 5, /^Carefully, you combine|^If you add anything more to this bundle|^You do not have anything to bundle!$/ + end + end + } + dothistimeout "put ##{GameObj.right_hand.id} in ##{herb_container.id}", 5, put_regex if checkright + dothistimeout "put ##{GameObj.left_hand.id} in ##{herb_container.id}", 5, put_regex if checkleft end end + fill_hands if done_empty_hands end - if deposit_silvers - start_script('go2', ['bank','_disable_confirm_']) - wait_while { running?('go2') } - if XMLData.room_title == '[Pinefar, Depository]' - if GameObj.npcs.any? { |npc| npc.noun == 'banker' } - fput "give banker #{check_silvers.call} silvers" - end - else - fput "deposit #{check_silvers.call}" - end - end + deposit.call unless Room.current.id == start_room.id - start_script 'go2', [ start_room.id.to_s ] - wait_while { running?('go2') } + Script.run('go2', start_room.id.to_s) end exit =begin @@ -898,7 +1186,7 @@ end unless ([Wounds.head, Wounds.neck, Wounds.torso, Wounds.limbs, Wounds.nerves, Scars.head, Scars.neck, Scars.torso, Scars.limbs, Scars.nerves].max > 0) or ((checkhealth + 7) < maxhealth) respond - respond 'Missing herb for major stupid.' + respond 'Missing herb for Hypochondriasis.' respond exit end @@ -906,15 +1194,21 @@ end # # set up # -if script.vars.any? { |var| var =~ /^--buy-missing=(on|off|true|false|yes|no)$/i } +if script.vars.any? { |var| var =~ /^--buy(?:-missing)?=(on|off|true|false|yes|no)$/i } fix_option = { 'on' => true, 'true' => true, 'yes' => true, 'off' => false, 'false' => false, 'no' => false } buy_missing = fix_option[$1] - script.vars.delete_if { |var| var =~ /^--buy-missing=(on|off|true|false|yes|no)$/i } + script.vars.delete_if { |var| var =~ /^--buy(?:-missing)?=(on|off|true|false|yes|no)$/i } script.vars[0] = script.vars[1..-1].join(' ') end -if script.vars.any? { |var| var =~ /^noget$/i } +if script.vars.any? { |var| var =~ /^--mending=(on|off|true|false|yes|no)$/i } + fix_option = { 'on' => true, 'true' => true, 'yes' => true, 'off' => false, 'false' => false, 'no' => false } + use_mending = fix_option[$1] + script.vars.delete_if { |var| var =~ /^--mending=(on|off|true|false|yes|no)$/i } + script.vars[0] = script.vars[1..-1].join(' ') +end +if script.vars.any? { |var| var =~ /^(?:--)?no-?get$/i } no_get = true - script.vars.delete_if { |var| var =~ /^noget$/i } + script.vars.delete_if { |var| var =~ /^(?:--)?no-?get$/i } script.vars[0] = script.vars[1..-1].join(' ') else no_get = false @@ -930,9 +1224,25 @@ if script.vars[1] end if script.vars[1] =~ /^\#\-?[0-9]+$/ herb_container = GameObj.new(script.vars[1].sub('#',''), '', '') + elsif script.vars[1] + unless herb_container = (GameObj.loot.find { |o| o.name =~ /#{script.vars[0]}/ } || GameObj.room_desc.find { |o| o.name =~ /#{script.vars[0]}/ }) + status_tags + result = dothistimeout "look #{preposition || 'in'} #{script.vars[0]}", 5, /^<.*?>(In|On|Under|Behind) .*?exist="(\-?\d+)" noun="(.*?)">(.*?)<\/a/ + status_tags + if result =~ /^<.*?>(In|On|Under|Behind) .*?exist="(\-?\d+)" noun="(.*?)">(.*?)<\/a/ + preposition = $1.downcase + herb_container = GameObj.new($2, $3, $4) + else + echo "error: failed to find herb container (#{script.vars[0]})" + exit + end + end + elsif UserVars.herbsack.nil? or UserVars.herbsack.empty? + echo "error: no herbsack set or specified on the command line" + eixt else - unless herb_container = GameObj.loot.find { |obj| obj.name =~ /#{Regexp.escape(script.vars[0].strip)}/i } || GameObj.loot.find { |obj| obj.name =~ /#{Regexp.escape(script.vars[0].strip).sub(' ', ' .*')}/i } || GameObj.room_desc.find { |obj| obj.name =~ /#{Regexp.escape(script.vars[0].strip)}/i } || GameObj.room_desc.find { |obj| obj.name =~ /#{Regexp.escape(script.vars[0].strip).sub(' ', ' .*')}/i } || GameObj.inv.find { |obj| obj.name =~ /#{Regexp.escape(script.vars[0].strip)}/i } || GameObj.inv.find { |obj| obj.name =~ /#{Regexp.escape(script.vars[0].strip).sub(' ', ' .*')}/i } - echo "error: failed to find herb container (#{script.vars[0]})" + unless herb_container = (GameObj.inv.find { |obj| obj.noun == UserVars.herbsack } || GameObj.inv.find { |obj| obj.name == UserVars.herbsack } || GameObj.inv.find { |obj| obj.name =~ /\b#{Regexp.escape(UserVars.herbsack)}$/i } || GameObj.inv.find { |obj| obj.name =~ /\b#{UserVars.herbsack.split(' ').collect { |n| Regexp.escape(n) }.join(".*\\b")}/i }) + echo "error: failed to find herb container" exit end end @@ -940,10 +1250,10 @@ if script.vars[1] for prep in [ 'in', 'on', 'under', 'behind' ] look_result = dothistimeout "look #{prep} ##{herb_container.id}", 5, /(?:In|On|Under|Behind) .*? you see|There is nothing|^That is closed\.$|^What were you referring to\?|^I could not find what you were referring to\./ if look_result =~ /^(?:In|On|Under|Behind) .*? you see/ - preposition = prep + preposition = $1.downcase break elsif look_result =~ /^That is closed\./ - open_result = dothistimeout "open ##{herb_container.id}", 5, /^You open|^What were you referring to\?|^I could not find what you were referring to\./ + open_result = dothistimeout "open ##{herb_container.id}", 5, open_regex close_herbsack = true redo if open_result =~ /^You open/ end @@ -954,13 +1264,13 @@ if script.vars[1] end end if herb_container.contents.nil? - open_result = dothistimeout "open ##{herb_container.id}", 10, /^You open|^That is already open\.$|^There doesn't seem to be any way to do that\.$|^What were you referring to\?|^I could not find what you were referring to\./ + open_result = dothistimeout "open ##{herb_container.id}", 10, open_regex if open_result =~ /^You open/ close_herbsack = true else dothistimeout "look #{preposition} ##{herb_container.id}", 10, /(?:In|On|Under|Behind) .*? you see|^There is nothing|^What were you referring to\?|^I could not find what you were referring to\./ if herb_container.contents.nil? - echo 'fixme 2' + echo 'fixme 293743' exit end end @@ -968,24 +1278,24 @@ if script.vars[1] else if UserVars.herbsack.nil? or UserVars.herbsack.empty? echo 'no container was given and herbsack is not set' - echo ' use ;setting change herbsack ' + echo ' use ;useherbs set herbsack ' echo ' or ;useherbs ' exit end - unless herb_container = GameObj.inv.find { |obj| obj.name =~ /#{Regexp.escape(UserVars.herbsack.strip)}/i } || GameObj.inv.find { |obj| obj.name =~ /#{Regexp.escape(UserVars.herbsack).sub(' ', ' .*')}/i } + unless herb_container = (GameObj.inv.find { |obj| obj.noun == UserVars.herbsack } || GameObj.inv.find { |obj| obj.name == UserVars.herbsack } || GameObj.inv.find { |obj| obj.name =~ /\b#{Regexp.escape(UserVars.herbsack)}$/i } || GameObj.inv.find { |obj| obj.name =~ /\b#{UserVars.herbsack.split(' ').collect { |n| Regexp.escape(n) }.join(".*\\b")}/i }) echo "error: unable to find container \"#{UserVars.herbsack}\" in your inventory." exit end if herb_container.contents.nil? - open_result = dothistimeout "open ##{herb_container.id}", 10, /^You open|^That is already open\.$|^There doesn't seem to be any way to do that\./ + open_result = dothistimeout "open ##{herb_container.id}", 10, open_regex if open_result =~ /^You open/ close_herbsack = true else dothistimeout "look in ##{herb_container.id}", 10, /In the .*? you see/ if herb_container.contents.nil? - echo 'fixme 2' + echo 'fixme 38923' exit end end @@ -998,30 +1308,26 @@ empty_hand # use herbs # while herb_type = next_herb_type.call - if CharSettings['use-mending'] and (mending = Spell[9713]) and !mending.active? and mending.known? and mending.affordable? - mending.cast - end - if CharSettings['use-haste'] and (haste = Spell[506]) and !haste.active? and haste.known? and haste.affordable? and not too_wounded_to_cast.call - haste.cast - end - if known_herbs.any? { |h| (h[:name].sub(/^(?:some|flagon of|barrel of) /, '') == GameObj.right_hand.name) and (h[:type] == herb_type) } + if $known_herbs.any? { |h| h[:type] == herb_type and (h[:name] == GameObj.right_hand.name or (h[:short_name] and h[:short_name] == GameObj.right_hand.name)) } herb = GameObj.right_hand - elsif known_herbs.any? { |h| (h[:name].sub(/^(?:some|flagon of|barrel of) /, '') == GameObj.left_hand.name) and (h[:type] == herb_type) } + elsif $known_herbs.any? { |h| h[:type] == herb_type and (h[:name] == GameObj.left_hand.name or (h[:short_name] and h[:short_name] == GameObj.left_hand.name)) } herb = GameObj.left_hand elsif [Wounds.leftArm, Wounds.rightArm].min < 3 if return_to_stow and start_room.id != Room.current.id - start_script 'go2', [ start_room.id.to_s ] - wait_while { running?('go2') } - dothistimeout "look in ##{herb_container.id}", 4, /^In the/ + Script.run('go2', start_room.id.to_s) + dothistimeout "look #{preposition} ##{herb_container.id}", 4, /(?:In|On|Under|Behind) .*? you see|^There is nothing|^What were you referring to\?|^I could not find what you were referring to\./ end if herb_container.contents.nil? - dothistimeout "look in ##{herb_container.id}", 4, /^In the/ + dothistimeout "look #{preposition} ##{herb_container.id}", 4, /(?:In|On|Under|Behind) .*? you see|^There is nothing|^What were you referring to\?|^I could not find what you were referring to\./ end - if herb = herb_container.contents.find { |i| known_herbs.find { |h| (h[:name] == i.name) and h[:type] == herb_type } } + if herb = herb_container.contents.find { |i| $known_herbs.find { |h| (h[:name] == i.name) and h[:type] == herb_type } } stow_herb.call unless no_get and (herb.name !~ drinkable) - get_result = dothistimeout "get ##{herb.id}", 5, /^^You (?:carefully )?(?:remove|grab|reach|slip|tuck)|^Get what\?$|^Why don't you leave some for others\?$|^You need a free hand for that\.|^You need a free hand to pick that up\./ - if get_result.nil? or (get_result == 'Get what?') or (get_result == "Why don't you leave some for others?") + get_result = dothistimeout "get ##{herb.id}#{get_from}", 5, get_regex + if (get_result =~ /^Get what/) and get_from.nil? + get_from = " from ##{herb_container.id}" + redo + elsif get_result.nil? or (get_result == 'Get what?') or (get_result == "Why don't you leave some for others?") echo 'fixme 4' exit elsif (get_result =~ /^You need a free hand for that\.|^You need a free hand to pick that up\./) and (!checkright or !checkleft) @@ -1044,7 +1350,7 @@ while herb_type = next_herb_type.call unless herb_shop_menu herb_shop_menu = read_menu.call end - herb_name = herb_shop_menu.keys.find { |name| known_herbs.any? { |h| (h[:type] == herb_type) and (name =~ /#{h[:name]}/ or name =~ /#{h[:name].sub(/sticky |gooey | green| fragrant| shiny| dirty/, '')}/) } } + herb_name = herb_shop_menu.keys.find { |name| $known_herbs.any? { |h| (h[:type] == herb_type) and (name =~ /#{h[:name]}/ or name =~ /#{h[:name].sub(/sticky |gooey | green| fragrant| shiny| dirty/, '')}/) } } unless order_number = herb_shop_menu[herb_name] echo "error: failed to find a herb for #{herb_type} in the menu" buy_missing = false @@ -1060,9 +1366,9 @@ while herb_type = next_herb_type.call else silvers = check_silvers.call end - if known_herbs.any? { |info| info[:name] =~ /#{checkright}/ } + if $known_herbs.any? { |info| info[:name] =~ /#{checkright}/ } herb = GameObj.right_hand - elsif known_herbs.any? { |info| info[:name] =~ /#{checkleft}/ } + elsif $known_herbs.any? { |info| info[:name] =~ /#{checkleft}/ } herb = GameObj.left_hand else echo 'fixme: 6' @@ -1070,6 +1376,9 @@ while herb_type = next_herb_type.call end end if herb + if use_mending and (mending = Spell[9713]) and !mending.active? and mending.known? and mending.affordable? + mending.cast + end used_herbs.push(herb.id) unless used_herbs.include?(herb.id) if herb.name =~ drinkable use_cmd = "drink ##{herb.id}" @@ -1099,7 +1408,7 @@ while herb_type = next_herb_type.call else skippable.push herb_type end - respond "\nMissing herb for #{herb_type}.\n\n #{known_herbs.find_all { |h| h[:type] == herb_type }.collect { |h| h[:name] }.join(', ')}\n\n" + respond "\nMissing herb for #{herb_type}.\n\n #{$known_herbs.find_all { |h| h[:type] == herb_type }.collect { |h| h[:name] }.join(', ')}\n\n" end end @@ -1108,14 +1417,8 @@ end # stow_herb.call fill_hand -dothistimeout "close ##{herb_container.id}", 5, /^You close|^That is already closed\.$/ if close_herbsack -dothistimeout "close ##{stow_container_id}", 5, /^You close|^That is already closed\.$/ if stow_container_id -if deposit_silvers - start_script('go2', ['bank','_disable_confirm_']) - wait_while { running?('go2') } - fput "deposit #{check_silvers.call}" -end +dothistimeout "close ##{herb_container.id}", 5, close_regex if close_herbsack +deposit.call unless Room.current.id == start_room.id - start_script('go2', [ start_room.id.to_s ]) - wait_while { running?('go2') } + Script.run('go2', start_room.id.to_s) end diff --git a/useimbed.lic b/useimbed.lic index a04436a..7615dd4 100644 --- a/useimbed.lic +++ b/useimbed.lic @@ -13,11 +13,24 @@ ;useimbed help - tillmen@lichproject.org + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: magic + version: 0.3 + required: Lich >= 4.6.0 + + changelog: + 0.3 (2015-08-31): + check for and release prepared spell + 0.2 (2015-03-14): + allow multiple imbeds for the same spell + change stance for some spells =end -UserVars.imbeds = Hash.new unless UserVars.imbeds.class == Hash +# fixme: automatically find item name when adding new items + +Vars.imbeds = Hash.new unless Vars.imbeds.class == Hash if script.vars[1] == 'add' script.vars.shift @@ -50,32 +63,36 @@ if script.vars[1] == 'add' output.concat " to add this item, type #{monsterbold_start};u #{script.name}#{monsterbold_end} \n" output.concat " to cancel, type #{monsterbold_start};k #{script.name}#{monsterbold_end} \n" output.concat "\n" - puts output + if defined?(_respond) + _respond output + else + puts output + end pause_script - UserVars.imbeds[name] = { :spell => spell.to_i, :charges => charges.to_i, :activator => activator, :worn => worn, :use_last_charge => last_charge } + Vars.imbeds[name] = { :spell => spell.to_i, :charges => charges.to_i, :activator => activator, :worn => worn, :use_last_charge => last_charge } echo 'imbed was added' exit elsif script.vars[1] =~ /^del(?:ete)?$/ - imbed_name, imbed_info = UserVars.imbeds.find { |iname,iinfo| iname == script.vars[2..-1].join(' ') } + imbed_name, imbed_info = Vars.imbeds.find { |iname,iinfo| iname == script.vars[2..-1].join(' ') } if imbed_name - UserVars.imbeds.delete(imbed_name) + Vars.imbeds.delete(imbed_name) echo "#{imbed_name} was deleted" else echo 'no matching imbed found' - echo "current imbeds: #{UserVars.imbeds.keys.join(', ')}" + echo "current imbeds: #{Vars.imbeds.keys.join(', ')}" end exit elsif script.vars[1] == 'list' max_name = 0 - UserVars.imbeds.keys.each { |name| max_name = [ max_name, name.length ].max } + Vars.imbeds.keys.each { |name| max_name = [ max_name, name.length ].max } output = "\n#{'name'.ljust(max_name)} spell charges activator worn use-last spell name\n" output.concat "#{'----'.ljust(max_name)} ----- ------- --------- ---- -------- ----------\n" if script.vars[2] == 'charges' - UserVars.imbeds.sort { |a,b| b[1][:charges] <=> a[1][:charges] }.each { |imbed| + Vars.imbeds.sort { |a,b| b[1][:charges] <=> a[1][:charges] }.each { |imbed| output.concat "#{imbed[0].ljust(max_name)} #{imbed[1][:spell].to_s.rjust(5)} #{imbed[1][:charges].to_s.rjust(7)} #{imbed[1][:activator].rjust(9)} #{if imbed[1][:worn]; 'yes'; else; ' no'; end} #{if imbed[1][:use_last_charge]; 'yes'; else ' no'; end} #{Spell[imbed[1][:spell]].name}\n" } else - UserVars.imbeds.sort { |a,b| a[1][:spell] <=> b[1][:spell] }.each { |imbed| + Vars.imbeds.sort { |a,b| a[1][:spell] <=> b[1][:spell] }.each { |imbed| output.concat "#{imbed[0].ljust(max_name)} #{imbed[1][:spell].to_s.rjust(5)} #{imbed[1][:charges].to_s.rjust(7)} #{imbed[1][:activator].rjust(9)} #{if imbed[1][:worn]; 'yes'; else; ' no'; end} #{if imbed[1][:use_last_charge]; 'yes'; else ' no'; end} #{Spell[imbed[1][:spell]].name}\n" } end @@ -90,6 +107,7 @@ elsif script.vars[1] !~ /^[0-9]+$/ output.concat " ;useimbed add \"polished silver wand\" 901 wave 10 use-last-charge\n" output.concat " ;useimbed add \"very ugly necklace\" 406 rub 6 worn use-last-charge\n" output.concat " ;useimbed add \"cloudy white diamond\" 410 tap 40\n" + output.concat " ;useimbed delete \"cloudy white diamond\"\n" output.concat "\n" output.concat " The name of the imbed must be an exact match to the GameObj name, and it must be in quotes.\n" output.concat "\n" @@ -102,11 +120,11 @@ elsif script.vars[1] !~ /^[0-9]+$/ exit end -if UserVars.magicsack.nil? or UserVars.magicsack.empty? +if Vars.magicsack.nil? or Vars.magicsack.empty? echo 'error: magicsack is not set. (;set change magicsack )' exit end -unless magicsack = (GameObj.inv.find { |obj| obj.name =~ /\b#{Regexp.escape(UserVars.magicsack.strip)}$/i } || GameObj.inv.find { |obj| obj.name =~ /\b#{Regexp.escape(UserVars.magicsack).sub(' ', ' .*')}$/i }) +unless magicsack = (GameObj.inv.find { |obj| obj.name =~ /\b#{Regexp.escape(Vars.magicsack.strip)}$/i } || GameObj.inv.find { |obj| obj.name =~ /\b#{Regexp.escape(Vars.magicsack).sub(' ', ' .*')}$/i }) echo 'error: failed to find your magicsack' exit end @@ -127,11 +145,112 @@ open_magicsack = proc { } if script.vars[2] - target = "at #{script.vars[2]}" + target = "at #{script.vars[2..-1].join(' ')}" else target = '' end +usedit = false +messages = Array.new + +Vars.imbeds.each_pair { |imbed_name,imbed_info| + next if imbed_info[:spell] != script.vars[1].to_i + if (imbed_info[:charges] <= 0) or ((imbed_info[:use_last_charge] != true) and (imbed_info[:charges] <= 1)) + messages.push "#{imbed_name} is out of charges" + next + end + + if imbed_info[:worn] + if imbed = GameObj.inv.find { |obj| obj.name == imbed_name } + Spell.lock_cast + waitrt? + waitcastrt? + if Spell[imbed_info[:spell]].stance and (checkstance != 'offensive') + dothistimeout 'stance offensive', 5, /^You are now in an? \w+ stance\.$|^You are unable to change your stance\.$/ + end + if checkprep != 'None' + put 'release' + end + dothistimeout "#{imbed_info[:activator]} ##{imbed.id} #{target}", 2, /^You (?:rub|tap)/ + Spell.unlock_cast + imbed_info[:charges] = imbed_info[:charges].to_i - 1 + respond "[ #{imbed_name}: #{imbed_info[:charges]} charges remaining. ]" + if Spell[imbed_info[:spell]].stance and (checkstance !~ /guarded|defensive/) + dothistimeout 'stance guarded', 5, /^You are now in an? \w+ stance\.$|^You are unable to change your stance\.$/ + end + usedit = true + break + else + open_magicsack.call + if imbed = magicsack.contents.find { |obj| obj.name == imbed_name } + Spell.lock_cast + waitrt? + waitcastrt? + empty_hand + dothistimeout "get ##{imbed.id}", 2, /^You remove/ + dothistimeout "wear ##{imbed.id}", 2, /^You/ + if Spell[imbed_info[:spell]].stance and (checkstance != 'offensive') + dothistimeout 'stance offensive', 5, /^You are now in an? \w+ stance\.$|^You are unable to change your stance\.$/ + end + if checkprep != 'None' + put 'release' + end + dothistimeout "#{imbed_info[:activator]} ##{imbed.id} #{target}", 2, /^You (?:rub|tap|raise|wave)/ + Spell.unlock_cast + imbed_info[:charges] = imbed_info[:charges].to_i - 1 + respond "[ #{imbed_name}: #{imbed_info[:charges]} charges remaining. ]" + if Spell[imbed_info[:spell]].stance and (checkstance !~ /guarded|defensive/) + dothistimeout 'stance guarded', 5, /^You are now in an? \w+ stance\.$|^You are unable to change your stance\.$/ + end + fill_hand + usedit = true + break + else + messages.push "warning: failed to find imbed: #{imbed_name}" + end + end + else + open_magicsack.call + if imbed = magicsack.contents.find { |obj| obj.name == imbed_name } + Spell.lock_cast + waitrt? + waitcastrt? + empty_hand + dothistimeout "get ##{imbed.id}", 2, /^You remove/ + if Spell[imbed_info[:spell]].stance and (checkstance != 'offensive') + dothistimeout 'stance offensive', 5, /^You are now in an? \w+ stance\.$|^You are unable to change your stance\.$/ + end + if checkprep != 'None' + put 'release' + end + dothistimeout "#{imbed_info[:activator]} ##{imbed.id} #{target}", 2, /^You (?:rub|tap|raise|wave)/ + Spell.unlock_cast + imbed_info[:charges] = [imbed_info[:charges].to_i, 40].min - 1 + respond "[ #{imbed_name}: #{imbed_info[:charges]} charges remaining. ]" + if Spell[imbed_info[:spell]].stance and (checkstance !~ /guarded|defensive/) + dothistimeout 'stance guarded', 5, /^You are now in an? \w+ stance\.$|^You are unable to change your stance\.$/ + end + dothistimeout "put ##{imbed.id} in ##{magicsack.id}", 2, /^You put/ + fill_hand + usedit = true + break + else + messages.push "failed to find imbed: #{imbed_name}" + end + end +} + +fput "close ##{magicsack.id}" if close_magicsack +unless usedit + if messages.empty? + echo "cannot find an imbed for spell number #{script.vars[1]}" + else + messages.each { |m| echo(m) } + end +end + + +=begin imbed_name, imbed_info = UserVars.imbeds.find { |iname,iinfo| iinfo[:spell] == script.vars[1].to_i } if imbed_name unless (imbed_info[:use_last_charge] == true and imbed_info[:charges] > 0) or (imbed_info[:charges] > 1) @@ -210,3 +329,4 @@ if imbed_name else echo 'no matching imbed found' end +=end diff --git a/waggle.lic b/waggle.lic index 9207510..a0a0484 100644 --- a/waggle.lic +++ b/waggle.lic @@ -7,15 +7,46 @@ This script is a rewrite of ultrawaggle from SpiffyJr, which is a heavily modified version of spellup from Shaelun and Blueland. - Required: Lich 4.4.6 + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: magic + required: Lich >= 4.4.6 + version: 0.12 - https://github.com/matt-lowe/lich-scripts - tillmen@lichproject.org + changelog: + 0.12 (2018-04-20): + fix --refreshable-min command line option + 0.11 (2015-11-25): + fix max_multicast formula for bards + 0.10 (2015-06-08): + fix multicast duration tracking (the cast every spell once and exit bug) + +=end +=begin + + 0.9 (2015-05-20): + add option to skip short duration spells on others + add option to use symbol of mana (Drafix) + 0.8 (2015-04-20): + don't "cast 1" for 1 multicast + 0.7 (2015-03-31): + fix bug where wracking/power was used when there wasn't enough spirit/stamina for a sign/sigil + 0.6 (2015-01-30): + do one cast of each stackable spell per round until spelled up, unless rapid-fire is active + 0.5 (2014-10-16): + fix max_multicast bug + 0.4 (2014-10-05): + typo + 0.3 (2014-10-05): + fix (maybe) max_multicast + 0.2 (2014-10-05): + fix wander-to-wrack option =end +# fixme: option to cast high level spells first # fixme: armor specialization -# fixme: eat bread +# fixme: option to not cast low duration spells on others start_at = CharSettings['start_at'] || 180 stop_at = CharSettings['stop_at'] || 180 @@ -30,10 +61,13 @@ use_power = CharSettings['use_power'] || false use_mana = CharSettings['use_mana'] || false use_concentration = CharSettings['use_concentration'] || false skip_jerks = CharSettings['skip_jerks'] || false +skip_short_spells = CharSettings['skip_short_spells'] || false reserve_mana = CharSettings['reserve_mana'] || 0 retribution_spell = CharSettings['retribution_spell'] cast_list = CharSettings['cast_list'] || [ 101, 102, 103, 107, 115, 120, 202, 211, 215, 219, 303, 307, 310, 313, 401, 406, 414, 425, 430, 503, 507, 508, 509, 513, 520, 601, 602, 606, 613, 617, 618, 625, 640, 712, 905, 911, 913, 920, 1109, 1119, 1125, 1130, 1601, 1603, 1606, 1610, 1611, 1612, 1616 ] did_something = false +fix_setting = { 'on' => true, 'off' => false } +short_spell_time = 3 if setting = script.vars.find { |var| var =~ /^\-\-start[_\-]at=[0-9]+$/ } start_at = setting.slice(/[0-9]+/).to_i @@ -47,7 +81,7 @@ if setting = script.vars.find { |var| var =~ /^\-\-stop[_\-]before=[0-9]+$/ } stop_before = setting.slice(/[0-9]+/).to_i script.vars.delete(setting) end -if setting = script.vars.find { |var| var =~ /^\-\-unstackable[_\-]min=[0-9]+$/ } +if setting = script.vars.find { |var| var =~ /^\-\-(?:unstackable|refreshable)[_\-]min=[0-9]+$/ } unstackable_min = setting.slice(/[0-9]+/).to_i script.vars.delete(setting) end @@ -56,40 +90,37 @@ if setting = script.vars.find { |var| var =~ /^\-\-cast[_\-]list=[0-9,]+$/ } script.vars.delete(setting) end if setting = script.vars.find { |var| var =~ /^\-\-use[_\-]multicast=(?:on|off)$/ } - fix_setting = { 'on' => true, 'off' => false } use_multicast = fix_setting[setting.slice(/on|off/)] script.vars.delete(setting) end if setting = script.vars.find { |var| var =~ /^\-\-use[_\-]wracking=(?:on|off)$/ } - fix_setting = { 'on' => true, 'off' => false } use_wracking = fix_setting[setting.slice(/on|off/)] script.vars.delete(setting) end if setting = script.vars.find { |var| var =~ /^\-\-wander[_\-]to[_\-]wrack=(?:on|off)$/ } - fix_setting = { 'on' => true, 'off' => false } wander_to_wrack = fix_setting[setting.slice(/on|off/)] script.vars.delete(setting) end if setting = script.vars.find { |var| var =~ /^\-\-use[_\-]power=(?:on|off)$/ } - fix_setting = { 'on' => true, 'off' => false } use_power = fix_setting[setting.slice(/on|off/)] script.vars.delete(setting) end -if setting = script.vars.find { |var| var =~ /^\-\-use[_\-]concentration=(?:on|off)$/ } - fix_setting = { 'on' => true, 'off' => false } - use_concentration = fix_setting[setting.slice(/on|off/)] - script.vars.delete(setting) -end if setting = script.vars.find { |var| var =~ /^\-\-use[_\-]mana=(?:on|off)$/ } - fix_setting = { 'on' => true, 'off' => false } use_mana = fix_setting[setting.slice(/on|off/)] script.vars.delete(setting) end +if setting = script.vars.find { |var| var =~ /^\-\-use[_\-]concentration=(?:on|off)$/ } + use_concentration = fix_setting[setting.slice(/on|off/)] + script.vars.delete(setting) +end if setting = script.vars.find { |var| var =~ /^\-\-skip[_\-]jerks=(?:on|off)$/ } - fix_setting = { 'on' => true, 'off' => false } skip_jerks = fix_setting[setting.slice(/on|off/)] script.vars.delete(setting) end +if setting = script.vars.find { |var| var =~ /^\-\-skip[_\-]short(?:[_\-]spells)?=(?:on|off)$/ } + skip_short_spells = fix_setting[setting.slice(/on|off/)] + script.vars.delete(setting) +end if setting = script.vars.find { |var| var =~ /^\-\-retribution[_\-]spell=(?:[0-9]+|off)$/ } if setting =~ /^\-\-retribution[_\-]spell=off$/ retribution_spell = nil @@ -107,9 +138,10 @@ if script.vars.include?('--save') CharSettings['use_multicast'] = use_multicast CharSettings['wander_to_wrack'] = wander_to_wrack CharSettings['use_power'] = use_power - CharSettings['use_mana'] = use_mana + CharSettings['use_mana'] = use_mana CharSettings['use_concentration'] = use_concentration CharSettings['skip_jerks'] = skip_jerks + CharSettings['skip_short_spells'] = skip_short_spells CharSettings['start_at'] = start_at CharSettings['stop_at'] = stop_at CharSettings['stop_before'] = stop_before @@ -146,9 +178,10 @@ elsif script.vars[1].downcase == 'help' respond " #{$clean_lich_char}#{script.name} wracking [on/off] use sign of wracking when out of mana" respond " #{$clean_lich_char}#{script.name} wander [on/off] wander up to 20 rooms to find an empty room to wrack in and return" respond " #{$clean_lich_char}#{script.name} power [on/off] use sigil of power when out of mana" - respond " #{$clean_lich_char}#{script.name} mana [on/off] use sigil of mana when out of mana" - respond " #{$clean_lich_char}#{script.name} concentration [on/off] use sigil of power when out of mana" + respond " #{$clean_lich_char}#{script.name} concentration [on/off] use sigil of concentration when out of mana" + respond " #{$clean_lich_char}#{script.name} mana [on/off] use symbol of mana when out of mana" respond " #{$clean_lich_char}#{script.name} skip-jerks [on/off] skip targets that don't share their current spell durations" + respond " #{$clean_lich_char}#{script.name} skip-short-spells [on/off] don't cast spells with a duration less than #{short_spell_time} minutes on others" respond " #{$clean_lich_char}#{script.name} retribution-spell [#|none] spell number for chant retribution after casting cloak of shadows" respond respond " #{$clean_lich_char}#{script.name} spell yourself up" @@ -158,7 +191,7 @@ elsif script.vars[1].downcase == 'help' respond respond " Any or all saved options can be overridden on the command line without being saved using the following syntax:" respond - respond " #{$clean_lich_char}#{script.name} --cast-list=401,406,503 --start-at=60 --stop-at=120 --stop-before=250 --refreshable-min=10 --use-wracking=on --wander-to-wrack=on --use-power=off --use-mana=off --use-concentration=off --skip-jerks=on --retribution-spell=717 Jim Joe Bob" + respond " #{$clean_lich_char}#{script.name} --cast-list=401,406,503 --start-at=60 --stop-at=120 --stop-before=250 --refreshable-min=10 --use-wracking=on --wander-to-wrack=on --use-power=off --use-concentration=off --use-mana=off --skip-jerks=on --skip-short-spells=on --retribution-spell=717 Jim Joe Bob" respond exit elsif script.vars[1] =~ /^setup$|^options$/i @@ -217,21 +250,26 @@ elsif script.vars[1] =~ /^setup$|^options$/i stop_before_entry.width_request = 50 stack_box = Gtk::VBox.new(false, 0) + temp_box = Gtk::HBox.new(false, 0) temp_box.pack_end(start_at_entry, false, false, 5) temp_box.pack_end(start_at_label, false, false, 5) stack_box.pack_start(temp_box, false, false, 5) + temp_box = Gtk::HBox.new(false, 0) temp_box.pack_end(stop_at_entry, false, false, 5) temp_box.pack_end(stop_at_label, false, false, 5) stack_box.pack_start(temp_box, false, false, 5) + temp_box = Gtk::HBox.new(false, 0) temp_box.pack_end(stop_before_entry, false, false, 5) temp_box.pack_end(stop_before_label, false, false, 5) stack_box.pack_start(temp_box, false, false, 5) - stack_frame = Gtk::Frame.new('Stackable Spells') + stack_box_spacer = Gtk::VBox.new stack_box_spacer.pack_start(stack_box, false, false, 4) + + stack_frame = Gtk::Frame.new('Stackable Spells') stack_frame.add(stack_box_spacer) nonstack_min_label = Gtk::Label.new(' Minimum:') @@ -247,33 +285,7 @@ elsif script.vars[1] =~ /^setup$|^options$/i nonstack_frame = Gtk::Frame.new('Non-stackable Spells') nonstack_frame.add(nonstack_box_spacer) - left_box = Gtk::VBox.new(false, 0) - left_box.pack_start(stack_frame, false, false, 5) - left_box.pack_start(nonstack_frame, false, false, 5) - - use_multicast_option = Gtk::CheckButton.new('multicast') - use_multicast_option.active = use_multicast - use_wracking_option = Gtk::CheckButton.new('wracking') - use_wracking_option.active = use_wracking - wander_to_wrack_option = Gtk::CheckButton.new('wander to wrack') - wander_to_wrack_option.active = wander_to_wrack - use_power_option = Gtk::CheckButton.new('power') - use_power_option.active = use_power - use_mana_option = Gtk::CheckButton.new('mana') - use_mana_option.active = use_mana - use_concentration_option = Gtk::CheckButton.new('concentration') - use_concentration_option.active = use_concentration - skip_jerks_option = Gtk::CheckButton.new('skip jerks') - skip_jerks_option.active = skip_jerks - - option_box = Gtk::VBox.new(false, 0) - option_box.pack_start(use_multicast_option, false, false, 4) - option_box.pack_start(use_wracking_option, false, false, 4) - option_box.pack_start(wander_to_wrack_option, false, false, 4) - option_box.pack_start(use_power_option, false, false, 4) - option_box.pack_start(use_mana_option, false, false, 4) - option_box.pack_start(use_concentration_option, false, false, 4) - option_box.pack_start(skip_jerks_option, false, false, 4) + other_option_box = Gtk::VBox.new(false, 0) retribution_spell_label = Gtk::Label.new('retribution spell:') retribution_spell_entry = Gtk::Entry.new @@ -282,7 +294,7 @@ elsif script.vars[1] =~ /^setup$|^options$/i temp_box = Gtk::HBox.new(false, 0) temp_box.pack_end(retribution_spell_entry, false, false, 5) temp_box.pack_end(retribution_spell_label, false, false, 5) - option_box.pack_start(temp_box, false, false, 4) + other_option_box.pack_start(temp_box, false, false, 4) reserve_mana_label = Gtk::Label.new('reserve mana:') reserve_mana_entry = Gtk::Entry.new @@ -291,7 +303,45 @@ elsif script.vars[1] =~ /^setup$|^options$/i temp_box = Gtk::HBox.new(false, 0) temp_box.pack_end(reserve_mana_entry, false, false, 5) temp_box.pack_end(reserve_mana_label, false, false, 5) - option_box.pack_start(temp_box, false, false, 4) + other_option_box.pack_start(temp_box, false, false, 4) + + other_option_box_spacer = Gtk::VBox.new + other_option_box_spacer.pack_start(other_option_box, false, false, 4) + + other_option_frame = Gtk::Frame.new('Options') + other_option_frame.add(other_option_box_spacer) + + left_box = Gtk::VBox.new(false, 0) + left_box.pack_start(stack_frame, false, false, 5) + left_box.pack_start(nonstack_frame, false, false, 5) + left_box.pack_start(other_option_frame, false, false, 5) + + use_multicast_option = Gtk::CheckButton.new('multicast') + use_multicast_option.active = use_multicast + use_wracking_option = Gtk::CheckButton.new('wracking') + use_wracking_option.active = use_wracking + wander_to_wrack_option = Gtk::CheckButton.new('wander to wrack') + wander_to_wrack_option.active = wander_to_wrack + use_power_option = Gtk::CheckButton.new('power') + use_power_option.active = use_power + use_concentration_option = Gtk::CheckButton.new('concentration') + use_concentration_option.active = use_concentration + use_mana_option = Gtk::CheckButton.new('mana') + use_mana_option.active = use_mana + skip_jerks_option = Gtk::CheckButton.new('skip jerks') + skip_jerks_option.active = skip_jerks + skip_short_option = Gtk::CheckButton.new('skip short spells on others') + skip_short_option.active = skip_short_spells + + option_box = Gtk::VBox.new(false, 0) + option_box.pack_start(use_multicast_option, false, false, 4) + option_box.pack_start(use_wracking_option, false, false, 4) + option_box.pack_start(wander_to_wrack_option, false, false, 4) + option_box.pack_start(use_power_option, false, false, 4) + option_box.pack_start(use_concentration_option, false, false, 4) + option_box.pack_start(use_mana_option, false, false, 4) + option_box.pack_start(skip_jerks_option, false, false, 4) + option_box.pack_start(skip_short_option, false, false, 4) option_box_spacer = Gtk::VBox.new option_box_spacer.pack_start(option_box, false, false, 4) @@ -301,8 +351,11 @@ elsif script.vars[1] =~ /^setup$|^options$/i columns = Gtk::HBox.new(true, 0) + right_box = Gtk::VBox.new + right_box.pack_start(option_frame, false, false, 0) + columns.pack_start(left_box, false, false, 0) - columns.pack_start(option_frame, false, false, 0) + columns.pack_start(right_box, false, false, 0) save_button = Gtk::Button.new('Ok') save_button.width_request = 75 @@ -429,16 +482,17 @@ elsif script.vars[1] =~ /^setup$|^options$/i else respond "[waggle: ignoring invalid entry: #{reserve_mana_entry.text}]" end - use_multicast = use_multicast_option.active? - use_wracking = use_wracking_option.active? - wander_to_wrack = wander_to_wrack_option.active? - use_power = use_power_option.active? - use_mana = use_mana_option.active? + use_multicast = use_multicast_option.active? + use_wracking = use_wracking_option.active? + wander_to_wrack = wander_to_wrack_option.active? + use_power = use_power_option.active? use_concentration = use_concentration_option.active? - skip_jerks = skip_jerks_option.active? - window_width = window.allocation.width - window_height = window.allocation.height - window_action = :save + use_mana = use_mana_option.active? + skip_jerks = skip_jerks_option.active? + skip_short_spells = skip_short_option.active? + window_width = window.allocation.width + window_height = window.allocation.height + window_action = :save } } window.signal_connect('delete_event') { @@ -460,9 +514,10 @@ elsif script.vars[1] =~ /^setup$|^options$/i CharSettings['use_wracking'] = use_wracking CharSettings['wander_to_wrack'] = wander_to_wrack CharSettings['use_power'] = use_power - CharSettings['use_mana'] = use_mana CharSettings['use_concentration'] = use_concentration + CharSettings['use_mana'] = use_mana CharSettings['skip_jerks'] = skip_jerks + CharSettings['skip_short_spells'] = skip_short_spells CharSettings['start_at'] = start_at CharSettings['stop_at'] = stop_at CharSettings['stop_before'] = stop_before @@ -515,9 +570,10 @@ elsif script.vars[1] =~ /^list$|^show$/i respond " sign of wracking: #{fix_setting[use_wracking]}" respond " wander to wrack: #{fix_setting[wander_to_wrack]}" respond " sigil of power: #{fix_setting[use_power]}" - respond " symbol of mana: #{fix_setting[use_mana]}" respond "sigil of concentration: #{fix_setting[use_concentration]}" + respond " symbol of mana: #{fix_setting[use_mana]}" respond " skip jerks: #{fix_setting[skip_jerks]}" + respond " skip short spells: #{fix_setting[skip_short_spells]}" respond " retribution spell: #{retribution_spell || 'none'}" respond " reserve mana: #{reserve_mana}" respond @@ -598,24 +654,24 @@ elsif script.vars[1].downcase =~ /^(?:use[_\-])?power$/ echo "You're doing it wrong..." end exit -elsif script.vars[1].downcase =~ /^(?:use[_\-])?mana$/ +elsif script.vars[1].downcase =~ /^(?:use[_\-])?concentration$/ if script.vars[2].downcase == 'on' - CharSettings['use_mana'] = true - echo "symbol of mana will be used" + CharSettings['use_concentration'] = true + echo "sigil of concentration will be used" elsif script.vars[2].downcase == 'off' - CharSettings['use_mana'] = false - echo "symbol of man will not be used" + CharSettings['use_concentration'] = false + echo "sigil of concentration will not be used" else echo "You're doing it wrong..." end exit -elsif script.vars[1].downcase =~ /^(?:use[_\-])?concentration$/ +elsif script.vars[1].downcase =~ /^(?:use[_\-])?mana$/ if script.vars[2].downcase == 'on' - CharSettings['use_concentration'] = true - echo "sigil of concentration will be used" + CharSettings['use_mana'] = true + echo "symbol of mana will be used" elsif script.vars[2].downcase == 'off' - CharSettings['use_concentration'] = false - echo "sigil of concentration will not be used" + CharSettings['use_mana'] = false + echo "symbol of man will not be used" else echo "You're doing it wrong..." end @@ -631,6 +687,17 @@ elsif script.vars[1].downcase =~ /^skip[_\-]jerks$/ echo "You're doing it wrong..." end exit +elsif script.vars[1].downcase =~ /^skip[_\-]short(?:[_\-]spells)?/ + if script.vars[2].downcase == 'on' + CharSettings['skip_short_spells'] = true + echo "spells with a duration of less than #{short_spell_time} minutes per cast will not be cast on others" + elsif script.vars[2].downcase == 'off' + CharSettings['skip_short_spells'] = false + echo "short spells will not be skipped" + else + echo "You're doing it wrong..." + end + exit elsif script.vars[1].downcase =~ /^retribution[_\-]spell$/ if script.vars[2].downcase =~ /^(?:off|none)$/ CharSettings['retribution_spell'] = nil @@ -696,7 +763,7 @@ wander_rooms = Array.new wander = proc { room = Room.current next_room_options = room.wayto.keys - next_room = next_room_options.find_all {|r| ((room.timeto[r].class == Float && room.timeto[r] <= 3) or (room.timeto[r].class == Proc && room.timeto[r].call != nil && room.timeto[r].call <= 3)) and not wander_rooms.include?(r)} + next_room = next_room_options.find_all { |r| ((room.timeto[r].class == Float && room.timeto[r] <= 3) or (room.timeto[r].class == Proc && room.timeto[r].call != nil && room.timeto[r].call <= 3)) and not wander_rooms.include?(r)} if next_room.empty? next_room = wander_rooms.find { |r| next_room_options.include?(r) } else @@ -713,39 +780,39 @@ wander = proc { } check_mana = proc { |spell, num_multicast| - unless spell.affordable?(:multicast => num_multicast) and (spell.mana_cost == 0 or mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana) - sigil_of_power = Spell[9718] - sign_of_wracking = Spell[9918] - symbol_of_mana = Spell[9813] - symbol_of_mana_cooldown = Spell[9048] - punishment = Spell[9012] - if use_power and sigil_of_power.known? and (spell.mana_cost > 0) and (spell.stamina_cost == 0) - until spell.affordable?(:multicast => num_multicast) and (spell.mana_cost == 0 or mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana) + unless spell.affordable?(:multicast => num_multicast) and ((spell.mana_cost == 0) or (mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana)) + sigil_of_power = Spell[9718] + sign_of_wracking = Spell[9918] + symbol_of_mana = Spell[9813] + symbol_of_mana_cooldown = Spell[9048] + punishment = Spell[9012] + if use_power and sigil_of_power.known? and (spell.mana_cost > 0) and (mana < (spell.mana_cost(:multicast => num_multicast) + reserve_mana)) and (spell.stamina_cost == 0) + until spell.affordable?(:multicast => num_multicast) and (mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana) if sigil_of_power.affordable? sigil_of_power.cast sleep 0.2 else fput 'release' unless checkprep == 'None' - echo 'waiting for mana or stamina...' - wait_until { (spell.affordable?(:multicast => num_multicast) and (spell.mana_cost == 0 or mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana)) or sigil_of_power.affordable? } + echo 'waiting for mana...' + wait_until { (spell.affordable?(:multicast => num_multicast) and (mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana)) or sigil_of_power.affordable? } end end - elsif use_mana and symbol_of_mana.known? and spell.mana_cost > 0 - until spell.affordable?(:multicast => num_multicast) and (mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana) - waitrt? - waitcastrt? - - if not symbol_of_mana_cooldown.active? - symbol_of_mana.cast - sleep 0.2 - else + elsif use_mana and symbol_of_mana.known? and spell.mana_cost > 0 + until spell.affordable?(:multicast => num_multicast) and (mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana) + waitrt? + waitcastrt? + if not symbol_of_mana_cooldown.active? + # fixme: might spam if out of favor + symbol_of_mana.cast + sleep 0.2 + else fput 'release' unless checkprep == 'None' echo 'waiting for mana or mana cooldown...' - wait_until { (spell.affordable?(:multicast => num_multicast) and (mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana)) or not symbol_of_mana_cooldown.active?} + wait_until { (spell.affordable?(:multicast => num_multicast) and (mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana)) or not symbol_of_mana_cooldown.active? } end - end - elsif use_wracking and sign_of_wracking.known? and not punishment.active? and (spell.mana_cost > 0) - until spell.affordable?(:multicast => num_multicast) and (spell.mana_cost == 0 or mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana) + end + elsif use_wracking and sign_of_wracking.known? and not punishment.active? and (spell.mana_cost > 0) and (mana < (spell.mana_cost(:multicast => num_multicast) + reserve_mana)) + until spell.affordable?(:multicast => num_multicast) and (mana >= spell.mana_cost(:multicast => num_multicast) + reserve_mana) waitrt? waitcastrt? if sign_of_wracking.affordable? and not punishment.active? @@ -828,7 +895,7 @@ cast_spell = proc { |spell, target, num_multicast| if num_multicast > 1 cast_result = spell.cast("at #{target} #{num_multicast}") else - cast_result = spell.cast("at #{target} #{num_multicast}") + cast_result = spell.cast("at #{target}") end end if cast_result =~ /^Be at peace my child, there is no need for spells of war in here\.$|Spells of War cannot be cast/ @@ -857,12 +924,28 @@ get_target_info = proc { |target| max_multicast = proc{ |spell| ranks = 0 - if [4, 5, 9].include?(spell.circle.to_i) - ranks = Skills.emc + ([Skills.smc, Skills.mmc].max / 2) - elsif [1, 2, 3, 6, 16, 11].include?(spell.circle.to_i) - ranks = Skills.smc + ([Skills.emc, Skills.mmc].max / 2) - elsif spell.circle.to_i == 7 - ranks = [Skills.emc,Skills.smc].max + ([Skills.emc,Skills.smc].min / 2) + if Char.prof == 'Wizard' + ranks = Skills.emc + elsif Char.prof =~ /^Cleric$|^Ranger$|^Paladin$/ + ranks = Skills.smc + elsif Char.prof =~ /^Empath$|^Monk$|^Bard$/ + if [1,2].include?(spell.circle.to_i) + ranks = Skills.smc + (Skills.mmc / 2) + elsif spell.circle.to_i == 11 + ranks = [Skills.mmc,Skills.smc].max + ([Skills.mmc,Skills.smc].min / 2) + elsif spell.circle.to_i == 12 + ranks = Skills.mmc + (Skills.smc / 2) + elsif spell.circle.to_i == 4 + ranks = Skills.emc + (Skills.mmc / 2) + end + elsif Char.prof =~ /^Sorcerer$|^Warrior$|^Rogue$/ + if spell.circle.to_i == 4 + ranks = Skills.emc + (Skills.smc / 2) + elsif spell.circle.to_i == 1 + ranks = Skills.smc + (Skills.emc / 2) + elsif spell.circle.to_i == 7 + ranks = [Skills.emc,Skills.smc].max + ([Skills.emc,Skills.smc].min / 2) + end end (ranks / 25) + 1 } @@ -898,6 +981,7 @@ if list_mode target_info.keys.each { |name| next unless spell.stackable?(:target => name) next unless spell.available?(:target => name) + next unless spell.time_per(:target => name) > short_spell_time next if (name == Char.name) and (spell.circlename == 'Bard') and spell.active? target_info[name][spell.num.to_s] ||= 0 dry_run[name] ||= Hash.new @@ -914,6 +998,7 @@ if list_mode target_info.keys.each { |name| next unless spell.refreshable?(:target => name) next unless spell.available?(:target => name) + next unless spell.time_per(:target => name) > short_spell_time next if (name == Char.name) and (spell.circlename == 'Bard') and spell.active? target_info[name][spell.num.to_s] ||= 0 if (target_info[name][spell.num.to_s] < refreshable_min) @@ -926,6 +1011,7 @@ if list_mode target_info.keys.each { |name| next if spell.stackable?(:target => name) or spell.refreshable?(:target => name) next unless spell.available?(:target => name) + next unless spell.time_per(:target => name) > short_spell_time next if (name == Char.name) and (spell.circlename == 'Bard') and spell.active? target_info[name][spell.num.to_s] ||= 0 unless target_info[name][spell.num.to_s] > 0 @@ -973,78 +1059,107 @@ else cast_list.delete(625) cast_list.unshift(625) end - skip_targets = Array.new - skip_spells = Array.new + skip_targets = Array.new + skip_spells = Array.new + did_first_cast = Hash.new # # cast stackable spells # - cast_list.each { |spell| - if use_concentration and (sigil_of_concentration = Spell[9714]) - sigil_of_concentration.cast if sigil_of_concentration.known? and sigil_of_concentration.affordable? and not sigil_of_concentration.active? - end - spell = fix_spell.call(spell) - target_info.keys.each { |name| - next unless spell.stackable?(:target => name) - next unless spell.available?(:target => name) - next if skip_targets.include?(name) or skip_spells.include?(spell.num) - next if (name == Char.name) and (spell.circlename == 'Bard') and spell.active? - target_info[name][spell.num.to_s] ||= 0 - if target_info[name][spell.num.to_s] < start_at - if use_multicast and spell.multicastable? - multicast_num = 0 - need_chant = false - while ( (target_info[name][spell.num.to_s] < stop_at) and (target_info[name][spell.num.to_s] + spell.time_per(:target => name)) < stop_before ) - need_chant = true if (spell.num == 712) and (name == Char.name) - multicast_num += 1 - target_info[name][spell.num.to_s] += spell.time_per(:target => name) - end - (multicast_num / max_multicast.call(spell)).times { - cast_result = cast_spell.call(spell, name, max_multicast.call(spell)) - if cast_result == :bad_spell - skip_spells.push(spell.num) - break - elsif cast_result == :bad_target - skip_targets.push(name) - break - end - } - unless ((multicast_num % max_multicast.call(spell)) < 1) or skip_targets.include?(name) or skip_spells.include?(spell.num) - cast_result = cast_spell.call(spell, name, (multicast_num % max_multicast.call(spell))) - if cast_result == :bad_spell - skip_spells.push(spell.num) - elsif cast_result == :bad_target - skip_targets.push(name) + loop { + did_cast = false + have_rapid = Spell[515].active? + cast_list.each { |spell| + if use_concentration and (sigil_of_concentration = Spell[9714]) + sigil_of_concentration.cast if sigil_of_concentration.known? and sigil_of_concentration.affordable? and not sigil_of_concentration.active? + end + spell = fix_spell.call(spell) + target_info.keys.each { |name| + next unless spell.stackable?(:target => name) + next unless spell.available?(:target => name) + next unless spell.time_per(:target => name) > short_spell_time + next if skip_targets.include?(name) or skip_spells.include?(spell.num) + next if (name == Char.name) and (spell.circlename == 'Bard') and spell.active? + target_info[name][spell.num.to_s] ||= 0 + did_first_cast[name] ||= Hash.new + if (target_info[name][spell.num.to_s] < start_at) or did_first_cast[name][spell.num.to_s] + did_first_cast[name][spell.num.to_s] = true + if use_multicast and spell.multicastable? + multicast_num = 0 + need_chant = false + dur = target_info[name][spell.num.to_s] + while ( (dur < stop_at) and (dur + spell.time_per(:target => name)) < stop_before ) + dur += spell.time_per(:target => name) + multicast_num += 1 + need_chant = true if (spell.num == 712) and (name == Char.name) end - end - else - need_chant = false - while ( (target_info[name][spell.num.to_s] < stop_at) and (target_info[name][spell.num.to_s] + spell.time_per(:target => name)) < stop_before ) - need_chant = true if (spell.num == 712) and (name == Char.name) - empty_hand if spell.num == 203 - cast_result = cast_spell.call(spell, name, 1) - if spell.num == 203 - if bread = [ GameObj.right_hand, GameObj.left_hand ].find { |obj| obj.noun =~ /^(?:flatbread|teacake|crisps|cake|waybread|biscuit|oatcake|fritter|loaf|ball|cornmeal|wheatberries|cracker|dumpling|bread|tart|dough|seeds)$/ } - 5.times { fput "eat ##{bread.id}" } + did_multicast = false + (multicast_num / max_multicast.call(spell)).times { + cast_result = cast_spell.call(spell, name, max_multicast.call(spell)) + target_info[name][spell.num.to_s] += (spell.time_per(:target => name) * max_multicast.call(spell)) + if cast_result == :bad_spell + skip_spells.push(spell.num) + break + elsif cast_result == :bad_target + skip_targets.push(name) + break + else + did_cast = true + end + did_multicast = true + break unless have_rapid + } + if have_rapid or not did_multicast + unless ((multicast_num % max_multicast.call(spell)) < 1) or skip_targets.include?(name) or skip_spells.include?(spell.num) + cast_result = cast_spell.call(spell, name, (multicast_num % max_multicast.call(spell))) + target_info[name][spell.num.to_s] += (spell.time_per(:target => name) * (multicast_num % max_multicast.call(spell))) + if cast_result == :bad_spell + skip_spells.push(spell.num) + elsif cast_result == :bad_target + skip_targets.push(name) + else + did_cast = true + end end - fill_hand - break end - if cast_result == :bad_spell - skip_spells.push(spell.num) - break - elsif cast_result == :bad_target - skip_targets.push(name) - break + else + need_chant = false + while ( (target_info[name][spell.num.to_s] < stop_at) and (target_info[name][spell.num.to_s] + spell.time_per(:target => name)) < stop_before ) + need_chant = true if (spell.num == 712) and (name == Char.name) + empty_hand if spell.num == 203 + cast_result = cast_spell.call(spell, name, 1) + if spell.num == 203 + if bread = [ GameObj.right_hand, GameObj.left_hand ].find { |obj| obj.noun =~ /^(?:flatbread|teacake|crisps|cake|waybread|biscuit|oatcake|fritter|loaf|ball|cornmeal|wheatberries|cracker|dumpling|bread|tart|dough|seeds)$/ } + if name == Char.name + 5.times { fput "eat ##{bread.id}" } + else + fput "drop ##{bread.id}" + end + end + fill_hand + break + end + if cast_result == :bad_spell + skip_spells.push(spell.num) + break + elsif cast_result == :bad_target + skip_targets.push(name) + break + else + did_cast = true + end + target_info[name][spell.num.to_s] += spell.time_per(:target => name) + break unless have_rapid end - target_info[name][spell.num.to_s] += spell.time_per(:target => name) + end + if need_chant and retribution_spell + fput "chant retribution #{retribution_spell}" end end - if need_chant and retribution_spell - fput "chant retribution #{retribution_spell}" - end - end + } + release_spell.call } - release_spell.call + break unless did_cast + break if have_rapid } # @@ -1058,6 +1173,7 @@ else target_info.keys.each { |name| next if spell.stackable?(:target => name) next unless spell.available?(:target => name) + next unless spell.time_per(:target => name) > short_spell_time next if skip_targets.include?(name) or skip_spells.include?(spell.num) next if (name == Char.name) and (spell.circlename == 'Bard') and spell.active? target_info[name][spell.num.to_s] ||= 0 @@ -1082,6 +1198,7 @@ else target_info.keys.each { |name| next if spell.stackable?(:target => name) or spell.refreshable?(:target => name) next unless spell.available?(:target => name) + next unless spell.time_per(:target => name) > short_spell_time next if (name == Char.name) and (spell.circlename == 'Bard') and spell.active? target_info[name][spell.num.to_s] ||= 0 unless target_info[name][spell.num.to_s] > 0 diff --git a/waitloot.lic b/waitloot.lic index bf4e2f8..faa9eef 100644 --- a/waitloot.lic +++ b/waitloot.lic @@ -4,10 +4,14 @@ meant for use with bigshot or another hunting script which expects a loot script to start and finish before it continues hunting. - tillmen@lichproject.org + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: loot + version: 0.1 + required: loot.lic =end start_script('loot') unless running?('loot') -10.times { break unless GameObj.npcs.any? { |npc| npc.status == 'dead' }; sleep 0.2 } -20.times { break unless $loot_working; waitrt?; sleep 0.2 } +10.times { break unless GameObj.npcs.any? { |npc| npc.status == 'dead' }; sleep 0.1 } +30.times { break unless $loot_working; waitrt?; sleep 0.2 } diff --git a/wander.lic b/wander.lic index dc34b1c..8de2bc8 100644 --- a/wander.lic +++ b/wander.lic @@ -1,75 +1,209 @@ =begin - This script replaces walk.lic + Moves around by selecting the adjacent room that was visited least recently. - Moves around randomly in any direction defined in the map database, trying not to backtrack. Stops in a room only if: there is a live, targetable npc in the room there are no characters in the room that aren't in your group there is no disk in the room that belongs to someone not in your group - Use ;wander add or ;wander del to set up boundaries and keep you in your hunting area. - Use ;wander to stop only for specific npcs. - use ;wander to stop only for targetable npcs. - tillmen@lichproject.org + Use ;wander add and + ;wander remove to set up boundaries to keep you in your hunting area. + Use ;wander delay to set the movement delay + Use ;wander to stop only for specific npcs. + Use ;wander to stop for another specific character. + Use ;wander to stop for any targetable npcs. -=end + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: movement + version: 0.8 + + changelog: + 0.8 (2015-04-29): + ignore pcs when wandering for loot + 0.7 (2015-04-13): + share confluence variables with map database + 0.6 (2015-04-11): + better wandering for the Elemental Confluence + 0.5 (2015-04-09): + fix searching for people + 0.4 (2015-04-05): + fix disk check + 0.3 (2015-03-05): + added support for the Elemental Confluence + 0.2 (2013-12-04): + added delay setting + allow adding/deleting multiple room ids at once -# fixme: add room titles to ;wander list +=end -CharSettings['boundary'] ||= Array.new +CharSettings['boundary'] ||= Array.new CharSettings['untargetable'] ||= Array.new -CharSettings['targetable'] ||= Array.new -$wander_rooms ||= Array.new +CharSettings['targetable'] ||= Array.new +CharSettings['delay'] ||= 1.0 +$wander_rooms ||= Array.new +$mapdb_confluence_wander ||= Array.new +dirs = [ 'north', 'northeast', 'east', 'southeast', 'south', 'southwest', 'west', 'northwest' ] +reverse_dir = { 'north' => 'south', 'northeast' => 'southwest', 'east' => 'west', 'southeast' => 'northwest', 'south' => 'north', 'southwest' => 'northeast', 'west' => 'east', 'northwest' => 'southeast' } +# fixme: room numbers are for Prime only +hot_confluence_rooms = [23282, 23283, 23284, 23285, 23286, 23287, 23288, 23289, 23290, 23291, 23292, 23293, 23294, 23295, 23296, 23297, 23298, 23299, 23300, 23301, 23302, 23303, 23329, 23330, 23331, 23332, 23333, 23334] +cold_confluence_rooms = [23304, 23305, 23306, 23307, 23308, 23309, 23310, 23311, 23312, 23313, 23314, 23315, 23316, 23317, 23318, 23319, 23320, 23321, 23322, 23323, 23324, 23325, 23326, 23327, 23328] wander = proc { - room = Room.current - next_room_options = room.wayto.keys - CharSettings['boundary'] - next_room_options.delete_if { |room_id| (room.timeto[room_id].class == Proc) and room.timeto[room_id].call.nil? } - next_room = next_room_options.find_all { |r| not $wander_rooms.include?(r) } - if next_room.empty? - next_room = $wander_rooms.find { |r| next_room_options.include?(r) } - else - next_room = next_room[rand(next_room.length)] - end - $wander_rooms.delete(next_room) - $wander_rooms.push(next_room) - way = room.wayto[next_room] - wait_while { ($loot_grab_list.length.to_i > 0) or $loot_working } - if way.class == String - move(way) + if (checkroom == '[Elemental Confluence]') and (XMLData.game == 'GSIV') + $mapdb_confluence_wayto ||= Hash.new + 1.times { + start_room = Room.current + if $mapdb_confluence_wayto[start_room.id].nil? + redo if Room.current != start_room + $mapdb_confluence_wayto[start_room.id] = Hash.new + XMLData.room_exits.each { |d| $mapdb_confluence_wayto[start_room.id][d] = nil } + end + if ($mapdb_confluence_wayto[start_room.id].keys != XMLData.room_exits) + redo if Room.current != start_room + $mapdb_confluence_wayto = Hash.new + redo + end + dir = $mapdb_confluence_wayto[start_room.id].keys.find { |d| $mapdb_confluence_wayto[start_room.id][d].nil? } + if dir.nil? + dir = $mapdb_confluence_wayto[start_room.id].keys.find { |d| not $mapdb_confluence_wander.include?($mapdb_confluence_wayto[start_room.id][d]) } + end + if dir.nil? + next_id = $mapdb_confluence_wander.find { |i| $mapdb_confluence_wayto[start_room.id].values.include?(i) } + dir = $mapdb_confluence_wayto[start_room.id].keys.find { |d| $mapdb_confluence_wayto[start_room.id][d] == next_id } + end + if dir.nil? + dir = XMLData.room_exits[rand(XMLData.room_exits.length)] + end + r = move dir.dup + if r == false + # maze probably changed and XMLData.room_exits is wrong + status_tags + result = dothistimeout 'look', 5, // + status_tags + options = result.scan(// + status_tags + options = result.scan(/ 0) or $loot_working } + if way.class == String + move(way) + else + way.call + end end } if script.vars[1] =~ /help/i - respond - respond ';wander add adds the current room to the boundary list' - respond ';wander add adds the given room id to the boundary list' - respond ';wander del deletes the current room to the boundary list' - respond ';wander del deletes the given room id to the boundary list' - respond ';wander clear clears the boundary list and npc info' - respond ';wander list shows saved boundaries and npc info' - respond ';wander wanders around, stopping only for the given npcs' - respond ';wander wanders around, stopping only for targetable npcs' - respond + output = "\n" + output.concat ";wander add adds the current room to the boundary list\n" + output.concat ";wander add adds the given room id to the boundary list\n" + output.concat ";wander rem deletes the current room to the boundary list\n" + output.concat ";wander rem deletes the given room id to the boundary list\n" + output.concat ";wander clear clears the boundary list and npc info\n" + output.concat ";wander delay sets the delay before moving to the next room\n" + output.concat ";wander list shows saved boundaries and npc info\n" + output.concat ";wander wanders around, stopping only for the given npcs\n" + output.concat ";wander wanders around, stopping only for targetable npcs\n" + output.concat "\n" + respond output elsif script.vars[1] =~ /^add$|^set$/i - if script.vars[2] and script.vars[2] =~ /^[0-9]+$/ - CharSettings['boundary'].push(script.vars[2]) - echo "room #{script.vars[2]} has been added to the boundary list" + if script.vars[2] + for var in script.vars[2..-1] + if var =~ /^[0-9]+$/ + CharSettings['boundary'].push(var) + echo "room #{var} has been added to the boundary list" + else + echo "ignoring #{var}: not a room id" + end + end elsif room = Room.current CharSettings['boundary'].push(room.id.to_s) echo "this room (#{room.id}) has been added to the boundary list" else - echo 'current room is uknown' + echo 'error: current room is uknown' end elsif script.vars[1] =~ /^del(?:ete)?$|^rem(?:ove)?$/i - if script.vars[2] and script.vars[2] =~ /^[0-9]+$/ - if CharSettings['boundary'].delete(script.vars[2]) - echo "room #{script.vars[2]} has been removed from the boundary list" - else - echo "room #{script.vars[2]} was not found in the boundary list" + if script.vars[2] + for var in script.vars[2..-1] + if var =~ /^[0-9]+$/ + if CharSettings['boundary'].delete(var) + echo "room #{var} has been removed from the boundary list" + else + echo "room #{var} was not found in the boundary list" + end + else + echo "ignoring #{var}: not a room id" + end end elsif room = Room.current if CharSettings['boundary'].delete(room.id.to_s) @@ -80,26 +214,33 @@ elsif script.vars[1] =~ /^del(?:ete)?$|^rem(?:ove)?$/i else echo 'current room is uknown' end +elsif (script.vars[1] =~ /^delay$/i) and (script.vars[2] =~ /^[0-9\.]+$/) + CharSettings['delay'] = script.vars[2].to_f + echo "movement delay is now #{CharSettings['delay']}" elsif script.vars[1] =~ /^list$/i - respond + output = "\n" if CharSettings['boundary'].empty? - respond ' boundaries: none' + output.concat " boundaries: none\n" else - respond " boundaries: #{CharSettings['boundary'].join(', ')}" + output.concat " boundaries:\n" + for boundary in CharSettings['boundary'] + output.concat " #{boundary.to_s.rjust(5)} #{Room[boundary].title.first}\n" + end end - respond + output.concat "\n" if CharSettings['targetable'].empty? - respond ' targetable npcs: none' + output.concat " targetable npcs: none\n" else - respond " targetable npcs: #{CharSettings['targetable'].join(', ')}" + output.concat " targetable npcs: #{CharSettings['targetable'].join(', ')}\n" end - respond + output.concat "\n" if CharSettings['untargetable'].empty? - respond 'untargetable npcs: none' + output.concat " untargetable npcs: none\n" else - respond "untargetable npcs: #{CharSettings['untargetable'].join(', ')}" + output.concat " untargetable npcs: #{CharSettings['untargetable'].join(', ')}\n" end - respond + output.concat "\n" + respond output elsif script.vars[1] =~ /^clear$/i CharSettings['boundary'] = Array.new CharSettings['untargetable'] = Array.new @@ -109,64 +250,45 @@ elsif script.vars.empty? loop { group = checkpcs.to_a wander.call - sleep 0.3 - # - # keep moving if there are people besides your group in the room - # - next unless (checkpcs.to_a - group).empty? - # - # keep moving if there's a disk that doesn't belong to your group - # - next if GameObj.loot.find { |obj| (obj.noun == 'disk') and (obj.name !~ /#{group.join('|')}/) } - # - # keep moving if there's no decent npcs in the room - # + group = group & checkpcs.to_a + group.push(Char.name) start_npcs = npcs = GameObj.npcs - npcs.delete_if { |npc| (npc.status == 'dead') or CharSettings['untargetable'].include?(npc.name) } - next if npcs.nil? or npcs.empty? - # - # stop if there's an npc that's known to be targetable - # - break if npcs.find { |npc| CharSettings['targetable'].include?(npc.name) } - sleep 0.1 - # - # check to see if there's an npc in the room that's targetable - # - clear - target_result = dothistimeout 'target random', 5, /^Could not find a valid target\.$|^You are now targeting/ - if target_result =~ /^You are now targeting \w+ (.*)\.$/ - target = $1 - CharSettings['targetable'].push(target) unless CharSettings['targetable'].include?(target) + npcs.delete_if { |npc| (npc.status =~ /dead/) or CharSettings['untargetable'].include?(npc.name) } + if ((checkpcs.to_a - group).length > 0) or GameObj.loot.find { |obj| (obj.noun == 'disk') and (obj.name !~ /#{group.join('|')}/) } or npcs.nil? or npcs.empty? + sleep CharSettings['delay'] + elsif npcs.any? { |npc| CharSettings['targetable'].include?(npc.name) } break - elsif target_result == 'Could not find a valid target.' - if GameObj.npcs == start_npcs - npcs.each { |npc| CharSettings['untargetable'].push(npc.name) unless CharSettings['untargetable'].include?(npc.name) } + else + clear + target_result = dothistimeout 'target random', 5, /^Could not find a valid target\.$|^You are now targeting/ + if target_result =~ /^You are now targeting \w+ (.*)\.$/ + target = $1 + CharSettings['targetable'].push(target) unless CharSettings['targetable'].include?(target) + break + elsif target_result == 'Could not find a valid target.' + if GameObj.npcs == start_npcs + npcs.each { |npc| CharSettings['untargetable'].push(npc.name) unless CharSettings['untargetable'].include?(npc.name) } + end + sleep CharSettings['delay'] end - next end - break } else - group = checkpcs.to_a loop { + group = checkpcs.to_a wander.call -# sleep 0.1 - # - # remove names from the group list if they didn't follow you - # group = group & checkpcs.to_a - # - # keep moving if there are people besides your group in the room - # - next unless (checkpcs.to_a - group).empty? - # - # keep moving if there's a disk that doesn't belong to your group - # - next if GameObj.loot.find { |obj| (obj.noun == 'disk') and (obj.name !~ /#{group.join('|')}/) } - # - # stop if a given npc is in the room - # - break if GameObj.npcs.any? { |npc| (npc.status != 'dead') and npc.name =~ /#{script.vars[1..-1].join('|')}/ } - break if GameObj.pcs.any? { |pc| pc.noun =~ /#{script.vars[1..-1].join('|')}/i } + group.push(Char.name) + if GameObj.pcs.any? { |pc| pc.noun =~ /#{script.vars[1..-1].join('|')}/i } + break + elsif GameObj.loot.any? { |loot| loot.name =~ /#{script.vars[1..-1].join('|')}/ } + break + elsif ((checkpcs.to_a - group).length > 0) or GameObj.loot.find { |obj| (obj.noun == 'disk') and (obj.name !~ /#{group.join('|')}/) } + sleep CharSettings['delay'] + elsif GameObj.npcs.any? { |npc| (npc.status != 'dead') and npc.name =~ /#{script.vars[1..-1].join('|')}/ } + break + else + sleep CharSettings['delay'] + end } end diff --git a/wiz_to_lich.lic b/wiz_to_lich.lic index daa799c..381c5dd 100644 --- a/wiz_to_lich.lic +++ b/wiz_to_lich.lic @@ -2,13 +2,27 @@ This here thing here tries to turn Wizard and Stormfront scripts into Lich scripts. - tillmen@lichproject.org + Place the script in your Lich script directory and do ";wiz_to_lich scriptname.cmd" + and it will create scriptname.lic. + + author: Tillmen (tillmen@lichproject.org) + game: any + tags: core + version: 0.2 + required: Lich >= 4.6.0 + + changelog: + 0.2 (2015-11-06): + don't kill the converted script when it starts a Lich script =end -#fixme: SF scripts starting Lich scripts +unless $SAFE == 0 + echo "this script must be trusted to work (;trust #{script.name})" + exit +end -unless script.vars[1] and script.vars[1] !~ /^help$/i +if script.vars[1].nil? or (script.vars[1] =~ /^help$/i) respond respond "Usage: ;wiz_to_lich " respond @@ -31,11 +45,7 @@ if File.exists?(out_file_name) exit end -file = File.open(file_name) -lines = file.readlines.collect { |line| line.chomp } -file.close -file = nil - +input_lines = File.open(file_name) { |f| f.readlines }.collect { |l| l.chomp } counter_action = { 'add' => '+', @@ -47,27 +57,26 @@ counter_action = { } setvars = Array.new -lines.each { |line| -begin -# respond line.inspect - setvars.push($1) if line =~ /[\s\t]*setvariable\s+([^\s\t]+)[\s\t]/i and not setvars.include?($1) -rescue - respond $! - respond $!.backtrace[0..1] - respond line.inspect - exit -end +input_lines.each { |line| + begin + # respond line.inspect + setvars.push($1) if line =~ /[\s\t]*setvariable\s+([^\s\t]+)[\s\t]/i and not setvars.include?($1) + rescue + respond $! + respond $!.backtrace[0..1] + respond line.inspect + exit + end } -has_counter = lines.find { |line| line =~ /%c/i } -has_save = lines.find { |line| line =~ /%s/i } -has_nextroom = lines.find { |line| line =~ /nextroom/i } +has_counter = input_lines.find { |line| line =~ /%c/i } +has_nextroom = input_lines.find { |line| line =~ /nextroom/i } fixstring = proc { |str| - while not setvars.empty? and str =~ /%(#{setvars.join('|')})%/io + while not setvars.empty? and (str =~ /%(#{setvars.join('|')})%/io) str.gsub!('%' + $1 + '%', '#{' + $1.downcase + '}') end str.gsub!(/%c(?:%)?/i, '#{c}') - str.gsub!(/%s(?:%)?/i, '#{sav}') + str.gsub!(/%s(?:%)?/i, '#{Settings[\'sav\']}') while str =~ /%([0-9])(?:%)?/ str.gsub!(/%#{$1}(?:%)?/, '#{script.vars[' + $1 + ']}') end @@ -84,19 +93,33 @@ fixline = proc { |line| line = "#{indent}c #{counter_action[action]}= #{fixstring.call(arg.inspect)}.to_i" elsif line =~ /^([\s\t]*)save[\s\t]+"?(.*?)"?[\s\t]*$/i indent, arg = $1, $2 - line = "#{indent}sav = #{fixstring.call(arg.inspect)}" + line = "#{indent}Settings['sav'] = #{fixstring.call(arg.inspect)}" elsif line =~ /^([\s\t]*)echo[\s\t]+(.+)/i indent, arg = $1, $2 line = "#{indent}echo #{fixstring.call(arg.inspect)}" elsif line =~ /^([\s\t]*)waitfor[\s\t]+(.+)/i indent, arg = $1, $2 line = "#{indent}waitfor #{fixstring.call(Regexp.escape(arg).inspect.gsub("\\\\ ", ' '))}" + elsif line =~ /^([\s\t]*)put[\s\t]+\.(.+)$/i + indent, arg = $1, $2 + if arg.include?(' ') + line = "#{indent}Script.start(#{fixstring.call(arg.slice(/^[^\s]+/).inspect)}, #{fixstring.call(arg.sub(/^[^\s]+\s+/,'').inspect)})\n#{indent}exit" + else + line = "#{indent}Script.start(#{fixstring.call(arg.inspect)})\n#{indent}exit" + end + elsif line =~ /^([\s\t]*)put[\s\t]+;(.+)$/i + indent, arg = $1, $2 + if arg.include?(' ') + line = "#{indent}Script.start(#{fixstring.call(arg.slice(/^[^\s]+/).inspect)}, #{fixstring.call(arg.sub(/^[^\s]+\s+/,'').inspect)})" + else + line = "#{indent}Script.start(#{fixstring.call(arg.inspect)})" + end elsif line =~ /^([\s\t]*)(put|move)[\s\t]+(.+)/i indent, cmd, arg = $1, $2, $3 line = "#{indent}waitrt?\n#{indent}clear\n#{indent}#{cmd.downcase} #{fixstring.call(arg.inspect)}" elsif line =~ /^([\s\t]*)goto[\s\t]+(.+)/i indent, arg = $1, $2 - line = "#{indent}goto #{fixstring.call(arg.inspect).downcase}" + line = "#{indent}goto #{fixstring.call(arg.downcase.inspect)}" elsif line =~ /^([\s\t]*)waitforre[\s\t]+(.+)/i indent, arg = $1, $2 line = "#{indent}waitforre #{arg}" @@ -107,16 +130,18 @@ fixline = proc { |line| line = "#{indent}pause #{arg}" elsif line =~ /^([\s\t]*)match[\s\t]+([^\s\t]+)[\s\t]+(.+)/i indent, label, arg = $1, $2, $3 - line = "#{indent}match #{fixstring.call(label.inspect).downcase}, #{fixstring.call(Regexp.escape(arg).inspect.gsub("\\\\ ", ' '))}" + line = "#{indent}match #{fixstring.call(label.downcase.inspect)}, #{fixstring.call(Regexp.escape(arg).inspect.gsub("\\\\ ", ' '))}" elsif line =~ /^([\s\t]*)matchre[\s\t]+([^\s\t]+)[\s\t]+(.+)/i indent, label, regex = $1, $2, $3 - line = "#{indent}matchre #{fixstring.call(label.inspect).downcase}, #{regex}" + line = "#{indent}matchre #{fixstring.call(label.downcase.inspect)}, #{regex}" elsif line =~ /^([\s\t]*)setvariable[\s\t]+([^\s\t]+)[\s\t]+(.+)/i indent, var, arg = $1, $2, $3 line = "#{indent}#{var.downcase} = #{fixstring.call(arg.inspect)}" elsif line =~ /^([\s\t]*)deletevariable[\s\t]+(.+)/i line = "#{$1}#{$2.downcase} = nil" - elsif line =~ /^([\s\t]*)(wait|nextroom|exit|echo)\b/i + elsif line =~ /^([\s\t]*)nextroom\b/i + line = "#{$1}nextroom.call" + elsif line =~ /^([\s\t]*)(wait|exit|echo)\b/i line = "#{$1}#{$2.downcase}" elsif line =~ /^([\s\t]*)matchwait\b/i line = "#{$1}matchwait" @@ -133,46 +158,42 @@ fixline = proc { |line| lich_block = false -lines.each_index { |idx| +input_lines.each_index { |idx| if lich_block - if lines[idx] =~ /\}[\s\t]*LICH[\s\t]*$/ - lines[idx] = lines[idx].sub(/\}[\s\t]*LICH[\s\t]*$/, '') + if input_lines[idx] =~ /\}[\s\t]*LICH[\s\t]*$/ + input_lines[idx] = input_lines[idx].sub(/\}[\s\t]*LICH[\s\t]*$/, '') lich_block = false else next end - elsif lines[idx] =~ /^[\s\t]*#|^[\s\t]*$/ + elsif input_lines[idx] =~ /^[\s\t]*#|^[\s\t]*$/ next - elsif lines[idx] =~ /^[\s\t]*LICH[\s\t]*\{/ - lines[idx] = lines[idx].sub(/LICH[\s\t]*\{/, '') - if lines[idx] =~ /\}[\s\t]*LICH[\s\t]*$/ - lines[idx] = lines[idx].sub(/\}[\s\t]*LICH[\s\t]*$/, '') + elsif input_lines[idx] =~ /^[\s\t]*LICH[\s\t]*\{/ + input_lines[idx] = input_lines[idx].sub(/LICH[\s\t]*\{/, '') + if input_lines[idx] =~ /\}[\s\t]*LICH[\s\t]*$/ + input_lines[idx] = input_lines[idx].sub(/\}[\s\t]*LICH[\s\t]*$/, '') else lich_block = true end else - lines[idx] = fixline.call(lines[idx]) + input_lines[idx] = fixline.call(input_lines[idx]) end } -if has_counter or has_save or has_nextroom - lines.each_index { |idx| - next if lines[idx] =~ /^[\s\t]*#/ - lines.insert(idx, '') +if has_counter or has_nextroom + input_lines.each_index { |idx| + next if input_lines[idx] =~ /^[\s\t]*#/ + input_lines.insert(idx, '') if has_counter - lines.insert(idx, 'c = 0') - end - if has_save - lines.insert(idx, "before_dying { Settings['sav'] = sav; Settings.save }") - lines.insert(idx, "sav = Settings['sav'] || String.new") - lines.insert(idx, "Settings.load") + input_lines.insert(idx, 'c = 0') end if has_nextroom - lines.insert(idx, "def nextroom\n\troom_count = XMLData.room_count\n\twait_while { room_count == XMLData.room_count }\nend") + input_lines.insert(idx, "nextroom = proc { room_count = XMLData.room_count; wait_while { room_count == XMLData.room_count } }") end - lines.insert(idx, '') + input_lines.insert(idx, '') break } end -File.open(out_file_name, 'w') { |f| f.write(lines.join("\n") + "\n") } +File.open(out_file_name, 'w') { |f| f.write input_lines.join("\n").concat("\n") } +echo 'done' diff --git a/xp.lic b/xp.lic index 5e602c0..d5e5369 100644 --- a/xp.lic +++ b/xp.lic @@ -1,190 +1,391 @@ #quiet =begin - This script sends "experience" to the game, and in the results adds the total and average experience and fame gained since the first and last check. + This script sends the experience verb to the game and adds info to the results, including + experience and fame gained since first use, first use this login, and last use; average + rate of gain for those time periods, and time until next level/points and arbitrary goal + at those rates. - tillmen@lichproject.org + ;xp help -=end + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + version: 0.6 + tags: cosmetic -silence_me + changelog: + 0.6 (2014-12-12): + fix time since last use + 0.5 (2014-12-10): + fix table spacing + 0.4 (2014-12-10): + fix typo + 0.3 (2014-12-10): + fix bug with ;xp reset + 0.2 (2014-12-10): + add realtime tracking + reformat output -if script.vars[1] =~ /^clear$/i - $xp = {} - respond "Your experience tracking has been reset." - exit -elsif script.vars[1] =~ /^setgoal$/i - xp_goal = script.vars[2].to_i - CharSettings['goal'] = xp_goal - echo 'Goal set to: ' + xp_goal.to_s - exit -elsif script.vars[1] =~ /realtime/ - CharSettings['realtime'] = :start - echo 'blah' +=end + +if script.vars[1] + if script.vars[1].downcase == 'reset' + $xp = nil + if script.vars[2].downcase == 'all' + CharSettings['realtime'] = nil + end + echo "Experience tracking has been reset." + elsif (script.vars[1].downcase == 'goal') and (script.vars[2] =~ /^[0-9]+$/) + CharSettings['goal'] = script.vars[2].to_i + echo "Experience goal set to #{CharSettings['goal']}." + else + output = "\n" + output.concat "usage:\n" + output.concat "\n" + output.concat " #{$clean_lich_char}#{script.name} show experience with extra info\n" + output.concat " #{$clean_lich_char}#{script.name} reset reset experience tracking since login\n" + output.concat " #{$clean_lich_char}#{script.name} reset all reset all experience tracking\n" + output.concat " #{$clean_lich_char}#{script.name} goal set a goal to show time until\n" + output.concat "\n" + respond output + end exit end -xp_goal = CharSettings['goal'] -xp_now = {} -xp_until_next = 0 -capped = false +CharSettings['goal'] ||= 0 +now = Hash.new +xp_until_next = 0 +time_since_max_width = Hash.new +time_until_next_max_width = Hash.new +time_until_goal_max_width = Hash.new + +add_commas = proc { |num| + num.to_s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse +} + +calc_seconds = proc { |foo| + seconds = foo % 60 + foo = (foo - seconds) / 60 + minutes = foo % 60 + foo = (foo - minutes) / 60 + hours = foo % 24 + days = (foo - hours) / 24 + [days, hours, minutes, seconds] +} + +format_time_since = proc { |foo| + time = calc_seconds.call(foo) + list = Array.new + if time[0] > 0 + list.push "#{time[0].to_s.rjust(time_since_max_width['days'])}d" + elsif time_since_max_width['days'] > 0 + list.push ''.rjust(time_since_max_width['days'] + 1) + end + if time[1] > 0 + list.push "#{time[1].to_s.rjust(time_since_max_width['hours'])}h" + elsif time_since_max_width['hours'] > 0 + list.push ''.rjust(time_since_max_width['hours'] + 1) + end + if time[2] > 0 + list.push "#{time[2].to_s.rjust(time_since_max_width['minutes'])}m" + elsif time_since_max_width['minutes'] > 0 + list.push ''.rjust(time_since_max_width['minutes'] + 1) + end + if time[3] > 0 + list.push "#{time[3].to_s.rjust(time_since_max_width['seconds'])}s" + elsif time_since_max_width['seconds'] > 0 + list.push ''.rjust(time_since_max_width['seconds'] + 1) + end + list.join(' ') +} + +format_time_until_next = proc { |time| + list = Array.new + if time[0] > 0 + list.push "#{time[0].to_s.rjust(time_until_next_max_width['days'])}d" + elsif time_until_next_max_width['days'] > 0 + list.push ''.rjust(time_until_next_max_width['days'] + 1) + end + if time[1] > 0 + list.push "#{time[1].to_s.rjust(time_until_next_max_width['hours'])}h" + elsif time_until_next_max_width['hours'] > 0 + list.push ''.rjust(time_until_next_max_width['hours'] + 1) + end + if time[2] > 0 + list.push "#{time[2].to_s.rjust(time_until_next_max_width['minutes'])}m" + elsif time_until_next_max_width['minutes'] > 0 + list.push ''.rjust(time_until_next_max_width['minutes'] + 1) + end + if time[3] > 0 + list.push "#{time[3].to_s.rjust(time_until_next_max_width['seconds'])}s" + elsif time_until_next_max_width['seconds'] > 0 + list.push ''.rjust(time_until_next_max_width['seconds'] + 1) + end + list.join(' ') +} + +format_time_until_goal = proc { |time| + list = Array.new + if time[0] > 0 + list.push "#{time[0].to_s.rjust(time_until_goal_max_width['days'])}d" + elsif time_until_goal_max_width['days'] > 0 + list.push ''.rjust(time_until_goal_max_width['days'] + 1) + end + if time[1] > 0 + list.push "#{time[1].to_s.rjust(time_until_goal_max_width['hours'])}h" + elsif time_until_goal_max_width['hours'] > 0 + list.push ''.rjust(time_until_goal_max_width['hours'] + 1) + end + if time[2] > 0 + list.push "#{time[2].to_s.rjust(time_until_goal_max_width['minutes'])}m" + elsif time_until_goal_max_width['minutes'] > 0 + list.push ''.rjust(time_until_goal_max_width['minutes'] + 1) + end + if time[3] > 0 + list.push "#{time[3].to_s.rjust(time_until_goal_max_width['seconds'])}s" + elsif time_until_goal_max_width['seconds'] > 0 + list.push ''.rjust(time_until_goal_max_width['seconds'] + 1) + end + list.join(' ') +} + clear -fput "experience" -loop { - line = get +silence_me +put "experience" + +while (line = get) if line =~ /^\s+Experience: ([0-9]+)/ - xp_now['exp'] = $1.to_i - elsif line =~ /^Exp\. until next: (\-?[0-9]+)/ + now['exp'] = $1.to_i + elsif line =~ /^Exp\. (?:until next|to next TP): (\-?[0-9]+)/ xp_until_next = $1.to_i - capped = false - elsif line =~ /^Exp\. to next TP: (\-?[0-9]+)/ - xp_until_next = $1.to_i - capped = true elsif line =~ /^\s+Mental TPs: [0-9]+\s+Fame: ([0-9]+)/ - xp_now['fame'] = $1.to_i + now['fame'] = $1.to_i elsif line =~ /Mana/ break end -} -xp_now['time'] = Time.now.to_i -if CharSettings['realtime'] == :start - CharSettings['realtime'] = Hash.new - CharSettings['realtime']['time'] = Time.now.to_i - CharSettings['realtime']['exp'] = xp_now['exp'] - CharSettings['realtime']['fame'] = xp_now['fame'] end -unless $xp['first'] +now['time'] = Time.now.to_i + +unless $xp $xp = {} - $xp['first'] = xp_now - $xp['last'] = xp_now - respond 'No information to show you yet. Try again later.' + $xp['first'] = now + $xp['last'] = now + echo 'no information yet' exit end -unless (xp_now['exp'] - $xp['first']['exp']) > 0 - respond 'No information to show you yet. Try again later.' + +unless CharSettings['realtime'] + CharSettings['realtime'] = Hash.new + CharSettings['realtime']['time'] = now['time'] + CharSettings['realtime']['exp'] = now['exp'] + CharSettings['realtime']['fame'] = now['fame'] +end + +unless (now['exp'] - $xp['first']['exp']) > 0 + echo 'no information yet' exit end -if CharSettings['realtime'] - seconds_since_realtime = Time.now.to_i - CharSettings['realtime']['time'] - xp_since_realtime = xp_now['exp'] - CharSettings['realtime']['exp'] - if xp_since_realtime == 0 - xp_since_realtime_avg = 0 - else - xp_since_realtime_avg = (xp_since_realtime * (3600 / seconds_since_realtime.to_f)).to_i.round +secs_since_realtime = Time.now.to_i - CharSettings['realtime']['time'] +time_since_realtime = calc_seconds.call(secs_since_realtime) + xp_since_realtime = now['exp'] - CharSettings['realtime']['exp'] + xp_since_realtime_avg = (xp_since_realtime * (3600 / secs_since_realtime.to_f)).to_i.round +fame_since_realtime = now['fame'] - CharSettings['realtime']['fame'] +fame_since_realtime_avg = (fame_since_realtime * (3600 / secs_since_realtime.to_f)).to_i.round + +secs_since_first = now['time'] - $xp['first']['time'] +time_since_first = calc_seconds.call(secs_since_first) + xp_since_first = now['exp'] - $xp['first']['exp'] + xp_since_first_avg = (xp_since_first * (3600 / secs_since_first.to_f)).to_i.round +fame_since_first = now['fame'] - $xp['first']['fame'] +fame_since_first_avg = (fame_since_first * (3600 / secs_since_first.to_f)).to_i.round + +secs_since_last = now['time'] - $xp['last']['time'] +time_since_last = calc_seconds.call(secs_since_last) + xp_since_last = now['exp'] - $xp['last']['exp'] + xp_since_last_avg = (xp_since_last * (3600 / secs_since_last.to_f)).to_i.round +fame_since_last = now['fame'] - $xp['last']['fame'] +fame_since_last_avg = (fame_since_last * (3600 / secs_since_last.to_f)).to_i.round + +for time in [ time_since_realtime, time_since_first, time_since_last ] + time_since_max_width['days'] = [ time_since_max_width['days'].to_i, (time[0] > 0 ? time[0].to_s.length : 0) ].max + time_since_max_width['hours'] = [ time_since_max_width['hours'].to_i, (time[1] > 0 ? time[1].to_s.length : 0) ].max + time_since_max_width['minutes'] = [ time_since_max_width['minutes'].to_i, (time[2] > 0 ? time[2].to_s.length : 0) ].max + time_since_max_width['seconds'] = [ time_since_max_width['seconds'].to_i, (time[3] > 0 ? time[3].to_s.length : 0) ].max +end +time_since_label_width = [ (time_since_max_width['days'] + time_since_max_width['minutes'] + time_since_max_width['hours'] + time_since_max_width['seconds'] + ([ time_since_max_width['days'], time_since_max_width['minutes'], time_since_max_width['hours'], time_since_max_width['seconds'] ].count { |i| i > 0 } * 2) - 1), 10 ].max + +begin + time_until_next_realtime = calc_seconds.call((xp_until_next / (xp_since_realtime / secs_since_realtime.to_f)).to_i) +rescue + time_until_next_realtime = nil +end +begin + time_until_next_first = calc_seconds.call((xp_until_next / (xp_since_first / secs_since_first.to_f)).to_i) +rescue + time_until_next_first = nil +end +begin + time_until_next_last = calc_seconds.call((xp_until_next / (xp_since_last / secs_since_last.to_f)).to_i) +rescue + time_until_next_last = nil +end + +for time in [ time_until_next_realtime, time_until_next_first, time_until_next_last ] + time_until_next_max_width['days'] = [ time_until_next_max_width['days'].to_i, (time[0] > 0 ? time[0].to_s.length : 0) ].max + time_until_next_max_width['hours'] = [ time_until_next_max_width['hours'].to_i, (time[1] > 0 ? time[1].to_s.length : 0) ].max + time_until_next_max_width['minutes'] = [ time_until_next_max_width['minutes'].to_i, (time[2] > 0 ? time[2].to_s.length : 0) ].max + time_until_next_max_width['seconds'] = [ time_until_next_max_width['seconds'].to_i, (time[3] > 0 ? time[3].to_s.length : 0) ].max +end +time_until_next_label_width = [ (time_until_next_max_width['days'] + time_until_next_max_width['minutes'] + time_until_next_max_width['hours'] + time_until_next_max_width['seconds'] + ([ time_until_next_max_width['days'], time_until_next_max_width['minutes'], time_until_next_max_width['hours'], time_until_next_max_width['seconds'] ].count { |i| i > 0 } * 2) - 1), 10 ].max + +xp_until_goal = CharSettings['goal'] - now['exp'] + +if xp_until_goal > 0 + begin + time_until_goal_realtime = calc_seconds.call((xp_until_goal / (xp_since_realtime / secs_since_realtime.to_f)).to_i) + rescue + time_until_goal_realtime = nil end - fame_since_realtime = xp_now['fame'] - CharSettings['realtime']['fame'] - if fame_since_realtime == 0 - fame_since_realtime_avg = 0 - else - fame_since_realtime_avg = (fame_since_realtime * (3600 / seconds_since_realtime.to_f)).to_i.round - end -end - -seconds_since_first = xp_now['time'] - $xp['first']['time'] -xp_since_first = xp_now['exp'] - $xp['first']['exp'] -xp_since_first_avg = (xp_since_first * (3600 / seconds_since_first.to_f)).to_i.round -fame_since_first = xp_now['fame'] - $xp['first']['fame'] -fame_since_first_avg = (fame_since_first * (3600 / seconds_since_first.to_f)).to_i.round - -seconds_since_last = xp_now['time'] - $xp['last']['time'] -xp_since_last = xp_now['exp'] - $xp['last']['exp'] -xp_since_last_avg = (xp_since_last * (3600 / seconds_since_last.to_f)).to_i.round -fame_since_last = xp_now['fame'] - $xp['last']['fame'] -fame_since_last_avg = (fame_since_last * (3600 / seconds_since_last.to_f)).to_i.round - -xp_until_goal = xp_goal - xp_now['exp'] - -format_hours_until = proc { |hours_until| - difference = (hours_until * 3600).to_i - seconds = difference % 60 - difference = (difference - seconds) / 60 - minutes = difference % 60 - difference = (difference - minutes) / 60 - hours = difference % 24 - days = (difference - hours) / 24 - temp = Array.new - temp.push "#{days} day#{'s' unless days == 1}" if days > 0 - temp.push "#{hours} hour#{'s' unless hours == 1}" if hours > 0 - temp.push "#{minutes} minute#{'s' unless minutes == 1}" if minutes > 0 - temp.push "#{seconds} second#{'s' unless seconds == 1}" if (seconds > 0) and (days == 0) - temp.join(', ') -} + begin + time_until_goal_first = calc_seconds.call((xp_until_goal / (xp_since_first / secs_since_first.to_f)).to_i) + rescue + time_until_goal_first = nil + end + begin + time_until_goal_last = calc_seconds.call((xp_until_goal / (xp_since_last / secs_since_last.to_f)).to_i) + rescue + time_until_goal_last = nil + end + + for time in [ time_since_realtime, time_since_first, time_since_last ] + time_until_goal_max_width['days'] = [ time_until_goal_max_width['days'].to_i, (time[0] > 0 ? time[0].to_s.length : 0) ].max + time_until_goal_max_width['hours'] = [ time_until_goal_max_width['hours'].to_i, (time[1] > 0 ? time[1].to_s.length : 0) ].max + time_until_goal_max_width['minutes'] = [ time_until_goal_max_width['minutes'].to_i, (time[2] > 0 ? time[2].to_s.length : 0) ].max + time_until_goal_max_width['seconds'] = [ time_until_goal_max_width['seconds'].to_i, (time[3] > 0 ? time[3].to_s.length : 0) ].max + end + time_until_goal_label_width = [ (time_until_goal_max_width['days'] + time_until_goal_max_width['minutes'] + time_until_goal_max_width['hours'] + time_until_goal_max_width['seconds'] + ([ time_until_goal_max_width['days'], time_until_goal_max_width['minutes'], time_until_goal_max_width['hours'], time_until_goal_max_width['seconds'] ].count { |i| i > 0 } * 2) - 1), 10 ].max + +end + +exp_width = [ add_commas.call(xp_since_realtime).length, add_commas.call(xp_since_first).length, add_commas.call(xp_since_last).length, 4 ].max +avg_exp_width = [ add_commas.call(xp_since_realtime_avg).length, add_commas.call(xp_since_first_avg).length, add_commas.call(xp_since_last_avg).length, 6 ].max +fame_width = [ add_commas.call(fame_since_realtime).length, add_commas.call(fame_since_first).length, add_commas.call(fame_since_last).length, 4 ].max +avg_fame_width = [ add_commas.call(fame_since_realtime_avg).length, add_commas.call(fame_since_first_avg).length, add_commas.call(fame_since_last_avg).length, 6 ].max + +output = "\n" +output.concat ' gain'.rjust(time_since_label_width/2) +output.concat 'ed in'.ljust((time_since_label_width/2.0).ceil) +output.concat ' ' +output.concat ' e'.rjust(exp_width/2) +output.concat 'xp'.ljust((exp_width/2.0).ceil) +output.concat ' ' +output.concat ' av'.rjust(avg_exp_width/2) +output.concat 'g/h'.ljust((avg_exp_width/2.0).ceil) +output.concat ' ' +if Vars.xp_ignore_fame != 'yes' + output.concat 'fa'.rjust(fame_width/2) + output.concat 'me'.ljust((fame_width/2.0).ceil) + output.concat ' ' + output.concat ' av'.rjust(avg_exp_width/2) + output.concat 'g/h'.ljust((avg_exp_width/2.0).ceil) + output.concat ' ' +end +output.concat 'until'.rjust(time_until_next_label_width/2) +output.concat ' next'.ljust((time_until_next_label_width/2.0).ceil) +if xp_until_goal > 0 + output.concat ' ' + output.concat 'until'.rjust(time_until_goal_label_width/2) + output.concat ' goal'.ljust((time_until_goal_label_width/2.0).ceil) +end +output.concat "\n" + +output.concat ''.rjust(time_since_label_width, '-') +output.concat ' ' +output.concat ''.rjust(exp_width, '-') +output.concat ' ' +output.concat ''.rjust(avg_exp_width, '-') +output.concat ' ' +if Vars.xp_ignore_fame != 'yes' + output.concat ''.rjust(fame_width, '-') + output.concat ' ' + output.concat ''.rjust(avg_fame_width, '-') + output.concat ' ' +end +output.concat ''.rjust(time_until_next_label_width, '-') +if xp_until_goal > 0 + output.concat ' ' + output.concat ''.rjust(time_until_goal_label_width, '-') +end +output.concat "\n" -if xp_until_next > 0 - hours_until_next = xp_until_next / xp_since_first_avg.to_f - difference = (hours_until_next * 3600).to_i - seconds = difference % 60 - difference = (difference - seconds) / 60 - minutes = difference % 60 - difference = (difference - minutes) / 60 - hours = difference % 24 - days = (difference - hours) / 24 - temp = Array.new - temp.push "#{days} day#{'s' unless days == 1}" if days > 0 - temp.push "#{hours} hour#{'s' unless hours == 1}" if hours > 0 - temp.push "#{minutes} minute#{'s' unless minutes == 1}" if minutes > 0 - temp.push "#{seconds} second#{'s' unless seconds == 1}" if (seconds > 0) and (days == 0) - time_until_next = temp.join(', ') +output.concat format_time_since.call(secs_since_realtime).rjust(time_since_label_width) +output.concat " #{add_commas.call(xp_since_realtime).rjust(exp_width)} #{add_commas.call(xp_since_realtime_avg).rjust(avg_exp_width)} " +if Vars.xp_ignore_fame != 'yes' + output.concat "#{add_commas.call(fame_since_realtime).rjust(fame_width)} #{add_commas.call(fame_since_realtime_avg).rjust(avg_fame_width)} " +end +if time_until_next_realtime + output.concat format_time_until_next.call(time_until_next_realtime).rjust(time_until_next_label_width) +else + output.concat '~'.rjust(time_until_next_label_width) +end +if xp_until_goal > 0 + output.concat ' ' + if time_until_goal_realtime + output.concat format_time_until_goal.call(time_until_goal_realtime).rjust(time_until_goal_label_width) + else + output.concat '~'.rjust(time_until_goal_label_width) + end end +output.concat "\n" +output.concat format_time_since.call(secs_since_first).rjust(time_since_label_width) +output.concat " #{add_commas.call(xp_since_first).rjust(exp_width)} #{add_commas.call(xp_since_first_avg).rjust(avg_exp_width)} " +if Vars.xp_ignore_fame != 'yes' + output.concat "#{add_commas.call(fame_since_first).rjust(fame_width)} #{add_commas.call(fame_since_first_avg).rjust(avg_fame_width)} " +end +if time_until_next_first + output.concat format_time_until_next.call(time_until_next_first).rjust(time_until_next_label_width) +else + output.concat '~'.rjust(time_until_next_label_width) +end if xp_until_goal > 0 - hours_until_goal = xp_until_goal / xp_since_first_avg.to_f - difference = (hours_until_goal * 3600).to_i - seconds = difference % 60 - difference = (difference - seconds) / 60 - minutes = difference % 60 - difference = (difference - minutes) / 60 - hours = difference % 24 - days = (difference - hours) / 24 - temp = Array.new - temp.push "#{days} day#{'s' unless days == 1}" if days > 0 - temp.push "#{hours} hour#{'s' unless hours == 1}" if hours > 0 - temp.push "#{minutes} minute#{'s' unless minutes == 1}" if minutes > 0 - temp.push "#{seconds} second#{'s' unless seconds == 1}" if (seconds > 0) and (days == 0) - time_until_goal = temp.join(', ') -end - -if CharSettings['realtime'] and xp_until_goal > 0 - hours_until_goal = xp_until_goal / xp_since_realtime_avg.to_f - difference = (hours_until_goal * 3600).to_i - seconds = difference % 60 - difference = (difference - seconds) / 60 - minutes = difference % 60 - difference = (difference - minutes) / 60 - hours = difference % 24 - days = (difference - hours) / 24 - temp = Array.new - temp.push "#{days} day#{'s' unless days == 1}" if days > 0 - temp.push "#{hours} hour#{'s' unless hours == 1}" if hours > 0 - temp.push "#{minutes} minute#{'s' unless minutes == 1}" if minutes > 0 - temp.push "#{seconds} second#{'s' unless seconds == 1}" if (seconds > 0) and (days == 0) - realtime_until_goal = temp.join(', ') -end - -lines = Array.new -lines.push "\n" -lines.push " Exp. Gained Avg per Hour Fame Gained Avg per Hour" -if CharSettings['realtime'] - lines.push "#{xp_since_realtime.to_s.rjust(12)} #{xp_since_realtime_avg.to_s.rjust(12)} #{fame_since_realtime.to_s.rjust(12)} #{fame_since_realtime_avg.to_s.rjust(12)} (#{(seconds_since_realtime / 60.0).as_time} since realtime)" -end -lines.push "#{xp_since_first.to_s.rjust(12)} #{xp_since_first_avg.to_s.rjust(12)} #{fame_since_first.to_s.rjust(12)} #{fame_since_first_avg.to_s.rjust(12)} (#{(seconds_since_first / 60.0).as_time} since first)" -lines.push "#{xp_since_last.to_s.rjust(12)} #{xp_since_last_avg.to_s.rjust(12)} #{fame_since_last.to_s.rjust(12)} #{fame_since_last_avg.to_s.rjust(12)} (#{(seconds_since_last / 60.0).as_time} since last)" -lines.push "\n" -if xp_until_next > 0 - if capped - lines.push "At this rate, you'll gain training points in #{time_until_next}." + output.concat ' ' + if time_until_goal_first + output.concat format_time_until_goal.call(time_until_goal_first).rjust(time_until_goal_label_width) else - lines.push "At this rate, you'll train in #{time_until_next}." + output.concat '~'.rjust(time_until_goal_label_width) end end +output.concat "\n" + +output.concat format_time_since.call(secs_since_last).rjust(time_since_label_width) +output.concat " #{add_commas.call(xp_since_last).rjust(exp_width)} #{add_commas.call(xp_since_last_avg).rjust(avg_exp_width)} " +if Vars.xp_ignore_fame != 'yes' + output.concat "#{add_commas.call(fame_since_last).rjust(fame_width)} #{add_commas.call(fame_since_last_avg).rjust(avg_fame_width)} " +end +if time_until_next_last + output.concat format_time_until_next.call(time_until_next_last).rjust(time_until_next_label_width) +else + output.concat '~'.rjust(time_until_next_label_width) +end if xp_until_goal > 0 - lines.push "At this rate, you'll reach your goal of #{xp_goal.to_s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse} experience in #{time_until_goal}." + output.concat ' ' + if time_until_goal_last + output.concat format_time_until_goal.call(time_until_goal_last).rjust(time_until_goal_label_width) + else + output.concat '~'.rjust(time_until_goal_label_width) + end end -if CharSettings['realtime'] and xp_until_goal > 0 - lines.push "At this rate (realtime), you'll reach your goal of #{xp_goal.to_s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse} experience in #{realtime_until_goal}." +output.concat "\n" + +if xp_until_goal > 0 + output.concat "\n" + output.concat "(#{add_commas.call(xp_until_goal)} experience needed to reach your goal of #{add_commas.call(CharSettings['goal'])})\n" end -lines.push '' -$xp['last'] = xp_now -respond lines + +output.concat "\n" +respond output + +$xp['last'] = now diff --git a/zombie.lic b/zombie.lic index 15a6eb7..d73a4ca 100644 --- a/zombie.lic +++ b/zombie.lic @@ -19,7 +19,9 @@ ;zombie help - tillmen@lichproject.org + author: Tillmen (tillmen@lichproject.org) + game: Gemstone + tags: death =end @@ -60,6 +62,36 @@ bank_list.push 10325 CharSettings['minimum-deeds'] ||= 2 +start_rooms = [ 285 ] + +wander_history = Array.new + +find_priestess_2 = proc { + until checknpcs.include?('priestess') or dead? + room = Room.current + next_room_options = room.wayto.keys.find_all { |k| room.wayto[k] =~ /^(?:north|northeast|east|southeast|south|southwest|west|northwest|out|n|ne|e|se|s|sw|w|nw)$/ } + next_room = next_room_options.find_all { |r| not wander_history.include?(r) } + if next_room.empty? + next_room = wander_history.find { |r| next_room_options.include?(r) } + else + next_room = next_room[rand(next_room.length)] + end + if next_room + wander_history.delete(next_room) + wander_history.push(next_room) + way = Room.current.wayto[next_room] + if way.class == String + move way + elsif way.class == Proc + way.call + end + else + echo 'fixme' + exit + end + end +} + find_priestess = proc { visited_rooms = Array.new until checknpcs.include?('priestess') or dead? @@ -160,7 +192,7 @@ remove_sting = proc { end empty_hands until (deaths_sting == 'None') or dead? - find_priestess.call + find_priestess_2.call result = dothistimeout "give ##{GameObj.npcs.find { |npc| npc.noun == 'priestess' }.id} #{potion_cost} silvers", 5, /^What is it you're trying to give\?$|^You start to hand the priestess [0-9]+ silvers, but she only takes|^You count your coins and realize that you don't have that much money!$|^You hand the priestess/ if result == "You count your coins and realize that you don't have that much money!" break if out_of_silvers