// problems: giving reclaim order on moving target causes commander // to walk (messing up subsequent dgun order if target still moving) // and does not take commander torso rotation time into account // void CDGunController::TrackAttackTarget(unsigned int currentFrame) { if (currentFrame - state.targetSelectionFrame == 5) { // five sim-frames have passed since selecting target, attack const UnitDef* udef = ai->cb->GetUnitDef(state.targetID); const float3 curTargetPos = ai->cb->GetUnitPos(state.targetID); // current target position const float3 commanderPos = ai->cb->GetUnitPos(commanderID); // current commander position const float targetDist = (commanderPos - curTargetPos).Length(); // distance to target const float3 targetDir = (curTargetPos - state.oldTargetPos).Normalize(); // target direction of movement const float targetSpeed = (curTargetPos - state.oldTargetPos).Length() / 5; // target speed per sim-frame during tracking interval const float dgunDelay = targetDist / commanderWD->projectilespeed; // sim-frames needed for dgun to reach target position const float3 dgunPos = curTargetPos + targetDir * (targetSpeed * dgunDelay); // position where target will be in <dgunDelay> frames const float maxRange = ai->cb->GetUnitMaxRange(commanderID); bool haveClearShot = true; int orderType = -1; AIHCTraceRay rayData = { commanderPos, targetDir, maxRange, commanderID, -1, 0 }; ai->cb->HandleCommand(AIHCTraceRayId, &rayData); if (rayData.hitUID != -1) { haveClearShot = (ai->cb->GetUnitAllyTeam(rayData.hitUID) != ai->cb->GetMyAllyTeam()); } if ((commanderPos - dgunPos).Length() < maxRange * 0.9f) { // multiply by 0.9 to ensure commander does not have to walk if ((ai->cb->GetEnergy()) >= DGUN_MIN_ENERGY_LEVEL) { if (udef != NULL && !udef->weapons.empty() && haveClearShot) { IssueOrder(dgunPos, orderType = CMD_DGUN, 0); } else { IssueOrder(state.targetID, orderType = CMD_CAPTURE, 0); } } else { if (ai->cb->GetUnitHealth(state.targetID) < ai->cb->GetUnitMaxHealth(state.targetID) * 0.5f) { IssueOrder(state.targetID, orderType = CMD_RECLAIM, 0); } else { IssueOrder(state.targetID, orderType = CMD_CAPTURE, 0); } } if (orderType == CMD_DGUN ) { state.dgunOrderFrame = ai->cb->GetCurrentFrame(); } if (orderType == CMD_RECLAIM) { state.reclaimOrderFrame = ai->cb->GetCurrentFrame(); } if (orderType == CMD_CAPTURE) { state.captureOrderFrame = ai->cb->GetCurrentFrame(); } } else { state.Reset(currentFrame, true); } } state.Reset(currentFrame, false); }
void PlanetWars::ExecuteOrders() { FleetMap::const_iterator begin = m_aFleets.begin(); FleetMap::const_iterator end = m_aFleets.end(); FleetMap::const_iterator it; for (it = begin ; it != end ; ++it) { if (it->second.GetStartTurn() == 0) { IssueOrder(it->second.GetSourcePlanet(), it->second.GetDestinationPlanet(), it->second.GetShipsCount()); GetPlanet(it->second.GetSourcePlanet()).RemoveRealShips(it->second.GetShipsCount()); } } }
// problems: giving reclaim order on moving target causes commander // to walk (messing up subsequent dgun order if target still moving) // and does not take commander torso rotation time into account // void CDGunController::TrackAttackTarget(unsigned int currentFrame) { if (currentFrame - state.targetSelectionFrame == 5) { // five sim-frames have passed since selecting target, attack const UnitDef* udef = ai->cb->GetUnitDef(state.targetID); const float3 curTargetPos = ai->cb->GetUnitPos(state.targetID); // current target position const float3 commanderPos = ai->cb->GetUnitPos(commanderID); // current commander position const float3 targetDif = (commanderPos - curTargetPos); const float targetDist = targetDif.Length(); // distance to target const float3 targetVel = (curTargetPos - state.oldTargetPos); float3 targetMoveDir = targetVel; float targetMoveSpeed = 0.0f; if (targetVel != ZeroVector) { targetMoveSpeed = targetVel.Length() / 5.0f; // target speed per sim-frame during tracking interval targetMoveDir = targetVel / (targetMoveSpeed * 5.0f); // target direction of movement } const float dgunDelay = targetDist / commanderWD->projectilespeed; // sim-frames needed for dgun to reach target position const float3 leadPos = targetMoveDir * (targetMoveSpeed * dgunDelay); const float3 dgunPos = curTargetPos + leadPos; // position where target will be in <dgunDelay> frames const float maxRange = ai->cb->GetUnitMaxRange(commanderID); bool haveClearShot = true; int orderType = -1; AIHCTraceRay rayData = { commanderPos, targetDif / targetDist, // direction maxRange, commanderID, -1, 0 }; ai->cb->HandleCommand(AIHCTraceRayId, &rayData); if (rayData.hitUID != -1) { // note: still fails when allied structure is between us and enemy // can also fail if enemy is in front of allied structure and both // are within the d-gun's range haveClearShot = (ai->cb->GetUnitAllyTeam(rayData.hitUID) != ai->cb->GetMyAllyTeam()); // TODO: get DGun weapon properties & check if it can pass through // a unit, if yes then allow executing the code below if(haveClearShot) { // check if there is a unit next to hit unit on DGun path... const float3 enemyPos = ai->cb->GetUnitPos(rayData.hitUID); const float segmentLeft = maxRange - commanderPos.distance(enemyPos); if(segmentLeft > 0.0) { AIHCTraceRay rayData2 = { enemyPos, targetDif / targetDist, segmentLeft, rayData.hitUID, -1, 0 }; ai->cb->HandleCommand(AIHCTraceRayId, &rayData2); if(rayData2.hitUID != -1) { haveClearShot = (ai->cb->GetUnitAllyTeam(rayData2.hitUID) != ai->cb->GetMyAllyTeam()); } } } } // multiply by 0.9 to ensure commander does not have to walk if ((commanderPos - dgunPos).Length() < maxRange * 0.9f) { bool canDGun = (ai->cb->GetEnergy() >= DGUN_MIN_ENERGY_LEVEL) && haveClearShot && (udef != NULL && !udef->weapons.empty()); if(canDGun) { IssueOrder(dgunPos, orderType = CMD_DGUN, 0); } else { bool bDanger = ai->tm->ThreatAtThisPoint(commanderPos/*curTargetPos*/) > ai->tm->GetAverageThreat(); if(bDanger) { state.Reset(currentFrame, true); } else { if (ai->cb->GetUnitHealth(state.targetID) < ai->cb->GetUnitMaxHealth(state.targetID) * 0.5f) { IssueOrder(state.targetID, orderType = CMD_RECLAIM, 0); } else { IssueOrder(state.targetID, orderType = CMD_CAPTURE, 0); } } } if (orderType == CMD_DGUN ) { state.dgunOrderFrame = ai->cb->GetCurrentFrame(); } if (orderType == CMD_RECLAIM) { state.reclaimOrderFrame = ai->cb->GetCurrentFrame(); } if (orderType == CMD_CAPTURE) { state.captureOrderFrame = ai->cb->GetCurrentFrame(); } } else { state.Reset(currentFrame, true); } } state.Reset(currentFrame, false); }
// problems: giving reclaim order on moving target causes commander // to walk (messing up subsequent dgun order if target still moving) // and does not take commander torso rotation time into account // void CDGunController::TrackAttackTarget(unsigned int currentFrame) { if (currentFrame - state.targetSelectionFrame == 5) { // five sim-frames have passed since selecting target, attack const UnitDef* udef = ai->cb->GetUnitDef(state.targetID); const float3 curTargetPos = ai->cb->GetUnitPos(state.targetID); // current target position const float3 commanderPos = ai->cb->GetUnitPos(commanderID); // current commander position const float3 targetDif = (commanderPos - curTargetPos); const float targetDist = targetDif.Length(); // distance to target const float3 targetVel = (curTargetPos - state.oldTargetPos); float3 targetMoveDir = targetVel; float targetMoveSpeed = 0.0f; if (targetVel != ZeroVector) { targetMoveSpeed = targetVel.Length() / 5.0f; // target speed per sim-frame during tracking interval targetMoveDir = targetVel / (targetMoveSpeed * 5.0f); // target direction of movement } const float dgunDelay = targetDist / commanderWD->projectilespeed; // sim-frames needed for dgun to reach target position const float3 leadPos = targetMoveDir * (targetMoveSpeed * dgunDelay); const float3 dgunPos = curTargetPos + leadPos; // position where target will be in <dgunDelay> frames const float maxRange = ai->cb->GetUnitMaxRange(commanderID); bool haveClearShot = true; int numSegments = 0; AIHCTraceRay rayData; float rayLen = maxRange * 1.1f; float3 rayPos = commanderPos; float3 rayDir = targetDif / targetDist; rayDir.y = 0.0f; while (haveClearShot && (rayLen >= 1.0f)) { rayData.rayPos = rayPos; rayData.rayDir = targetDif / targetDist; rayData.rayLen = rayLen; rayData.srcUID = commanderID; rayData.hitUID = -1; rayData.flags = 0; // modifies hitUID and rayLen ai->ccb->HandleCommand(AIHCTraceRayId, &rayData); // note: even if hitUnitID is -1, we can still end up destroying // our own units because dgun projectiles keep hugging the ground // rather than being absorbed by it on impact (which is assumed by // the trace) if (rayData.hitUID != -1) { if (ai->cb->GetUnitAllyTeam(rayData.hitUID) == ai->cb->GetMyAllyTeam()) { // hitUID is an allied unit haveClearShot = false; } else { // hitUID is an enemy unit rayPos = ai->ccb->GetUnitPos(rayData.hitUID); } } // make sure we always terminate rayLen -= rayData.rayLen; } // multiply by 0.9 to ensure commander does not have to walk if ((commanderPos - dgunPos).Length() < maxRange * 0.9f) { bool canDGun = (ai->cb->GetEnergy() >= DGUN_MIN_ENERGY_LEVEL) && haveClearShot && (udef != NULL && !udef->weapons.empty()); if (canDGun) { IssueOrder(dgunPos, CMD_DGUN, 0); } else { bool bDanger = ai->tm->ThreatAtThisPoint(commanderPos/*curTargetPos*/) > ai->tm->GetAverageThreat(); if (bDanger) { state.Reset(currentFrame, true); } else { if (ai->cb->GetUnitHealth(state.targetID) < ai->cb->GetUnitMaxHealth(state.targetID) * 0.5f) { IssueOrder(state.targetID, CMD_RECLAIM, 0); } else { IssueOrder(state.targetID, CMD_CAPTURE, 0); } } } } else { state.Reset(currentFrame, true); } } state.Reset(currentFrame, false); }