Bug Status (current MP specifically) not updated in outfit change

When changing an outfit, if your MP changes mafia is not aware of it:

Example:
My current MP and MaxMP are both 3550 and I have a libram that costs 3487 to cast.
I change my outfit to Vile Vagrant Vestments
Now my MP is 3417 and MaxMP is 3946 however, mafia is reporting the old numbers (it is reporting the correct adjusted cost of the libram at 3482)
So, my code:

Code:
if(my_mp() > mp_cost($skill[Summon BRICKOs]))
{
    try
    {
        if(use_skill(1, $skill[Summon BRICKOs]) {}
    }
    finally
    {}
}

It thinks I have enough MP but KoL reports that I don't and now the workaround for handling aborts no longer handles this case either (I'm guessing there are probably other workarounds).

As far as I can tell, if doing this step by step in the gCLI, it is not an issue, only when scripting do I have an issue and the recent changes to try/finally broken my method of ignoring this issue.
 

lostcalpolydude

Developer
Staff member
So there's a way to change outfits that doesn't load api.php I expect. Except I can't reproduce it in a script (printing my_mp() before and after an outfit() change that makes me lose MP gives expected results).
 
So there's a way to change outfits that doesn't load api.php I expect. Except I can't reproduce it in a script (printing my_mp() before and after an outfit() change that makes me lose MP gives expected results).

I used outfit("Vile Vagrant Vestments");

The failure of use_skill causes the character status to get reloaded but the abort continues regardless now so I may regress to an earlier version to retain prior abort precedence.
 

Darzil

Developer
It's clutching at straws, but do you have some Smiths stuff equipped?

KoL doesn't handle it very well, unfortunately (or maybe we are buggy by supporting it right), so if you put on an outfit that includes Smiths stuff, KoL doesn't increase outfit effects based on the new Smithsness level until you refresh, so Mafia can think you have more MP than KoL thinks you do. Hitting refresh on the character pane (or through API) gets KoL to recalculate Smithsness and the two match again.
 
What "abort"?

When I try to use the skill with use_skill(), I get red text "Not enough mana to cast Summon BRICKOs." and the automation stops. I have assumed this is an "abort" but I don't know quite the mechanism that is going on. Since it seems that my outfit change (and possibly interaction with smithness) causes mafia and KoL to be out-of-sync, mafia thinks I have enough mp but the actual use_skill() attempt fails server side.

In any case, I will try it tomorrow with a clean build just in case I did something to screw it up and edit verify it or blame myself for the problem.

It's clutching at straws, but do you have some Smiths stuff equipped?

KoL doesn't handle it very well, unfortunately (or maybe we are buggy by supporting it right), so if you put on an outfit that includes Smiths stuff, KoL doesn't increase outfit effects based on the new Smithsness level until you refresh, so Mafia can think you have more MP than KoL thinks you do. Hitting refresh on the character pane (or through API) gets KoL to recalculate Smithsness and the two match again.

Yeah, smithsness. Lost messaged me asking about that and it is indeed a situation here. My current workaround is to "refresh status" before checking the MP cost of the libram but I'd love to remove that server hit. Before the change to how try/finally were handled, I could ignore the failure of use_skill(). I suspect I can still do so now but I don't know how so any longer.
 
Last edited:

Veracity

Developer
Staff member
Yeah, OK, that does look like an abort.

UseSkillRequest.parseResponse():

Code:
		if ( responseText.contains( "You don't have enough" ) )
		{
			String skillName = SkillDatabase.getSkillName( skillId );

			UseSkillRequest.lastUpdate = "Not enough mana to cast " + skillName + ".";
			ApiRequest.updateStatus();
			return true;
		}
and UseSkillRequest.processResults():

Code:
		boolean shouldStop = UseSkillRequest.parseResponse( this.getURLString(), this.responseText );

		if ( !UseSkillRequest.lastUpdate.equals( "" ) )
		{
			MafiaState state = shouldStop ? MafiaState.ABORT : MafiaState.CONTINUE;
			KoLmafia.updateDisplay( state, UseSkillRequest.lastUpdate );

			if ( BuffBotHome.isBuffBotActive() )
			{
				BuffBotHome.timeStampedLogEntry( BuffBotHome.ERRORCOLOR, UseSkillRequest.lastUpdate );
			}

			return;
		}
So, yes - if KoL says you are out of mana, we print it in red and go into the ABORT state.
RuntimeLibrary.use_skill():

