Aller au contenu

Photo

How do I destroy body bags


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

#1
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
I want to clear body bags from a couple of areas and I made a script to do it, but I can't run it from the console - it returns unsuccessful.


Here is the script:

//destroys body bag in the 2023

void main ()
{
object oArea = GetObjectByTag("area_2023");
object oObject = GetFirstObjectInArea(oArea);
string sTag;
while (GetIsObjectValid(oObject))
 {
 sTag = GetTag(oObject);
 if (sTag=="BodyBag")
  {
  SetPlotFlag(oObject,FALSE);
//  SetImmortal(oObject,FALSE);
  DestroyObject(oObject);
  oObject = GetFirstObjectInArea(oArea);
  }
 else
  {
  oObject = GetNextObjectInArea(oArea);
  }
 }
}

#2
kevL

kevL
  • Members
  • 4 075 messages
hey Matt,

i just did some tests on this (well, i ran it a few times ...)

Some things i noticed:
- console reported "unsuccessful" but, having put in a SendMessageToPC() it *did* run, and found a bunch of objects - in fact, *way too many* with sTag == "BodyBag" !
- when i ran it with a Companion selected it destroyed a corpse (not a bodybag), but then when switched to run from mainPC it actually seemed to clean up some stuff (even that pale blue glowing VFX that bothers me). So maybe it has to run from a particular object, like mainPC perhaps.


gonna play with this at leisure,



Edit, oops forgot to change the Area ..... Image IPB

Modifié par kevL, 15 janvier 2012 - 08:48 .


#3
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
Wow, KevL, good testing. There are certainly some peculiarities with body bags. It would be nice to get a reliable script to clean them up, though.

#4
Dann-J

Dann-J
  • Members
  • 3 161 messages
It may be that objects aren't destroyed while the script is running, but rather queued up in some way to be deleted when the script ends. If that's the case, then using GetFirstObjectInArea again after destroying the first one found may be putting you in an infinite loop.

You could try something like this:

void main ()
{
object oArea = GetObjectByTag("area_2023");
object oObject = GetFirstObjectInArea(oArea);
string sTag;
while (GetIsObjectValid(oObject))
{
sTag = GetTag(oObject);
if (sTag=="BodyBag")
{
SetPlotFlag(oObject,FALSE);
DestroyObject(oObject);
}// end if
oObject = GetNextObjectInArea(oArea);
}// end while
}

This script will loop through *all* objects (creatures, placeables, lights, doors, etc). Personally, I'd put an iPoint in each area with a tag of [areatag]_obj (or whatever suffix you want), then use GetNearestObject based on that, and specifying OBJECT_TYPE_PLACEABLE. That would speed things up considerably in complex areas.

#5
kevL

kevL
  • Members
  • 4 075 messages

DannJ wrote...

using GetFirstObjectInArea again ... may be putting you in an infinite loop.


yep.
- found some more stuff out. oArea defaults to area of the caller. More importantly, the bodybag has to be empty. here's my test script:

// mr_destroy
void main ()
{
	object oPC = GetFirstPC(FALSE);
	string sTag;

	object oObject = GetFirstObjectInArea();
	while (GetIsObjectValid(oObject))
	{
		sTag = GetTag(oObject);
		if (sTag == "BodyBag")
		{
			SendMessageToPC(oPC, "found a BodyBag");
			SendMessageToPC(oPC, ". " + GetName(oObject));
			SetPlotFlag(oObject, FALSE);
			SetImmortal(oObject, FALSE);
			AssignCommand(oObject, SetIsDestroyable(TRUE, FALSE, FALSE));
			DelayCommand(0.1f, DestroyObject(oObject));
		}
		oObject = GetNextObjectInArea();
	}
}


In some ways it's overkill, but the bodybag has to be empty, it seems. You could try writing a subroutine that goes through the Inventory of "BodyBag" and delete the stuff ...

// Get the first item in oTarget's inventory (start to cycle through oTarget's
// inventory).
// * Returns OBJECT_INVALID if the caller is not a creature, item, placeable or store,
//   or if no item is found.
object GetFirstItemInInventory(object oTarget=OBJECT_SELF);

// Get the next item in oTarget's inventory (continue to cycle through oTarget's
// inventory).
// * Returns OBJECT_INVALID if the caller is not a creature, item, placeable or store,
//   or if no item is found.
object GetNextItemInInventory(object oTarget=OBJECT_SELF);


