Author Topic: How to make the Beggar take up itens automatically on the ground?  (Read 994 times)

Legacy_WhiteTiger

  • Hero Member
  • *****
  • Posts: 889
  • Karma: +0/-0


               

So, I am trying to make the Beggar take itens dropped in your around, possibly these settings must be made in OnPerception Event.


If it sees an item on the ground, have it picked up and added it to his inventory.


 


It's possible? write yours suggestions on comments please


 


Thanks all.


 


 


beggar.jpg


 


SOLVED.


Add this to Creature Beggar OnHeartBeat event - especifically (save as a copy if you're using the original onheartbeat script).



//////////////////////////////////////////////////////////////
///////////////SCRIPT By WhiteTiger and henesua///////////////
//////////////////////////////////////////////////////////////
 
    //START - Beggar Pick Up Items
            object oItem = GetFirstObjectInShape(SHAPE_SPHERE, 25.0, GetLocation(OBJECT_SELF), TRUE, OBJECT_TYPE_ITEM);
            if (oItem!=OBJECT_INVALID)
    {
        ClearAllActions();
        ActionPickUpItem(oItem);
        return;
    }
    //END
 
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////


               
               

               


                     Modifié par WhiteTiger, 13 mars 2014 - 10:30 .
                     
                  


            

Legacy_Proleric

  • Hero Member
  • *****
  • Posts: 1750
  • Karma: +0/-0
How to make the Beggar take up itens automatically on the ground?
« Reply #1 on: March 09, 2014, 11:28:24 pm »


               Certainly possible, but the OnPerception event is for creatures, not items.


You could use the module OnUnacquireItem event; when the PC drops an item in the beggar 's area, and the beggar sees it (GetObjectSeen), action him to pick it up.
               
               

               
            

Legacy_The Mad Poet

  • Hero Member
  • *****
  • Posts: 715
  • Karma: +0/-0
How to make the Beggar take up itens automatically on the ground?
« Reply #2 on: March 09, 2014, 11:35:02 pm »


               

I think I recall something called a 'Trash Fairy' script. I tried looking, but I couldn't find it. It was a fairy that spawned into areas when there were items left loose for so long. It ran around and picked them up, then destroyed itself.


 


It isn't exactly what you looking for... but I can't see why it can't be changed a bit to work what you want. If anyone can find it anyway.



               
               

               
            

Legacy_WhiteTiger

  • Hero Member
  • *****
  • Posts: 889
  • Karma: +0/-0
How to make the Beggar take up itens automatically on the ground?
« Reply #3 on: March 10, 2014, 01:58:12 am »


               

1.Thanks, Proleric. Then now I'll not work with OnPerception events.


I'm thinking about starting to do module OnUnacquireItem script using this:


What's the "When the PC Drops an item in the beggar's area"?


 


2. Thanks, The Mad Poet. The item does not need to necessarily be with the beggar, this was to kill then and recover the itens. And its not need to work as a cleaning map itens, but the beggar should pick the item quickly. But it would be good if you can post the link of this system.



               
               

               


                     Modifié par WhiteTiger, 10 mars 2014 - 04:19 .
                     
                  


            

Legacy_Proleric

  • Hero Member
  • *****
  • Posts: 1750
  • Karma: +0/-0
How to make the Beggar take up itens automatically on the ground?
« Reply #4 on: March 10, 2014, 08:13:30 am »


               You can determine whether the PC and the beggar are in the same area using GetArea.

I'm not clear now whether you're looking for realistic behaviour from the beggar, in a fixed place, or whether you want to sweep several areas for discarded items occasionally?

If it's the latter, you'd need to spawn the beggar into the area from time to time, or else when there's an item to collect. You could tell the beggar to home in on the items, or, less efficiently, have them wander around until they see one. Note that if the PC has left the area, the beggar will become almost inactive, unless you bump up his AI level.

If the beggar's activity is not simultaneous with the item drop, you'll need a way of knowing which items the beggar can retrieve. Using OnUnacquireItem, you could make a list of discarded items, using local variables on the module, area or PC. However, you might find it easier to use the area OnHeartbeat event, cycling through the objects in the area until you find an item.

All this is assuming that you're changing the official campaign or a single player module. If you're thinking about a PW, there are significant efficiency issues, which the PW experts here can tell you about.
               
               

               
            

Legacy_Pstemarie

  • Hero Member
  • *****
  • Posts: 4368
  • Karma: +0/-0
How to make the Beggar take up itens automatically on the ground?
« Reply #5 on: March 10, 2014, 10:40:26 am »


               

You could use the module OnUnAcquireItem event. When the PC puts down an item, the beggar walks over to it and picks it up, placing it in his inventory. No need for raising the AI of the beggar or sweeping the area for the item. To make the beggar wander the area, make sure you are using the XP2 Monster AI scripts for its script events and then just assign the int variable X2_L_SPAWN_USE_AMBIENT = 1 to make the beggar move around the area. 


 


The beggar will move around randomly until the PC drops an item, at which point, he will head straight for it and pick it up. If you want the beggar to stay alive, set his Plot flag to TRUE (i.e. check the box under the Basic tab in the Creature Properties window.


 


Place this code in your modules UnAcquireItem event...


 


void doPickupItem(object oItem)
{
    ActionMoveToObject(oItem); // OR
    //ActionMoveToLocation(GetLocation(oItem));
    ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0, 4.0);
    ActionPickUpItem(oItem);
}
 
void main ()
{
     //existing code
 

    // * Looting Beggar Custom Code
    if (!GetIsObjectValid(oOwner)) //confirm item was dropped - might be better way to do this
    {
        object oBeggar = GetNearestObjectByTag("LOOT_BEGGAR", oPC);
        if (GetIsObjectValid(oBeggar))
        {
            AssignCommand(oBeggar, ClearAllActions());
            AssignCommand(oBeggar, doPickupItem(oItem));
        }
    }     

}

               
               

               
            

Legacy_WhiteTiger

  • Hero Member
  • *****
  • Posts: 889
  • Karma: +0/-0
How to make the Beggar take up itens automatically on the ground?
« Reply #6 on: March 10, 2014, 01:43:36 pm »


               

Proleric,


 


Yes, it's a realist action.


 


Pstemarie,


 


Thanks for the contribution script. The commoner Beggar are created by a Painting Encounters, so he is free to walk around the area.


My OnUnacquire Event module are using this information:


 


    object oItem = GetModuleItemLost();

    object oPC = GetModuleItemLostBy();

    object oCurrentPossessor = GetItemPossessor(oItem);

 

What's the setup do you mean with oBeggar and oOwner?


               
               

               
            

Legacy_Pstemarie

  • Hero Member
  • *****
  • Posts: 4368
  • Karma: +0/-0
How to make the Beggar take up itens automatically on the ground?
« Reply #7 on: March 10, 2014, 02:02:14 pm »


               


 


Pstemarie,


 


Thanks for the contribution script. The commoner Beggar are created by a Painting Encounters, so he is free to walk around the area.


My OnUnacquire Event module are using this information:


 


    object oItem = GetModuleItemLost();

    object oPC = GetModuleItemLostBy();

    object oCurrentPossessor = GetItemPossessor(oItem);

 

What's the setup do you mean with oBeggar and oOwner?

 




 


In the script snibbets I posted above - which was inserted into the default BioWare module OnAquireItem script - if oItem doesn't have an owner (object oOwner is OBJECT_INVALID), then oItem must have been placed on the ground and is thus free to pickup by the beggar.


 


You could also extend this by giving the beggar a store. After all, what good are all the items he's picked up if he can't trade for coin with which to buy whiskey?



               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
How to make the Beggar take up itens automatically on the ground?
« Reply #8 on: March 10, 2014, 02:13:32 pm »


               

Pstemarie - I think he was asking how your object labels work with his object labels.


 


I think they go as follows:


oCurrentPossessor   = oOwner


oBeggar is defined by Pstemarie's script.



               
               

               
            

Legacy_WhiteTiger

  • Hero Member
  • *****
  • Posts: 889
  • Karma: +0/-0
How to make the Beggar take up itens automatically on the ground?
« Reply #9 on: March 10, 2014, 04:12:29 pm »


               

Pstemarie,


"You could also extend this by giving the beggar a store. After all, what good are all the items he's picked up if he can't trade for coin with which to buy whiskey?" yeah, good idea


 


henesua,


 


object oOwner = GetItemPossessor(oItem);


 


object oPC = GetModuleItemLostBy();


 


OK.


 


EDITED*


 


OK, all working fine.



               
               

               
            

Legacy_WhiteTiger

  • Hero Member
  • *****
  • Posts: 889
  • Karma: +0/-0
How to make the Beggar take up itens automatically on the ground?
« Reply #10 on: March 10, 2014, 05:20:22 pm »


               

Sometimes he tries to get the item, but another action cancels. The beggar is subject to move constantly time by time and this cancell the pickuping item. Do not have a function that can help us?



               
               

               
            

Legacy_The Mad Poet

  • Hero Member
  • *****
  • Posts: 715
  • Karma: +0/-0
How to make the Beggar take up itens automatically on the ground?
« Reply #11 on: March 10, 2014, 06:28:45 pm »


               

//Treasure trash Fairy
//Modified Heartbeat script based on the funky trash fairy script by
//Undead Waiter.
//Instead of collecting items dropped by players, this fairy loots the
//bodybags of dead monsters. A script developed as my module slowed
//severely when people left treasure they didn't want.
//As with the trash fairy, set character to plot and place this script in
//the on heartbeat event script of it. Set the creature to SLOW or V.SLOW
//to give players the time to decide whethere they want the treasure or
//not.
//Adjust perception as needed.


// Created 7.27.2002 by Undead Waiter
// Modified 16th April 2003 by Ogotu.
void main()
{
//Main variable declarations
int iResetValue = GetLocalInt(OBJECT_SELF, "ResetNumber");
//For Multiple faires that work together, change this for each fairy
//and save the H/B script as a different name.
//Note first will attract the fairy to the first object spawned
//object oBodyBagDestroy = GetObjectByTag("BodyBag",0);
object oBodyBagDestroy = GetObjectByTag("BodyBag",1);
//object oBodyBagDestroy = GetObjectByTag("BodyBag",2);
//object oBodyBagDestroy = GetObjectByTag("BodyBag",3);
//object oBodyBagDestroy = GetObjectByTag("BodyBag",4);
int iHasInventory = GetHasInventory(oBodyBagDestroy);

//Make sure no one has created an item called "BodyBag" by checking for an
//inventory
if (iHasInventory == TRUE)
  {
     if (oBodyBagDestroy != OBJECT_INVALID)

        {

         //I know, i'm just too lazy to do a loop.
         ActionMoveToObject(oBodyBagDestroy,FALSE,100.0);
         ActionTakeItem(GetFirstItemInInventory(oBodyBagDestroy),oBodyBagDestroy);
         ActionTakeItem(GetNextItemInInventory(oBodyBagDestroy),oBodyBagDestroy);
         ActionTakeItem(GetNextItemInInventory(oBodyBagDestroy),oBodyBagDestroy);
         ActionTakeItem(GetNextItemInInventory(oBodyBagDestroy),oBodyBagDestroy);
         ActionTakeItem(GetNextItemInInventory(oBodyBagDestroy),oBodyBagDestroy);
         ActionTakeItem(GetNextItemInInventory(oBodyBagDestroy),oBodyBagDestroy);
         ActionTakeItem(GetNextItemInInventory(oBodyBagDestroy),oBodyBagDestroy);
         ActionTakeItem(GetNextItemInInventory(oBodyBagDestroy),oBodyBagDestroy);
         ActionTakeItem(GetNextItemInInventory(oBodyBagDestroy),oBodyBagDestroy);
         ActionTakeItem(GetNextItemInInventory(oBodyBagDestroy),oBodyBagDestroy);
         ActionTakeItem(GetNextItemInInventory(oBodyBagDestroy),oBodyBagDestroy);
         ActionTakeItem(GetNextItemInInventory(oBodyBagDestroy),oBodyBagDestroy);
         //Too lazy here too
         ActionDoCommand(DestroyObject(GetFirstItemInInventory(OBJECT_SELF)));
         ActionDoCommand(DestroyObject(GetNextItemInInventory(OBJECT_SELF)));
         ActionDoCommand(DestroyObject(GetNextItemInInventory(OBJECT_SELF)));
         ActionDoCommand(DestroyObject(GetNextItemInInventory(OBJECT_SELF)));
         ActionDoCommand(DestroyObject(GetNextItemInInventory(OBJECT_SELF)));
         ActionDoCommand(DestroyObject(GetNextItemInInventory(OBJECT_SELF)));
         ActionDoCommand(DestroyObject(GetNextItemInInventory(OBJECT_SELF)));
         ActionDoCommand(DestroyObject(GetNextItemInInventory(OBJECT_SELF)));
         ActionDoCommand(DestroyObject(GetNextItemInInventory(OBJECT_SELF)));
         ActionDoCommand(DestroyObject(GetNextItemInInventory(OBJECT_SELF)));
         ActionDoCommand(DestroyObject(GetNextItemInInventory(OBJECT_SELF)));
         ActionDoCommand(DestroyObject(GetNextItemInInventory(OBJECT_SELF)));
         ActionDoCommand(DestroyObject(GetNextItemInInventory(OBJECT_SELF)));
         ActionDoCommand(DestroyObject(GetNextItemInInventory(OBJECT_SELF)));
        }
   }
}

This is the one I found from ' http://nwvault.ign.c....Detail&id=1731 '


 


Looking at it now... I'm sure there is a much better way to do this then what this code is. But maybe it'll spark an idea.



// Modified Trash Fairy
// Place on HeartBeat of your trash fairy
// Kudos to the original Trash Fairy Authors

void DestroyIfNoOwner (object oItem)
    {
    object oHolder = GetItemPossessor(oItem);
    if ((oHolder == OBJECT_INVALID) || (GetTag (oHolder) == "BodyBag"))
        DestroyObject (oItem);
    }

void main()
{
object oItem = GetNearestObject(OBJECT_TYPE_ITEM);
object oInventory;
if (oItem == OBJECT_INVALID)
    oItem = GetNearestObjectByTag ("BodyBag");

if (oItem != OBJECT_INVALID)
    {
    ActionMoveToObject(oItem);

    if (GetHasInventory (oItem))
        {
        oInventory = GetFirstItemInInventory (oItem);
        while (oInventory != OBJECT_INVALID)
            {
            ActionDoCommand (DestroyIfNoOwner (oInventory));
            oInventory = GetNextItemInInventory (oItem);
            }
        }
    else
        {
        ActionDoCommand(DestroyIfNoOwner(oItem));
        }
    }
}

This is the second one I found from ' http://nwvault.ign.c....Detail&id=2203 '


 


This one looks a little better anyway. Still a HB script though. You could probably make a similar effect by making it work OnEnter though with a trigger, or as was suggested on the UnAcquire. Then there is the all famous Pseudo HB. I'm not sure what method would be best for you, and I'm not sure which is the best use of resources. Personally... I'd go with the UnAcquired script. That one fires less often, and only when there actually is something to pick up. Far as I know with scripting the usual answer is 'Less is More'.


 


 




Sometimes he tries to get the item, but another action cancels. The beggar is subject to move constantly time by time and this cancell the pickuping item. Do not have a function that can help us?





 


If your running the animations from the ambient system then they are probably firing off and interfering. I've had that problem before when scripting actions. Maybe once the script starts you can find a way to disable them until they're done picking up the garbage? Maybe removing the variable from the beggar, then giving it back after 30 seconds or so would work? I'm not THAT familiar with the ambient animations, so I'm unsure.



               
               

               
            

Legacy_WhiteTiger

  • Hero Member
  • *****
  • Posts: 889
  • Karma: +0/-0
How to make the Beggar take up itens automatically on the ground?
« Reply #12 on: March 10, 2014, 07:01:32 pm »


               

Pstemarie help us with a nice system. Possibly we will not need more the Trash Fairy script for now. The problem is that the beggar has a time to complete the action to pick up the item from the floor, the duration is 1 second to 4 seconds was chosen in


 


ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0, 4.0);


 


