void CWeapon::SlowUpdate(bool noAutoTargetOverride) { #ifdef TRACE_SYNC tracefile << "Weapon slow update: "; tracefile << owner->id << " " << weaponNum << "\n"; #endif // If we can't get a line of fire from the muzzle, try // the aim piece instead (since the weapon may just be // turned in a wrong way) int weaponPiece = -1; bool weaponAimed = (useWeaponPosForAim == 0); if (!weaponAimed) { weaponPiece = owner->script->QueryWeapon(weaponNum); if (useWeaponPosForAim > 1) useWeaponPosForAim--; } else { weaponPiece = owner->script->AimFromWeapon(weaponNum); } relWeaponMuzzlePos = owner->script->GetPiecePos(weaponPiece); weaponMuzzlePos = owner->pos + owner->frontdir * relWeaponMuzzlePos.z + owner->updir * relWeaponMuzzlePos.y + owner->rightdir * relWeaponMuzzlePos.x; weaponPos = owner->pos + owner->frontdir * relWeaponPos.z + owner->updir * relWeaponPos.y + owner->rightdir * relWeaponPos.x; if (!weaponAimed) { weaponPiece = owner->script->AimFromWeapon(weaponNum); } relWeaponPos = owner->script->GetPiecePos(weaponPiece); 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; } predictSpeedMod = 1.0f + (gs->randFloat() - 0.5f) * 2 * (1.0f - owner->limExperience); hasCloseTarget = ((targetPos - weaponPos).SqLength() < relWeaponPos.SqLength() * 16); if (targetType != Target_None && !TryTarget(targetPos, haveUserTarget, targetUnit)) { HoldFire(); } if (targetType == Target_Unit) { // stop firing at cloaked targets if (targetUnit != NULL && targetUnit->isCloaked && !(targetUnit->losStatus[owner->allyteam] & (LOS_INLOS | LOS_INRADAR))) HoldFire(); if (!haveUserTarget) { // stop firing at neutral targets (unless in FAW mode) // note: HoldFire sets targetUnit to NULL, so recheck if (targetUnit != NULL && targetUnit->neutral && owner->fireState <= FIRESTATE_FIREATWILL) HoldFire(); // stop firing at allied targets // // this situation (unit keeps attacking its target if the // target or the unit switches to an allied team) should // be handled by /ally processing now if (targetUnit != NULL && teamHandler->Ally(owner->allyteam, targetUnit->allyteam)) HoldFire(); } } if (slavedTo) { // use targets from the thing we are slaved to if (targetUnit) { DeleteDeathDependence(targetUnit, DEPENDENCE_TARGETUNIT); targetUnit = NULL; } targetType = Target_None; if (slavedTo->targetType == Target_Unit) { const float3 tp = helper->GetUnitErrorPos(slavedTo->targetUnit, owner->allyteam) + errorVector * (weaponDef->targetMoveError * GAME_SPEED * slavedTo->targetUnit->speed.Length() * (1.0f - owner->limExperience)); if (TryTarget(tp, false, slavedTo->targetUnit)) { targetType = Target_Unit; targetUnit = slavedTo->targetUnit; targetPos = tp; AddDeathDependence(targetUnit, DEPENDENCE_TARGETUNIT); } } else if (slavedTo->targetType == Target_Pos) { if (TryTarget(slavedTo->targetPos, false, 0)) { targetType = Target_Pos; targetPos = slavedTo->targetPos; } } return; } if (!noAutoTargetOverride && AllowWeaponTargetCheck()) { lastTargetRetry = gs->frameNum; std::multimap<float, CUnit*> targets; std::multimap<float, CUnit*>::const_iterator nextTargetIt; std::multimap<float, CUnit*>::const_iterator lastTargetIt; helper->GenerateWeaponTargets(this, targetUnit, targets); if (!targets.empty()) lastTargetIt = --targets.end(); for (nextTargetIt = targets.begin(); nextTargetIt != targets.end(); ++nextTargetIt) { CUnit* nextTargetUnit = nextTargetIt->second; if (nextTargetUnit->neutral && (owner->fireState <= FIRESTATE_FIREATWILL)) { continue; } // when only one target is available, <nextTarget> can equal <targetUnit> // and we want to attack whether it is in our bad target category or not // (if only bad targets are available and this is the last, just pick it) if (nextTargetUnit != targetUnit && (nextTargetUnit->category & badTargetCategory)) { if (nextTargetIt != lastTargetIt) { continue; } } const float weaponLead = weaponDef->targetMoveError * GAME_SPEED * nextTargetUnit->speed.Length(); const float weaponError = weaponLead * (1.0f - owner->limExperience); float3 nextTargetPos = nextTargetUnit->midPos + (errorVector * weaponError); const float appHeight = ground->GetApproximateHeight(nextTargetPos.x, nextTargetPos.z) + 2.0f; if (nextTargetPos.y < appHeight) { nextTargetPos.y = appHeight; } if (TryTarget(nextTargetPos, false, nextTargetUnit)) { if (targetUnit) { DeleteDeathDependence(targetUnit, DEPENDENCE_TARGETUNIT); } targetType = Target_Unit; targetUnit = nextTargetUnit; targetPos = nextTargetPos; AddDeathDependence(targetUnit, DEPENDENCE_TARGETUNIT); break; } } } if (targetType != Target_None) { owner->haveTarget = true; if (haveUserTarget) { owner->haveUserTarget = true; } } else { // if we can't target anything, try switching aim point if (useWeaponPosForAim == 1) { useWeaponPosForAim = 0; } else { useWeaponPosForAim = 1; } } }
void CWeapon::SlowUpdate() { #ifdef TRACE_SYNC tracefile << "Weapon slow update: "; tracefile << owner->id << " " << weaponNum << "\n"; #endif std::vector<int> args; args.push_back(0); if(useWeaponPosForAim) { owner->cob->Call(COBFN_QueryPrimary+weaponNum,args); if(useWeaponPosForAim>1) useWeaponPosForAim--; } else { owner->cob->Call(COBFN_AimFromPrimary+weaponNum,args); } relWeaponPos=owner->localmodel->GetPiecePos(args[0]); 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 predictSpeedMod=1+(gs->randFloat()-0.5)*2*(1-owner->limExperience); if((targetPos-weaponPos).SqLength() < relWeaponPos.SqLength()*16) hasCloseTarget=true; else hasCloseTarget=false; if(targetType!=Target_None && !TryTarget(targetPos,haveUserTarget,targetUnit)) { HoldFire(); } if(targetType==Target_Unit && targetUnit->isCloaked && !(targetUnit->losStatus[owner->allyteam] & (LOS_INLOS | LOS_INRADAR))) HoldFire(); if(slavedTo) { //use targets from the thing we are slaved to if(targetUnit) { DeleteDeathDependence(targetUnit); targetUnit=0; } targetType=Target_None; if(slavedTo->targetType==Target_Unit) { float3 tp=helper->GetUnitErrorPos(slavedTo->targetUnit,owner->allyteam); tp+=errorVector*(weaponDef->targetMoveError*30*slavedTo->targetUnit->speed.Length()*(1.0-owner->limExperience)); if(TryTarget(tp,false,slavedTo->targetUnit)) { targetType=Target_Unit; targetUnit=slavedTo->targetUnit; targetPos=tp; AddDeathDependence(targetUnit); } } else if(slavedTo->targetType==Target_Pos) { if(TryTarget(slavedTo->targetPos,false,0)) { targetType=Target_Pos; targetPos=slavedTo->targetPos; } } return; } if(!weaponDef->noAutoTarget) { if(owner->fireState==2 && !haveUserTarget && (targetType==Target_None || (targetType==Target_Unit && (targetUnit->category & badTargetCategory)) || gs->frameNum>lastTargetRetry+65)) { std::map<float,CUnit*> targets; helper->GenerateTargets(this,targetUnit,targets); for(std::map<float,CUnit*>::iterator ti=targets.begin(); ti!=targets.end(); ++ti) { if(targetUnit && (ti->second->category & badTargetCategory)) continue; float3 tp(ti->second->midPos); tp+=errorVector*(weaponDef->targetMoveError*30*ti->second->speed.Length()*(1.0-owner->limExperience)); if(TryTarget(tp,false,ti->second)) { if(targetUnit) { DeleteDeathDependence(targetUnit); } targetType=Target_Unit; targetUnit=ti->second; targetPos=tp; AddDeathDependence(targetUnit); break; } } } } if(targetType!=Target_None) { owner->haveTarget=true; if(haveUserTarget) owner->haveUserTarget=true; } else { //if we cant target anything try switching aim point if(useWeaponPosForAim && useWeaponPosForAim==1) { useWeaponPosForAim=0; } else { useWeaponPosForAim=1; } } }
void CWeapon::StopAttackingAllyTeam(int ally) { if (targetUnit && targetUnit->allyteam == ally) { HoldFire(); } }
void CWeapon::SlowUpdate(bool noAutoTargetOverride) { #ifdef TRACE_SYNC tracefile << "Weapon slow update: "; tracefile << owner->id << " " << weaponNum << "\n"; #endif std::vector<int> args; args.push_back(0); if(useWeaponPosForAim){ //If we can't get a line of fire from the muzzle try the aim piece instead since the weapon may just be turned in a wrong way owner->cob->Call(COBFN_QueryPrimary+weaponNum,args); if(useWeaponPosForAim>1) useWeaponPosForAim--; } else { owner->cob->Call(COBFN_AimFromPrimary+weaponNum,args); } relWeaponMuzzlePos=owner->localmodel->GetPiecePos(args[0]); weaponMuzzlePos=owner->pos+owner->frontdir*relWeaponMuzzlePos.z+owner->updir*relWeaponMuzzlePos.y+owner->rightdir*relWeaponMuzzlePos.x; owner->cob->Call(COBFN_AimFromPrimary+weaponNum,args); relWeaponPos=owner->localmodel->GetPiecePos(args[0]); weaponPos=owner->pos+owner->frontdir*relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*relWeaponPos.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 predictSpeedMod=1+(gs->randFloat()-0.5f)*2*(1-owner->limExperience); if((targetPos-weaponPos).SqLength() < relWeaponPos.SqLength()*16) hasCloseTarget=true; else hasCloseTarget=false; if(targetType!=Target_None && !TryTarget(targetPos,haveUserTarget,targetUnit)){ HoldFire(); } if(targetType==Target_Unit && targetUnit->isCloaked && !(targetUnit->losStatus[owner->allyteam] & (LOS_INLOS | LOS_INRADAR))) HoldFire(); if (targetType==Target_Unit && !haveUserTarget && targetUnit->neutral && owner->fireState < 3) HoldFire(); //happens if the target or the unit has switched teams if (targetType==Target_Unit && !haveUserTarget && targetUnit->allyteam == owner->allyteam) HoldFire(); if(slavedTo){ //use targets from the thing we are slaved to if(targetUnit){ DeleteDeathDependence(targetUnit); targetUnit=0; } targetType=Target_None; if(slavedTo->targetType==Target_Unit){ float3 tp=helper->GetUnitErrorPos(slavedTo->targetUnit,owner->allyteam); tp+=errorVector*(weaponDef->targetMoveError*30*slavedTo->targetUnit->speed.Length()*(1.0f-owner->limExperience)); if(TryTarget(tp,false,slavedTo->targetUnit)){ targetType=Target_Unit; targetUnit=slavedTo->targetUnit; targetPos=tp; AddDeathDependence(targetUnit); } } else if(slavedTo->targetType==Target_Pos){ if(TryTarget(slavedTo->targetPos,false,0)){ targetType=Target_Pos; targetPos=slavedTo->targetPos; } } return; } /* owner->fireState>=2 && !haveUserTarget && if (!weaponDef->noAutoTarget && !noAutoTargetOverride) { ((targetType == Target_None) || ((targetType == Target_Unit) && ((targetUnit->category & badTargetCategory) || (targetUnit->neutral && (owner->fireState < 3)))) || (gs->frameNum > lastTargetRetry + 65))) { */ if (!noAutoTargetOverride && ShouldCheckForNewTarget()) { lastTargetRetry = gs->frameNum; std::map<float, CUnit*> targets; helper->GenerateTargets(this, targetUnit, targets); for (std::map<float,CUnit*>::iterator ti=targets.begin();ti!=targets.end();++ti) { if (ti->second->neutral && (owner->fireState < 3)) { continue; } if (targetUnit && (ti->second->category & badTargetCategory)) { continue; } float3 tp(ti->second->midPos); tp+=errorVector*(weaponDef->targetMoveError*30*ti->second->speed.Length()*(1.0f-owner->limExperience)); float appHeight=ground->GetApproximateHeight(tp.x,tp.z)+2; if (tp.y < appHeight) { tp.y = appHeight; } if (TryTarget(tp, false, ti->second)) { if (targetUnit) { DeleteDeathDependence(targetUnit); } targetType = Target_Unit; targetUnit = ti->second; targetPos = tp; AddDeathDependence(targetUnit); break; } } } if (targetType != Target_None) { owner->haveTarget = true; if (haveUserTarget) { owner->haveUserTarget = true; } } else { //if we cant target anything try switching aim point if (useWeaponPosForAim && (useWeaponPosForAim == 1)) { useWeaponPosForAim = 0; } else { useWeaponPosForAim = 1; } } }