Author Topic: Finding objects  (Read 410 times)

Legacy_Leurnid

  • Sr. Member
  • ****
  • Posts: 473
  • Karma: +0/-0
Finding objects
« on: May 21, 2012, 08:11:42 pm »


               For purposes of this query, let us assume a switch when used, does something to one or more objects in the area.

The most common means of doing this, when the number of objects is variable, is to GetFirstObjectInArea (oArea); then in a while loop, check tags, GetNextObjectInArea, rinse and repeat.

If this script is firing in an area with hundreds of placeables, and only a few are going to be tagged by the script, is there a more efficient means of finding those objects? 
               
               

               
            

Legacy_Leurnid

  • Sr. Member
  • ****
  • Posts: 473
  • Karma: +0/-0
Finding objects
« Reply #1 on: May 21, 2012, 08:34:38 pm »


               I am thinking that using GetObjectInShape would be a good way to avoid cycling hundreds of items in an area, as long as the target object is fairly close to the switch (which it will be), but based on another recent topic, that sounds as if it may have it's own performance issues associated.... if the sphere or cylinder shape being checked is targeted on the first object by tag, and if any additional objects are to be influenced by the switch, they will be within 1 tile of the first object (by tag), then it seems like a good targeted method of switching things.

snippet:
[code=auto:0]
oTarget = GetFirstObjectInShape(SHAPE_SPHERE, 10.0, GetObjectByTag(sTag), TRUE, OBJECT_TYPE_PLACEABLE);

while(GetIsObjectValid(oTarget))
{
  //do stuff here
  oTarget = GetNextObjectInShape(SHAPE_SPHERE, 10.0, GetObjectByTag(sTag), TRUE, OBJECT_TYPE_PLACEABLE);
}
[code=auto:0]


EDIT:  Lexicon states that GetFirstObjectInShape is bugged and will not return a placeable....  bugger!
               
               

               


                     Modifié par Leurnid, 21 mai 2012 - 07:42 .
                     
                  


            

Legacy__Guile

  • Hero Member
  • *****
  • Posts: 1308
  • Karma: +0/-0
Finding objects
« Reply #2 on: May 21, 2012, 09:11:24 pm »


               I believe you need an "/" before code in the last [ code]

like so
[/code]

-------------------------

I really need to know what your script will do (in essence) to help you further mate...

You aren't being very informative. '<img'>

Anyway, it's best to use GetNearestObjectByTag(oArea, "thistag", #);

Then use a For Loop to suppliment the # using the i Integer...

e.g.

object oArea = ????; ///Define oArea...
int nWhich = 11;   // (e.g. 1 - 10)
int i;
for(i=1; i<nWhich;i++)
{
  oSomething = GetNearestObjectByTag(oArea, "thistag", i);
}

Obviously nWhich would need to be the # of objects you want to look at (Plus 1), if you are wanting to look at them all, then enter that number plus one, e.g. if 20 put nWhich = 21;

Otherwise yes, you may be able to use the while loop as you shew above...

However you have an error in that script, as you are using "GetObjectByTag(sTag)" in the actual definition of oObject....  which GetObjectByTag(sTag) is a loop in itself, so it would kick out an error...

If you want to use a double loop, then write a custom function / prototype to do another loop once oObject has been defined by the first loop, this should prevent the TMI (Too Many Instructions) error, but that's NOT guaranteed.

':wizard:'

I could probably help you a lot more if I knew exactly what you were trying to achieve, ultimately.. '^_^'
               
               

               


                     Modifié par _Guile, 21 mai 2012 - 08:30 .
                     
                  


            

Legacy_Leurnid

  • Sr. Member
  • ****
  • Posts: 473
  • Karma: +0/-0
