Dave312
Censored for your safe viewing
- Reaction score
- 269
I have started looking into creating AI systems and unfortunately there seems to be very little information around on the subject. I have an AI controlled player which starts the game with some bunkers under its control and some marines and firebats placed next to them for the AI to autoload. The problem I'm having is that the marines are loaded into the bunkers but the firebats aren't. There is room left in the bunkers for the firebats to jump in.
I have managed to figure out that the autoload script for the bunker AI is specified in the AI: Tactical AI Function property on the bunker unit in the Data Editor. The value for this property is AIThinkBunker which references this function in the TactTerrAI.galaxy file (I have pasted the relevant script into the spoiler tags below). While I have no problem reading the galaxy script syntax, I can't seem to make head or tails as to why the marines will autoload but not the firebats?
I have managed to figure out that the autoload script for the bunker AI is specified in the AI: Tactical AI Function property on the bunker unit in the Data Editor. The value for this property is AIThinkBunker which references this function in the TactTerrAI.galaxy file (I have pasted the relevant script into the spoiler tags below). While I have no problem reading the galaxy script syntax, I can't seem to make head or tails as to why the marines will autoload but not the firebats?
Code:
void AIThinkBunker(int player, unit aiUnit, unitgroup scanGroup) {
CargoDefend(player, aiUnit, scanGroup, 8, 10, c_emptyString, c_AB_BunkerChange);
}
bool CargoDefend (int player, unit aiUnit, unitgroup scanGroup, int searchRange, int loadRange, string wanted, string command) {
aifilter filter;
unitgroup nearBunkerGroup;
int bunkerCount;
unit unitToCheck;
order ord = null;
bool autoLoad = false;
bool wantsToBeInBunker;
unitgroup targetGroup;
targetGroup = UnitGroupFilterThreat(scanGroup, aiUnit, null, 0);
targetGroup = UnitGroupFilterRegion(targetGroup, RegionCircle(UnitGetPosition(aiUnit), searchRange), 0);
if (UnitGroupCount(targetGroup, c_unitCountAlive) == 0) { // no nearby enemies.
// Both checks are needed because auto loading bunkers is needed on campaign before the
// AI is active.....
if (AIIsCampaign(player)) {
autoLoad = true;
}
else if (AIGetDifficulty(player, c_diffAutoLoadBunkers)) {
autoLoad = true;
}
if (autoLoad && (command == c_AB_BunkerChange)) {
// handle bunkers on campaign differently.
unitToCheck = CampaignWantsToBeInBunker(player, aiUnit, UnitCargoGroup(aiUnit), c_bunkerUnload);
if (unitToCheck != null) {
ord = AICreateOrder(player, command, e_AB_TransportUnloadUnit); // unload the bunker.
OrderSetTargetPassenger(ord, unitToCheck);
}
if (ord == null) {
nearBunkerGroup = AIFindUnits(player, wanted, UnitGetPosition(aiUnit), c_campaignBunkerLoadRange, c_noMaxCount);
if (wanted == c_emptyString) {
filter = AIFilter(player);
AISetFilterMelee(filter, c_onlyRanged);
AISetFilterValidPassenger(filter, aiUnit);
nearBunkerGroup = AIGetFilterGroup(filter, nearBunkerGroup);
}
unitToCheck = CampaignWantsToBeInBunker(player, aiUnit, nearBunkerGroup, c_bunkerLoad);
if (unitToCheck != null) {
ord = AICreateOrder(player, command, e_AB_TransportLoadUnit); // load the bunker.
OrderSetTargetUnit(ord, unitToCheck);
}
}
}
else { // not a campaign bunker
if (UnitCargoValue(aiUnit, c_unitCargoSpaceUsed) == 0) { // nothing to unload
return false;
}
ord = AICreateOrder(player, command, e_AB_TransportUnloadAll); // unload bunker
}
}
else { // nearby enemies found.
if (UnitCargoValue(aiUnit, c_unitCargoSpaceFree) == 0) { // check for space
return false;
}
if (command == c_AB_CommandCenterChange) {
if (!AIAnyWorkersFleeingNearby(player,UnitGetPosition(aiUnit),8.0)) {
return false;
}
}
nearBunkerGroup = AIFindUnits(player, wanted, UnitGetPosition(aiUnit), loadRange, c_noMaxCount);
if (wanted == c_emptyString) {
filter = AIFilter(player);
AISetFilterMelee(filter, c_onlyRanged);
AISetFilterValidPassenger(filter, aiUnit);
nearBunkerGroup = AIGetFilterGroup(filter, nearBunkerGroup);
}
bunkerCount = UnitGroupCount(nearBunkerGroup, c_unitCountAll);
while (bunkerCount > 0) {
unitToCheck = UnitGroupUnit(nearBunkerGroup, bunkerCount);
bunkerCount = bunkerCount - 1;
if (!UnitIsAlive(unitToCheck)) {
continue;
}
if (AIIsScriptControlled(unitToCheck)) {
continue;
}
if (UnitTestState(unitToCheck, c_unitStateInsideTransport)) {
continue;
}
if (command == c_AB_CommandCenterChange) {
ord = AICreateOrder(player, command, e_AB_TransportLoadAll);
}
else {
ord = AICreateOrder(player, command, e_AB_TransportLoadUnit);
OrderSetTargetUnit(ord, unitToCheck);
}
break;
}
}
if (!UnitOrderIsValid(aiUnit, ord)) {
return false;
}
AICast(aiUnit, ord, c_noMarker, c_castHold);
return true;
}
unit CampaignWantsToBeInBunker (int player, unit aiUnit, unitgroup bunkerGroup, bool unload) {
int bunkerCount;
unit unitToCheck;
bool wantsToBeInBunker;
order unitOrder;
// When loading, check to see if there is space in the bunker at all.
//
if (!unload) {
if (UnitCargoValue(aiUnit, c_unitCargoSpaceFree) == 0) {
return null;
}
}
bunkerCount = UnitGroupCount(bunkerGroup, c_unitCountAll);
while (bunkerCount > 0) {
unitToCheck = UnitGroupUnit(bunkerGroup, bunkerCount);
bunkerCount = bunkerCount - 1;
// Make sure the unit is alive.
//
if (!UnitIsAlive(unitToCheck)) {
continue;
}
if (AIIsScriptControlled(unitToCheck)) {
continue;
}
// When loading, make sure the unit is not allready in a transport.
//
if (!unload) {
if (UnitTestState(unitToCheck, c_unitStateInsideTransport)) {
continue;
}
}
// The unit wants to be somewhere far away, do not load it.
//
wantsToBeInBunker = true;
if (AIControlForceToMove(unitToCheck)) {
// If the unit is forced to move, it shouldn't be in the bunker even in combat
wantsToBeInBunker = false;
}
else if (!AIUnitIsInCombat(unitToCheck) && !AIUnitIsInCombat(aiUnit)) {
// Otherwise the unit will only want to be out of the bunker if not combat is happening
// The unit wants to execute a non attack order.
unitOrder = UnitOrder(aiUnit, 0);
if (unitOrder != null && !AIIsAttackOrder(unitOrder)) {
wantsToBeInBunker = false;
}
// The unit wants to move.
else if (AIControlWantsToMove(unitToCheck)) {
wantsToBeInBunker = false;
}
// Unit has no home point
else if (AIGetHomePosition(unitToCheck) == c_nullPoint) {
wantsToBeInBunker = false;
}
// Unit's home point is too far away
else if (!PointsInRange(UnitGetPosition(aiUnit), AIGetHomePosition(unitToCheck), c_campaignBunkerLoadRange)) {
wantsToBeInBunker = false;
}
}
// Do not care about units that want to be in bunker when we want to unload.
// Similarly, do not care about units that do not want to be in bunker when we want to load.
//
if (wantsToBeInBunker == unload) {
continue;
}
return unitToCheck;
}
return null;
}