DestroyObject - Why Does This Function Fail? (RESOLVED)

Hi All,

I have a home-brew function designed to destroy nearby objects with the tag “DESTROYME” in a loop. The problem is that while it works when I use GetNearestObjectByTag for the loop check, it does not when I use GetNearestObject … even though BOTH loops detect the objects to destroy! In the latter loop (using GetNearestObject), only one object is ever destroyed.

Can someone please explain what may going on so it can be used with the latter function.

Thanks in advance!

UPDATE: I updated the function to destroy objects related to their distance from the PC instead (not ideal), and the function worked. I still want the function to work in relation to the original clicked object really. NOTE: Even when I passed the object to the function (without relying on OBJECT_SELF), the function still only destroys the first instance using GetNearestObject. Still hoping someone has a better answer.

void DestroyRelatedObjects();
void DestroyRelatedObjects()
{	
	int nCount = 1; 
	
	object oDestroy = GetNearestObject(OBJECT_TYPE_ALL, OBJECT_SELF, nCount); 	
	//object oDestroy = GetNearestObjectByTag("DESTROYME", OBJECT_SELF, nCount); 
	
	while(oDestroy != OBJECT_INVALID)
	{
		string sTagNear = GetTag(oDestroy);	
		int iVarNear = GetLocalInt(oDestroy, "DESTROYME");
		float fDis = GetDistanceBetween(oDestroy, OBJECT_SELF);			
		
		if(fDis < 3.0) 
		{
			if(sTagNear == "DESTROYME" || iVarNear == 1)
			{				
				// THIS DOES DEBUG THE CORRECT ITEMS TO DESTROY IN BOTH LOOP TYPES
				SendMessageToPC(GetFirstPC(FALSE), GetTag(OBJECT_SELF) + " OBJ NAME>> " + GetName(oDestroy) + " OBJ TAG " + GetTag(oDestroy));			
													
				SetPlotFlag(oDestroy, FALSE);
				AssignCommand(oDestroy, SetIsDestroyable(TRUE, FALSE));
				DelayCommand(0.1, DestroyObject(oDestroy));	
			}
		}
		
		if(fDis >= 3.0){break;}
			
		nCount = nCount + 1; 
		oDestroy = GetNearestObject(OBJECT_TYPE_ALL, OBJECT_SELF, nCount); 
		//oDestroy = GetNearestObjectByTag("DESTROYME", OBJECT_SELF, nCount); 
	}
}

it worked completely as expected here, Lance

fired from the console w/ this script →

void main()
{
	object oDirt = GetNearestObjectByTag("dirtmound");
	AssignCommand(oDirt, DestroyRelatedObjects());
}
1 Like

@kevL_s

Huh? So, using the GetNearestObject as the function in the loop, it worked for you?

If that’s the case, let me explain my current environment, in case it has any bearing …

I have groups of mushrooms … 2 - 3 in a group. A number of these groups are spread around the area.

I make one mushroom the useable one and the others nearby are supposed to be destroyed when it is picked up.

Therefore, the only difference that seems to be here is that you have one “group” compared to my many. Can you drop a few groups around and re-test?

I will try the opposite test with one group in area to see iff I can duplicate your result.

Thanks!

EDIT: Oh my! Something really weird just happened when I tested in one area: Rather than DESTROY all, it recreated one where I took it away!

oh. Try removing the break; if fDist >= 3

//		if(fDis >= 3.0){break;}

 

/lol

@kevL_s

Yes! I have to, else I’d cry!

This is really weird … I did as you said commented out the break, but it still only updates one mushroom!

The one replaced appears to be replacing directly over the original.

so i guess you have an OnUsed script on the usable mushroom? And it destroys itself, and calls DestroyRelatedObjects() to destroy its surrounding mushrooms ? care to post it …

1 Like

@kevL_s

Exactly, yes I will update the version I am testing with now … back in a bit. (This gives a whole new meaning behind “magic mushrooms”!)

I will keep editing this post until completed …