Finding objects
« Reply #3 on: May 21, 2012, 09:40:43 pm »


               I was just spit balling that... thinking aloud, in a manner of speaking... this is a snippet from an actual switch I am currently using, and it works fine:


 //declarations removed
   object oLight = GetFirstObjectInArea(oArea);
 //stuff removed
        while(GetIsObjectValid(oLight))
        {
            if (GetTag(oLight) == sLights )
            {
                if (GetLocalInt(oLight, "iStandardLight"))
                {
                    AssignCommand(oLight, ActionPlayAnimation(ANIMATION_PLACEABLE_ACTIVATE));
                    SetPlaceableIllumination(oLight, TRUE);
                }
                else
                {
                    sColor = "White 5";
                    if (GetLocalInt(oLight,"iHaveVFX")) sColor = (GetLocalString (oLight, "sColor"));
                    else if (GetLocalInt(OBJECT_SELF,"iHaveVFX")) sColor = (GetLocalString (OBJECT_SELF, "sColor"));
                    int nColor = FindSubString (sColors, GetStringLowerCase( GetStringLeft (sColor, 3)));
                    int nSize = (StringToInt (GetStringRight (sColor, 2)) / 5) - 1;
                    if (nSize < 0) nSize = 0;
                    else if (nSize > 3) nSize = 3;
                    eLight = EffectVisualEffect(153 + nColor + nSize);
                    ApplyEffectToObject(DURATION_TYPE_PERMANENT, eLight, oLight);
                }
            }
        oLight = GetNextObjectInArea(oArea);
        }
//more stuff removed


There isn't a specific case I am working with where I want somebody to wave a magic wand and make it work.  I am trying to figure alternate and conditionally better ways to script solutions.

My current query is: Are there alternate ways to script the sort of loop used above that will process more quickly in areas with a lot of placeables to process.
               
               

               


                     Modifié par Leurnid, 21 mai 2012 - 08:45 .
                     
                  


            

Legacy__Guile

  • Hero Member
  • *****
  • Posts: 1308
  • Karma: +0/-0
Finding objects
« Reply #4 on: May 21, 2012, 11:58:31 pm »


               I set variables on the placeables, like so...

PERM_VFX_1  /  int  /   #
PERM_VFX_2  /  int  /  #
etc..
Where # = the VFX Constant #...

