Universal Recovery Script

That option means that anything in your inventory is considered to be worth 0 meat. Like it says...

The script buying items after it goes outside the 25% flexibility is a different bug. :)
 
I'm coming across a problem in boriscore. The recovery script always opts to deplete all my meat at the good doctor instead of burning mana on Laugh it Up. Sorry if this was asked before and fixed I did a quick search and only found problems pertaining to laugh it up being cast too much instead of too little.

Laugh it up is cast once then the script goes and buys ailment ointments.
 
If you don't have any better versions of mana recovery than the doctor, then it's less expensive to use him for healing than casting LIU. If you do, however, have the black market or something else unlocked, UR will realize that and use LIU as HP recovery instead...
 
That's weird.. I have the black market open and it's still going to the doctor. But even without the market open, I thought it was set up to burn mana from double-ice cap/sackbut by casting laugh it up?
 
Oh I didn't have recast buffs set to anything. I only set it to start recasting at some percentage and I thought mafia would recognize that since LIU is not really a buff. Well it work now after setting recast buffs, thanks!
 
Because turning on "Recasting" has the undesirable effect of allowing Mafia to buy hundreds of turns of my current song which will be lost the next time I need Glorious Lunch I have ended up editing my copy of UR so that the "boris()" function is now:
void boris() {
if(my_path() != "Avatar of Boris") return;
int extra_mp = my_mp() - 0.8 * my_maxmp();
if(extra_mp < 1 || my_hp() >= my_maxhp())
return;
int casts = min(extra_mp, (my_maxhp() - my_hp()) / 1.5);
use_skill(casts, $skill[Laugh It Off]);
}
This allows a steady trickle of MP to bolster my HP at times when I am MP rich while allowing me to keep Rebalance Buffs turned off. I'm currently thinking that I should use mpAutoRecoveryTarget rather than a fixed 0.8.
I've also modified restore() to call boris() directly after the call to hp_heal() but that is largely cosmetic. The call to boris() hardly ever fires on the MP restore call.
 
Isn't there also a way, thanks to the glorious machinations of our devs, to limit specific skills to specific numbers of casts?
 
There appears to be a little problem with this script as you come out of the Avatar of Boris run, at least if you choose a SC run afterwards. It got stuck trying to restore my HP with Medicinal Herbs despite me not having access to the guild yet. Trying to get access to the guild was also slightly problematic since it continued to loop the same:
Code:
 > Current HP: 415, MP: 848
 > In mallmode, best HP restorative is: Medicinal Herb's medicinal herbs @ 100.0 meat total.
 > In mallmode, best MP restorative is: ancient Magi-Wipes @ 751.63635 meat total.
 > Mall price to restore 20MP is 71 meat.
 > Trying to use 1 Medicinal Herb's medicinal herbs
 > Failed to use an item from the mall.

Over and over again until I told Mafia to not use a recovery script for a while :)
 
I would like to suggest that the script recover as normal at the new Hidden Temple.

(Got beaten up by cave bars today and the script just restored 1 hp and I only got beaten up in the first place b/c no recovery happened after fighting the cave bars the first time, leaving me with not enough hp to beat them the second time.)
 
Sorry. I thought I'd already pushed out that update. Doing it now.

Universal recovery v 3.9.4 released!



Changelog:
version 3.9.4 March 31, 2012
  • Need to heal at the Hidden Temple now
 
