void CWaitCommandsAI::SquadWait::RemoveUnit(CUnit* unit) { if (buildUnits.erase(unit)) DeleteDeathDependence(unit, DEPENDENCE_WAITCMD); if (waitUnits.erase(unit)) DeleteDeathDependence(unit, DEPENDENCE_WAITCMD); }
void CWaitCommandsAI::SquadWait::RemoveUnit(CUnit* unit) { CUnitSet::iterator bit = buildUnits.find(unit); if (bit != buildUnits.end()) { DeleteDeathDependence(*bit); buildUnits.erase(bit); } CUnitSet::iterator wit = waitUnits.find(unit); if (wit != waitUnits.end()) { DeleteDeathDependence(*wit); waitUnits.erase(wit); } }
bool CWeapon::AttackGround(float3 pos, bool userTarget) { if (!userTarget && weaponDef->noAutoTarget) { return false; } if (weaponDef->interceptor || !weaponDef->canAttackGround || (weaponDef->onlyTargetCategory != 0xffffffff)) { return false; } if (!weaponDef->waterweapon && (pos.y < 1.0f)) { pos.y = 1.0f; } weaponMuzzlePos=owner->pos+owner->frontdir*relWeaponMuzzlePos.z+owner->updir*relWeaponMuzzlePos.y+owner->rightdir*relWeaponMuzzlePos.x; if(weaponMuzzlePos.y<ground->GetHeight2(weaponMuzzlePos.x,weaponMuzzlePos.z)) weaponMuzzlePos=owner->pos+UpVector*10; //hope that we are underground because we are a popup weapon and will come above ground later if(!TryTarget(pos,userTarget,0)) return false; if(targetUnit){ DeleteDeathDependence(targetUnit); targetUnit=0; } haveUserTarget=userTarget; targetType=Target_Pos; targetPos=pos; return true; }
CCommandAI::~CCommandAI() { if (orderTarget) { DeleteDeathDependence(orderTarget); orderTarget = 0; } }
void CAirMoveType::CheckForCollision(void) { if (!collide) return; SyncedFloat3& pos = owner->midPos; SyncedFloat3& forward = owner->frontdir; float3 midTestPos = pos + forward * 121; std::vector<CUnit*> others = qf->GetUnitsExact(midTestPos, 115); float dist = 200; if (lastColWarning) { DeleteDeathDependence(lastColWarning); lastColWarning = 0; lastColWarningType = 0; } for (std::vector<CUnit*>::iterator ui = others.begin(); ui != others.end(); ++ui) { if (*ui == owner || !(*ui)->unitDef->canfly) continue; SyncedFloat3& op = (*ui)->midPos; float3 dif = op - pos; float3 forwardDif = forward * (forward.dot(dif)); if (forwardDif.SqLength() < dist * dist) { float frontLength = forwardDif.Length(); float3 ortoDif = dif - forwardDif; // note that the radii are multiplied by two since we rely on // aircraft having half-size hitspheres (see unitloader) // // FIXME: with the new collision volumes, is this still true? // // yes: for backward compatibility, aircraft that do not define // their own custom volumes get halved hitspheres by default float minOrtoDif = ((*ui)->radius + owner->radius) * 2 + frontLength * 0.1f + 10; if (ortoDif.SqLength() < minOrtoDif * minOrtoDif) { dist = frontLength; lastColWarning = (*ui); } } } if (lastColWarning) { lastColWarningType = 2; AddDeathDependence(lastColWarning); return; } for (std::vector<CUnit*>::iterator ui = others.begin(); ui != others.end(); ++ui) { if (*ui == owner) continue; if (((*ui)->midPos - pos).SqLength() < dist * dist) { lastColWarning = *ui; } } if (lastColWarning) { lastColWarningType = 1; AddDeathDependence(lastColWarning); } return; }
bool CWeapon::AttackUnit(CUnit *unit,bool userTarget) { if((!userTarget && weaponDef->noAutoTarget)) return false; if(weaponDef->interceptor) return false; weaponPos=owner->pos+owner->frontdir*relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*relWeaponPos.x; if(weaponPos.y<ground->GetHeight2(weaponPos.x,weaponPos.z)) weaponPos=owner->pos+10; //hope that we are underground because we are a popup weapon and will come above ground later if(!unit) { if(targetType!=Target_Unit) //make the unit be more likely to keep the current target if user start to move it targetType=Target_None; haveUserTarget=false; return false; } float3 targetPos(helper->GetUnitErrorPos(unit,owner->allyteam)); targetPos+=errorVector*(weaponDef->targetMoveError*30*unit->speed.Length()*(1.0-owner->limExperience)); if(!TryTarget(targetPos,userTarget,unit)) return false; if(targetUnit) { DeleteDeathDependence(targetUnit); targetUnit=0; } haveUserTarget=userTarget; targetType=Target_Unit; targetUnit=unit; targetPos=unit->midPos+float3(0,0.3,0)*unit->radius; AddDeathDependence(targetUnit); return true; }
void CWaitCommandsAI::GatherWait::Update() { if (waitUnits.size() < 2) { delete this; return; } CUnitSet::iterator it = waitUnits.begin(); while (it != waitUnits.end()) { WaitState state = GetWaitState(*it); if (state == Active) { // do nothing } else if(state == Queued) { return; } else if (state == Missing) { DeleteDeathDependence(*it); it = RemoveUnitFromSet(it, waitUnits); if (waitUnits.empty()) { delete this; return; } continue; } ++it; } // all units are actively waiting on this command, unblock them and die SendWaitCommand(waitUnits); delete this; }
void RepairTask::SetRepairTarget (aiUnit *u) { if (target) DeleteDeathDependence (target); target = u; if (u) AddDeathDependence (u); }
bool CWeapon::AttackUnit(CUnit* unit, bool userTarget) { if ((!userTarget && weaponDef->noAutoTarget)) return false; if (weaponDef->interceptor) return false; weaponPos = owner->pos + owner->frontdir * relWeaponPos.z + owner->updir * relWeaponPos.y + owner->rightdir * relWeaponPos.x; weaponMuzzlePos = owner->pos + owner->frontdir * relWeaponMuzzlePos.z + owner->updir * relWeaponMuzzlePos.y + owner->rightdir * relWeaponMuzzlePos.x; if (weaponMuzzlePos.y < ground->GetHeightReal(weaponMuzzlePos.x, weaponMuzzlePos.z)) { // hope that we are underground because we are a popup weapon and will come above ground later weaponMuzzlePos = owner->pos + UpVector * 10; } if (!unit) { if (targetType != Target_Unit) { // make the unit be more likely to keep the current target if user starts to move it targetType = Target_None; } haveUserTarget = false; return false; } float3 tempTargetPos = helper->GetUnitErrorPos(unit, owner->allyteam) + errorVector * (weaponDef->targetMoveError * GAME_SPEED * unit->speed.Length() * (1.0f - owner->limExperience)); const float appHeight = ground->GetApproximateHeight(tempTargetPos.x, tempTargetPos.z) + 2.0f; if (tempTargetPos.y < appHeight) tempTargetPos.y = appHeight; if (!TryTarget(tempTargetPos, userTarget, unit)) return false; if (targetUnit) { DeleteDeathDependence(targetUnit, DEPENDENCE_TARGETUNIT); targetUnit = NULL; } haveUserTarget = userTarget; targetType = Target_Unit; targetUnit = unit; targetPos = tempTargetPos; AddDeathDependence(targetUnit, DEPENDENCE_TARGETUNIT); avoidTarget = false; return true; }
void CAirCAI::ExecuteAreaAttack(Command &c) { assert(owner->unitDef->canAttack); AAirMoveType* myPlane = (AAirMoveType*) owner->moveType; if (targetDied) { targetDied = false; inCommand = false; } const float3 pos(c.params[0], c.params[1], c.params[2]); const float radius = c.params[3]; if (inCommand) { if (myPlane->aircraftState == AAirMoveType::AIRCRAFT_LANDED) inCommand = false; if (orderTarget && orderTarget->pos.SqDistance2D(pos) > Square(radius)) { inCommand = false; DeleteDeathDependence(orderTarget); orderTarget = 0; } if (owner->commandShotCount < 0) { if ((c.params.size() == 4) && (commandQue.size() > 1)) { owner->AttackUnit(0, true); FinishCommand(); } else if (owner->userAttackGround) { // reset the attack position after each run float3 attackPos = pos + (gs->randVector() * radius); attackPos.y = ground->GetHeightAboveWater(attackPos.x, attackPos.z); owner->AttackGround(attackPos, false); owner->commandShotCount = 0; } } } else { owner->commandShotCount = -1; if (myPlane->aircraftState != AAirMoveType::AIRCRAFT_LANDED) { inCommand = true; std::vector<int> enemyUnitIDs; helper->GetEnemyUnits(pos, radius, owner->allyteam, enemyUnitIDs); if (enemyUnitIDs.empty()) { float3 attackPos = pos + gs->randVector() * radius; attackPos.y = ground->GetHeightAboveWater(attackPos.x, attackPos.z); owner->AttackGround(attackPos, false); } else { // note: the range of randFloat() is inclusive of 1.0f const unsigned int idx(gs->randFloat() * (enemyUnitIDs.size() - 1)); orderTarget = uh->GetUnitUnsafe( enemyUnitIDs[idx] ); owner->AttackUnit(orderTarget, false); AddDeathDependence(orderTarget); } } } }
void CWaitCommandsAI::DeathWait::RemoveUnit(CUnit* unit) { CUnitSet::iterator it = waitUnits.find(unit); if (it != waitUnits.end()) { DeleteDeathDependence(*it); waitUnits.erase(it); } }
void CUnit::FinishedBuilding(void) { beingBuilt = false; buildProgress = 1.0f; if (soloBuilder) { DeleteDeathDependence(soloBuilder); soloBuilder = NULL; } if (!(immobile && (mass == 100000))) { mass = unitDef->mass; //set this now so that the unit is harder to move during build } ChangeLos(realLosRadius,realAirLosRadius); if (unitDef->startCloaked) { wantCloak = true; isCloaked = true; } if (unitDef->windGenerator>0) { if (wind.curStrength > unitDef->windGenerator) { cob->Call(COBFN_SetSpeed, (int)(unitDef->windGenerator * 3000.0f)); } else { cob->Call(COBFN_SetSpeed, (int)(wind.curStrength * 3000.0f)); } cob->Call(COBFN_SetDirection, (int)GetHeadingFromVector(-wind.curDir.x, -wind.curDir.z)); } if (unitDef->activateWhenBuilt) { Activate(); } gs->Team(team)->metalStorage += unitDef->metalStorage; gs->Team(team)->energyStorage += unitDef->energyStorage; //Sets the frontdir in sync with heading. frontdir = GetVectorFromHeading(heading) + float3(0,frontdir.y,0); if (unitDef->isAirBase) { airBaseHandler->RegisterAirBase(this); } luaCallIns.UnitFinished(this); globalAI->UnitFinished(this); if (unitDef->isFeature) { UnBlock(); CFeature* f = featureHandler->CreateWreckage(pos, wreckName, heading, buildFacing, 0, team, false, ""); if (f) { f->blockHeightChanges = true; } KillUnit(false, true, 0); } }
void CWeapon::HoldFire() { if(targetUnit) { DeleteDeathDependence(targetUnit); targetUnit=0; } targetType=Target_None; haveUserTarget=false; }
void CTAAirMoveType::CheckForCollision(void) { if (!collide) return; SyncedFloat3& pos = owner->midPos; SyncedFloat3 forward = owner->speed; forward.Normalize(); float3 midTestPos = pos + forward * 121; std::vector<CUnit*> others = qf->GetUnitsExact(midTestPos, 115); float dist = 200; if (lastColWarning) { DeleteDeathDependence(lastColWarning); lastColWarning = 0; lastColWarningType = 0; } for (std::vector<CUnit*>::iterator ui = others.begin(); ui != others.end(); ++ui) { if (*ui == owner || !(*ui)->unitDef->canfly) continue; SyncedFloat3& op = (*ui)->midPos; float3 dif = op - pos; float3 forwardDif = forward * (forward.dot(dif)); if (forwardDif.SqLength() < dist * dist) { float frontLength = forwardDif.Length(); float3 ortoDif = dif - forwardDif; // note: the radius is multiplied by two since we rely on aircraft // having small spheres (see unitloader) float minOrtoDif = ((*ui)->radius + owner->radius) * 2 + frontLength * 0.05f + 5; if (ortoDif.SqLength() < minOrtoDif * minOrtoDif) { dist = frontLength; lastColWarning = (*ui); } } } if (lastColWarning) { lastColWarningType = 2; AddDeathDependence(lastColWarning); return; } for (std::vector<CUnit*>::iterator ui = others.begin(); ui != others.end(); ++ui) { if (*ui == owner) continue; if (((*ui)->midPos - pos).SqLength() < dist * dist) { lastColWarning = *ui; } } if (lastColWarning) { lastColWarningType = 1; AddDeathDependence(lastColWarning); } return; }
void UnitGroup::UnitDestroyed (aiUnit *unit) { ForceUnit *fu = dynamic_cast<ForceUnit*>(unit); assert (fu); DeleteDeathDependence (fu); units.erase (fu); delete fu; }
void CSelectedUnitsHandler::RemoveUnit(CUnit* unit) { if (selectedUnits.erase(unit)) DeleteDeathDependence(unit, DEPENDENCE_SELECTED); selectionChanged = true; possibleCommandsChanged = true; selectedGroup = -1; unit->isSelected = false; }
void CWeapon::HoldFire() { if (targetUnit) { DeleteDeathDependence(targetUnit, DEPENDENCE_TARGETUNIT); targetUnit = NULL; } targetType = Target_None; haveUserTarget = false; }
void CWaitCommandsAI::SquadWait::Update() { if (buildUnits.empty() && ((int)waitUnits.size() < squadCount)) { // FIXME -- unblock remaining waitUnits ? delete this; return; } if ((int)waitUnits.size() >= squadCount) { CUnitSet unblockSet; CUnitSet::iterator it = waitUnits.begin(); while (it != waitUnits.end()) { WaitState state = GetWaitState(*it); if (state == Active) { unblockSet.insert(*it); if ((int)unblockSet.size() >= squadCount) { break; // we've got our squad } } else if (state == Queued) { // do nothing } else if (state == Missing) { DeleteDeathDependence(*it); it = RemoveUnitFromSet(it, waitUnits); continue; } ++it; } if ((int)unblockSet.size() >= squadCount) { // FIXME -- rebuild the order queue so // that formations are created? SendWaitCommand(unblockSet); for (it = unblockSet.begin(); it != unblockSet.end(); ++it) { DeleteDeathDependence(*it); waitUnits.erase(*it); } } } UpdateText(); // FIXME -- clean builders }
void CUnit::SetLastAttacker(CUnit* attacker) { lastAttack=gs->frameNum; if(lastAttacker && lastAttacker!=userTarget) DeleteDeathDependence(lastAttacker); lastAttacker=attacker; if(attacker) AddDeathDependence(attacker); }
void CSelectedUnits::RemoveUnit(CUnit* unit) { GML_RECMUTEX_LOCK(sel); // RemoveUnit if (selectedUnits.erase(unit)) DeleteDeathDependence(unit, DEPENDENCE_SELECTED); selectionChanged = true; possibleCommandsChanged = true; selectedGroup = -1; unit->isSelected = false; }
void CSelectedUnits::RemoveUnit(CUnit* unit) { GML_RECMUTEX_LOCK(sel); // RemoveUnit selectedUnits.erase(unit); DeleteDeathDependence(unit); selectionChanged=true; possibleCommandsChanged=true; selectedGroup=-1; unit->commandAI->selected=false; }
void CSelectedUnitsHandler::ClearSelected() { for (CUnit* u: selectedUnits) { u->isSelected = false; DeleteDeathDependence(u, DEPENDENCE_SELECTED); } selectedUnits.clear(); selectionChanged = true; possibleCommandsChanged = true; selectedGroup = -1; }
void CSelectedUnits::RemoveUnit(CUnit* unit) { selectedUnits.erase(unit); DeleteDeathDependence(unit); selectionChanged=true; possibleCommandsChanged=true; selectedGroup=-1; PUSH_CODE_MODE; ENTER_MIXED; unit->commandAI->selected=false; POP_CODE_MODE; }
void CCommandAI::SlowUpdate() { if(commandQue.empty()) return; Command& c=commandQue.front(); switch(c.id){ case CMD_WAIT: break; case CMD_STOP:{ owner->AttackUnit(0,true); std::vector<CWeapon*>::iterator wi; for(wi=owner->weapons.begin();wi!=owner->weapons.end();++wi) (*wi)->HoldFire(); FinishCommand(); break;}; case CMD_ATTACK: case CMD_DGUN: if(inCommand){ if(targetDied || (c.params.size() == 1 && uh->units[int(c.params[0])] && !(uh->units[int(c.params[0])]->losStatus[owner->allyteam] & LOS_INRADAR))){ FinishCommand(); break; } if ((c.params.size() == 3) && (owner->commandShotCount > 0) && (commandQue.size() > 1)) { FinishCommand(); break; } } else { if(c.params.size()==1){ if(uh->units[int(c.params[0])]!=0 && uh->units[int(c.params[0])]!=owner){ owner->AttackUnit(uh->units[int(c.params[0])], c.id==CMD_DGUN); if(orderTarget) DeleteDeathDependence(orderTarget); orderTarget=uh->units[int(c.params[0])]; AddDeathDependence(orderTarget); inCommand=true; } else { FinishCommand(); } } else { float3 pos(c.params[0],c.params[1],c.params[2]); owner->AttackGround(pos, c.id==CMD_DGUN); inCommand=true; } } break; default: FinishCommand(); break; } }
void CUnit::SetLastAttacker(CUnit* attacker) { if(gs->Ally(team, attacker->team)){ return; } if(lastAttacker && lastAttacker!=userTarget) DeleteDeathDependence(lastAttacker); lastAttack=gs->frameNum; lastAttacker=attacker; if(attacker) AddDeathDependence(attacker); }
void CUnit::SetUserTarget(CUnit* target) { if(userTarget && lastAttacker!=userTarget) DeleteDeathDependence(userTarget); userTarget=target; for(vector<CWeapon*>::iterator wi=weapons.begin(); wi!=weapons.end(); ++wi) (*wi)->haveUserTarget=false; if(target) { AddDeathDependence(target); } }
void CFactory::StopBuild() { cob->Call("StopBuilding"); if(curBuild){ if(curBuild->beingBuilt){ AddMetal(curBuild->metalCost*curBuild->buildProgress); uh->DeleteUnit(curBuild); } DeleteDeathDependence(curBuild); } curBuild=0; quedBuild=false; }
void CWaitCommandsAI::DeathWait::Update() { if (waitUnits.empty()) { delete this; return; } unitPos.clear(); if (!deathUnits.empty()) { return; // more must die } CUnitSet unblockSet; CUnitSet::iterator it = waitUnits.begin(); while (it != waitUnits.end()) { WaitState state = GetWaitState(*it); if (state == Active) { unblockSet.insert(*it); DeleteDeathDependence(*it); it = RemoveUnitFromSet(it, waitUnits); continue; } else if (state == Queued) { // do nothing } else if (state == Missing) { DeleteDeathDependence(*it); it = RemoveUnitFromSet(it, waitUnits); continue; } ++it; } SendWaitCommand(unblockSet); if (waitUnits.empty()) { delete this; return; } }
void CFactory::StopBuild() { // cancel a build-in-progress script->StopBuilding(); if (curBuild) { if (curBuild->beingBuilt) { AddMetal(curBuild->metalCost * curBuild->buildProgress, false); curBuild->KillUnit(false, true, NULL); } DeleteDeathDependence(curBuild); } curBuild = 0; quedBuild = false; }
void CAirCAI::ExecuteAreaAttack(Command &c) { assert(owner->unitDef->canAttack); CAirMoveType* myPlane = (CAirMoveType*) owner->moveType; if(targetDied){ targetDied = false; inCommand = false; } const float3 pos(c.params[0], c.params[1], c.params[2]); const float radius = c.params[3]; if(inCommand){ if(myPlane->aircraftState == CAirMoveType::AIRCRAFT_LANDED) inCommand = false; if(orderTarget && orderTarget->pos.distance2D(pos) > radius){ inCommand = false; DeleteDeathDependence(orderTarget); orderTarget = 0; } if (owner->commandShotCount > 0) { if ((c.params.size() == 4) && (commandQue.size() > 1)) { owner->AttackUnit(0, true); FinishCommand(); } else if (owner->userAttackGround) { // reset the attack position after each run float3 attackPos = pos + (gs->randVector() * radius); attackPos.y = ground->GetHeight(attackPos.x, attackPos.z); owner->AttackGround(attackPos, false); owner->commandShotCount = 0; } } } else { owner->commandShotCount = -1; if(myPlane->aircraftState != CAirMoveType::AIRCRAFT_LANDED){ inCommand = true; std::vector<int> eu; helper->GetEnemyUnits(pos, radius, owner->allyteam, eu); if(eu.empty()){ float3 attackPos = pos + gs->randVector() * radius; attackPos.y = ground->GetHeight(attackPos.x, attackPos.z); owner->AttackGround(attackPos, false); } else { int num = (int) (gs->randFloat() * eu.size()); orderTarget = uh->units[eu[num]]; owner->AttackUnit(orderTarget, false); AddDeathDependence(orderTarget); } } } }