void CFlameProjectile::Update() { if (!luaMoveCtrl) { SetPosition(pos + speed); UpdateGroundBounce(); SetVelocityAndSpeed(speed + spread); } UpdateInterception(); radius = radius + weaponDef->sizeGrowth; sqRadius = radius * radius; drawRadius = radius * weaponDef->collisionSize; curTime += invttl; if (curTime > physLife) { checkCol = false; } if (curTime > 1) { curTime = 1; deleteMe = true; } explGenHandler->GenExplosion(cegID, pos, speed, curTime, 0.0f, 0.0f, NULL, NULL); }
void CLightningProjectile::Update() { if (--ttl <= 0) { deleteMe = true; } else { explGenHandler->GenExplosion(cegID, startPos + ((targetPos - startPos) / ttl), (targetPos - startPos), 0.0f, displacements[0], 0.0f, NULL, NULL); } for (size_t d = 1; d < displacements_size; ++d) { displacements[d] += (gs->randFloat() - 0.5f) * 0.3f; displacements2[d] += (gs->randFloat() - 0.5f) * 0.3f; } UpdateInterception(); }
void CLargeBeamLaserProjectile::Update() { if ((--ttl) <= 0) { deleteMe = true; } else { for (int i = 0; i < 3; i++) { coreColStart[i] = (unsigned char) (coreColStart[i] * decay); edgeColStart[i] = (unsigned char) (edgeColStart[i] * decay); } explGenHandler->GenExplosion(cegID, startPos + ((targetPos - startPos) / ttl), (targetPos - startPos), 0.0f, flaresize, 0.0f, NULL, NULL); } UpdateInterception(); }
void CLargeBeamLaserProjectile::Update() { if (ttl > 0) { for (int i = 0; i < 3; i++) { coreColStart[i] = (unsigned char) (coreColStart[i] * decay); edgeColStart[i] = (unsigned char) (edgeColStart[i] * decay); } gCEG->Explosion(cegID, startpos + ((targetPos - startpos) / ttl), 0.0f, flaresize, NULL, 0.0f, NULL, targetPos - startpos); ttl--; } else { deleteMe = true; } UpdateInterception(); }
void CBeamLaserProjectile::Update() { ttl--; if (ttl <= 0) { deleteMe = true; } else { for (int i = 0; i < 3; i++) { coreColStart[i] *= decay; coreColEnd[i] *= decay; edgeColStart[i] *= decay; edgeColEnd[i] *= decay; } gCEG->Explosion(cegID, startpos + ((targetPos - startpos) / ttl), 0.0f, flaresize, 0x0, 0.0f, 0x0, targetPos - startpos); } UpdateInterception(); }
void CFlameProjectile::Update() { if (!luaMoveCtrl) { SetPosition(pos + speed); UpdateGroundBounce(); SetVelocityAndSpeed(speed + spread); } UpdateInterception(); radius = radius + weaponDef->sizeGrowth; sqRadius = radius * radius; drawRadius = radius * weaponDef->collisionSize; curTime += invttl; checkCol &= (curTime <= physLife); curTime = std::min(curTime, 1.0f); deleteMe |= (curTime >= 1.0f); explGenHandler->GenExplosion(cegID, pos, speed, curTime, 0.0f, 0.0f, nullptr, nullptr); }
void CFireBallProjectile::Update() { if (checkCol) { if (!luaMoveCtrl) { pos += speed; if (weaponDef->gravityAffected) { speed.y += mygravity; } } if (weaponDef->noExplode && TraveledRange()) { checkCol = false; } EmitSpark(); } else { if (sparks.empty()) { deleteMe = true; } } for (unsigned int i = 0; i < sparks.size(); i++) { sparks[i].ttl--; if (sparks[i].ttl == 0) { sparks.pop_back(); break; } if (checkCol) { sparks[i].pos += sparks[i].speed; } sparks[i].speed *= 0.95f; } gCEG->Explosion(cegID, pos, ttl, !sparks.empty() ? sparks[0].size : 0.0f, NULL, 0.0f, NULL, speed); UpdateGroundBounce(); UpdateInterception(); }
void CExplosiveProjectile::Update() { CProjectile::Update(); if (--ttl == 0) { Collision(); } else { if (ttl > 0) { explGenHandler->GenExplosion(cegID, pos, speed, ttl, damages->damageAreaOfEffect, 0.0f, NULL, NULL); } } curTime += invttl; curTime = std::min(curTime, 1.0f); if (weaponDef->noExplode && TraveledRange()) { CProjectile::Collision(); return; } UpdateGroundBounce(); UpdateInterception(); }
void CFlameProjectile::Update() { if (!luaMoveCtrl) { pos += speed; UpdateGroundBounce(); speed += spread; } UpdateInterception(); radius = radius + weaponDef->sizeGrowth; sqRadius = radius * radius; drawRadius = radius * weaponDef->collisionSize; curTime += invttl; if (curTime > physLife) { checkCol = false; } if (curTime > 1) { curTime = 1; deleteMe = true; } gCEG->Explosion(cegID, pos, curTime, 0.0f, NULL, 0.0f, NULL, speed); }
void CEmgProjectile::Update() { // disable collisions when ttl reaches 0 since the // projectile will travel far past its range while // fading out checkCol &= (ttl >= 0); deleteMe |= (intensity <= 0.0f); if (!luaMoveCtrl) { pos += speed; } if (ttl <= 0) { // fade out over the next 10 frames at most intensity -= 0.1f; intensity = std::max(intensity, 0.0f); } else { explGenHandler->GenExplosion(cegID, pos, speed, ttl, intensity, 0.0f, NULL, NULL); } UpdateGroundBounce(); UpdateInterception(); --ttl; }
void CWeaponProjectile::Update() { CProjectile::Update(); UpdateGroundBounce(); UpdateInterception(); }
void CStarburstProjectile::Update() { ttl--; uptime--; missileAge++; if (target && weaponDef->tracks && owner()) { targetPos = target->pos; CUnit* u = dynamic_cast<CUnit*>(target); if (u) { targetPos = helper->GetUnitErrorPos(u, owner()->allyteam, true); } } if (uptime > 0) { if (!luaMoveCtrl) { if (curSpeed < maxSpeed) { curSpeed += weaponDef->weaponacceleration; } speed = dir * curSpeed; } } else if (doturn && ttl > 0 && distanceToTravel > 0.0f) { if (!luaMoveCtrl) { float3 dif(targetPos - pos); dif.Normalize(); dif += aimError; dif.Normalize(); if (dif.dot(dir) > 0.99f) { dir = dif; doturn = false; } else { dif = dif - dir; dif -= dir * (dif.dot(dir)); dif.Normalize(); if (weaponDef->turnrate != 0) { dir += dif * weaponDef->turnrate; } else { dir += dif * 0.06; } dir.Normalize(); } speed = dir * curSpeed; if (distanceToTravel != MAX_PROJECTILE_RANGE) { distanceToTravel -= speed.Length2D(); } } } else if (ttl > 0 && distanceToTravel > 0.0f) { if (!luaMoveCtrl) { if (curSpeed < maxSpeed) { curSpeed += weaponDef->weaponacceleration; } float3 dif = (targetPos - pos).Normalize(); if (dif.dot(dir) > maxGoodDif) { dir = dif; } else { dif = dif - dir; dif -= dir * (dif.dot(dir)); dif.SafeNormalize(); dir += dif * tracking; dir.SafeNormalize(); } speed = dir * curSpeed; if (distanceToTravel != MAX_PROJECTILE_RANGE) { distanceToTravel -= speed.Length2D(); } } } else { if (!luaMoveCtrl) { dir.y += mygravity; dir.Normalize(); curSpeed -= mygravity; speed = dir * curSpeed; } } if (!luaMoveCtrl) { pos += speed; } if (ttl > 0) { gCEG->Explosion(cegID, pos, ttl, areaOfEffect, NULL, 0.0f, NULL, dir); } { curTracerPart++; curTracerPart %= NUM_TRACER_PARTS; TracerPart* tracerPart = (GML::SimEnabled()) ? (TracerPart* volatile)(&tracerParts[curTracerPart]) : &tracerParts[curTracerPart]; tracerPart->pos = pos; tracerPart->dir = dir; tracerPart->speedf = curSpeed; int newsize = 0; for (float aa = 0; aa < curSpeed + 0.6f; aa += TRACER_PARTS_STEP, ++newsize) { const float ageMod = (missileAge < 20) ? 1.0f : (0.6f + (rand() * 0.8f) / RAND_MAX); if (tracerPart->ageMods.size() <= newsize) { tracerPart->ageMods.push_back(ageMod); } else { tracerPart->ageMods[newsize] = ageMod; } } if (tracerPart->ageMods.size() != newsize) { tracerPart->ageMods.resize(newsize); } } age++; numParts++; if (weaponDef->visuals.smokeTrail && !(age & 7)) { if (curCallback) { curCallback->drawCallbacker = 0; } curCallback = new CSmokeTrailProjectile(pos, oldSmoke, dir, oldSmokeDir, owner(), age == 8, false, 7, SMOKE_TIME, 0.7f, drawTrail, this, weaponDef->visuals.texture2); oldSmoke = pos; oldSmokeDir = dir; numParts = 0; useAirLos = curCallback->useAirLos; if (!drawTrail) { const float3 camDir = (pos - camera->pos).ANormalize(); const float camDist = (camera->pos.distance(pos) * 0.2f + (1 - math::fabs(camDir.dot(dir))) * 3000); drawTrail = (camDist > 300.0f); } } UpdateInterception(); }
void CTorpedoProjectile::Update() { // tracking only works when we are underwater if (!weaponDef->submissile && pos.y > 0.0f) { if (!luaMoveCtrl) { // must update dir and speed.w here SetVelocityAndSpeed(speed + (UpVector * mygravity)); } } else { if (--ttl > 0) { if (!luaMoveCtrl) { float3 targetVel; if (speed.w < maxSpeed) speed.w += std::max(0.2f, tracking); if (target != NULL) { const CSolidObject* so = dynamic_cast<const CSolidObject*>(target); const CWeaponProjectile* po = dynamic_cast<const CWeaponProjectile*>(target); targetPos = target->pos; if (so != NULL) { targetPos = so->aimPos; targetVel = so->speed; if (allyteamID != -1 && pos.SqDistance(so->aimPos) > Square(150.0f)) { const CUnit* u = dynamic_cast<const CUnit*>(so); if (u != NULL) { targetPos = u->GetErrorPos(allyteamID, true); } } } if (po != NULL) { targetVel = po->speed; } } if (!weaponDef->submissile && targetPos.y > 0.0f) { targetPos.y = 0.0f; } const float3 targetLeadVec = targetVel * (pos.distance(targetPos) / maxSpeed) * 0.7f; const float3 targetLeadDir = (targetPos + targetLeadVec - pos).Normalize(); float3 targetDirDif = targetLeadDir - dir; if (targetDirDif.Length() < tracking) { dir = targetLeadDir; } else { // <tracking> is the projectile's turn-rate targetDirDif = (targetDirDif - (dir * targetDirDif.dot(dir))).SafeNormalize(); dir = (dir + (targetDirDif * tracking)).SafeNormalize(); } // do not need to update dir or speed.w here CWorldObject::SetVelocity(dir * speed.w); } explGenHandler->GenExplosion(cegID, pos, speed, ttl, areaOfEffect, 0.0f, NULL, NULL); } else { if (!luaMoveCtrl) { // must update dir and speed.w here SetVelocityAndSpeed((speed * 0.98f) + (UpVector * mygravity)); } } } if (!luaMoveCtrl) { SetPosition(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( owner(), pos + gs->randVector(), pspeed, 40 + gs->randFloat() * GAME_SPEED, 1 + gs->randFloat() * 2, 0.01f, 0.3f + gs->randFloat() * 0.3f ); } } UpdateGroundBounce(); UpdateInterception(); }
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 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(); }
void CStarburstProjectile::Update() { ttl--; uptime--; missileAge++; if (target != nullptr && weaponDef->tracks) { const CSolidObject* so = dynamic_cast<const CSolidObject*>(target); if (so != NULL) { targetPos = so->aimPos; if (allyteamID != -1 && !ignoreError) { const CUnit* u = dynamic_cast<const CUnit*>(so); if (u != nullptr) targetPos = u->GetErrorPos(allyteamID, true); } } else { targetPos = target->pos; } targetPos += aimError; } if (!luaMoveCtrl) { UpdateTrajectory(); } if (ttl > 0) { explGenHandler->GenExplosion(cegID, pos, dir, ttl, damages->damageAreaOfEffect, 0.0f, NULL, NULL); } { const unsigned int newTracerPart = (curTracerPart + 1) % NUM_TRACER_PARTS; curTracerPart = newTracerPart; TracerPart* tracerPart = &tracerParts[curTracerPart]; tracerPart->pos = pos; tracerPart->dir = dir; tracerPart->speedf = speed.w; unsigned int newsize = 0; for (float aa = 0; aa < speed.w + 0.6f && newsize < MAX_NUM_AGEMODS; aa += TRACER_PARTS_STEP, ++newsize) { const float ageMod = (missileAge < 20) ? 1.0f : (0.6f + (rand() * 0.8f) / RAND_MAX); tracerPart->ageMods[newsize] = ageMod; } if (tracerPart->numAgeMods != newsize) { tracerPart->numAgeMods = newsize; } } age++; numParts++; if (weaponDef->visuals.smokeTrail) { if (smokeTrail) { smokeTrail->UpdateEndPos(pos, dir); oldSmoke = pos; oldSmokeDir = dir; } if ((age % 8) == 0) { smokeTrail = new CSmokeTrailProjectile( owner(), pos, oldSmoke, dir, oldSmokeDir, age == 8, false, 7, SMOKE_TIME, 0.7f, weaponDef->visuals.texture2 ); numParts = 0; useAirLos = smokeTrail->useAirLos; } } UpdateInterception(); }