Monday, July 14, 2014

Clothing Update Part I

So, it feels like I've been working on Roodylib a lot over the last few weeks.  It'll be interesting when I put up the next official release and go over all of the updates one last time for the changelog.

Robb Sherwin has been looking to get his game Cryptozookeeper sold online at places such as Steam and Desura, so I've been looking over the code to suggest tweaks to make this or that more user-friendly to those not familiar with IF.  Anyhow, looking at some of the things that game does made me go, "oh yeah, that probably should be an option in Roodylib!" on several occasions.

One thing CZK does is list worn clothing items before listing the rest of the inventory.  I actually wrote that code in the first place, but I didn't like how it replaced SpecialDesc in such an awkward way.  I felt, this time around that, hey, Roodylib can do it better!

So, first off, Roodylib has a new LIST_CLOTHES_FIRST flag that you should set if you want to run the new code. Then, for any character you want clothing to be automatically listed for, you add this:


    list_contents
        return ListClothesFirst(self)

Interestingly, ListClothesFirst only returns true if the character is wearing all of their belongings (this keeps an extra space from being printed after the worn-clothing list).  If you have an NPC where you only want clothing and held items to be listed when you examined them (and not in room descriptions), you could do this:


    list_contents
    {
        if verbroutine = &DoLookAround
            return true
        else
            return ListClothesFirst(self)
    }


Here is a screenshots of this system in action:




So, let's take a look at how this works. First off, of course, there's that ListClothesFirst routine:


routine ListClothesFirst(char)
{
    local x,w,c, list_save, v
    v = verbroutine
    verbroutine = &ListClothesFirst
    list_save = list_count
    list_count = 0
    for x in char
    {
        if x is worn and x is clothing
        {
            w++
            list_count++
        }
        elseif x is not hidden
        {
            x is already_listed
            c++
        }
    }
    if w and c
        list_nest = 1
    if list_count
    {
        if v ~= &DoInventory
            Indent
        if v = &DoLook
            FORMAT = FORMAT | USECHARNAMES_F
        RLibMessage(&ListClothesFirst,1,char) ! "You are wearing"
        ListObjects(char)
        if FORMAT & USECHARNAMES_F
            FORMAT = FORMAT & ~USECHARNAMES_F
        else
            FORMAT = FORMAT & ~USECHARNAMES_F
        list_nest = 0
    }
    for x in char
    {
        if x is not worn or (x is not clothing and x is worn)
            x is not already_listed
        else
        {
            AddSpecialDesc(x) ! tags worn items as already_listed
        }
    }
    verbroutine = v
    list_count = list_save - w
    return (not c and w)
}

It checks to see if any objects are worn, lists them, and marks them as already_listed.  I also needed to add this bit to ListObjects:


The ClothingCheck routine makes sure that children of worn clothing items aren't listed a second time (as they were listed by the ListClothesFirst routine).  There's also some code to make sure character names are used when it might be confusing.

Anyhow, here is the ClothingCheck routine:


routine ClothingCheck(a)
{
#ifset LIST_CLOTHES_FIRST
    if (a is worn and a is clothing and verbroutine ~= &ListClothesFirst) or
        (a is not worn and verbroutine = &ListClothesFirst)
        return true
    else
#endif
        return false
}


As you see, it has to check the verbroutine (which ListClothesFirst temporarily sets).

Anyhow, part of the reason I break this all down is because it's very possible you'll want to split up your player's or characters' inventories in other ways, and hopefully this is enough of a blueprint to get you on your way.

(All of this will be in the next official Roodylib release... coming soon!)

No comments:

Post a Comment