Then from the OnEnter Event of the area (OBJECT_SELF), I run the loop to apply the Permanent VFXs to Placeables.. (provided VFXs haven't been set before, I use a variable set on the area to check this from the same script)...

You could do the same for just a trigger (onenter) as well, but the PC's would probably see the VFXs being applied, instead of all ready being applied when they walked by...

Don't know the intents of your scripting, but I hope that helps in some way...
               
               

               


                     Modifié par _Guile, 21 mai 2012 - 10:59 .
                     
                  


            

Legacy_Leurnid

  • Sr. Member
  • ****
  • Posts: 473
  • Karma: +0/-0
Finding objects
« Reply #5 on: May 22, 2012, 12:51:35 am »


               Now, here is something interesting: I took the basic script routine above, and tweaked it so it was looking for sound objects with a designated tag to toggle on.  I can bullseye a single sound object just fine, but if I try to use a while-loop to find sounds by tag, they won't play.  I am about to slap some floating texts in there to see if/where things are and aren't popping.

void main()
{
    object oObject  = OBJECT_SELF;
    object oArea  = GetArea(oObject);
    object oSound = GetFirstObjectInArea(oArea);

    while(GetIsObjectValid(oSound))    // Loop all objects in the area
    {
        if (GetTag(oSound) == (GetTag(oObject)+"_sound"))
        {  
        //DelayCommand(0.3,SoundObjectPlay(oSound)); //this variant failed
        SoundObjectPlay(oSound); //this variant failed too
        }
        oSound = GetNextObjectInArea(oArea);
    }
//    SoundObjectPlay(GetObjectByTag(GetTag(oObject)+"_sound"));  //this variant works fine.
}


My initial guess is that sound objects do not track as objects for either the 'GetIsObjectValid' or the 'GetFirst- GetNextObjectInArea'


Just to be clear, I am not trying to do accomplish anything in particular, I am experimenting with what can be done. I don't want solutions, I want options.
               
               

               


                     Modifié par Leurnid, 21 mai 2012 - 11:55 .
                     
                  


            

Legacy_GhostOfGod

  • Hero Member
  • *****
  • Posts: 1490
  • Karma: +0/-0
Finding objects
« Reply #6 on: May 22, 2012, 03:37:54 am »


               One thing I recommend is trying NOT to use any GetFirst/NextObjectInXxxxx function unless you absolutely have to. GetObjectByTag has been shown in past threads to be a lot faster. That being said, one option for your experiment would be to do something more like so:

void main()
{
    int iNth = 0;
    object oSound = GetObjectByTag("AREA_1_SOUND", iNth);
    while (GetIsObjectValid(oSound))
    {
        SoundObjectPlay(oSound);
        iNth++;
        oSound = GetObjectByTag("AREA_1_SOUND", iNth);
    }
}

For thist test I placed 3 different sound objects and gave them the same but unique tags( If the tags were not unique to this area than any sound object in the mod with the same tags would play) This script searches for the 1st, 2nd, 3rd, etc objects with a particular tag and then plays them. And if for some reason you need to separate out a particular sound, since they all have the same tag, you can use the GetName function to then single one out (assuming they have different "names").

Hope that makes sense.

As to why yours didn't work I'm not sure. At first glance it seems like it should. The first things that came to mind;
-The placeable tag didn't match the sound tag as you intended.
-The sound was too far away to hear and wasn't flagged to play everywhere in area.

You can also use the same idea for other placeables and use the resref as an alternative check.
               
               

               


                     Modifié par GhostOfGod, 22 mai 2012 - 02:49 .
                     
                  


            

Legacy_Failed.Bard

  • Hero Member
  • *****
  • Posts: 1409
  • Karma: +0/-0
Finding objects
« Reply #7 on: May 22, 2012, 03:46:10 am »


               If GetObjectByTag is working for selecting them, you would just need to standardize the naming so that you can get them using a loop on that function instead.  Area tag + sound + night/day, perhaps, so you can toggle on/off certain sound placeables based on time of day as well.
               
               

               
            

Legacy__Guile

  • Hero Member
  • *****
  • Posts: 1308
  • Karma: +0/-0
Finding objects
« Reply #8 on: May 22, 2012, 04:45:02 am »


               Interesting, with lots of sounds in an area, I wonder if this would kick out a TMI?
               
               

               
            

Legacy_Leurnid

  • Sr. Member
  • ****
  • Posts: 473
  • Karma: +0/-0
Finding objects
« Reply #9 on: May 22, 2012, 04:47:12 am »


               

GhostOfGod wrote...

One thing I recommend is trying NOT to use any GetFirst/NextObjectInXxxxx function unless you absolutely have to. GetObjectByTag has been shown in past threads to be a lot faster. That being said, one option for your experiment would be to do something more like so:

void main()
{
    int iNth = 0;
    object oSound = GetObjectByTag("AREA_1_SOUND", iNth);
    while (GetIsObjectValid(oSound))
    {
        SoundObjectPlay(oSound);
        iNth++;
        oSound = GetObjectByTag("AREA_1_SOUND", iNth);
    }
}

For thist test I placed 3 different sound objects and gave them the same but unique tags( If the tags were not unique to this area than any sound object in the mod with the same tags would play) This script searches for the 1st, 2nd, 3rd, etc objects with a particular tag and then plays them. And if for some reason you need to separate out a particular sound, since they all have the same tag, you can use the GetName function to then single one out (assuming they have different "names").

Hope that makes sense.

As to why yours didn't work I'm not sure. At first glance it seems like it should. The first things that came to mind;
-The placeable tag didn't match the sound tag as you intended.
-The sound was too far away to hear and wasn't flagged to play everywhere in area.

You can also use the same idea for other placeables and use the resref as an alternative check.


I tested the placeable name by using the commented out line and commenting the while-loop, so the object tag was good, and the placeable sound was about 1 meter in front of the door... but your method is a bit cleaner anyway, and still caters to my love of generic-ness.

Thank you.
               
               

               
            

Legacy_GhostOfGod

  • Hero Member
  • *****
  • Posts: 1490
  • Karma: +0/-0
Finding objects
« Reply #10 on: May 22, 2012, 05:47:28 am »


               So I got a bit curious and experimented with the "GetFirst/NextObject" funtions as well. It seems that sound objects return both "OBJECT_TYPE_ALL" and "OBJECT_TYPE_INVALID" which is just the same thing as 32767. So you can use the "GetFirst/NextObjectInShape" functions if you needed to, to get sounds as well. Like so:

void main()
{
    object oPC = GetLastUsedBy();
    //debug line
    SendMessageToPC(oPC, "Sound Test Script Run!");
    location lLoc = GetLocation(OBJECT_SELF);
    object oArea = GetArea(OBJECT_SELF);
    //object oSound = GetFirstObjectInArea(oArea);
    object oSound = GetFirstObjectInShape(SHAPE_SPHERE, 10.0, lLoc, FALSE, 32767);
    while (GetIsObjectValid(oSound))
    {
        if (GetTag(oSound) == "AREA_1_SOUND")
        {
            SoundObjectPlay(oSound);
            //debug line
            SendMessageToPC(oPC, "1 sound found!");
        }
        //oSound = GetNextObjectInArea(oArea);
        oSound = GetNextObjectInShape(SHAPE_SPHERE, 10.0, lLoc, FALSE, 32767);
    }
}

I still can't get it to work with "GetFirst/NextObjectInArea" though. This function most likely skips this particular object type.

P.S. You can just replace the 32767 with OBJECT_TYPE_ALL or OBJECT_TYPE_INVALID. I was just being lazy and wanted to keep the script a bit shorter.
               
               

               


                     Modifié par GhostOfGod, 22 mai 2012 - 04:59 .
                     
                  


            

Legacy_Leurnid

  • Sr. Member
  • ****
  • Posts: 473
  • Karma: +0/-0
Finding objects
« Reply #11 on: May 22, 2012, 06:49:09 am »


               I was going to try the Get...ObjectInShape, but I read in the Lexicon that it was bugged when used to get placeables, and I assumed that a sound object qualified as a placeable, so skipped it without trying. Glad to see it actually works, and happier still to see a viable example of it coded.  I would have spent a day or two at it just to wind up with a much uglier version of your code, and it probably still wouldn't work.

I prefer the 'ByTag' solution anyway, it's a slimmer bit of code all around, and seems to offer more flexibility in a 'generic' implementation. I might want to trip sounds or lights in other areas, or at least spread out far enough to make InShape impractical.


*Right now, I am just trying to hone a collection of generic scripts that use tags and local variables to control multiple effects consolidated into as few scripts as possible. Finding tight and tidy solutions that work for the broadest range of outcomes is my ultimate goal.
               
               

               
            

Legacy_Leurnid

  • Sr. Member
  • ****
  • Posts: 473
  • Karma: +0/-0
Finding objects
« Reply #12 on: May 22, 2012, 06:58:46 am »


               

Failed.Bard wrote...

If GetObjectByTag is working for selecting them, you would just need to standardize the naming so that you can get them using a loop on that function instead.  Area tag + sound + night/day, perhaps, so you can toggle on/off certain sound placeables based on time of day as well.


Using the GetObjectByTag script snip of GoG's, you don't need area or day/night checks:  Place the sound objects, then on the advanced tab, uncheck 'active' but set the time the sound should play.  When the script runs, those sounds turn active until you use another script similar to it to deactive them, but they will only play according to the time params. So when the object with the script event is tripped, all the correctly tagged sounds will activate, but only play based on time of day. '<img'>
               
               

               


                     Modifié par Leurnid, 22 mai 2012 - 07:51 .
                     
                  


            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Finding objects
« Reply #13 on: May 22, 2012, 11:28:56 am »


               

Leurnid wrote...

EDIT:  Lexicon states that GetFirstObjectInShape is bugged and will not return a placeable....  bugger!

Unfortunately one can really believe neither to lexicon or wiki. The informations there are old and uproofed.

For the InShape functions, they return placeables and door fine.
               
               

               


                     Modifié par ShaDoOoW, 22 mai 2012 - 10:30 .
                     
                  


            

Legacy_Failed.Bard

  • Hero Member
  • *****
  • Posts: 1409
  • Karma: +0/-0
Finding objects
« Reply #14 on: May 22, 2012, 12:05:36 pm »


               

Leurnid wrote...

Failed.Bard wrote...

If GetObjectByTag is working for selecting them, you would just need to standardize the naming so that you can get them using a loop on that function instead.  Area tag + sound + night/day, perhaps, so you can toggle on/off certain sound placeables based on time of day as well.


Using the GetObjectByTag script snip of GoG's, you don't need area or day/night checks:  Place the sound objects, then on the advanced tab, uncheck 'active' but set the time the sound should play.  When the script runs, those sounds turn active until you use another script similar to it to deactive them, but they will only play according to the time params. So when the object with the script event is tripped, all the correctly tagged sounds will activate, but only play based on time of day. '<img'>


  I'm just not personally a fan of global switching, since it implies being HB driven.  Area tagged day/night specific sounds can be easily turned on or off in an areas OnEnter script, and the mods HB script can toggle them twice a day in the areas currently occupied by PCs if needed.
  That way, short of putting 5000+ sounds in a given area, you're never risking a TMI error or noticeable lag to the script.

  Now, if you're planning to have some sounds that only play during a specific hour, then you'd be best with on and off time ints stored to the sound objects, but tagging them Area Tag + sound (or sound + area tag) allows for them to be toggled specifically where needed off a single compact generic script.