If waypoint call Beggar before 4 seconds playing animation to walk out, the ActionPickUpItem(oItem); does not occur.


 


PS: I already tryied reduce/remove the animation time, it isn't a good way to solve it.



               
               

               
            

Legacy_The Mad Poet

  • Hero Member
  • *****
  • Posts: 715
  • Karma: +0/-0
How to make the Beggar take up itens automatically on the ground?
« Reply #13 on: March 10, 2014, 07:06:34 pm »


               


Pstemarie help us with a nice system. Possibly we will not need the script Trash Fairy now. But the problem is that the beggar has a time to complete the action to pick up the item from the floor, the duration is 1 second to 4 seconds was chosen in


 


ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0, 4.0);


 


If waypoint call Beggar before 4 seconds playing animation to walk out, the ActionPickUpItem(oItem); does not occur.




 


Oh... you got both actions running and it que's the other out. Well timing is the only solution I can think of. You can delay it I believe... something like:


 


ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0, 4.0);



DelayCommand(4.5f,ActionPickUpItem(oItem));


 

Then the action to pick up the item shouldn't be up until after the animation is already done.


               
               

               
            

Legacy_WhiteTiger

  • Hero Member
  • *****
  • Posts: 889
  • Karma: +0/-0
How to make the Beggar take up itens automatically on the ground?
« Reply #14 on: March 10, 2014, 08:31:32 pm »


               

This don't work... We need disable AI (Artificial inteligence).


 


first


 


SetAILevel(oBeggar, AI_LEVEL_VERY_LOW); 


 


after


 


DelayCommand(10.0, SetAILevel(oBeggar, AI_LEVEL_NORMAL));