Mood Scripting

Unless I'm not seeing the documentation on it, mood scripting could really be improved.

The thing I'm having trouble with, is you can add a trigger to an existing mood easily enough, but at the end of the script, you want to remove the triggers you added to get back to your default mood. But I can't seem to find a way to script the equivalent of "right click on a trigger in the mood setup tab and select remove selected".

Of course, you can reference named moods (+items, +noncombat) and just include all your default buffs in those moods, but doing cli_execute("mood +items") for someone who doesn't have a mood called +items isn't going to get very far.

We also need a way to detect how many AT buffs a character has active. When you're changing moods, it's handy to know if you need to shrug a song to make room for a new one.

Am I missing something major?
 
Last edited:

Bale

Minion
The thing I'm having trouble with, is you can add a trigger to an existing mood easily enough, but at the end of the script, you want to remove the triggers you added to get back to your default mood. But I can't seem to find a way to script the equivalent of "right click on a trigger in the mood setup tab and select remove selected".

Select the trigger you want to remove and press the delete key.


Am I missing something major?

Yes. It is possible to put ash or even an entire script into a mood. For instance my combat mood looks like this:

Code:
When I run low on Carlweather's Cantata of Confrontation cast 1 Carlweather's Cantata of Confrontation
When I run low on Hippy Stench ashq if(can_interact() || (my_location() == $location[Wartime Sonofa Beach] && item_amount($item[handful of pine needles]) + item_amount($item[reodorant]) > 0)) cli_execute("use either 1 handful of pine needles, 1 reodorant");
When I run low on Musk of the Moose cast 1 Musk of the Moose

That's a fairly simple example. (I love being able to run several moods concurrently!) Notice how I'll only use Hippy Stench if I'm in aftercore or I'm in at Sonofa Beach? It's very possible to script anything you want in a mood. I've got a much more complicated mood for the Orchard and and another for Nuns that checks what buffs I currently have available and automatically sets me up for those zones.

I've also got a standard mood script I run in my default mood. It does a lot of basic and continuous handling, much like zarqon's BestBetweenBattle, but it is designed to handle as a mood so that it will play nice with the relay browser.

Code:
Always, call betweenBattleMood.ash


We also need a way to detect how many AT buffs a character has active. When you're changing moods, it's handy to know if you need to shrug a song to make room for a new one.

Well, on the skills tab all AT songs have a special icon in front of them to make counting easy, but I would agree it could be nice to have the total current AT songs displayed as a number on the mood tab.
 
Last edited:
Select the trigger you want to remove and press the delete key.
Ok, that didn't answer my question. Say i'm writing a script to do some place where I want noncombats, in addition to my default mood, i can script <cli_execute("trigger lose_effect, smooth movement, cast 1 smooth");> but at the end of the script, I'd like to cancel that trigger to return to the default mood... a killtrigger. :)

Now, I gotta say, the stuff about what you put into a mood, and having a whole script that can handle various mood changing tasks based on $location is kinda cool, and I think exactly what I'm looking for for what I'd like to do, but doesn't really solve the problem of being able include some temporary mood alterations in scripts written with a broader audience in mind.
 

Winterbay

Active member
I guess you could write a moodscript that you have people download and then their mood has only to be "Always, call <mymoodscript>". This script could then adapt it's doings based on how many AT-buffs you have on, where you are and what you want to do. If your main script sets some settings (either zlib or mafia) then the two script could comunicate as well.
 

Bale

Minion
Ok, that didn't answer my question. Say i'm writing a script to do some place where I want noncombats, in addition to my default mood, i can script <cli_execute("trigger lose_effect, smooth movement, cast 1 smooth");> but at the end of the script, I'd like to cancel that trigger to return to the default mood... a killtrigger. :)

Ouch. I now know what you want to do. Sadly, while it is possible for a script to clear an entire mood with "trigger clear", it is impossible for a script to remove a single trigger from a mood. I have already posted a FEATURE REQUEST to do that. My request was not shined upon by the KoLmafia gods.

Perhaps if you posted about your problem in the feature request thread and explain how you would use that feature, you might convince someone to spend time on it.
 
Request bumped.

Yeah, now that I have a basic idea of what I can do locally, I can create a function that will clear and rebuild my default mood from a given list of skills. But I'm usually writing for at least 2 different characters of my own, one that plays HC and one that plays SC and they have very different skills, items, playstyles, and needs. ;)

That doesn't even begin to touch whether Joe-User-Who-Just-Downloaded-Mafia-So-He-Could-Run-My-New-Cool-Script is able to figure out :confused: how to make it stop buying knob goblin eyedrops when the script is done.
 

fronobulax

Developer
Staff member
My request was not shined upon by the KoLmafia gods.

Or maybe just not noticed?

I respond here because this is where the discussion has been.

Suppose I write ShinyScript. Before ShinyScript runs it saves the current mood and replaces it with a mood called ShinyMood. When it stops it restores the mood that had been there before. Under the hood ShinyScript builds ShinyMood presumably by copying the current mood and adding the ShinyScript required triggers if they are not there or changing the actions as appropriate.

Is the above possible? If so then it seems to me to provide a solution to the problem posed. If it is not possible then I view this as an opportunity to learn about KoLmafia features that I don't understand. And of course, there is always the possibility that I don't understand the problem.

Thanks.
 

slyz

