// This sends supply from s to d, subtracting from losses and adding to it's supply traffic field // Updates values to amount which actually made it. returns 0 if none made it. int SendSupply (Objective s, Objective d, int *supply, int *fuel) { Objective c; PathClass path; int i,l,n,loss,type; if (!*supply && !*fuel) return 0; if (GetObjectivePath(&path,s,d,Foot,s->GetTeam(),PATH_MARINE) < 1) return 0; c = s; loss = 0; AddSupply(s,*supply/10,*fuel/10); for (i=0; i<path.GetLength(); i++) { n = path.GetDirection(i); c = c->GetNeighbor(n); type = c->GetType(); if (type == TYPE_ROAD || type == TYPE_INTERSECT || type == TYPE_RAILROAD || type == TYPE_BRIDGE) { AddSupply(c,*supply/10,*fuel/10); l = c->GetObjectiveSupplyLosses() + 2; // Automatic loss rate of 2% per objective *supply = *supply*(100-l)/100; *fuel = *fuel*(100-l)/100; } if (!*supply && !*fuel) return 0; } return 1; }
int BrigadeClass::CheckTactic (int tid) { Objective o; if (tid < 1) return 0; if (haveWeaps < 0) { FalconEntity *e; GridIndex x,y,dx,dy; e = GetTarget(); if (Engaged() && !e) SetEngaged(0); if (GetUnitSupply() > 20) haveWeaps = 1; else haveWeaps = 0; GetLocation(&x,&y); o = GetUnitObjective(); ourObjOwner = 0; if (o && o->GetTeam() == GetTeam()) ourObjOwner = 1; if (o) o->GetLocation(&dx,&dy); else GetUnitDestination(&dx,&dy); ourObjDist = FloatToInt32(Distance(x,y,dx,dy)); } if (!CheckUnitType(tid, GetDomain(), GetType())) return 0; if (!CheckTeam(tid,GetTeam())) return 0; if (!CheckEngaged(tid,Engaged())) return 0; if (!CheckCombat(tid,Combat())) return 0; if (!CheckLosses(tid,Losses())) return 0; if (!CheckRetreating(tid,Retreating())) return 0; if (!CheckAction(tid,GetUnitOrders())) return 0; if (!CheckOwned(tid,ourObjOwner)) return 0; if (TeamInfo[GetTeam()]->GetGroundAction()->actionType != GACTION_OFFENSIVE && !CheckRole(tid,0)) return 0; if (!CheckRange(tid,ourObjDist)) return 0; // if (!CheckDistToFront(tid,ourFrontDist)) // return 0; if (!CheckStatus(tid,Broken())) return 0; // if (!CheckOdds(tid,odds)) // return 0; return GetTacticPriority(tid); }
// KCK: This is an admittidly hackish way of determining which lists to add the objective to, // but it's either this or call IsValidObjective() for each order type which would require many // more checks.. HOWEVER, we need to keep this and IsValidObjective() in sync (they must agree) int GroundTaskingManagerClass::GetAddBits (Objective o, int to_collect) { int add_now = to_collect; if (!o) return 0; if (!o->IsSecondary()) add_now &= ~(COLLECT_RESERVE | COLLECT_CAPTURE | COLLECT_SECURE | COLLECT_ASSAULT | COLLECT_AIRBORNE | COLLECT_DEFEND); if (o->IsNearfront()) add_now &= ~(COLLECT_RESERVE | COLLECT_ASSAULT | COLLECT_AIRBORNE); else add_now &= ~(COLLECT_CAPTURE | COLLECT_DEFEND); if (owner != o->GetTeam()) add_now &= ~(COLLECT_RESERVE | COLLECT_SECURE | COLLECT_DEFEND | COLLECT_SUPPORT | COLLECT_REPAIR | COLLECT_AIRDEFENSE | COLLECT_RADAR); if (GetRoE(owner,o->GetTeam(),ROE_GROUND_CAPTURE) != ROE_ALLOWED) add_now &= ~(COLLECT_CAPTURE | COLLECT_ASSAULT | COLLECT_AIRBORNE | COLLECT_COMMANDO); if (o->Abandoned()) add_now &= ~COLLECT_DEFEND; if (!o->IsFrontline() && !o->IsSecondline()) add_now &= ~(COLLECT_SECURE); if (!o->IsBeach()) add_now &= ~(COLLECT_ASSAULT); if (1) // defended add_now &= ~(COLLECT_AIRBORNE); if (!o->CommandoSite()) add_now &= ~(COLLECT_COMMANDO); if (!o->ArtillerySite()) add_now &= ~(COLLECT_SUPPORT); if (!o->NeedRepair() || o->GetObjectiveStatus() > 50) add_now &= ~(COLLECT_REPAIR); if (!o->SamSite()) add_now &= ~(COLLECT_AIRDEFENSE); if (!o->RadarSite()) add_now &= ~(COLLECT_RADAR); return add_now; }
int OnValidObjective (Unit e, int role, F4PFList nearlist) { VuListIterator vuit(nearlist); Objective bo = GetFirstObjective(&vuit); while (bo && bo->Id() != e->GetUnitObjectiveID()) bo = GetNextObjective(&vuit); if (bo) { GridIndex x,y; e->GetLocation(&x,&y); if (ScorePosition (e, role, 100, bo, x, y, (bo->GetTeam() == e->GetTeam())? 1:0) < -30000) bo = NULL; } if (bo) return 1; return 0; }
void GroundTaskingManagerClass::AddToLists (Unit u, int to_collect) { int i,role; // Units with valid orders are not reassigned if (u->GetUnitOrders() != GRO_RESERVE) { int orders = u->GetUnitOrders(); if ((to_collect & (0x01 << orders)) && IsValidObjective(orders,u->GetUnitObjective())) { Objective o = u->GetUnitObjective(); GODNode curo = objList[orders]; while (curo) { if (curo->obj == o) { if (orders == GORD_CAPTURE) sOffensiveAssigned++; #ifdef KEV_GDEBUG UnitCount[orders]++; #endif AssignUnit(u,orders,o,999); // Their objective is removed from the satisfy list if (objList[orders]) objList[orders] = objList[orders]->Remove(o); return; } curo = curo->next; } } } // Immobile units just do what they do best.. if (u->GetMovementType() == NoMove) { GridIndex x,y; Objective o; float d=-1.0F; u->GetLocation(&x,&y); o = FindNearestObjective(x,y,&d); if (!o || d > 2.0F || GetRoE(o->GetTeam(),owner,ROE_GROUND_FIRE) == ROE_ALLOWED) { // Overrun! u->KillUnit(); return; } i = GetGroundOrders(u->GetUnitNormalRole()); #ifdef KEV_GDEBUG UnitCount[i]++; #endif AssignUnit(u,i,o,999); if (objList[i]) objList[i] = objList[i]->Remove(o); return; } // Broken/unsupplied units get tasked as reserve only if (u->Broken() || u->GetUnitSupply() < 50) { AddToList(u, GORD_RESERVE); return; } u->SetUnitOrders(GORD_RESERVE); u->SetAssigned(0); // Check for one role units role = u->GetUnitNormalRole(); if (role == GRO_FIRESUPPORT || role == GRO_AIRDEFENSE || role == GRO_ENGINEER) // KCK: Radar units here? { AddToList(u, GetGroundOrders(role)); AddToList(u, GORD_RESERVE); return; } // Add it to a list for each type of orders it's capible of performing for (i=0; i<GORD_LAST; i++) { if (!(to_collect & (0x01 << i))) continue; if (i == GORD_ASSAULT && u->GetUnitNormalRole() != GRO_ASSAULT) continue; if (i == GORD_COMMANDO && !u->Commando()) continue; if (i == GORD_AIRBORNE && u->GetUnitNormalRole() != GRO_AIRBORNE) continue; if (i == GORD_SUPPORT || i == GORD_REPAIR || i == GORD_AIRDEFENSE) continue; if (i == GORD_RADAR && u->GetUnitNormalRole() != GRO_RECON) continue; if (!i || u->GetUnitRoleScore(GetGroundRole(i), CALC_MAX, 0) > MIN_ALLOWABLE_ROLE_SCORE) { // Add to canidate list AddToList(u, i); } } }
// Determine if this objective can accept the passed orders int GroundTaskingManagerClass::IsValidObjective (int orders, Objective o) { if (!o) return 0; switch (orders) { case GORD_CAPTURE: if (o->IsSecondary() && o->IsNearfront() && GetRoE(owner,o->GetTeam(),ROE_GROUND_CAPTURE) == ROE_ALLOWED) return 1; break; case GORD_SECURE: if (o->IsSecondary() && owner == o->GetTeam() && (o->IsFrontline() || o->IsSecondline())) return 1; break; case GORD_ASSAULT: if (o->IsSecondary() && !o->IsNearfront() && o->IsBeach() && GetRoE(owner,o->GetTeam(),ROE_GROUND_CAPTURE) == ROE_ALLOWED) return 1; break; case GORD_AIRBORNE: if (o->IsSecondary() && !o->IsNearfront() && GetRoE(owner,o->GetTeam(),ROE_GROUND_CAPTURE) == ROE_ALLOWED) // && !defended) return 1; break; case GORD_COMMANDO: if (o->CommandoSite() && GetRoE(owner,o->GetTeam(),ROE_GROUND_CAPTURE) == ROE_ALLOWED) return 1; break; case GORD_DEFEND: if (o->IsSecondary() && o->IsNearfront() && owner == o->GetTeam() && !o->Abandoned()) return 1; break; case GORD_SUPPORT: if (owner == o->GetTeam() && o->ArtillerySite()) return 1; break; case GORD_REPAIR: if (owner == o->GetTeam() && o->NeedRepair() && o->GetObjectiveStatus() < 51) return 1; break; case GORD_AIRDEFENSE: if (owner == o->GetTeam() && o->SamSite()) return 1; break; case GORD_RECON: return 0; break; case GORD_RADAR: if (owner == o->GetTeam() && o->RadarSite()) return 1; break; case GORD_RESERVE: default: if (o->IsSecondary() && owner == o->GetTeam() && !o->IsNearfront()) return 1; break; } return 0; }
void GroundTaskingManagerClass::DoCalculations(void) { Objective o; int score,fs,es,i; float d; Team t; GridIndex x,y; POData pd; // Don't do this if we're not active, or not owned by this machine if (!(TeamInfo[owner]->flags & TEAM_ACTIVE) || !IsLocal()) return; topPriority = 0; VuListIterator poit(POList); o = GetFirstObjective(&poit); while (o != NULL) { // Get score for proximity to front o->GetLocation(&x,&y); d = DistanceToFront(x,y); fs = FloatToInt32((200.0F - d) * 0.2F); t = o->GetTeam(); pd = GetPOData(o); es = 0; // Get score for enemy strength if (d < 100.0F) { for (i=1; i<NUM_TEAMS; i++) { if (GetRoE(owner,i,ROE_GROUND_FIRE)) es += pd->ground_assigned[i]/50; // 1 assignment pt = 1 vehicle, so 1 enemy strength pt per 50 vehs.. } if (es > 30) es = 30; // Cap enemy strength after 1500 vehicles if (owner != t) es = -es + (rand()%5) - 2; } score = fs + es + (rand()%5); if (o->GetObjectivePriority() > 95) score += 50; if (o->GetObjectivePriority() > 90) score += 20; else score += o->GetObjectivePriority() - 80; // os = (o->GetObjectivePriority()-80)*3; // score = os + fs + es + (rand()%5); if (score < 0) score = 0; if (score > 100) score = 100; // Minimum of 1 priority if it's owned by us. if (!score && t == owner) score = 1; // KCK: AI's air and ground priorities are identical for now if (!(pd->flags & GTMOBJ_SCRIPTED_PRIORITY)) { pd->ground_priority[owner] = score; pd->air_priority[owner] = score; // KCK: player_priority only used now if it's >= 0 // if (!(pd->flags & GTMOBJ_PLAYER_SET_PRIORITY)) // pd->player_priority[owner] = pd->air_priority[owner]; } if (!GetRoE(owner,t,ROE_GROUND_CAPTURE) && owner != t) pd->ground_priority[owner] = 0; if (!GetRoE(owner,t,ROE_AIR_ATTACK) && owner != t) pd->air_priority[owner] = 0; if (score > topPriority) { topPriority = score; priorityObj = o->GetCampID(); } o = GetNextObjective(&poit); } }