- not sure how that plays with stacks of items tho

oh, Virtual Machine reports successful,

#6
kevL

kevL
  • Members
  • 4 075 messages
ps. good idea, DJ
& perhaps cover everything up by running it from the OnExitArea event

DannJ wrote...

This script will loop through *all* objects (creatures, placeables, lights, doors, etc). Personally, I'd put an iPoint in each area with a tag of [areatag]_obj (or whatever suffix you want), then use GetNearestObject based on that, and specifying OBJECT_TYPE_PLACEABLE. That would speed things up considerably in complex areas.


though BodyBags might be OBJECT_TYPE_ITEM .. *shurg

#7
Dann-J

Dann-J
  • Members
  • 3 161 messages
I've always wanted to toy with the idea of hiring a local boy to run around after a battle and pick up anything left in body bags. I might just build on your ideas kevL, and see if I can write a script that moves items from all those body bag inventories to a chest somewhere, so the PC can sort through the items at their leisure and not have to pick them up one at a time like some potato-picking commoner. You'd just have to give the lad the name of the area, and a bit of gold for his trouble, and off he'd go.

You'd have to be careful how you went about it though. Giving a young boy money and then asking him to rumage around in your junk could conceivably be misinterpreted.

#8
The Fred

The Fred
  • Members
  • 2 516 messages
Having actual scavengers is a nice idea. It reflects the fact that things left lying around don't normally stay that way. In Baldur's Gate I remember that things left on the ground disappeared after a while, though they weren't carried off by anyone or anything.

#9
Dann-J

Dann-J
  • Members
  • 3 161 messages

kevL wrote...

ps. good idea, DJ
& perhaps cover everything up by running it from the OnExitArea event

DannJ wrote...

This script will loop through *all* objects (creatures, placeables, lights, doors, etc). Personally, I'd put an iPoint in each area with a tag of [areatag]_obj (or whatever suffix you want), then use GetNearestObject based on that, and specifying OBJECT_TYPE_PLACEABLE. That would speed things up considerably in complex areas.


though BodyBags might be OBJECT_TYPE_ITEM .. *shurg


That depends on what exactly body bags are. If they have an inventory of their own, then chances are they're usable placeables. However I wouldn't be surprised if body bags were some sort of special object  hard-coded into the game (which would make scripting for them very difficult). I'm hoping for the former.

#10
kevL

kevL
  • Members
  • 4 075 messages
Did anyone spend time on the NwN persistent world of Nordock? There's a large area full of badgers/deers/panthers/etc that was for getting crafting pelts. And there was a little pixie that slowly flew around cleaning up ... it was really cool

anyway,

#11
Dann-J

Dann-J
  • Members
  • 3 161 messages
Here's a loot collecting script that I've tested. It turns out that the easiest way to destroy body bags is to remove all their contents. Then they disappear by themselves.

A variation of this (using GetFirst/NextObjectInShape) could be used in a 'wand of loot collection' that transfers all body bag items within a certain radius of the player into their inventory (much like the looting button in Sacred II).

I wonder if you could transfer the items to a store object? Something else to test...


// Transfer all items in body bags in an area to a container or creature
// Body bags will then disappear
//
// sOriginTag = tag of object in the area to loot (blank uses conversation owner)
// sChestTag = tag of the chest or creature to move items to (blank uses PC speaker)

#include "x0_i0_corpses"

void main(string sOriginTag, string sChestTag)
{
object oOrigin = OBJECT_SELF;
if (sOriginTag != "")
oOrigin = GetObjectByTag(sOriginTag);

object oLootChest = GetPCSpeaker();
if (sChestTag != "")
oLootChest = GetObjectByTag(sChestTag);

int i = 1;
object oLoot = GetNearestObject(OBJECT_TYPE_PLACEABLE, oOrigin, i);

while ( GetIsObjectValid(oLoot) )
{
i++;
if ( GetTag(oLoot) == "BodyBag")
{
LootInventory(oLoot, oLootChest);
}//end if
oLoot = GetNearestObject(OBJECT_TYPE_PLACEABLE, oOrigin, i);
}//end while

}

Modifié par DannJ, 16 janvier 2012 - 09:44 .