Developer
My request was not shined upon by the KoLmafia gods.
I think the KoLmafia god is Holatuwol, in this case. This request was probably made before he started reworking moods, but I guess he disappeared again before adding this feature.

With all the changes he made, could it be possible for the user to supply the name of a mood to a script, and have the script add that mood to the one he creates?
 
The only solution I can think of in the current context is that you can have the end-user specify a global list (array, map?) of the buffs they would like in their default mood. Then the scripter can build that mood on the fly, add to it, and still have a reference of what to return to at the end of the script.

Code:
void mood_default() {
    cli_execute("mood clear");
    foreach buff in $skills[antiphon, curiosity of br'er tarrypin, mojomuscular]
        if( have_skill(buff) ) cli_execute("trigger lose_effect, "+buff.to_string()+", cast 1 "+buff.to_string());
}
void mood_items() {
    mood_default();
    foreach buff in $skills[phat loot, leash, empathy]
        if( have_skill(buff) ) cli_execute("trigger lose_effect, "+buff.to_string()+", cast 1 "+buff.to_string());
    if( dispensary_available() ) {
        cli_execute("trigger lose_effect, heavy petting, use 1 pet-buffing spray");
        cli_execute("trigger lose_effect, peeled eyeballs, use 1 knob goblin eyedrops");
    }
}
To facilitate multiple users, that global should probably be saved as zlib variable, much the same way SmartStasis maintains a list of monsters you'd like to always olfact as a property.

Fronobulax said:
Before ShinyScript runs it saves the current mood and replaces it with a mood called ShinyMood. When it stops it restores the mood that had been there before.

This would be better. It stands to reason that a player's current mood is being stored as an array of triggers somewhere anyhow. If we could make a copy (requiring no user-interaction) of that to save for the end, that would work as well ie "checkpoint mood".

AT Song Handling
I've written some functions that work for detecting how many and which AT songs are active. I'm just not sure what logic a person would write to decide which existing song you would shrug to make room for a new mood, if needed.

Code:
int num_at_songs_active() {
    int num_at_active = 0;
    foreach song in $effects[moxious madrigal, mojomuscular melody, celerity, power ballad, polka, symphony of destruction, phat loot, anthem of absorption, psalm of pointiness, shanty of superiority, antiphon of aptitude, ode to booze, sonata of sneakiness, cantata of 		confrontation, ur-kel's aria, dirge of dreadfulness, don ho's, chorale of companionship, 	benetton's medley, prelude of precision, richie thingfinder, explosive etude, cringle's curative carol, inigo's inspiration]
        if (have_effect(song)>0) num_at_active += 1;
    return num_at_active;
}

string list_at_songs_active() {
    string list_at_active = "";
    foreach song in $effects[moxious madrigal, mojomuscular melody, celerity, power ballad, polka, symphony of destruction, phat loot, anthem of absorption, psalm of pointiness, shanty of superiority, antiphon of aptitude, ode to booze, sonata of sneakiness, cantata of confrontation, ur-kel's aria, dirge of dreadfulness, don ho's, chorale of companionship, benetton's medley, prelude of precision, richie thingfinder, explosive etude, cringle's curative carol, inigo's inspiration]
        if (have_effect(song)>0) {
            if (list_at_active == "") list_at_active += song.to_string();
            else list_at_active += ", "+song.to_string();
        }
    return list_at_active;
}

int at_songs_max() {
    int at_max = 3;
    foreach it in $items[plexiglass pendant, brimstone beret, super-sweet boom box]
        if (have_equipped(it)) { at_max += 1; break; }
    if (my_class()==$class[accordion thief] && have_equipped($item[la hebilla del Cinturón de Lopez])) at_max += 1;
    return at_max;
}
 
Last edited:

Bale

Minion
Suppose I write ShinyScript. Before ShinyScript runs it saves the current mood and replaces it with a mood called ShinyMood. When it stops it restores the mood that had been there before. Under the hood ShinyScript builds ShinyMood presumably by copying the current mood and adding the ShinyScript required triggers if they are not there or changing the actions as appropriate.

Is the above possible? If so then it seems to me to provide a solution to the problem posed. If it is not possible then I view this as an opportunity to learn about KoLmafia features that I don't understand. And of course, there is always the possibility that I don't understand the problem.

That would be great if there were mafia commands to do that. Not only is there no command to remove a trigger, there is also no command to copy a mood. These are things that can only be done manually through the UI.
 

Winterbay

Active member
You can however switch moods so you could save the name of the current mood, create a new one/switch to another one and fill that with what you want and then afterwards switch back the the original one. BCCascend does something similar I think.
 

fronobulax

Developer
Staff member
That would be great if there were mafia commands to do that. Not only is there no command to remove a trigger, there is also no command to copy a mood. These are things that can only be done manually through the UI.

Got it. Thanks.
 
So, I'm digging around today and turns out, all your defined moods are saved in settings/myname_moods.txt.

Your currently active mood name is held in the property "currentMood".

So, now I'm thinking... why can't you search myname_moods.txt for currentMood.. then save that section as a string somewhere, to restore it at the end of your script?
 

Winterbay

Active member
I don't think there's a way for a script to read anything from the \settings-folder. You can for example not make a script that prints all your preferences, only the default ones since exist in Mafia's internal database.
 

Donavin69

Member
I have wanted to create a 'mood script' and do certain things that Bale has pointed out that he already does (like use the evil eye) but I don't know where to put it or how to call it.
 
Top