void ClassicMode::SlideResolution() { if (0 != MyScene.GetSelectedObjectId() && bModelMovedByUser) { bool bCollisionExists = CheckForCollision(); // Snap back if (!bCollisionExists) { SnapPersp(Back); bCollisionExists = CheckForCollision(); } // Snap front if (bCollisionExists) { int nIterations = 3; do SnapPersp(Front); while ((bCollisionExists = CheckForCollision()) && nIterations-- > 0); } if (!bCollisionExists) bModelMovedByUser = false; } }
bool MenuCheckBox::HoldOnCollision(int fingerid, float x, float y, bool releaseifnottouching, bool fingerwentdown) { if( m_FingerHolding != -1 ) return true; if( CheckForCollision( x, y ) ) { PlaySound(); //LOGInfo( LOGTag, "CheckBox Held\n" ); m_FingerHolding = fingerid; m_State = MCBS_HeldDown; return true; } else if( releaseifnottouching ) { //if( m_FingerHolding != -1 ) // LOGInfo( LOGTag, "CheckBox releaseifnottouching\n" ); m_FingerHolding = -1; m_State = MCBS_Idle; } return false; }
void DIYPhysicScene::Update(float dt) { CheckForCollision(); for (PhysicsObject* po : actors) { po->Update(gravity, dt); } }
// Spiele Logik hier void Spiel::Update() { if(_steinNeu->GetStatus()) { if(!CheckForCollision()) _steinNeu->Fallen(); } else { _spielSteine.push_back(*_steinNeu); _steinNeu = new Stein(RandomStein(), _viewNeu); } }
// ----------------------------------------------------------------------- // // // ROUTINE: CLightCycleMgr::Update // // PURPOSE: Updates the light cycle mgr // // ----------------------------------------------------------------------- // void CLightCycleMgr::Update() { if(!m_bUpdating) return; // Vars LTVector vPos; LTVector vOldForward; LIGHT_CYCLIST* pCyclist; LIGHT_CYCLE_TRAIL *pTrail; std::vector<LIGHT_CYCLIST*>::iterator iter; // Walk the list for(iter=m_collCyclists.begin();iter!=m_collCyclists.end();iter++) { pCyclist = (*iter); if(pCyclist->bUpdating) { // Update his trail ASSERT(pCyclist->hObject); g_pLTServer->GetObjectPos(pCyclist->hObject,&vPos); pTrail = pCyclist->pCurTrail; // Check to see if we have a trail if(pTrail) { vOldForward = pCyclist->vForward; // Update the trail UpdateLightCycleTrail(pCyclist, vPos); } else { // Simple case: We're starting a new trail BeginLightCycleTrail(pCyclist,vPos); } // Now we check to see if this guy collided LightCycleCollisionInfo info; if(CheckForCollision(pCyclist,info)) { // Uh-oh. We have a crash. And crashing is bad, m'kay? HandleCollision(pCyclist,info); } } } }
int MenuCheckBox::TriggerOnCollision(int fingerid, float x, float y, bool careifheld, bool releaseifnocollision) { if( careifheld && m_FingerHolding != fingerid ) return -1; if( CheckForCollision( x, y ) ) { PlaySound(); //LOGInfo( LOGTag, "CheckBox TriggerOnCollision\n" ); m_Checked = !m_Checked; return m_Action; } return -1; }
float MenuCheckBox::TestCollision(int fingerid, float x, float y, bool fingerwentdown) { //if( m_FingerHolding != -1 ) // return true; if( CheckForCollision( x, y ) ) { float posx = m_Transform.m41; float posy = m_Transform.m42; float dist = (posx - x)*(posx - x) + (posy - y)*(posy - y); return dist; } return -1; }
bool MenuCheckBox::ReleaseOnNoCollision(int fingerid, float x, float y) { if( m_FingerHolding != fingerid ) return false; if( CheckForCollision( x, y ) ) { return false; } else { if( m_State == MCBS_HeldDown ) { PlaySound(); //LOGInfo( LOGTag, "CheckBox ReleaseOnNoCollision\n" ); m_FingerHolding = -1; m_State = MCBS_Idle; return true; } } return false; }
void CAirMoveType::UpdateFighterAttack(void) { float3 &pos = owner->pos; SyncedFloat3 &rightdir = owner->rightdir; SyncedFloat3 &frontdir = owner->frontdir; SyncedFloat3 &updir = owner->updir; float3 &speed = owner->speed; float speedf = owner->speed.Length(); if (speedf < 0.01f) { UpdateAirPhysics(0, 0, 0, 1, owner->frontdir); return; } if (!((gs->frameNum + owner->id) & 3)) CheckForCollision(); bool groundTarget = !owner->userTarget || !owner->userTarget->unitDef->canfly || owner->userTarget->unitDef->hoverAttack; bool airTarget = owner->userTarget && owner->userTarget->unitDef->canfly && !owner->userTarget->unitDef->hoverAttack; //only "real" aircrafts (non gunship) if (groundTarget) { if (frontdir.dot(goalPos - pos) < 0 && (pos - goalPos).SqLength() < turnRadius * turnRadius * (loopbackAttack ? 4 : 1)) { float3 dif = pos - goalPos; dif.y = 0; dif.Normalize(); goalPos = goalPos + dif * turnRadius * 4; } else if (loopbackAttack && !airTarget) { bool hasFired = false; if (!owner->weapons.empty() && owner->weapons[0]->reloadStatus > gs->frameNum && owner->weapons[0]->salvoLeft == 0) hasFired = true; if (frontdir.dot(goalPos - pos) < owner->maxRange * (hasFired ? 1.0f : 0.7f)) maneuver = 1; } else if (frontdir.dot(goalPos - pos) < owner->maxRange * 0.7f) { goalPos += exitVector * (owner->userTarget ? owner->userTarget->radius + owner->radius + 10 : owner->radius + 40); } } float3 tgp = goalPos + (goalPos - oldGoalPos) * 8; oldGoalPos = goalPos; goalPos = tgp; float goalLength = (goalPos - pos).Length(); float3 goalDir = (goalLength > 0.0f)? (goalPos - pos) / goalLength: ZeroVector; float aileron = 0; float rudder = 0; float elevator = 0; float engine = 0; float gHeight = ground->GetHeight(pos.x, pos.z); float goalDotRight = rightdir.dot(goalDir); float goalDotFront = goalDir.dot(frontdir) * 0.5f + 0.501f; if (goalDotFront != 0.0f) { goalDotRight /= goalDotFront; } if (goalDir.dot(frontdir) < -0.2f + inefficientAttackTime * 0.002f && frontdir.y > -0.2f && speedf > 2.0f && gs->randFloat() > 0.996f) maneuver = 1; if (goalDir.dot(frontdir) < -0.2f + inefficientAttackTime * 0.002f && fabs(frontdir.y) < 0.2f && gs->randFloat() > 0.996f && gHeight + 400 < pos.y) { maneuver = 2; maneuverSubState = 0; } // roll if (speedf > 0.45f && pos.y + owner->speed.y * 60 * fabs(frontdir.y) + std::min(0.0f, float(updir.y)) * 150 > gHeight + 60 + fabs(rightdir.y) * 150) { float goalBankDif = goalDotRight + rightdir.y * 0.2f; if (goalBankDif > maxAileron * speedf * 4.0f) { aileron = 1; } else if (goalBankDif < -maxAileron * speedf * 4.0f) { aileron = -1; } else { aileron = goalBankDif / (maxAileron * speedf * 4.0f); } } else { if (rightdir.y > 0.0f) { if (rightdir.y > maxAileron * speedf || frontdir.y < -0.7f) { aileron = 1; } else { if (speedf > 0.0f) { aileron = rightdir.y / (maxAileron * speedf); } } } else { if (rightdir.y < -maxAileron * speedf || frontdir.y < -0.7f) { aileron = -1; } else { if (speedf > 0.0f) { aileron = rightdir.y / (maxAileron * speedf); } } } } // yaw if (pos.y > gHeight + 30) { if (goalDotRight < -maxRudder * speedf) { rudder = -1; } else if (goalDotRight > maxRudder * speedf) { rudder = 1; } else { if (speedf > 0.0f) { rudder = goalDotRight / (maxRudder * speedf); } } } float upside = 1; if (updir.y < -0.3f) upside = -1; // pitch if (speedf < 1.5f) { if (frontdir.y < 0.0f) { elevator = upside; } else if (frontdir.y > 0.0f) { elevator = -upside; } } else { float gHeight2 = ground->GetHeight(pos.x + speed.x * 40, pos.z + speed.z * 40); float hdif = std::max(gHeight, gHeight2) + 60 - pos.y - frontdir.y * speedf * 20; float minPitch = 1.0f; // min(1.0f, hdif / (maxElevator * speedf * speedf * 20)); if (hdif < -(maxElevator * speedf * speedf * 20)) { minPitch = -1; } else if (hdif > (maxElevator * speedf * speedf * 20)) { minPitch = 1; } else { minPitch = hdif / (maxElevator * speedf * speedf * 20); } // } else { if (lastColWarning && lastColWarningType == 2 && frontdir.dot(lastColWarning->pos + lastColWarning->speed * 20 - pos-owner->speed * 20) < 0) { /* float pitchMod = (updir.y > 0.0f)? 1: -1; if (lastColWarning->pos.y > pos.y) elevator = -pitchMod; else elevator = pitchMod; */ elevator = (updir.dot(lastColWarning->midPos - owner->midPos) > 0.0f)? -1 : 1; } else { float hdif = goalDir.dot(updir); if (hdif < -maxElevator * speedf) { elevator = -1; } else if (hdif > maxElevator * speedf) { elevator = 1; } else { elevator = hdif / (maxElevator * speedf); } } if (elevator * upside < minPitch) elevator = minPitch * upside; } #ifdef DEBUG_AIRCRAFT GML_RECMUTEX_LOCK(sel); // UpdateFighterAttack if (selectedUnits.selectedUnits.find(this) != selectedUnits.selectedUnits.end()){ logOutput.Print("FAttack %.1f %.1f %.2f", pos.y - gHeight, goalLength, goalDir.dot(frontdir)); } #endif if (groundTarget) engine = 1; else engine = std::min(1.f, (float)(goalLength / owner->maxRange + 1 - goalDir.dot(frontdir) * 0.7f)); UpdateAirPhysics(rudder, aileron, elevator, engine, owner->frontdir); }
void CheckSignalNet(struct signal *signalPointer) { struct pin *pinPointer; char *signal_name; int pinType; char signalPins[MAXPERNET]; inputPinCount = 0; outputPinCount = 0; sinkPinCount = 0; sourcePinCount = 0; analogPinCount = 0; undeclaredPinCount = 0; totalPinCount = 0; signal_name = signalPointer -> bucket -> name; if (cFlag) { fprintf(stdout, "%s:", signal_name); if (xFlag) printf("\n"); else if (signalPointer -> pin_count > MAXPERNET) Bug("signal net too large in CheckSignalNet"); } /* end if */ for (pinPointer = signalPointer -> first_pin; pinPointer != NULL_STRUCT(pin); pinPointer = pinPointer -> instance_chain) { (void) CheckForCollision(signalPointer, pinPointer); pinType = PinType(pinPointer, cFlag & xFlag); if (cFlag & !xFlag) signalPins[totalPinCount] = pinType; else (void) DoPinType(pinPointer, signalPointer, pinType); totalPinCount++; } /* end for */ if (cFlag) { if (!xFlag) { signalPins[totalPinCount] = '\0'; fprintf(stdout, "\t%s\n", signalPins); } /* end if */ if (pFlag) fprintf(stdout, "\t\t\t\t%di,%do,%ds,%dS,%da,%du\n", inputPinCount, outputPinCount, sinkPinCount, sourcePinCount, analogPinCount, undeclaredPinCount); return; } /* end if */ if ((sinkPinCount > 0) && (sourcePinCount == 0) && (!PowerGroundNet(signalPointer)) && (!AnalogNet(signalPointer))) if (OpenCollectorNet(signalPointer)) (void) ParanoidSignalWarning(signalPointer, "no o.c. pullup"); else (void) ParanoidSignalWarning(signalPointer, "no source"); if ((!PowerGroundNet(signalPointer)) && (inputPinCount > 0) && (outputPinCount == 0)) (void) ParanoidSignalWarning(signalPointer, "no outputs"); if ((!PowerGroundNet(signalPointer)) && (outputPinCount > 0) && (inputPinCount == 0)) (void) ParanoidSignalWarning(signalPointer, "no inputs"); (void) CheckSignalPins(signalPointer); } /* end CheckSignalNet */
void CheckSignal(struct signal *signalPointer) { int pins; int pinType; char message[STRLEN]; char *pinName; struct pin *thePin; struct pin_definitions *pinDefinitions; if (tFlag) printf("%s: #%d\n", signalPointer -> bucket -> name, signalPointer -> pin_count); pins = signalPointer -> pin_count; if (signalPointer -> type & IGNORE_SIGNAL) return; if (pins == 0) (void) Warning("net %s has no pins?", signalPointer -> bucket -> name); else if (pins == 1) { if (signalPointer -> type & MACRO_SIGNAL & mFlag) return; thePin = signalPointer -> first_pin; if (LFlag && (signalPointer -> bucket -> name[0] == '$')) return; /* ignore local nets */ pinDefinitions = thePin -> instance -> chip -> pin_definitions; if (cFlag) return; if (xFlag) { pinName = ""; pinType = NO_TYPE; if ((pinDefinitions != NULL_STRUCT(pin_definitions)) && (pinDefinitions -> pin_names) && (pinDefinitions -> pin_names[(thePin -> pin_number) - 1])) { pinName = pinDefinitions -> pin_names[(thePin -> pin_number) - 1]; pinType = TypePin(pinDefinitions -> pin_types[(thePin -> pin_number) - 1]); } if (wFlag) (void) sprintf(message, "lone%s pin at %s.%d (%s.%s) [%s]", pinDirectionString[PinDirection(pinType)], thePin -> instance -> bucket -> name, thePin -> pin_number, thePin -> instance -> chip -> bucket -> name, pinName, wFiles[thePin -> fileindex]); else (void) sprintf(message, "lone%s pin at %s.%d (%s.%s)", pinDirectionString[PinDirection(pinType)], thePin -> instance -> bucket -> name, thePin -> pin_number, thePin -> instance -> chip -> bucket -> name, pinName); } /* end if */ else (void) sprintf(message, "lone%s pin at %s.%d", pinDirectionString[PinDirection(pinType)], thePin -> instance -> bucket -> name, thePin -> pin_number); (void) SignalWarning(signalPointer, FULL_PIN, message); (void) CheckForCollision(signalPointer, thePin); } /* end if */ else (void) CheckSignalNet(signalPointer); } /* end CheckSignal */
void CAirMoveType::UpdateFlying(float wantedHeight,float engine) { float3 &pos = owner->pos; float3 &rightdir = owner->rightdir; float3 &frontdir = owner->frontdir; float3 &updir = owner->updir; float3 &speed = owner->speed; float speedf=speed.Length(); float goalLength=(goalPos-pos).Length(); float3 goalDir=(goalPos-pos)/goalLength; goalDir.Normalize(); float aileron=0; float rudder=0; float elevator=0; float gHeight=ground->GetHeight(pos.x,pos.z); if(!((gs->frameNum+owner->id)&3)) CheckForCollision(); float otherThreat=0; float3 otherDir; if(lastColWarning){ float3 otherDif=lastColWarning->pos-pos; float otherLength=otherDif.Length(); otherDir=otherDif/otherLength; otherThreat=max(1200.f,goalLength)/otherLength*0.036; } float goalDot=rightdir.dot(goalDir); goalDot/=goalDir.dot(frontdir)*0.5+0.501; if(goalDir.dot(frontdir)<-0.1 && goalLength<turnRadius #ifdef DIRECT_CONTROL_ALLOWED && (!owner->directControl || owner->directControl->mouse2) #endif ) goalDot=-goalDot; if(lastColWarning){ goalDot-=otherDir.dot(rightdir)*otherThreat; } //roll if(speedf>1.5 && pos.y+speed.y*10>gHeight+wantedHeight*0.6){ float goalBankDif=goalDot+rightdir.y*0.5; if(goalBankDif>maxAileron*speedf*4 && rightdir.y>-maxBank){ aileron=1; } else if(goalBankDif<-maxAileron*speedf*4 && rightdir.y<maxBank){ aileron=-1; } else { if(fabs(rightdir.y)<maxBank) aileron=goalBankDif/(maxAileron*speedf*4); else { if(rightdir.y<0 && goalBankDif<0) aileron=-1; else if(rightdir.y>0 && goalBankDif>0) aileron=1; } } } else { if(rightdir.y>0.01){ aileron=1; } else if(rightdir.y<-0.01){ aileron=-1; } } //yaw if(pos.y>gHeight+15){ if(goalDot<-maxRudder*speedf*2){ rudder=-1;; } else if(goalDot>maxRudder*speedf*2){ rudder=1; } else { rudder=goalDot/(maxRudder*speedf*2); } } //pitch if(speedf>0.8){ if(lastColWarningType==2 && frontdir.dot(lastColWarning->midPos+lastColWarning->speed*20 - owner->midPos - owner->speed*20)<0){ /* float pitchMod=updir.y>0?1:-1; if(lastColWarning->pos.y>pos.y) elevator=-pitchMod; else elevator=pitchMod; /*/ elevator=updir.dot(lastColWarning->midPos-owner->midPos)>0?-1:1;/**/ } else { float gHeight2=ground->GetHeight(pos.x+speed.x*40,pos.z+speed.z*40); float hdif=max(gHeight,gHeight2)+wantedHeight-pos.y-frontdir.y*speedf*20; if(hdif<-(maxElevator*speedf*speedf*20) && frontdir.y>-maxPitch){ elevator=-1; } else if(hdif>(maxElevator*speedf*speedf*20) && frontdir.y<maxPitch){ elevator=1; } else { if(fabs(frontdir.y)<maxPitch) elevator=hdif/(maxElevator*speedf*speedf*20); } } } else { if(frontdir.y<-0.1){ elevator=1; } else if(frontdir.y>0.15){ elevator=-1; } } UpdateAirPhysics(rudder,aileron,elevator,engine,owner->frontdir); }
void CTAAirMoveType::UpdateAirPhysics() { float3& pos = owner->pos; float3& speed = owner->speed; if (!((gs->frameNum + owner->id) & 3)) { CheckForCollision(); } float yspeed = speed.y; speed.y = 0.0f; float3 delta = wantedSpeed - speed; float dl = delta.Length(); if (delta.dot(speed) > 0.0f) { // accelerate if (dl < accRate) { speed = wantedSpeed; } else { if (dl > 0.0f) { speed += delta / dl * accRate; } } } else { // break if (dl < decRate) { speed = wantedSpeed; } else { if (dl > 0.0f) { speed += delta / dl * decRate; } } } speed.y = yspeed; float h = pos.y - std::max( ground->GetHeight(pos.x, pos.z), ground->GetHeight(pos.x + speed.x * 40.0f, pos.z + speed.z * 40.0f)); if (h < 4.0f) { speed.x *= 0.95f; speed.z *= 0.95f; } float wh = wantedHeight; if (lastColWarningType == 2) { const float3 dir = lastColWarning->midPos - owner->midPos; const float3 sdir = lastColWarning->speed - speed; if (speed.dot(dir + sdir * 20.0f) < 0.0f) { if (lastColWarning->midPos.y > owner->pos.y) { wh -= 30.0f; } else { wh += 50.0f; } } } float ws = 0.0f; if (h < wh) { ws = altitudeRate; if (speed.y > 0.0f && (wh - h) / speed.y * accRate * 1.5f < speed.y) ws = 0.0f; } else { ws = -altitudeRate; if (speed.y < 0.0f && (wh - h) / speed.y * accRate * 0.7f < -speed.y) ws = 0.0f; } if (speed.y > ws) { speed.y = std::max(ws, speed.y - accRate * 1.5f); } else { // let them accelerate upward faster if close to ground speed.y = std::min(ws, speed.y + accRate * (h < 20.0f? 2.0f: 0.7f)); } pos += speed; }
void CAirMoveType::UpdateFighterAttack(void) { float3 &pos = owner->pos; float3 &rightdir = owner->rightdir; float3 &frontdir = owner->frontdir; float3 &updir = owner->updir; float3 &speed = owner->speed; float speedf=owner->speed.Length(); if(speedf<0.01){ UpdateAirPhysics(0,0,0,1,owner->frontdir); return; } if(!((gs->frameNum+owner->id)&3)) CheckForCollision(); bool groundTarget=!owner->userTarget || !owner->userTarget->unitDef->canfly; if(groundTarget){ if(frontdir.dot(goalPos-pos)<0 && (pos-goalPos).SqLength()<turnRadius*turnRadius){ float3 dif=pos-goalPos; dif.y=0; dif.Normalize(); goalPos=goalPos+dif*turnRadius*4; } else if(frontdir.dot(goalPos-pos)<owner->maxRange*0.7){ goalPos+=exitVector*(owner->userTarget?owner->userTarget->radius+owner->radius+10:owner->radius+40); } } float3 tgp=goalPos+(goalPos-oldGoalPos)*8; oldGoalPos=goalPos; goalPos=tgp; float goalLength=(goalPos-pos).Length(); float3 goalDir=(goalPos-pos)/goalLength; float aileron=0; float rudder=0; float elevator=0; float engine=0; float gHeight=ground->GetHeight(pos.x,pos.z); float goalDot=rightdir.dot(goalDir); goalDot/=goalDir.dot(frontdir)*0.5+0.501; if(goalDir.dot(frontdir)<-0.2+inefficientAttackTime*0.002 && frontdir.y>-0.2 && speedf>2.0 && gs->randFloat()>0.996) maneuver=1; if(goalDir.dot(frontdir)<-0.2+inefficientAttackTime*0.002 && fabs(frontdir.y)<0.2 && gs->randFloat()>0.996 && gHeight+400<pos.y){ maneuver=2; maneuverSubState=0; } //roll if(speedf>0.45 && pos.y+owner->speed.y*60*fabs(frontdir.y)+min(0.f,updir.y)*150>gHeight+60+fabs(rightdir.y)*150){ float goalBankDif=goalDot+rightdir.y*0.2; if(goalBankDif>maxAileron*speedf*4){ aileron=1; } else if(goalBankDif<-maxAileron*speedf*4){ aileron=-1; } else { aileron=goalBankDif/(maxAileron*speedf*4); } } else { if(rightdir.y>0){ if(rightdir.y>maxAileron*speedf || frontdir.y<-0.7) aileron=1; else aileron=rightdir.y/(maxAileron*speedf); } else { if(rightdir.y<-maxAileron*speedf || frontdir.y<-0.7) aileron=-1; else aileron=rightdir.y/(maxAileron*speedf); } } //yaw if(pos.y>gHeight+30){ if(goalDot<-maxRudder*speedf){ rudder=-1; } else if(goalDot>maxRudder*speedf){ rudder=1; } else { rudder=goalDot/(maxRudder*speedf); } } float upside=1; if(updir.y<-0.3) upside=-1; //pitch if(speedf<1.5){ if(frontdir.y<0.0){ elevator=upside; } else if(frontdir.y>0.0){ elevator=-upside; } } else { float gHeight2=ground->GetHeight(pos.x+speed.x*40,pos.z+speed.z*40); float hdif=max(gHeight,gHeight2)+60-pos.y-frontdir.y*speedf*20; float minPitch;//=min(1.0f,hdif/(maxElevator*speedf*speedf*20)); if(hdif<-(maxElevator*speedf*speedf*20)){ minPitch=-1; } else if(hdif>(maxElevator*speedf*speedf*20)){ minPitch=1; } else { minPitch=hdif/(maxElevator*speedf*speedf*20); } /* if(pos.y+min(0,owner->speed.y)*70*fabs(frontdir.y)+min(0,updir.y)*50<gHeight+50){ if(frontdir.y<0.5){ elevator=upside; } else if(frontdir.y>0.55){ elevator=-upside; }*/ // } else { if(lastColWarningType==2 && frontdir.dot(lastColWarning->pos+lastColWarning->speed*20-pos-owner->speed*20)<0){ /* float pitchMod=updir.y>0?1:-1; if(lastColWarning->pos.y>pos.y) elevator=-pitchMod; else elevator=pitchMod; /*/ elevator=updir.dot(lastColWarning->midPos-owner->midPos)>0?-1:1;/**/ } else { float hdif=goalDir.dot(updir); if(hdif<-maxElevator*speedf){ elevator=-1; } else if(hdif>maxElevator*speedf){ elevator=1; } else { elevator=hdif/(maxElevator*speedf); } } if(elevator*upside<minPitch) elevator=minPitch*upside; } #ifdef DEBUG_AIRCRAFT if(selectedUnits.selectedUnits.find(this)!=selectedUnits.selectedUnits.end()){ info->AddLine("FAttack %.1f %.1f %.2f",pos.y-gHeight,goalLength,goalDir.dot(frontdir)); } #endif if(groundTarget) engine=1; else engine=min(1.f,(float)(goalLength/owner->maxRange+1-goalDir.dot(frontdir)*0.7)); UpdateAirPhysics(rudder,aileron,elevator,engine,owner->frontdir); /* std::vector<CWeapon*>::iterator wi; for(wi=owner->weapons.begin();wi!=owner->weapons.end();++wi){ (*wi)->targetPos=goalPos; if(owner->userTarget){ (*wi)->AttackUnit(owner->userTarget,true); } }*/ /* DrawLine dl; dl.color=UpVector; dl.pos1=pos; dl.pos2=goalPos; lines.push_back(dl); dl.color=float3(1,0,0); dl.pos1=pos; dl.pos2=pos+frontdir*maxRange; lines.push_back(dl);/**/ }
void CTAAirMoveType::UpdateAirPhysics() { float3& pos=owner->pos; float3& speed=owner->speed; if(!((gs->frameNum+owner->id)&3)) CheckForCollision(); /* if(lastColWarningType==1){ int g=geometricObjects->AddLine(owner->pos,lastColWarning->pos,10,1,1); geometricObjects->SetColor(g,0.2f,1,0.2f,0.6f); } else if(lastColWarningType==2){ int g=geometricObjects->AddLine(owner->pos,lastColWarning->pos,10,1,1); if(speed.dot(lastColWarning->midPos+lastColWarning->speed*20 - owner->midPos - owner->speed*20)<0) geometricObjects->SetColor(g,1,0.2f,0.2f,0.6f); else geometricObjects->SetColor(g,1,1,0.2f,0.6f); } */ float yspeed=speed.y; speed.y=0; float3 delta = wantedSpeed - speed; float dl=delta.Length(); if(delta.dot(speed)>0){ //accelerate if(dl<accRate) speed=wantedSpeed; else speed+=delta/dl*accRate; } else { //break if(dl<decRate) speed=wantedSpeed; else speed+=delta/dl*decRate; } speed.y=yspeed; float h = pos.y - max(ground->GetHeight(pos.x, pos.z),ground->GetHeight(pos.x+speed.x*40,pos.z+speed.z*40)); if(h<4){ speed.x*=0.95f; speed.z*=0.95f; } float wh=wantedHeight; if(lastColWarningType==2 && speed.dot(lastColWarning->midPos+lastColWarning->speed*20-owner->midPos-speed*20)<0){ if(lastColWarning->midPos.y>owner->pos.y) wh-=30; else wh+=50; } float ws; if (h < wh){ ws= altitudeRate; if(speed.y>0 && (wh-h)/speed.y*accRate*1.5f < speed.y) ws=0; } else { ws= -altitudeRate; if(speed.y<0 && (wh-h)/speed.y*accRate*0.7f < -speed.y) ws=0; } if(speed.y>ws) speed.y=max(ws,speed.y-accRate*1.5f); else speed.y=min(ws,speed.y+accRate*(h<20?2.0f:0.7f)); //let them accelerate upward faster if close to ground pos+=speed; }
void CHoverAirMoveType::UpdateAirPhysics() { const float3& pos = owner->pos; const float4& spd = owner->speed; // copy vertical speed const float yspeed = spd.y; if (((gs->frameNum + owner->id) & 3) == 0) { CheckForCollision(); } // cancel out vertical speed, acc and dec are applied in xz-plane owner->SetVelocity(spd * XZVector); const float3 deltaSpeed = wantedSpeed - spd; const float deltaDotSpeed = deltaSpeed.dot(spd); const float deltaSpeedSq = deltaSpeed.SqLength(); if (deltaDotSpeed >= 0.0f) { // accelerate if (deltaSpeedSq < Square(accRate)) { owner->SetVelocity(wantedSpeed); } else { if (deltaSpeedSq > 0.0f) { owner->SetVelocity(spd + (deltaSpeed / math::sqrt(deltaSpeedSq) * accRate)); } } } else { // deccelerate if (deltaSpeedSq < Square(decRate)) { owner->SetVelocity(wantedSpeed); } else { if (deltaSpeedSq > 0.0f) { owner->SetVelocity(spd + (deltaSpeed / math::sqrt(deltaSpeedSq) * decRate)); } } } // absolute and relative ground height at (pos.x, pos.z) // if this aircraft uses the smoothmesh, these values are // calculated with respect to that (for changing vertical // speed, but not for ground collision) float curAbsHeight = owner->unitDef->canSubmerge? CGround::GetHeightReal(pos.x, pos.z): CGround::GetHeightAboveWater(pos.x, pos.z); // always stay above the actual terrain (therefore either the value of // <midPos.y - radius> or pos.y must never become smaller than the real // ground height) // note: unlike StrafeAirMoveType, UpdateTakeoff and UpdateLanding call // UpdateAirPhysics() so we ignore terrain while we are in those states if (modInfo.allowAircraftToHitGround) { const bool groundContact = (curAbsHeight > (owner->midPos.y - owner->radius)); const bool handleContact = (aircraftState != AIRCRAFT_LANDED && aircraftState != AIRCRAFT_TAKEOFF && padStatus == PAD_STATUS_FLYING); if (groundContact && handleContact) { owner->Move(UpVector * (curAbsHeight - (owner->midPos.y - owner->radius) + 0.01f), true); } } if (UseSmoothMesh()) { curAbsHeight = owner->unitDef->canSubmerge? smoothGround->GetHeight(pos.x, pos.z): smoothGround->GetHeightAboveWater(pos.x, pos.z); } // restore original vertical speed, then compute new UpdateVerticalSpeed(spd, pos.y - curAbsHeight, yspeed); if (modInfo.allowAircraftToLeaveMap || (pos + spd).IsInBounds()) { owner->Move(spd, true); } }
void CHoverAirMoveType::UpdateAirPhysics() { const float3& pos = owner->pos; const float4& spd = owner->speed; // copy vertical speed const float yspeed = spd.y; if (((gs->frameNum + owner->id) & 3) == 0) { CheckForCollision(); } owner->SetVelocity(spd * XZVector); const float3 deltaSpeed = wantedSpeed - spd; const float deltaDotSpeed = deltaSpeed.dot(spd); const float deltaSpeedSq = deltaSpeed.SqLength(); if (deltaDotSpeed >= 0.0f) { // accelerate if (deltaSpeedSq < Square(accRate)) { owner->SetVelocity(wantedSpeed); } else { if (deltaSpeedSq > 0.0f) { owner->SetVelocity(spd + (deltaSpeed / math::sqrt(deltaSpeedSq) * accRate)); } } } else { // deccelerate if (deltaSpeedSq < Square(decRate)) { owner->SetVelocity(wantedSpeed); } else { if (deltaSpeedSq > 0.0f) { owner->SetVelocity(spd + (deltaSpeed / math::sqrt(deltaSpeedSq) * decRate)); } } } // absolute and relative ground height at (pos.x, pos.z) // if this aircraft uses the smoothmesh, these values are // calculated with respect to that (for changing vertical // speed, but not for ground collision) float curAbsHeight = owner->unitDef->canSubmerge? ground->GetHeightReal(pos.x, pos.z): ground->GetHeightAboveWater(pos.x, pos.z); float curRelHeight = 0.0f; float wh = wantedHeight; // wanted RELATIVE height (altitude) float ws = 0.0f; // wanted vertical speed // always stay above the actual terrain (therefore either the value of // <midPos.y - radius> or pos.y must never become smaller than the real // ground height) // note: unlike StrafeAirMoveType, UpdateTakeoff and UpdateLanding call // UpdateAirPhysics() so we ignore terrain while we are in those states if (modInfo.allowAircraftToHitGround) { const bool groundContact = (curAbsHeight > (owner->midPos.y - owner->radius)); const bool handleContact = (aircraftState != AIRCRAFT_LANDED && aircraftState != AIRCRAFT_TAKEOFF && padStatus == PAD_STATUS_FLYING); if (groundContact && handleContact) { owner->Move(UpVector * (curAbsHeight - (owner->midPos.y - owner->radius) + 0.01f), true); } } if (UseSmoothMesh()) { curAbsHeight = owner->unitDef->canSubmerge? smoothGround->GetHeight(pos.x, pos.z): smoothGround->GetHeightAboveWater(pos.x, pos.z); } // restore original vertical speed owner->SetVelocity((spd * XZVector) + (UpVector * yspeed)); if (lastColWarningType == 2) { const float3 dir = lastColWarning->midPos - owner->midPos; const float3 sdir = lastColWarning->speed - spd; if (spd.dot(dir + sdir * 20.0f) < 0.0f) { if (lastColWarning->midPos.y > owner->pos.y) { wh -= 30.0f; } else { wh += 50.0f; } } } curRelHeight = pos.y - curAbsHeight; if (curRelHeight < wh) { ws = altitudeRate; if ((spd.y > 0.0001f) && (((wh - curRelHeight) / spd.y) * accRate * 1.5f) < spd.y) { ws = 0.0f; } } else { ws = -altitudeRate; if ((spd.y < -0.0001f) && (((wh - curRelHeight) / spd.y) * accRate * 0.7f) < -spd.y) { ws = 0.0f; } } if (!owner->beingBuilt) { if (math::fabs(wh - curRelHeight) > 2.0f) { if (spd.y > ws) { owner->SetVelocity((spd * XZVector) + (UpVector * std::max(ws, spd.y - accRate * 1.5f))); } else { // accelerate upward faster if close to ground owner->SetVelocity((spd * XZVector) + (UpVector * std::min(ws, spd.y + accRate * ((curRelHeight < 20.0f)? 2.0f: 0.7f)))); } } else { owner->SetVelocity((spd * XZVector) + (UpVector * spd.y * 0.95f)); } } owner->SetSpeed(spd); if (modInfo.allowAircraftToLeaveMap || (pos + spd).IsInBounds()) { owner->Move(spd, true); } }
/* Function: modEuler * Description: Modified Euler Integrator using Implicit and Explicit * vi(t + h) = vi(t) + (ALPHA / h) * (gi(t) - xi(t)) + (h / mi) * Fext(t) * xi(t + h) = xi(t) + h * vi(t + h) * Input: None * Output: None */ void ModEuler(phyzx *phyzxObj, int mIndex, int deformMode) { point vertex, velocity, extVel, position, velDamp; point vDiff, velTotal, newPos, temp; matrix R, matTemp; memset( (void*)&temp, 0, sizeof(temp)); memset((void*)&extVel, 0, sizeof(point)); memset((void*)&velocity, 0, sizeof(point)); memset((void*)&position, 0, sizeof(point)); memset((void*)&vDiff, 0, sizeof(point)); memset((void*)&velTotal, 0, sizeof(point)); memset((void*)&newPos, 0, sizeof(point)); memset((void*)&phyzxObj->avgVel, 0, sizeof(point)); matInit(&R, 0, 0); matInit(&matTemp, 0, 0); if (deformMode == 3) quadDeformRot(&R, phyzxObj); for (unsigned int index = STARTFROM; index <= phyzxObj->model->numvertices; index++) { if (deformMode == 3) { // Compute Quadratic Deformation Goal Positions matMult(R, phyzxObj->q[index], &matTemp); // R(q) temp = matToPoint(matTemp); // Data type conversion pSUM(temp, phyzxObj->cmDeformed, phyzxObj->goal[index]); // g = R(q) + xcm } //end if else { // Compute Goal Positions matMult3331(phyzxObj->R, phyzxObj->relStableLoc[index], &temp); // R(xi0 - xcm0) pSUM(temp, phyzxObj->cmDeformed, phyzxObj->goal[index]); // g = R(xi0 - xcm0) + xcm } //end if vertex.x = phyzxObj->model->vertices[3*index]; vertex.y = phyzxObj->model->vertices[3*index + 1]; vertex.z = phyzxObj->model->vertices[3*index + 2];\ if (stickyFloor == 1) if (vertex.y <= -WALLDIST) continue; // Add user force if (mIndex == iMouseModel && lMouseVal == 2 && objectName != -1)// && index == objectName) { //point uForce; /*GLMnode *node; node = NBVStruct[objectName]; while (node->next != NULL) { pSUM(phyzxObj->extForce[node->index], userForce, phyzxObj->extForce[node->index]); node = node->next; } //end while*/ /*if (index != objectName) { point extPos = vMake(phyzxObj->model->vertices[3*objectName], phyzxObj->model->vertices[3*objectName+1], phyzxObj->model->vertices[3*objectName+2]); double dist = vecLeng(extPos, vertex); //if (dist > 0.04) //{ pMULTIPLY(userForce, (1.0/dist), uForce); pSUM(phyzxObj->extForce[index], uForce, phyzxObj->extForce[index]); //pDisp("user", userForce); //} //end if //else //{ //pSUM(phyzxObj->extForce[index], userForce, phyzxObj->extForce[index]); //} //end else } //end if else {*/ pSUM(phyzxObj->extForce[index], userForce, phyzxObj->extForce[index]); //} //end else } //end if // Explicit Euler Integrator for veloctiy -> vi(t + h) pDIFFERENCE(phyzxObj->goal[index], vertex, vDiff); // gi(t) - xi(t) pMULTIPLY(vDiff, (phyzxObj->alpha / phyzxObj->h), velocity); // vi(h) = (ALPHA / h) * (gi(t) - xi(t)) pMULTIPLY(phyzxObj->extForce[index], (phyzxObj->h / phyzxObj->mass[index]), extVel); // (h / mi) * Fext(t) // pMULTIPLY(phyzxObj->extForce[index], phyzxObj->h, extVel); // (h / mi) * Fext(t) pSUM(velocity, extVel, velTotal); // vi(h) = (ALPHA / h) * (gi(t) - xi(t)) + (h / mi) * Fext(t) pSUM(phyzxObj->velocity[index], velTotal, phyzxObj->velocity[index]); // vi(t + h) = vi(t) + vi(h) // Velocity Damping pMULTIPLY(phyzxObj->velocity[index], -phyzxObj->delta, velDamp); pSUM(phyzxObj->velocity[index], velDamp, phyzxObj->velocity[index]); // Implicity Euler Integrator for position pMULTIPLY(phyzxObj->velocity[index], phyzxObj->h, position); // xi(h) = h * vi(t + h) pSUM(vertex, position, newPos); // xi(t + h) = xi(t) + xi(h) // Store new position into data structure phyzxObj->model->vertices[3*index] = newPos.x; phyzxObj->model->vertices[3*index + 1] = newPos.y; phyzxObj->model->vertices[3*index + 2] = newPos.z; pSUM(phyzxObj->avgVel, phyzxObj->velocity[index], phyzxObj->avgVel); //if (objCollide) CheckForCollision(index, phyzxObj, mIndex); } //end for pMULTIPLY(phyzxObj->avgVel, 1.0 / phyzxObj->model->numvertices, phyzxObj->avgVel); delete[] R.data; delete[] matTemp.data; } //end ModEuler()
void CHoverAirMoveType::UpdateAirPhysics() { const float3& pos = owner->pos; float3& speed = owner->speed; if (!((gs->frameNum + owner->id) & 3)) { CheckForCollision(); } const float yspeed = speed.y; speed.y = 0.0f; const float3 deltaSpeed = wantedSpeed - speed; const float deltaDotSpeed = (speed != ZeroVector)? deltaSpeed.dot(speed): 1.0f; if (deltaDotSpeed == 0.0f) { // we have the wanted speed } else if (deltaDotSpeed > 0.0f) { // accelerate const float sqdl = deltaSpeed.SqLength(); if (sqdl < Square(accRate)) { speed = wantedSpeed; } else { speed += (deltaSpeed / math::sqrt(sqdl) * accRate); } } else { // break const float sqdl = deltaSpeed.SqLength(); if (sqdl < Square(decRate)) { speed = wantedSpeed; } else { speed += (deltaSpeed / math::sqrt(sqdl) * decRate); } } // absolute and relative ground height at (pos.x, pos.z) // if this aircraft uses the smoothmes, these values are // calculated with respect to that for changing vertical // speed, but not for ground collision float curAbsHeight = owner->unitDef->canSubmerge? ground->GetHeightReal(pos.x, pos.z): ground->GetHeightAboveWater(pos.x, pos.z); float curRelHeight = 0.0f; float wh = wantedHeight; // wanted RELATIVE height (altitude) float ws = 0.0f; // wanted vertical speed // always stay above the actual terrain (therefore either the value of // <midPos.y - radius> or pos.y must never become smaller than the real // ground height) // note: unlike StrafeAirMoveType, UpdateTakeoff calls UpdateAirPhysics // so we ignore terrain while we are in the takeoff state to avoid jumps if (modInfo.allowAircraftToHitGround) { const bool groundContact = (curAbsHeight > (owner->midPos.y - owner->radius)); const bool handleContact = (aircraftState != AIRCRAFT_LANDED && aircraftState != AIRCRAFT_TAKEOFF); if (groundContact && handleContact) { owner->Move1D(curAbsHeight - (owner->midPos.y - owner->radius) + 0.01f, 1, true); } } if (UseSmoothMesh()) { curAbsHeight = owner->unitDef->canSubmerge? smoothGround->GetHeight(pos.x, pos.z): smoothGround->GetHeightAboveWater(pos.x, pos.z); } speed.y = yspeed; curRelHeight = pos.y - curAbsHeight; if (lastColWarningType == 2) { const float3 dir = lastColWarning->midPos - owner->midPos; const float3 sdir = lastColWarning->speed - speed; if (speed.dot(dir + sdir * 20.0f) < 0.0f) { if (lastColWarning->midPos.y > owner->pos.y) { wh -= 30.0f; } else { wh += 50.0f; } } } if (curRelHeight < wh) { ws = altitudeRate; if ((speed.y > 0.0001f) && (((wh - curRelHeight) / speed.y) * accRate * 1.5f) < speed.y) { ws = 0.0f; } } else { ws = -altitudeRate; if ((speed.y < -0.0001f) && (((wh - curRelHeight) / speed.y) * accRate * 0.7f) < -speed.y) { ws = 0.0f; } } if (!owner->beingBuilt) { if (math::fabs(wh - curRelHeight) > 2.0f) { if (speed.y > ws) { speed.y = std::max(ws, speed.y - accRate * 1.5f); } else { // accelerate upward faster if close to ground speed.y = std::min(ws, speed.y + accRate * ((curRelHeight < 20.0f)? 2.0f: 0.7f)); } } else { speed.y *= 0.95; } } if (modInfo.allowAircraftToLeaveMap || (pos + speed).IsInBounds()) { owner->Move3D(speed, true); } }
void CAirMoveType::UpdateFlying(float wantedHeight, float engine) { float3& pos = owner->pos; SyncedFloat3& rightdir = owner->rightdir; SyncedFloat3& frontdir = owner->frontdir; SyncedFloat3& updir = owner->updir; float3& speed = owner->speed; float speedf = speed.Length(); float3 goalDir = (goalPos - pos); float goalLength = std::max(0.001f, goalDir.Length2D()); goalDir /= goalLength; float3 adjustedGoalDir = float3(goalPos.x, 0, goalPos.z) - float3(pos.x, 0, pos.z); adjustedGoalDir.SafeANormalize(); float aileron = 0.0f; float rudder = 0.0f; float elevator = 0.0f; // do not check if the plane can be submerged here, since it'll cause // ground collisions later on float gHeight = ground->GetHeight(pos.x, pos.z); if (!((gs->frameNum + owner->id) & 3)) CheckForCollision(); float otherThreat = 0.0f; float3 otherDir; if (lastColWarning) { float3 otherDif = lastColWarning->pos - pos; float otherLength = otherDif.Length(); otherDir = (otherLength > 0.0f)? (otherDif / otherLength): ZeroVector; otherThreat = (otherLength > 0.0f)? std::max(1200.0f, goalLength) / otherLength * 0.036f: 0.0f; } float goalDotRight = rightdir.dot(adjustedGoalDir); float goalDotFront = adjustedGoalDir.dot(frontdir) * 0.5f + 0.501f; if (goalDotFront > 0.01f) { goalDotRight /= goalDotFront; } if (adjustedGoalDir.dot(frontdir) < -0.1f && goalLength < turnRadius && (!owner->directControl || owner->directControl->mouse2)) goalDotRight = -goalDotRight; if (lastColWarning) { goalDotRight -= otherDir.dot(rightdir) * otherThreat; } // roll if (speedf > 1.5f && pos.y + speed.y * 10 > gHeight + wantedHeight * 0.6f) { float goalBankDif = goalDotRight + rightdir.y * 0.5f; if (goalBankDif > maxAileron*speedf * 4 && rightdir.y > -maxBank) { aileron = 1; } else if (goalBankDif < -maxAileron * speedf * 4 && rightdir.y < maxBank) { aileron = -1; } else { if (fabs(rightdir.y) < maxBank) { aileron = goalBankDif / (maxAileron * speedf * 4); } else { if (rightdir.y < 0.0f && goalBankDif < 0.0f) { aileron = -1; } else if (rightdir.y > 0.0f && goalBankDif > 0.0f) { aileron = 1; } } } } else { if (rightdir.y > 0.01f) { aileron = 1; } else if (rightdir.y < -0.01f) { aileron = -1; } } // yaw if (pos.y > gHeight + 15) { if (goalDotRight < -maxRudder * speedf * 2) { rudder = -1; } else if (goalDotRight > maxRudder * speedf * 2) { rudder = 1; } else { if (speedf > 0.0f && maxRudder > 0.0f) { rudder = goalDotRight / (maxRudder * speedf * 2); } else { rudder = 0; } } } // pitch if (speedf > 0.8f) { bool notColliding = true; if (lastColWarningType == 2) { const float3 dir = lastColWarning->midPos - owner->midPos; const float3 sdir = lastColWarning->speed - owner->speed; if (frontdir.dot(dir + sdir * 20) < 0) { elevator = updir.dot(dir) > 0 ? -1 : 1; notColliding = false; } } if (notColliding) { float gHeight2 = ground->GetHeight(pos.x + speed.x * 40, pos.z + speed.z * 40); float hdif = std::max(gHeight, gHeight2) + wantedHeight - pos.y - frontdir.y * speedf * 20; if (hdif < -(maxElevator * speedf * speedf * 20) && frontdir.y > -maxPitch) { elevator = -1; } else if (hdif > (maxElevator * speedf * speedf * 20) && frontdir.y < maxPitch) { elevator = 1; } else { if (fabs(frontdir.y) < maxPitch) elevator = hdif / (maxElevator * speedf * speedf * 20); } } } else { if (frontdir.y < -0.1f) { elevator = 1; } else if (frontdir.y > 0.15f) { elevator = -1; } } UpdateAirPhysics(rudder, aileron, elevator, engine, owner->frontdir); }
void CTAAirMoveType::UpdateAirPhysics() { float3& pos = owner->pos; float3& speed = owner->speed; if (!((gs->frameNum + owner->id) & 3)) { CheckForCollision(); } const float yspeed = speed.y; speed.y = 0.0f; float3 delta = wantedSpeed - speed; const float deltaDotSpeed = (speed != ZeroVector)? delta.dot(speed): 1.0f; if (deltaDotSpeed == 0.0f) { // we have the wanted speed } else if (deltaDotSpeed > 0.0f) { // accelerate const float sqdl = delta.SqLength(); if (sqdl < Square(accRate)) { speed = wantedSpeed; } else { speed += delta / math::sqrt(sqdl) * accRate; } } else { // break const float sqdl = delta.SqLength(); if (sqdl < Square(decRate)) { speed = wantedSpeed; } else { speed += delta / math::sqrt(sqdl) * decRate; } } speed.y = yspeed; float h; if (UseSmoothMesh()) { h = pos.y - std::max( smoothGround->GetHeightAboveWater(pos.x, pos.z), smoothGround->GetHeightAboveWater(pos.x + speed.x * 20.0f, pos.z + speed.z * 20.0f)); } else { h = pos.y - std::max( ground->GetHeightAboveWater(pos.x, pos.z), ground->GetHeightAboveWater(pos.x + speed.x * 40.0f, pos.z + speed.z * 40.0f)); } if (h < 4.0f) { speed.x *= 0.95f; speed.z *= 0.95f; } float wh = wantedHeight; if (lastColWarningType == 2) { const float3 dir = lastColWarning->midPos - owner->midPos; const float3 sdir = lastColWarning->speed - speed; if (speed.dot(dir + sdir * 20.0f) < 0.0f) { if (lastColWarning->midPos.y > owner->pos.y) { wh -= 30.0f; } else { wh += 50.0f; } } } float ws = 0.0f; if (h < wh) { ws = altitudeRate; if (speed.y > 0.0001f && (wh - h) / speed.y * accRate * 1.5f < speed.y) { ws = 0.0f; } } else { ws = -altitudeRate; if (speed.y < -0.0001f && (wh - h) / speed.y * accRate * 0.7f < -speed.y) { ws = 0.0f; } } if (fabs(wh - h) > 2.0f) { if (speed.y > ws) { speed.y = std::max(ws, speed.y - accRate * 1.5f); } else if (!owner->beingBuilt) { // let them accelerate upward faster if close to ground speed.y = std::min(ws, speed.y + accRate * (h < 20.0f? 2.0f: 0.7f)); } } else { speed.y = speed.y * 0.95; } if (modInfo.allowAirPlanesToLeaveMap || (pos+speed).CheckInBounds()) { pos += speed; } }
void CHoverAirMoveType::UpdateAirPhysics() { const float3& pos = owner->pos; float3& speed = owner->speed; if (!((gs->frameNum + owner->id) & 3)) { CheckForCollision(); } const float yspeed = speed.y; speed.y = 0.0f; const float3 deltaSpeed = wantedSpeed - speed; const float deltaDotSpeed = (speed != ZeroVector)? deltaSpeed.dot(speed): 1.0f; if (deltaDotSpeed == 0.0f) { // we have the wanted speed } else if (deltaDotSpeed > 0.0f) { // accelerate const float sqdl = deltaSpeed.SqLength(); if (sqdl < Square(accRate)) { speed = wantedSpeed; } else { speed += (deltaSpeed / math::sqrt(sqdl) * accRate); } } else { // break const float sqdl = deltaSpeed.SqLength(); if (sqdl < Square(decRate)) { speed = wantedSpeed; } else { speed += (deltaSpeed / math::sqrt(sqdl) * decRate); } } float minHeight = 0.0f; // absolute ground height at (pos.x, pos.z) float curHeight = 0.0f; // relative ground height at (pos.x, pos.z) == pos.y - minHeight (altitude) float wh = wantedHeight; // wanted RELATIVE height (altitude) float ws = 0.0f; // wanted vertical speed if (UseSmoothMesh()) { minHeight = owner->unitDef->canSubmerge? smoothGround->GetHeight(pos.x, pos.z): smoothGround->GetHeightAboveWater(pos.x, pos.z); } else { minHeight = owner->unitDef->canSubmerge? ground->GetHeightReal(pos.x, pos.z): ground->GetHeightAboveWater(pos.x, pos.z); } // [?] aircraft should never be able to end up below terrain // if (pos.y < minHeight) // owner->Move1D(std::min(minHeight - pos.y, altitudeRate), 1, true); speed.y = yspeed; curHeight = pos.y - minHeight; if (curHeight < 4.0f) { speed.x *= 0.95f; speed.z *= 0.95f; } if (lastColWarningType == 2) { const float3 dir = lastColWarning->midPos - owner->midPos; const float3 sdir = lastColWarning->speed - speed; if (speed.dot(dir + sdir * 20.0f) < 0.0f) { if (lastColWarning->midPos.y > owner->pos.y) { wh -= 30.0f; } else { wh += 50.0f; } } } if (curHeight < wh) { ws = altitudeRate; if ((speed.y > 0.0001f) && (((wh - curHeight) / speed.y) * accRate * 1.5f) < speed.y) { ws = 0.0f; } } else { ws = -altitudeRate; if ((speed.y < -0.0001f) && (((wh - curHeight) / speed.y) * accRate * 0.7f) < -speed.y) { ws = 0.0f; } } if (!owner->beingBuilt) { if (math::fabs(wh - curHeight) > 2.0f) { if (speed.y > ws) { speed.y = std::max(ws, speed.y - accRate * 1.5f); } else { // accelerate upward faster if close to ground speed.y = std::min(ws, speed.y + accRate * ((curHeight < 20.0f)? 2.0f: 0.7f)); } } else { speed.y *= 0.95; } } if (modInfo.allowAircraftToLeaveMap || (pos + speed).IsInBounds()) { owner->Move3D(speed, true); } }