void CMissileProjectile::Update() { if (--ttl > 0) { if (!luaMoveCtrl) { if (curSpeed < maxSpeed) { curSpeed += weaponDef->weaponacceleration; } float3 targSpeed(ZeroVector); if (weaponDef->tracks && target) { CSolidObject* so = dynamic_cast<CSolidObject*>(target); CWeaponProjectile* po = dynamic_cast<CWeaponProjectile*>(target); targetPos = target->pos; if (so) { targetPos = so->aimPos; targSpeed = so->speed; if (owner()) { CUnit* u = dynamic_cast<CUnit*>(so); if (u) { targetPos = CGameHelper::GetUnitErrorPos(u, owner()->allyteam, true); } } } if (po) { targSpeed = po->speed; } } if (isWobbling) { --wobbleTime; if (wobbleTime == 0) { float3 newWob = gs->randVector(); wobbleDif = (newWob - wobbleDir) * (1.0f / 16); wobbleTime = 16; } wobbleDir += wobbleDif; dir += wobbleDir * weaponDef->wobble * (owner()? (1.0f - owner()->limExperience * 0.5f): 1); dir.Normalize(); } if (isDancing) { --danceTime; if (danceTime <= 0) { danceMove = gs->randVector() * weaponDef->dance - danceCenter; danceCenter += danceMove; danceTime = 8; } pos += danceMove; } const float3 orgTargPos = targetPos; const float3 targetDir = (targetPos - pos).SafeNormalize(); const float dist = pos.distance(targetPos) + 0.1f; if (extraHeightTime > 0) { extraHeight -= extraHeightDecay; --extraHeightTime; targetPos.y += extraHeight; if (dir.y <= 0.0f) { // missile has reached apex, smoothly transition // to targetDir (can still overshoot when target // is too close or height difference too large) const float horDiff = (targetPos - pos).Length2D() + 0.01f; const float verDiff = (targetPos.y - pos.y) + 0.01f; const float dirDiff = math::fabs(targetDir.y - dir.y); const float ratio = math::fabs(verDiff / horDiff); dir.y -= (dirDiff * ratio); } else { // missile is still ascending dir.y -= (extraHeightDecay / dist); } } float3 dif = (targetPos + targSpeed * (dist / maxSpeed) * 0.7f - pos).SafeNormalize(); float3 dif2 = dif - dir; if (dif2.SqLength() < Square(weaponDef->turnrate)) { dir = dif; } else { dif2 -= (dir * (dif2.dot(dir))); dif2.SafeNormalize(); dir += (dif2 * weaponDef->turnrate); dir.SafeNormalize(); } targetPos = orgTargPos; speed = dir * curSpeed; } gCEG->Explosion(cegID, pos, ttl, areaOfEffect, NULL, 0.0f, NULL, dir); } else { if (weaponDef->selfExplode) { Collision(); } else { // only when TTL <= 0 do we (missiles) // get influenced by gravity and drag if (!luaMoveCtrl) { speed *= 0.98f; speed.y += mygravity; dir = speed; dir.SafeNormalize(); } } } if (!luaMoveCtrl) { pos += speed; } age++; numParts++; if (weaponDef->visuals.smokeTrail && !(age & 7)) { CSmokeTrailProjectile* tp = new CSmokeTrailProjectile( pos, oldSmoke, dir, oldDir, owner(), age == 8, false, 7, SMOKE_TIME, 0.6f, drawTrail, 0, weaponDef->visuals.texture2 ); oldSmoke = pos; oldDir = dir; numParts = 0; useAirLos = tp->useAirLos; if (!drawTrail) { const float3 camDir = (pos - camera->pos).ANormalize(); if ((camera->pos.distance(pos) * 0.2f + (1 - math::fabs(camDir.dot(dir))) * 3000) > 300) { drawTrail = true; } } } UpdateInterception(); UpdateGroundBounce(); }
void CMissileProjectile::Update(void) { ttl--; if(ttl>0){ if(curSpeed<maxSpeed) curSpeed+=weaponDef->weaponacceleration; float3 targSpeed(0,0,0); if(weaponDef->tracks && (decoyTarget || target)){ if(decoyTarget){ targPos=decoyTarget->pos; targSpeed=decoyTarget->speed; } else { targSpeed=target->speed; if((target->physicalState==CSolidObject::Flying && (target->midPos-pos).SqLength()<150*150) || !owner) targPos=target->midPos; else targPos=helper->GetUnitErrorPos(target,owner->allyteam); } } if(isWobbling){ --wobbleTime; if(wobbleTime==0){ float3 newWob=gs->randVector(); wobbleDif=(newWob-wobbleDir)*(1.0f/16); wobbleTime=16; } wobbleDir+=wobbleDif; dir+=wobbleDir*weaponDef->wobble*(owner?(1-owner->limExperience*0.5f):1); dir.Normalize(); } float3 orgTargPos(targPos); float dist=targPos.distance(pos); if(dist==0) dist=0.1f; if(extraHeightTime){ extraHeight-=extraHeightDecay; --extraHeightTime; targPos.y+=extraHeight; dir.y-=extraHeightDecay/dist; //geometricObjects->AddLine(pos,targPos,3,1,1); } float3 dif(targPos + targSpeed*(dist/maxSpeed)*0.7f - pos); dif.Normalize(); float3 dif2=dif-dir; float tracking=weaponDef->turnrate; if(dif2.Length()<tracking){ dir=dif; } else { dif2-=dir*(dif2.dot(dir)); dif2.Normalize(); dir+=dif2*tracking; dir.Normalize(); } speed=dir*curSpeed; targPos=orgTargPos; } else { speed*=0.995f; speed.y+=gs->gravity; dir=speed; dir.Normalize(); } pos+=speed; age++; numParts++; if(!(age&7)){ CSmokeTrailProjectile* tp=SAFE_NEW CSmokeTrailProjectile(pos,oldSmoke,dir,oldDir,owner,age==8,false,7,Smoke_Time,0.6f,drawTrail); oldSmoke=pos; oldDir=dir; numParts=0; useAirLos=tp->useAirLos; if(!drawTrail){ ENTER_MIXED; float3 camDir=(pos-camera->pos).Normalize(); if(camera->pos.distance(pos)*0.2f+(1-fabs(camDir.dot(dir)))*3000 > 300) drawTrail=true; ENTER_SYNCED; } } //CWeaponProjectile::Update(); }
void CTorpedoProjectile::Update() { if (!weaponDef->submissile && pos.y > -3.0f) { // tracking etc only works when we are underwater if (!luaMoveCtrl) { speed.y += mygravity; dir = speed; dir.Normalize(); } } else { if (!weaponDef->submissile && pos.y-speed.y > -3.0f) { // level out torpedo a bit when hitting water if (!luaMoveCtrl) { dir.y *= 0.5f; dir.Normalize(); } } if (--ttl > 0) { if (!luaMoveCtrl) { if (curSpeed < maxSpeed) { curSpeed += std::max(0.2f, tracking); } if (target) { CSolidObject* so = dynamic_cast<CSolidObject*>(target); CWeaponProjectile* po = dynamic_cast<CWeaponProjectile*>(target); targetPos = target->pos; float3 targSpeed(ZeroVector); if (so) { targetPos = so->aimPos; targSpeed = so->speed; if (pos.SqDistance(so->aimPos) > 150 * 150 && owner()) { CUnit* u = dynamic_cast<CUnit*>(so); if (u) { targetPos = helper->GetUnitErrorPos(u, owner()->allyteam, true); } } } if (po) { targSpeed = po->speed; } if (!weaponDef->submissile && targetPos.y > 0) { targetPos.y = 0; } const float dist = pos.distance(targetPos); float3 dif = (targetPos + targSpeed * (dist / maxSpeed) * 0.7f - pos).Normalize(); float3 dif2 = dif - dir; if (dif2.Length() < tracking) { dir = dif; } else { dif2 -= dir * (dif2.dot(dir)); dif2.SafeNormalize(); dir += dif2 * tracking; dir.SafeNormalize(); } } speed = dir * curSpeed; } gCEG->Explosion(cegID, pos, ttl, areaOfEffect, NULL, 0.0f, NULL, speed); } else { if (!luaMoveCtrl) { speed *= 0.98f; speed.y += mygravity; dir = speed; dir.SafeNormalize(); } } } if (!luaMoveCtrl) { pos += speed; } if (pos.y < -2.0f) { --nextBubble; if (nextBubble == 0) { nextBubble = 1 + (int) (gs->randFloat() * 1.5f); const float3 pspeed = (gs->randVector() * 0.1f) + float3(0.0f, 0.2f, 0.0f); new CBubbleProjectile( pos + gs->randVector(), pspeed, 40 + gs->randFloat() * 30, 1 + gs->randFloat() * 2, 0.01f, owner(), 0.3f + gs->randFloat() * 0.3f ); } } UpdateGroundBounce(); UpdateInterception(); }