Author Topic: How to use World_AIW2.Instance.CentralEntityLookup_Squad  (Read 322 times)

Offline rogerbacon

  • Newbie Mark II
  • *
  • Posts: 11
How to use World_AIW2.Instance.CentralEntityLookup_Squad
« on: May 03, 2020, 09:15:51 PM »
I'm trying to get the Hive's Yellow Jacket squad and dynamically modify the TypeData based on an event occurring. However it is returning null. I can find other GameEntities, such as teh Hive Ark itself. Here is my code. Am I using this method in the correct way?

Code: [Select]
var squadPair = World_AIW2.Instance.CentralEntityLookup_Squad.FirstOrDefault(x => x.Value != null &&
                                                                                    x.Value.TypeData != null &&
                                                                                    x.Value.TypeData.DisplayName != null &&
                                                                                    x.Value.TypeData.DisplayName.Contains("Yellow Jacket"));
            if (squadPair.Value != null)
            {
                UnityEngine.Debug.Log("Found " + squadPair.Value.TypeData.DisplayName);
            }
            else
            {
                UnityEngine.Debug.Log("SquadPair value is null");
            }

Offline Draco18s

  • Resident Velociraptor
  • Core Member Mark V
  • *****
  • Posts: 4,244
Re: How to use World_AIW2.Instance.CentralEntityLookup_Squad
« Reply #1 on: May 03, 2020, 10:42:11 PM »
I would really hope those things weren't null by the time your code runs.
But I also wouldn't use the display name and string comparisons to do the lookup. My guess would be that the display name for the squad you're looking for isn't actually "Yellow Jacket"

Offline rogerbacon

  • Newbie Mark II
  • *
  • Posts: 11
Re: How to use World_AIW2.Instance.CentralEntityLookup_Squad
« Reply #2 on: May 04, 2020, 08:40:02 AM »
I would really hope those things weren't null by the time your code runs.
But I also wouldn't use the display name and string comparisons to do the lookup. My guess would be that the display name for the squad you're looking for isn't actually "Yellow Jacket"


It wasn't the display name. That was fine; I copied it directly from teh xml. The problem was that if the Yellow Jackets weren't out flying around they can't be found by CentralEntityLookup_Squad.  When I moved the hive in to attack something and called the code again when the yellow jackets were out flying around the code worked fine.

So... I guess my real question is: What is the best way to itterate over all the membergroups of a fleet or all membergroups of all fleets and find a specific one even if it isn't currently flying around on the map?

Offline BadgerBadger

  • Arcen Volunteer
  • Hero Member Mark III
  • *****
  • Posts: 1,210
  • BadgerBadgerBadgerBadger
Re: How to use World_AIW2.Instance.CentralEntityLookup_Squad
« Reply #3 on: May 04, 2020, 07:47:29 PM »
I would not recommend trying to change the type of drones built by the Hive Golem mid game. At best it would reset itself every time you reloaded. At worst it would crash.

Offline x4000

  • Chris McElligott Park, Arcen Founder and Lead Dev
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 31,620
Re: How to use World_AIW2.Instance.CentralEntityLookup_Squad
« Reply #4 on: May 05, 2020, 09:55:03 AM »
So... I guess my real question is: What is the best way to itterate over all the membergroups of a fleet or all membergroups of all fleets and find a specific one even if it isn't currently flying around on the map?

So, essentially the World_AIW2.Instance.CentralEntityLookup_Squad lookup is the absolute last-ditch way to find entities when you don't have a better way of finding them.  It's one giant dictionary and useful when you need to look something up by ID, but if you have anything better to go on, then you should use another method.

The information about the type of a unit is in their Fleet.Membership, and usually the best way to find a fleet membership is by finding the fleet of some specific unit. Hopefully you know where your hive golem is -- if not, then the best way to find it would be to loop over all your fleets for the current player and look at their centerpiece units, since a hive golem would always be a centerpiece unit.

Something like this:

Code: [Select]
Faction localFaction = World_AIW2.Instance.GetLocalPlayerFaction();

Fleet hiveGolemFleet = null;
World_AIW2.Instance.DoForFleets( localFaction, FleetStatus.CenterpieceMustLive, delegate ( Fleet fleet )
{
   if ( fleet.Centerpiece != null && fleet.InternalName == "HiveGolem" )
   {
          hiveGolemFleet  = fleet;
          return DelReturn.Break;
   }
   return DelReturn.Continue;
} );

if ( hiveGolemFleet != null )
{
    //now do your stuff
    //and this is assuming you have only one hive golem fleet
}

If you had many hive golem fleets, potentially, then alter the code to be:

Code: [Select]
Faction localFaction = World_AIW2.Instance.GetLocalPlayerFaction();

World_AIW2.Instance.DoForFleets( localFaction, FleetStatus.CenterpieceMustLive, delegate ( Fleet fleet )
{
   if ( fleet.Centerpiece != null && fleet.InternalName == "HiveGolem" )
   {
          //now do your stuff
          //inner loops or whatever is fine.
          return DelReturn.Break;
   }
   return DelReturn.Continue;
} );


For reference, you'd be looping over a few hundred things at most that way, versus thousands or tens of thousands or even hundreds of thousands when looking at the central list. 

Also, the InternalName is considered stable, and is the "name" field on the unit itself.  It can't ever be changed without a fair hassle in the code, and so it tends to be stable forever.  Check based on that.  If we decide to rename the Yellow Jackets to be Yellow Field Jackets for some reason, which isn't out of the question for the sort of thing we might do with some unit, then your code would stop finding them based on DisplayName.  BUT, we'd have left the InternalName alone, so you could still find them that way.

Once you have found the fleet with the hive golem, or each fleet with the hive golem, assuming you did not already have that, then you would need to find the membership with the yellow jackets.  This will exist no matter what, even if the jackets are all dead or are all undeployed or whatever else.

That would look like this:

Quote
            fleet.DoForMemberGroups( delegate ( Membership mem )
            {
                if ( mem.TypeData.InternalName == "YellowJacket" )
                {
                      //do your code in here.
                     mem.DoForEntities( delegate ( GameEntity_Squad ship )
                     {
                          //this code would let you loop over all the deployed entities, for instance.
                          return DelReturn.Continue;
                     } );
                     //this code lets you know what is being transported, not relevant for here but for other types
                     mem.TransportContents.Count;
                     //this gives you the count of undeployed drones
                     mem.NumberCreatedButNotDeployed;
                     //note that to change the number of drones created but not deployed you need to use AddOrSetNumberCreatedButNotDeployed();
                }
                return DelReturn.Continue;
            } );

All of that would get you to the fleet membership, which is where the TypeData lives for entities.  Changing the fleet membership TypeData would be... not a great idea.  All of the background threads are likely to get confused and may throw random errors.  Multiplayer will have a desync, etc.

If you're wanting to transform things, right now the only way to do that is to create a new fleet membership and then add to its number of undeployed drones and remove from the undeployed drones on the original yellowjacket fleet membership.

For any entities in there, you'd need to loop over them and then call TransformInto() on each squad.  You would pass in the new type, and it would automatically put itself into the fleet membership in that fleet that matches that type.

You would also need to change some stuff on the old membership and the new one.  I'd suggest setting the ExplicitBaseSquadCap on the new one to be whatever the old one is, and then set ExplicitBaseSquadCap to zero on the old one.  I think that would survive savegames, but I can't swear to it.  This is also something that is going through kind of a side band channel, so it's probably not going to work well with multiplayer until it's done in a more robust way.  But it shouldn't cause single-player to error out.

Hope that helps!
Have ideas or bug reports for one of our games?  Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!