Code:
		KoLmafiaCLI.DEFAULT_SHELL.executeCommand( "cast", count + " " + SkillDatabase.getSkillName( (int) skill.intValue() ) );
		return UseSkillRequest.lastUpdate.equals( "" ) ? RuntimeLibrary.continueValue() : DataTypes.FALSE_VALUE;
should return false. Of course, we are in an ABORT state. You are "capturing" that value via "if(use_skill(1, $skill[Summon BRICKOs]) {}" so I would have thought that would reset the ABORT state.

It's been a long time since I've looked at how that works. I'll investigate further.
 

Veracity

Developer
Staff member
Yeah. Interpreter.captureValue():

Code:
	public final void captureValue( final Value value )
	{
		// We've just executed a command in a context that captures the
		// return value.

		if ( KoLmafia.refusesContinue() || value == null )
		{
			// User aborted
			this.setState( STATE_EXIT );
			return;
		}

		// Even if an error occurred, since we captured the result,
		// permit further execution.

		this.setState( STATE_NORMAL );
		KoLmafia.forceContinue();
	}
If you are in an ABORT state, even capturing the value will not permit you to continue.

Playing games with try/finally - i.e., depending on a bug in the implementation of that construct - is not the solution.

I guess the question is why UseSkillRequest goes into an ABORT state, rather than an ERROR state. Either should print in red, and either should stop a CLI script, but only the latter can be "captured" by an ASH script.
 

Veracity

Developer
Staff member
Yeah. This ASH script:

Code:
if ( use_skill( 1, $skill[ the polka of plenty ], "boogerator" ) ) {
    print( "it worked" );
} else {
    print( "it failed" );
}
Does this:

Code:
[color=green]> us.ash[/color]

Casting The Polka of Plenty on boogerator 1 times...
[color=red]Selected target is not a valid target.[/color]
Notice that it did not capture the value.

Looking at UseSkillCommand, when the "cast" command wants to abort, it will do this, for example:

Code:
				KoLmafia.updateDisplay( MafiaState.ERROR,
					"You don't have a skill uniquely matching \"" + parameters + "\"" );
It goes into ERROR.

I'll try changing UseSkillRequest.processResults to go into ERROR rather than ABORT.
 

Veracity

Developer
Staff member
Doing that and running that script, I get this:

Code:
[color=green]> us.ash[/color]

Casting The Polka of Plenty on boogerator 1 times...
[color=red]Selected target is not a valid target.[/color]
it failed
it successfully captures the failed use_skill() call.

I'll submit a fix to enable that, but that does not resolve the original issue you reported of KoLmafia not having the accurate value for MP.

Can we see the ASH code you used to put on the outfit, please?

Thanks.
 
Doing that and running that script, I get this:

Code:
[color=green]> us.ash[/color]

Casting The Polka of Plenty on boogerator 1 times...
[color=red]Selected target is not a valid target.[/color]
it failed
it successfully captures the failed use_skill() call.

I'll submit a fix to enable that, but that does not resolve the original issue you reported of KoLmafia not having the accurate value for MP.

Can we see the ASH code you used to put on the outfit, please?

Thanks.

Sounds good. And I can verify that it plays nicely with my try/finally again.

I'm guessing smithsness is to blame but it boils down to:

Code:
# In a postadventure script:
if((my_basestat($stat[mysticality]) >= 200) && (my_buffedstat($stat[mysticality]) >= 200))
{
    outfit("Vile Vagrant Vestments");
}

if(have_skill($skill[Pastamancery]) && (my_mp() > mp_cost($skill[Pastamancery]))
{
    use_skill(1, $skill[Pastamancery]);
}

#A few more spells...

skill libram = $skill[Summon BRICKOs];
		if((my_mp() - mp_cost(libram)) > 32)
		{
			print("Mymp: " + my_mp() + " of " + my_maxmp() + " and cost: " + mp_cost(libram), "blue");
			cli_execute("refresh status");
			if((my_mp() - mp_cost(libram)) > 32)
			{
				print("Mymp: " + my_mp() + " of " + my_maxmp() + " and cost: " + mp_cost(libram), "blue");
				#boolean temp = use_skill(1, libram);
				try
				{
					#if(use_skill(1, libram)) {}
					boolean temp = use_skill(1, libram);
				}
				finally
				{
					print("Mymp: " + my_mp() + " of " + my_maxmp() + " and cost: " + mp_cost(libram), "blue");
				}
			}
			else
			{
				print("No longer have enough MP.", "red");
				print("Mymp: " + my_mp() + " of " + my_maxmp() + " and cost: " + mp_cost(libram), "blue");
				wait(5);
			}
		}

This was updated to try to figure out what was going on, I can end up in the "No longer have enough MP" case.
 
Last edited:
Top