Aller au contenu

Photo

"Custom" Bodybags [solved]


  • Veuillez vous connecter pour répondre
4 réponses à ce sujet

#1
BillHoyt

BillHoyt
  • Members
  • 109 messages
I have a script that can spawn items into an existing level; unfortunately that requires the PC to leave the area while the item is spawned on re-entry. But I wanted to spawn an item "under his feet," so to speak, so I got the idea to use the SpawnBodyBag function to spawn an item immediately.  The only problem is that the item I wish to spawn is not a normal bodybag.  In this case, it's a carpet.

The quest is simple: place a silk carpet inventory item in a pre-determined spot on the floor and the carpet will appear.  To accomplish that, I created an invisible container on the floor which will be destroyed upon successful carpet placement, then I will spawn a bodybag where the placeable used to be.

The pleaceable script (in part) is below:

case EVENT_TYPE_INVENTORY_ADDED:
        {
        // add IF statement here to ensure that item inserted is
        // a silk carpet:
           object[] oInventory = GetItemsInInventory(OBJECT_SELF, GET_ITEMS_OPTION_ALL,
           0,"gen_im_treas_silcarp");
           object oCarpet = GetObjectByTag("gen_im_treas_silcarp");
               
             // IF item is silk carpet
                WR_SetPlotFlag(PLT_INTERIOR_DECORATION, CARPET1_PLACED, TRUE);
                Safe_Destroy_Object(OBJECT_SELF);
                SpawnBodyBag(OBJECT_SELF,TRUE);
            break;
        }

The problem is twofold.  The easy part ought to be determining if the correct item is placed in the container. But while I have tried comparing oInventory and oCarpet, I seem to get weird compiler errors, so I need some way to determine if the case is "true," i.e. if  gen_im_treas_silcarp was placed in the container's inventory.

The second problem is harder.  Bodybags are defined in APR_base.XLS, and there is no bodybag defined for the placeable (let's call it "spot_on_the_floor".) So how do I create an override of  APR_base.XLS without actually changing the file?

Any help (even to tell me this is a stupid idea that will never work) would be appreciated.

Modifié par BillHoyt, 16 avril 2010 - 08:48 .


#2
TimelordDC

TimelordDC
  • Members
  • 923 messages
oInventory is an array of objects while oCarpet is an object. You cannot compare them directly. This should give you the object being added to the inventory -
object oItem = GetEventObject(ev, 0);


To add to APR_base, you need to extend it using an M2DA -> basically the APR_base worksheet with just your new entry for the bodybag with a unique ID; process it into a .GDA and place it in your module override folder.

Edit: You cannot destroy the placeable in the placeable script and spawn something. You should handle that in the plot script under the plot flag you are setting.

Modifié par TimelordDC, 14 avril 2010 - 07:54 .


#3
BillHoyt

BillHoyt
  • Members
  • 109 messages
Thanks, TimelordDC, that helps a lot. For those of you following along at home, here's the working part of the placeable script that notes when a specific object is placed in a container:

//----------------------------------------------------------------------
// Checks for silk carpet in inventory.
//----------------------------------------------------------------------
case EVENT_TYPE_INVENTORY_ADDED:
{
    object oItem = GetEventObject(ev, 0);
    if (oItem == GetObjectByTag("gen_im_treas_silkcarp",0))
     { 
        Safe_Destroy_Object(oItem); //to prevent removal of carpet
        Safe_Destroy_Object(OBJECT_SELF); //container destroyed on close
        WR_SetPlotFlag(PLT_INTERIOR_DECORATION, CARPET1_PLACED, TRUE);
     }
    break;
}

Two lines of interest deserve separate comments. The first is the Safe_Destroy_Object on oItem. This is done because the quest is fulfilled on placing the item in the container, but the container is not destroyed until it is closed.  That leaves the PC the "bug" opportunity to put the item in the container (thus completing the quest) and taking it back out before closing the container. When oItem is safe_destroyed, it never shows up in the container's inventory at all; it just "disappears" as you hear the familiar and relaxing sound of Quest Completed. 

The second line of interest if the safe_destroy of OBJECT_SELF.  As I mentioned, this occurs when the container is closed and it will destroy any object within it. So if you put Grandma's dentures in there along with a silk carpet, well, she's going to be eating a lot of jello unless you take them out before you close it. But the container just acts as a persistent container for any other object, until it is destroyed by putting a carpet in it.

The APR_base Override I think I can handle, as it looks pretty straightforward, but I am curious about handling the spawn in the plot script.  I obviously can't use a SpawnBodyBag(OBJECT_SELF,TRUE) there, as the OBJECT_SELF is no longer the same as in the item script.  Can you give me an idea what the CASE statement there ought to look like?

-- I apologize for asking to be led by the hand, but I'm an old-school COBOL programmer (the icon is not as inappropriate as I would like) and so C and C++ are pretty new to me, like "2 weeks" new. --

#4
TimelordDC

TimelordDC
  • Members
  • 923 messages
First, I didn't know that the EVENT_TYPE_INVENTORY_ADDED fired only when the inventory screen was closed. I will keep that in mind.

Second, aren't BodyBags only for creatures? Even otherwise, if you set the carpet as the custom bodybag of the invisible placeable, it will be lootable; the carpet (bodybag) itself will not go into the player's inventory. Is this what you want?
If so, you can do that in the EVENT_TYPE_DEATH event in the placeable script -> that should work, I haven't tested it.

Sorry for my initial suggestion about the plot script suggestion. I assumed SpawnBodyBag was spawning the bodybag of some other creature and you had put in OBJECT_SELF by mistake. My bad, I didn't read the first post thoroughly.

#5
BillHoyt

BillHoyt
  • Members
  • 109 messages
EVENT_TYPE_INVENTORY_ADDED fires immediately, but the container itself can't be safe_destroyed until it's closed. You can safe_destroy any item placed into the container while it's still open, just not the container.

Thanks again for the help,

EDIT: Anyway, I gave up on this idea; it turned out much easier just to CreateObject in precisely the same location as the other one was destroyed. The bodybag thing turned out to be a $50 solution to a $2 problem.

Modifié par BillHoyt, 16 avril 2010 - 08:47 .