How choose one randomly actor founded by ThinkerIterator?
I need find all child of current actor and then perform warp of master to one randomly chosen child, until something, player, dont stop it by killing it. Better say, save all founded actor and give to them some pointer available from any part of a mod.
How do I do so?
Choose result of ThinkerIterator
Moderator: GZDoom Developers
Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.
Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.
Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
-
- Posts: 1606
- Joined: Mon Jun 12, 2017 12:57 am
Re: Choose result of ThinkerIterator
Where all GLORIUS ZSCRIPT MASTER RACE?
Is it even possible?
Is it even possible?
-
- Posts: 1339
- Joined: Tue Jul 15, 2003 4:18 pm
Re: Choose result of ThinkerIterator
Untested code, but the function should essentially do what you want. Just don't call it too often, because too many calls of ThinkerIterator can slow down processing to a crawl...
Code: Select all
class MyActorThatWarpsToChildren : Actor
{
States
{
...
Warp:
UNKN A 1 A_DoRandomWarp();
Goto See;
}
void A_DoRandomWarp()
{
Array<Actor> Children;
ThinkerIterator ChildFinder = ThinkerIterator.Create("Actor", Thinker.STAT_DEFAULT);
Actor mo;
while (mo = Actor(ChildFinder.Next()))
{
if (mo.master == self)
{
Children.Push(mo);
}
}
if (Children.Size < 1) { return; }
Actor warptarget = Children[Random(0, Children.Size - 1)];
if (warptarget)
{
Warp(warptarget);
}
}
}
-
- Posts: 1606
- Joined: Mon Jun 12, 2017 12:57 am
Re: Choose result of ThinkerIterator
So I cant save pointer to all found childen one time, and then just check if it alive!?
Or every Children%_number_% personifies its own actor?
Or every Children%_number_% personifies its own actor?
-
- Posts: 1339
- Joined: Tue Jul 15, 2003 4:18 pm
Re: Choose result of ThinkerIterator
Here's a slightly modified version that lets you find all of the children once and then reference the array of pointers from then on:
Basically, when you tell the actor to call A_CollectChildren, the Children array will be populated with pointers to all actors that have this actor set as their master. There is no internal list of children maintained by the engine; every A_*DoSomethingto*Children function uses an iterator internally.
The A_DoRandomWarp function picks a random index in the array (so, a random pointer to a child), checks if the health is greater than 0, and warps to the actor's location... If it wasn't valid, the child pointer is deleted from the array.
Code: Select all
class MyActorThatWarpsToChildren : Actor
{
Array<Actor> Children; // Array that is used to store pointers to all child actors
States
{
...
SomeStateAfterChildrenSpawned:
UNKN A 1 A_CollectChildren();
Goto See;
Warp:
UNKN A 1 A_DoRandomWarp();
Goto See;
}
void A_CollectChildren()
{
Children.Clear(); // Clear the Children array, in case this gets called more than once
// Find all Actor thinkers
ThinkerIterator ChildFinder = ThinkerIterator.Create("Actor", Thinker.STAT_DEFAULT);
Actor mo;
// Loop through all of the actors...
while (mo = Actor(ChildFinder.Next()))
{
// ...and find any actors that have this actor set as their master
if (mo.master == self)
{
Children.Push(mo); // Push a pointer to the found actor into the Children array
}
}
}
void A_DoRandomWarp()
{
if (Children.Size < 1) { return; } // If there aren't any children, don't bother running the rest of the code
int targetindex = Random(0, Children.Size - 1); // Pick a random index into the Children array
if (Children[targetindex] && Children[targetindex].health > 0 ) // If the array index is a valid actor and the actor has health...
{
Warp(Children[targetindex]); // ...warp to the actor's location
}
else
{
Children.Delete(targetindex); // If it was dead or invalid, delete it from the Children array so we don't have to deal with it again
}
}
}
The A_DoRandomWarp function picks a random index in the array (so, a random pointer to a child), checks if the health is greater than 0, and warps to the actor's location... If it wasn't valid, the child pointer is deleted from the array.
-
- Posts: 1606
- Joined: Mon Jun 12, 2017 12:57 am
Re: Choose result of ThinkerIterator
Thanks.
Looks like I need read chapter "using array in C++"...
Looks like I need read chapter "using array in C++"...
-
- Posts: 1339
- Joined: Tue Jul 15, 2003 4:18 pm
Re: Choose result of ThinkerIterator
That'd probably be useful... There's a [wiki=Dynamic_arrays]wiki page[/wiki] with a pretty good breakdown of the various commands that you can use.
The very basics that are used here:
The very basics that are used here:
- Declaration: Array<type> ArrayName; - "type" determines what the array is of... Can be any class/type (int, string, Thinker, ACtor, ZombieMan, etc.)
- ArrayName[x] - access array member at index 'x'... So, 'ArrayName[3]' will give you the 4th member of the array (zero-based numbering, so 0 is the first).
- ArrayName.Push(whatever) - adds 'whatever' to the end of the array
- ArrayName.Delete(i) - deletes the pointer at index 'i' from the array
- ArrayName.Size - returns how many values are in the array... Note that this is one off from the maximum index of the array due to the index numbers starting at 0, not 1
- ArrayName.Clear() - deletes everything from the array