Proper familiar equipment management?

Linknoid

Member
I'm wondering what is the best practice is for managing familiar equipment.

I have various general familiar equipment which can be equipped on any familiar, like Snow Suit, li'l businessman suit, Astral pet sweater, Mayflower bouquet, ittah bittah hookah, sugar shield, little bitty bathysphere, etc.

When I have tried to equip familiar equipment that was on another familiar, it just errors out instead of removing it from the other one first. And when you swap out a familiar, the equipment doesn't get returned to your inventory, it stays with the inactive familiar (or if locked, moves to the new familiar).

Right now, my scripts are removing any generic familiar equipment before swapping familiars, just in case the new familiar should be using that equipment. I do this by equipping "none". But instead of actually removing the equipment, it chooses another one, saying that's a better choice than "none". I've seen it choose Mayflower bouquet as the alternative. So what happens when I take off my snow suit to make it available for others, and it substitutes the Mayflower bouquet, then swap familiars, and now try to equip the mayflower bouquet?

It looks like I can query each familiar's equipment with familiar_equipped_equipment, but I don't see any obvious way to remove equipment from an inactive familiar if another one want to use it. Should I just leave it equipped, and use visit_url("familiar.php?pwd=" + my_hash() + "&action=unequip&famid=" + familiar.to_int()) to remove it when someone else needs it?

But doing that leaves another issue: I can't find a function to iterate all owned familiars. So I need to parse the terrarium page manually, or maintain a list of familiars in my script to check against?

Or I could maintain a list of generic equipment that hopefully everyone has, like the ant tools etc., and use them for swapping in instead of "none". Which would probably work unless the player auto-sells such things. And this whole "unequip before familiar swap" has it's own issues, like unnecessary server hits, and not accounting for equipment that's already tied to an inactive familiar.

How do other scripts deal with this?
 

lostcalpolydude

Developer
Staff member
When I have tried to equip familiar equipment that was on another familiar, it just errors out instead of removing it from the other one first.
How are you trying to equip stuff? This is not what I would expect.

But doing that leaves another issue: I can't find a function to iterate all owned familiars. So I need to parse the terrarium page manually, or maintain a list of familiars in my script to check against?
Code:
foreach it in $familiars[]
{
	if ( have_familiar( it ) ) print( it );
}
That should be easy to modify to something more useful. But it shouldn't be needed either.

How do other scripts deal with this?
I expect they use
Code:
equip( $item[astral pet sweater] )
and it handles everything.

It may or may not be useful, but you can create a familiarScript to augment or bypass mafia's normal familiar equipment handling when switching familiars.
 

Linknoid

Member
OK, I went back and explicitly tested it. You are correct, it does equip properly. I should have tested it before posting. But I think I now remember why I coded in the "remove equipment before swap familiars".

It must be because the script couldn't tell that I actually had the equipment to equip it. Normally I check for owning a piece of equipment like this (intentionally ignore stuff in the closet and storage):

"eq.item_amount() > 0 || eq.have_equipped()"

Is there something simple I can add to my check to see if it's on an inactive familiar? Or do I need to parse the terrarium HTML for a list of familiars and query each one for active equipment?
 

lostcalpolydude

Developer
Staff member
You already pointed out that you can iterate over familiars and checked familiar_equipped_equipment() for each one, so you don't need to visit the page to check. Maybe there was a time when you tried equipping something you didn't have at all (astral pet sweater when you took something else)? That would lead to problems if you didn't check.
 

Linknoid

Member
In case there's not a better way, here's what I came up with for getting a list of owned familiars:

Code:
familiar[int] GetFamiliarList()
{
    string page = visit_url("familiar.php");
    static string findStr = " onClick='fam(";

    familiar[int] result;

    if (my_familiar().to_string() != "none")
        result[my_familiar().to_int()] = my_familiar();

    int ix = page.index_of(findStr);
    while (ix > 0)
    {
        ix += findStr.length();
        string familiarStr = page.substring(ix, ix + 4); // up to 4 digits
        // strip off up to 3 non-digits from the end
        familiarStr = familiarStr.replace_string(")", "");
        familiarStr = familiarStr.replace_string("'", "");
        familiarStr = familiarStr.replace_string(">", "");
        familiarStr = familiarStr.replace_string(" ", "");
        print("parsing string " + familiarStr);
        int familiarId = familiarStr.to_int();
        if (familiarId > 0)
        {
            familiar f = familiarId.to_familiar();
            if (f.to_string() != "none" && page.contains_text(f.to_string()))
            {
                result[familiarId] = f;
            }
        }
        ix = page.index_of(findStr, ix);
    }
    return result;
}

Which can then be cached and used as a reference to lookup equipment like this:

Code:
familiar[int] list = GetFamiliarList();
foreach id, fam in list
{
    print("familiar " + fam + " wearing " + familiar_equipped_equipment(fam));
}
 

Linknoid

Member
You already pointed out that you can iterate over familiars and checked familiar_equipped_equipment() for each one, so you don't need to visit the page to check. Maybe there was a time when you tried equipping something you didn't have at all (astral pet sweater when you took something else)? That would lead to problems if you didn't check.

Actually, I was pointing out I couldn't find a way to iterate familiars. Maybe there is a way, but I couldn't find it in the documentation. So I wrote a parsing routine in ash until I can find a better solution.
 

lostcalpolydude

Developer
Staff member
Oh, I thought the code block in my first post would lead you to that.

You don't actually need to check if you have a familiar, so
Code:
foreach fam in $familiars[]
{
    if ( familiar_equipped_equipment(fam) != $item[none] )
    {
        print("familiar " + fam + " wearing " + familiar_equipped_equipment(fam));
    }
}
You don't actually need the if check there, but it lets you skip printing a bunch of familiars with no equipment.
 

Linknoid

Member
Oh yes, excellent, $familiars[] is a much simpler way to initialize the list than my parsing routine. Thanks!

Sorry I missed it the first time.
 
Top