Last edited:
SUggestion: Change use_herb to the following to avoid having incredible problems if you choose a muscle class after your Boris-run ends:
Code:
boolean use_herb = contains_text(hpAutoRecoveryItems, "medicinal herb's medicinal herbs")
	&& my_path() != "Bees Hate You" && my_path() != "Avatar of Boris" && my_level() > 2 && guild_store_available()
	&& (my_primestat() == $stat[muscle] || item_amount($item[Medicinal Herb's medicinal herbs]) > 0
	|| (my_class() == $class[accordion thief] && my_level() >= 9))
(i.e. add guild_store_available())
 
Okay, I have no idea how I messed the script up, but I must have done something. It was working fine for the longest time and now it's acting crazy.
I clicked on my HP to restore my health, and then this happened. At the time I had Pheonix Downs, Echo Eyedrops, etc. from the Airship. In my recovery options I have most of the options checked.
Code:
You've had the crap beaten out of you... attempting to find some more crap.
Using 1 tiny house...
You gain 21 hit points
You gain 22 Muscularity Points
Finished using 1 tiny house.
Beaten Up will be removed by item tiny house...
Using 1 tiny house...
You gain 24 hit points
You gain 21 Muscularity Points
Finished using 1 tiny house.
Unable to cure beaten up! Go adventure someplace wussier.
Restoring HP! Currently at 45 of 123 HP, 57 of 57 MP, current meat: 18104 ... Target HP = 117.
Medicinal Herb's medicinal herbs: you are not yet out of ronin, and are unable to buy this item from a NPC store.
Casting Laugh It Off 1 times...
You gain 1 hit point
Laugh It Off was successfully cast.
Medicinal Herb's medicinal herbs: you are not yet out of ronin, and are unable to buy this item from a NPC store.
Visiting Doc Galaktik...

Restore 70 HP at Doc Galaktik's
You gain 70 hit points
You spent 420 Meat
Cure purchased.

It always buys cures now, even when I have ancient Magi-wipes or carbonated water lilies or scrolls of drastic healing, etc on me. The above is stranger than normal, but the end result is generally the same, laugh once, then buy cure up to full.
 
Last edited:
Code:
[COLOR="#FF0000"]Casting Laugh It Off 13 times...
You gain 20 hit points
Laugh It Off was successfully cast.[/COLOR]
Restoring HP! Currently at 32 of 83 HP, 5 of 24 MP, current meat: 28 ... Target HP = 63.
Casting Laugh It Off 1 times...
You gain 2 hit points
Laugh It Off was successfully cast.
Insufficient meat to fully restore HP without wasting restoratives!
Did not fully restore HP for some reason.
(The text in red is from me casting Laugh It Off leaving me only 5 MP efore your script kicked in.) This is odd... running as AoB, I keep seeing it screw me out of Cleave/Heroic Belch by casting Laugh It Off only once. If it burned all my MP, I could understand, but why does it only cast it once no matter how I set the options?
 
I remember noticing something about UR casting Laughing Off once too. I haven't looked at the code, but it looked like it did it before deciding how to heal.
I keep seeing it screw me out of Cleave/Heroic Belch by casting Laugh It Off only once.
The "Insufficient meat to fully restore HP without wasting restoratives!" should precede an abort. The script doesn't "screw you", it simply fails to restore, and you are warned about it before adventuring.

EDIT:

There is a new boris() function, which is always called before the actual restoring begins:
PHP:
void boris() {
	if(my_path() != "Avatar of Boris") return;
	float manaBurningThreshold = get_property("manaBurningThreshold").to_float();
	if(manaBurningThreshold < 0) return;
	int extra_mp = my_mp() - manaBurningThreshold * my_maxmp();
	if(extra_mp < 1 || my_hp() >= my_maxhp())
		return;
	
	int casts = min(extra_mp, (my_maxhp() - my_hp()) / 1.5);
	use_skill(casts, $skill[Laugh It Off]);
}
It should only cast Laugh It Off to burn any MP that is above your manaBurningThreshold.
 
Last edited:
It appears that, if you're unable to fully restore HP/MP due to low meat, it will always cast LIO once or twice, as per this (restore_hp and restore_mp are in both my bBS and aBS, due to things like the dolphin whistle triggering and leading immediately into another fight, without another chance to heal up before/after.
Restoring HP! Currently at 102 of 445 HP, 44 of 137 MP, current meat: 2 ... Target HP = 423.
Casting Laugh It Off 1 times...
You gain 1 hit point
Laugh It Off was successfully cast.
Restoring MP! Currently at 103 of 445 HP, 43 of 137 MP, current meat: 2 ... Target MP = 137.
Insufficient meat to fully restore MP without wasting restoratives!
Restoring MP! Currently at 103 of 445 HP, 43 of 137 MP, current meat: 2 ... Target MP = 137.
Insufficient meat to fully restore MP without wasting restoratives!
Recovery target reduced to healing trigger (289)to conserve meat.
Insufficient meat to fully restore HP without wasting restoratives!
Did not fully restore HP for some reason.
Restoring HP! Currently at 103 of 445 HP, 43 of 137 MP, current meat: 2 ... Target HP = 423.
Casting Laugh It Off 1 times...
KoLmafia declares world peace.
You gain 2 hit points
Obviously I haven't hit my mana burning threshold... I don't even have enough for UR/mafia to be happy with me. And yet, each incarnation of restore_hp(0) casts LIO once.

As shown by:
> ash (my_mp() - get_property("manaBurningThreshold").to_float() * my_maxmp())

Returned: -67.6
Yet it gets used...

It IS definitely some function of restore("hp") though.
> ash import <universal_recovery.ash> restore("hp", 106);

Restoring HP! Currently at 105 of 445 HP, 42 of 137 MP, current meat: 2 ... Target HP = 423.
Casting Laugh It Off 1 times...
You gain 1 hit point
Laugh It Off was successfully cast.
Restoring MP! Currently at 106 of 445 HP, 41 of 137 MP, current meat: 2 ... Target MP = 137.
Insufficient meat to fully restore MP without wasting restoratives!
Restoring MP! Currently at 106 of 445 HP, 41 of 137 MP, current meat: 2 ... Target MP = 137.
Insufficient meat to fully restore MP without wasting restoratives!
Returned: true

> ash import <universal_recovery.ash> restore("hp", 120);

Restoring HP! Currently at 106 of 445 HP, 41 of 137 MP, current meat: 2 ... Target HP = 423.
Casting Laugh It Off 1 times...
You gain 2 hit points
Laugh It Off was successfully cast.
Restoring MP! Currently at 108 of 445 HP, 40 of 137 MP, current meat: 2 ... Target MP = 137.
Insufficient meat to fully restore MP without wasting restoratives!
Restoring MP! Currently at 108 of 445 HP, 40 of 137 MP, current meat: 2 ... Target MP = 137.
Insufficient meat to fully restore MP without wasting restoratives!
Insufficient meat to fully restore HP without wasting restoratives!
Returned: false

> ash import <universal_recovery.ash> boris();

Returned: void

In case it helps, here's the 120 heal on chatterbox (verbosity 3) settings:
> ash import <universal_recovery.ash> restore("hp", 120);

Calling Universal Recovery for type=hp, amount=120
Restoring HP! Currently at 108 of 445 HP, 40 of 137 MP, current meat: 2 ... Target HP = 423.
Trying to fullheal
Casting Laugh It Off 1 times...
You gain 2 hit points
Laugh It Off was successfully cast.
Try to heal HP from inventory.
Trying to fullheal
Try to heal HP with skills.
Restoring MP! Currently at 110 of 445 HP, 39 of 137 MP, current meat: 2 ... Target MP = 137.
Try to heal MP from inventory.
Last attempt to purchase MP with meat.
Insufficient meat to fully restore MP without wasting restoratives!
Restoring MP! Currently at 110 of 445 HP, 39 of 137 MP, current meat: 2 ... Target MP = 137.
Try to heal MP from inventory.
Last attempt to purchase MP with meat.
Insufficient meat to fully restore MP without wasting restoratives!
Last attempt to purchase HP with meat.
Insufficient meat to fully restore HP without wasting restoratives!
Returned: false

Nope, not the fullheal section. Tried that and it didn't fail. Maybe the (futile) section of hpheal?
Code:
		if(cheap_skill != $skill[none] && cast_quant(cheap_skill, target)>0) {
			// Inventory won't completely heal, so better to cast this skill BEFORE wasting a healing item
			if(my_mp()>= skills[cheap_skill].mp || (my_maxhp() >= skills[cheap_skill].mp && mp_heal(skills[cheap_skill].mp))) {
				if(my_hp() >= target) return true; // mp restoration may have restores hp
				cast(1, cheap_skill);
			}
			futile = max_heal(options) < target - my_hp();	// Recheck futility
		}
Yep, definitely that. Disabled the cast line, got the upper. Re-enabled it, got the bottom.
> ash import <universal_recovery.ash> restore("hp", 120);

Restoring HP! Currently at 111 of 445 HP, 38 of 137 MP, current meat: 2 ... Target HP = 423.
Restoring MP! Currently at 111 of 445 HP, 38 of 137 MP, current meat: 2 ... Target MP = 137.
Insufficient meat to fully restore MP without wasting restoratives!
Restoring MP! Currently at 111 of 445 HP, 38 of 137 MP, current meat: 2 ... Target MP = 137.
Insufficient meat to fully restore MP without wasting restoratives!
Insufficient meat to fully restore HP without wasting restoratives!
Returned: false

> ash import <universal_recovery.ash> restore("hp", 120);

Restoring HP! Currently at 111 of 445 HP, 38 of 137 MP, current meat: 2 ... Target HP = 423.
Casting Laugh It Off 1 times...
You gain 2 hit points
Laugh It Off was successfully cast.
Restoring MP! Currently at 113 of 445 HP, 37 of 137 MP, current meat: 2 ... Target MP = 137.
Insufficient meat to fully restore MP without wasting restoratives!
Restoring MP! Currently at 113 of 445 HP, 37 of 137 MP, current meat: 2 ... Target MP = 137.
Insufficient meat to fully restore MP without wasting restoratives!
Insufficient meat to fully restore HP without wasting restoratives!
Returned: false
Guessing that the if (futile) is actually supposed to be while (futile) or something similar, since you set the value of futile again inside, but it never gets used again. Otherwise there's no reason to "recheck futility" as the comments say. Problem with setting it to while is that it burns all your mana, then loops at 0 mp trying to restore one more MP forever. :)

One rather odd thing is that it has a cast_quant(skill, HP-target)>0 check in the futile casting, but you use a MAX(1, casts-needed) in cast_quant, so it will ALWAYS be >0.

Well, my solution for now will just be to comment out the single futile cast. :) Least that keeps my MP more safe, since I'd rather have that one MP and be able to use my skills than to be able to have one more HP and lose 50.
 
Last edited:
The "Insufficient meat to fully restore HP without wasting restoratives!" should precede an abort. The script doesn't "screw you", it simply fails to restore, and you are warned about it before adventuring.
Sorry, had a touch of frustration as I was trying to save 5 MP and then "Hey, you can't use that skill without MP!" If it really was screwing me, I'd hope it'd byuy me dinner first!
Code:
		if(cheap_skill != $skill[none] && cast_quant(cheap_skill, target)>0) {
			// Inventory won't completely heal, so better to cast this skill BEFORE wasting a healing item
			if(my_mp()>= skills[cheap_skill].mp || (my_maxhp() >= skills[cheap_skill].mp && mp_heal(skills[cheap_skill].mp))) {
				if(my_hp() >= target) return true; // mp restoration may have restores hp
				cast(1, cheap_skill);
			}
			futile = max_heal(options) < target - my_hp();	// Recheck futility
		}
Guessing that the if (futile) is actually supposed to be while (futile) or something similar, since you set the value of futile again inside, but it never gets used again. Otherwise there's no reason to "recheck futility" as the comments say. Problem with setting it to while is that it burns all your mana, then loops at 0 mp trying to restore one more MP forever. :)

One rather odd thing is that it has a cast_quant(skill, HP-target)>0 check in the futile casting, but you use a MAX(1, casts-needed) in cast_quant, so it will ALWAYS be >0.

Well, my solution for now will just be to comment out the single futile cast. :) Least that keeps my MP more safe, since I'd rather have that one MP and be able to use my skills than to be able to have one more HP and lose 50.
Wow. Thanks for analysis. I don't think I'd know to do in there, but now I have an idea.
 
Well, it's easy to stop... just search for futile, and replace the section above with this:
Code:
	if(futile) {
		if(fullheal()) return true;
		if(cheap_skill != $skill[none] && cast_quant(cheap_skill, target)>0) {
			// Inventory won't completely heal, so better to cast this skill BEFORE wasting a healing item
			if(my_mp()>= skills[cheap_skill].mp || (my_maxhp() >= skills[cheap_skill].mp && mp_heal(skills[cheap_skill].mp))) {
				if(my_hp() >= target) return true; // mp restoration may have restores hp
#				cast(1, cheap_skill);
			}
			futile = max_heal(options) < target - my_hp();	// Recheck futility
		}
		if(my_hp() >= target) return true;
	}
Basically, put a # on the front of the line that says cast(1, cheap_skill); in the futile segment. Don't take out the one in fullheal... that would disable using cocoon and good skills. But disabling the futile cast means that, when UR knows it won't succeed, don't even waste any mana that it isn't supposed to on healing.

From the looks of it, this is supposed to loop somehow, but isn't still implemented in the way it originally was meant to work.
 
Back
Top