void main()
{
	object oPC = GetPlaceableLastClickedBy();
	if(oPC == OBJECT_INVALID){oPC = GetLastUsedBy();}		
		
	string sPLACETAG = GetTag(OBJECT_SELF);	
	
	xDestroyRelatedObjects();   // "x" version is the local test version of the function
	
	return;	// REST OF MY SCRIPT FOLLOWED
}

CURRENT TEST FUNCTION STATE

void xDestroyRelatedObjects();
void xDestroyRelatedObjects()
{	
	int nCount = 1;  int iTEST = 0;
	
	object oDestroy = GetNearestObject(OBJECT_TYPE_ALL, OBJECT_SELF, nCount); 	
	//object oDestroy = GetNearestObjectByTag("DESTROYME", OBJECT_SELF, nCount); 
	
	while(oDestroy != OBJECT_INVALID)
	{
		string sTagNear = GetTag(oDestroy);	
		int iVarNear = GetLocalInt(oDestroy, "DESTROYME");
		float fDis = GetDistanceBetween(oDestroy, OBJECT_SELF);			
		
		if(fDis < 3.0) 
		{
			if(sTagNear == "DESTROYME" || iVarNear == 1)
			{				
				iTEST = iTEST + 1;
				
				// THIS DOES DEBUG THE CORRECT ITEMS TO DESTROY IN BOTH LOOP TYPES
				SendMessageToPC(GetFirstPC(FALSE), GetTag(OBJECT_SELF) + " OBJ NAME>> " + GetName(oDestroy) + " OBJ TAG " + GetTag(oDestroy) + " NCOUNT> " + IntToString(nCount) + " ITEST> " + IntToString(iTEST));			
																	
				if(iTEST == 1)
				{
					SendMessageToPC(GetFirstPC(FALSE), "GOT 1");
					SetUseableFlag(oDestroy, TRUE);
				}
				
				else
				{
					SendMessageToPC(GetFirstPC(FALSE), "GOT 2");
					SetUseableFlag(oDestroy, TRUE);	
				}			
				
				//SetPlotFlag(oDestroy, FALSE);
				//AssignCommand(oDestroy, SetIsDestroyable(TRUE, FALSE));
				//DelayCommand(0.1, DestroyObject(oDestroy));	
			}
		}
		
		//if(fDis >= 3.0){break;}
			
		nCount = nCount + 1; 
		
		oDestroy = GetNearestObject(OBJECT_TYPE_ALL, OBJECT_SELF, nCount); 
		//oDestroy = GetNearestObjectByTag("DESTROYME", OBJECT_SELF, nCount); 
	}
}
1 Like

(its been a loong time)

ok, will set something up similar to what you’ve described

ps.

iTEST = iTEST + 1;

just do  ++iTEST;

you appear to be using GetNearest*() on the object itself to destroy it … not sure that that is well defined …

probly should destroy the usable mushroom in its OnUsed script* then let the subfunction destroy its accomplices …

* it can be tricky to run a function from an object that’s about to be destroyed, though

@kevL_s

The weird thing is, even if I comment out the objects own destruction (just to check the destruction code is working), I still only get one of the remaining mushrooms destroyed.

i.e. The mushroom is clicked, the function is called, and even though the two nearby DESTROYME mushrooms are found, only one is destroyed. (And the clicked on one remains because I am leaving it undestroyed in the test.)

is the other one nonstatic, has HP, etc etc?

I checked that as well, and I even copied and pasted the one that did work, so I knew they were identical … Also, just to say, I copied and pasted a set of three to a new area (as you know) and now also duplicated that group and tested further and still only ever one is destroyed from each group.

the thing is, If your OBJECT_SELF mushroom (the usable one) gets found and destroyed before all the others, it might stop the destruction process

try a destroy line like this:

AssignCommand(GetModule(), DestroyObject(oDestroy));

this way all the DestroyObject() commands get lined up and executed by the module-object after the script completes.

 
ps. don’t delay DestroyObject() … no need i think. ( And if you really do want a delay, use the arg in DestroyObject() itself )

@kevL_s

I only started trying other stuff after the standard did not appear to work, as I agree with all you say here … :slight_smile:

As I say above, in this test, I do not even destroy the original yet. I just want to see the sidekicks destroyed first. lol:

But, I am still only having one destroyed after clicking on the original (which has a completely different tag and is NOT a DESTROYME one.) It is the weirdest thing.

It’s a custom model, but that would not affect it would it?

UPDATE: Actually, my loop (using GetNearestObject) is now only detecting one mushroom in the debug feedback! So at least that now adds up … but now why is it not “getting” the next mushroom?

nah

1 Like

generic answer: because something is breaking the loop

btw. I like to loop over objects in an area w/ GetFirst/NextObjectInArea() … that could change the way you’re thinking about this

@kevL_s

Yes, I have used that loop system before as well, but was trying to keep the loop minimal. But, I am beginning to suspect that GetNearestObject to be a little “buggy”. I do not use it in many places, and most of the time I only use it to get the first nearest object. And as GetNearestObjectBytag appeared to work flawlessly … I will do a test using the GetFirstObjectInArea and see what happens there …

Hold tight, will be back in a bit …

I don’t like the look of this … I used that loop type and it only returns the first item again!

Can something break a module? (E.g. I removed “resources.dat” when I had a problem Saturday, but it replaced that on further usage.)

UPDATE: Doh! Had to comment out the break again … and now that loops correctly.

UPDATE 2: Using the GetFirstobjectInArea works as well then! At least that allows me to work with all object types again now, so I think I will just have to go with that. I reckon the GetNearestObject function is a little wonky in a larger working environment.

I will just tidy the code up a bit and make sure it is working and report back.

1 Like

@kevL_s

Yes! Using the GetFirstObjectInArea loop function instead works.

My conclusion is that there is something a bit borked with that GetNearestObject function when trying to use it within a loop within a working environment with multiple objects then. Maybe it has a “limited reach” kind of thing?

Anyway, using that other area wide function, (which feels far less efficient due to having to check through every area object) does work as expected, and allows me to check al the object types if required, so I will use that instead now.

Once again, Thank you KevL for sticking with me on this. :+1: At least you can also keep an eye open for weird happenings with that function as well now. I will go though my own code and just double check I have not relied on a similar loop usage of that function elsewhere now. :wink:

1 Like

for mushrooms and giggles, if you have an inclination, try this

void DestroyPatch(object oSelf);

void main()
{
    object oSelf = OBJECT_SELF;

    DestroyPatch(oSelf);

    SetPlotFlag(oSelf, FALSE);
    AssignCommand(oSelf, SetIsDestroyable(TRUE));
    DestroyObject(oSelf, 0.25f);
}

const string sDESTROYME = "DESTROYME";
//
void DestroyPatch(object oSelf)
{
    int i = 1;
    object o = GetNearestObject(OBJECT_TYPE_ALL, oSelf, i);
    while (GetIsObjectValid(o))
    {
        if (GetDistanceToObject(o) <= 3.f
            && (GetLocalInt(o, sDESTROYME) == 1 || GetTag(o) == sDESTROYME))
        {
            SetPlotFlag(o, FALSE);
            AssignCommand(o, SetIsDestroyable(TRUE));
            DestroyObject(o);
        }
        o = GetNearestObject(OBJECT_TYPE_ALL, oSelf, ++i);
    }
}

I set up an area with 3 patches of (1 dirtmound + 4 bonepiles). Clicking the dirtmound with the above script destroy_bones in the OnUsed slot worked perfectly.

ps. I think i’ve seen GetNearestObject() fail but so rarely [once, and it might have been GetObject() instead] i don’t consider it bugged, really.

both functs are going to loop over each object in an area … unless there’s fDist to break either loop. But doing that is dicey in this situation since they could return an object that’s outside fDist before getting all objects within fDist – although that should not happen with GetNearest() since, you know, it ought start with the nearest object … anyway. glad you got it working :)

 
pps. :zzz:

1 Like

Yes, I realised that when I got my first error and then realised that is what happened … and then it occurred to me that they must be both searching the entire area afterwards.

I will check that code out and see what happens my end - and let you know if I experience any weirdness. No news will be good news. :+1:

1 Like