One somewhat difficult issue in scripting missions etc for CLOD, is sometimes you need to get rid of old ground actors--artillery, ships, vehicles, whatever.
Getting the full list of these objects doesn't seem to be as easy as it is for aircraft.
Here is my (somewhat/very) kludgy solution. It has quite a bit of overkill built into it, but it does GET RID of any/all ground objects, ship, artillery, etc. It doesn't try to be smooth--most likely there would be a rather large freeze for the player while you run this things. But, it does work in the sense of zapping ground targets--any and all.
Note that this doesn't check whether a player is in any of the items, so you might want to add that little check (if you don't, players working artillery, for example, will just be unceremoniously dumped out).
I'm posting this partly in the hope that some kind person might have the truly elegant solution to this problem.
FWIW the two key elements of this code:
Code:
GamePlay.gpGroundStationarys(x, y, distance) //gets a list of all stationaries within a certain distance of a certain point
GamePlay.gpActorByName(name) as AiGroundActor //gets actor by name
The "by name" thing is pretty powerful, because you can see a list of object names by right-clicking in CLOD and "view aircraft" "view vehicle" "view ship" "view misc" etc - and see the name there. Pretty soon you see they are named like "1:12_Chief0" and such, so it become easy to make a list of all (possible) names.
Another possible approach would be to keep a list of all actors as they spawn in, using "OnActorCreated". However I believe that still leaves you with "sub-Actors" of the group, which are like "1:12_Chief1", "1:12_Chief2", "1:12_Chief3", etc.
Code:
public bool DEBUG = false;
private void destroyAllGroundActors(int missionNumber = -1)
{
//TODO: Make it list only the actors in that mission by prefixing "XX:" if missionNumber is included.
try
{
//if (!DEBUG) return;
if (DEBUG) GamePlay.gpLogServer(null, "Destroying all ground actors:", new object[] { });
int group_count = 0;
if (GamePlay.gpArmies() != null && GamePlay.gpArmies().Length > 0)
{
foreach (int army in GamePlay.gpArmies())
{
//List a/c in player army if "inOwnArmy" == true; otherwise lists a/c in all armies EXCEPT the player's own army
if (GamePlay.gpGroundGroups(army) != null && GamePlay.gpGroundGroups(army).Length > 0)
{
foreach (AiGroundGroup group in GamePlay.gpGroundGroups(army))
{
destroyAGVGroundGroup(group);
}
}
}
}
}
catch (Exception e) { System.Console.WriteLine("laa: " + e.ToString()); }
}
//Destroys a given Ground Group, along with any stationaries within the given area
//you can set distance to be quite close to your given group or leave it large (50000 meters) to basically collect all stationaries on the map
//maxSubItems catches all the chief1 chief2 chief3 chief4 type things. If you happen to have more than chief99 then you'll need to
//increase maxSubItems
private bool destroyAGVGroundGroup(AiGroundGroup group, bool destroyElements = true, bool destroyGroup = true, bool destroyNearbyGroundStationaries = true, bool destroyStatics = true, double distance = 500000, int maxSubItems=20, int maxStatics=500)
{
try
{
bool success = false;
if (group != null)
{
//first, we get rid of any stationaries associated with this mission
string missionNumber = group.Name().Split(':')[0];
//string subStatName = missionNumber + ":" + i.ToString() + "_Static";
string subStatPrefix = missionNumber + ":";
if (DEBUG) GamePlay.gpLogServer(null, "DEBUG: Destroying Stationaries associated with Mission "
+ subStatPrefix, new object[] { });
//Ok, this part is a bit belt&suspenders, just searching by a (potentially very LARGE) area for any ground stationaries that are in the same
//mission as our object:
if (destroyNearbyGroundStationaries && GamePlay.gpGroundStationarys() != null)
{
foreach (GroundStationary gg in GamePlay.gpGroundStationarys(group.Pos().x, group.Pos().y, distance)) //all stationaries w/i 500000 or whatever meters of this object
{
if (gg.Name.StartsWith(subStatPrefix))
{
gg.Destroy();
if (DEBUG) GamePlay.gpLogServer(null, "DEBUG: Destroyed " + gg.Name, new object[] { });
}
}
}
//Now we destroy any Actors or sub-Actors of this group
//The issue is that we don't know how many sub-actors a particular group might have
//Going up to 100 should get them all but if there are some left over in specific cases,
//just increase maxSubItems in the method call
//These are like trailers & various vehicles within a single convoy (I believe)
if (destroyElements)
{
for (int i = 0; i < maxSubItems; i++)
{
string subName = group.Name() + (i).ToString();
if (DEBUG) GamePlay.gpLogServer(null, "DEBUG: Destroying group element: "
+ subName, new object[] { });
AiGroundActor subActor = GamePlay.gpActorByName(subName) as AiGroundActor;
if (subActor != null)
{
if (DEBUG) GamePlay.gpLogServer(null, "DEBUG: Destroyed : "
+ subActor.Name(), new object[] { });
//destroyGroundGroup(subActor as AiGroundGroup);
(subActor as AiCart).Destroy();
}
}
}
//Now we destroy any Statics within the same mission as the group.
//The issue is that we don't know how many statics a particular mission might have
//Going up to say 500 should get them all but if there are some left over in specific cases,
//just increase maxStatics in the method call
if (destroyStatics)
{
for (int i = 0; i < maxStatics; i++)
{
string subName = subStatPrefix + "Static" + (i).ToString();
if (DEBUG) GamePlay.gpLogServer(null, "DEBUG: Destroying group element: "
+ subName, new object[] { });
AiGroundActor subActor = GamePlay.gpActorByName(subName) as AiGroundActor;
if (subActor != null)
{
if (DEBUG) GamePlay.gpLogServer(null, "DEBUG: Destroyed : "
+ subActor.Name(), new object[] { });
//destroyGroundGroup(subActor as AiGroundGroup);
(subActor as AiCart).Destroy();
}
}
}
if (destroyGroup)
{
if (DEBUG) GamePlay.gpLogServer(null, "DEBUG: Finished destroying group: "
+ group.Name() + " "
//+ group.CallSign() + " "
//+ group.Type() + " "
//+ group.TypedName() + " "
//+ group.AirGroup().ID()
//+ group.GroupType() + " "
//+ group.ID() + " "
, new object[] { });
//group.Destroy();
if ((group as AiGroundActor) != null) (group as AiGroundActor).Destroy();
success = true;
}
}
return success;
}
catch (Exception e) { System.Console.WriteLine("dag2: " + e.ToString()); return false; }
}
Bookmarks