void CProjectileHandler::CheckGroundCollisions(ProjectileContainer& pc) { ProjectileContainer::iterator pci; for (pci = pc.begin(); pci != pc.end(); ++pci) { CProjectile* p = *pci; if (!p->checkCol) { continue; } // NOTE: if <p> is a MissileProjectile and does not // have selfExplode set, it will never be removed (!) if (p->GetCollisionFlags() & Collision::NOGROUND) { continue; } // NOTE: don't add p->radius to groundHeight, or most // projectiles will collide with the ground too early const float groundHeight = ground->GetHeightReal(p->pos.x, p->pos.z); const bool belowGround = (p->pos.y < groundHeight); const bool insideWater = (p->pos.y <= 0.0f && !belowGround); const bool ignoreWater = p->ignoreWater; if (belowGround || (insideWater && !ignoreWater)) { // if position has dropped below terrain or into water // where we cannot live, adjust it and explode us now // (if the projectile does not set deleteMe = true, it // will keep hugging the terrain) p->pos.y = belowGround? groundHeight: 0.0f; p->Collision(); } } }
void CProjectileHandler::CheckGroundCollisions(ProjectileContainer& pc) { ProjectileContainer::iterator pci; for (pci = pc.begin(); pci != pc.end(); ++pci) { CProjectile* p = *pci; if (p->checkCol) { // too many projectiles seem to impact the ground before // actually hitting so don't subtract the projectile radius if (ground->GetHeight(p->pos.x, p->pos.z) > p->pos.y /* - p->radius*/) { p->Collision(); } } } }
void CProjectileHandler::CheckUnitFeatureCollisions(ProjectileContainer& pc) { static std::vector<CUnit*> tempUnits(uh->MaxUnits(), NULL); static std::vector<CFeature*> tempFeatures(uh->MaxUnits(), NULL); for (ProjectileContainer::iterator pci = pc.begin(); pci != pc.end(); ++pci) { CProjectile* p = *pci; if (p->checkCol && !p->deleteMe) { const float3 ppos0 = p->pos; const float3 ppos1 = p->pos + p->speed; const float speedf = p->speed.Length(); CUnit** endUnit = &tempUnits[0]; CFeature** endFeature = &tempFeatures[0]; qf->GetUnitsAndFeaturesExact(p->pos, p->radius + speedf, endUnit, endFeature); CheckUnitCollisions(p, tempUnits, endUnit, ppos0, ppos1); CheckFeatureCollisions(p, tempFeatures, endFeature, ppos0, ppos1); } } }
void CProjectileHandler::UpdateProjectileContainer(ProjectileContainer& pc, bool synced) { ProjectileContainer::iterator pci = pc.begin(); while (pci != pc.end()) { CProjectile* p = *pci; if (p->deleteMe) { if (p->synced) { assert(synced); if(p->weapon || p->piece) { //! iterator is always valid const ProjectileMap::iterator it = syncedProjectileIDs.find(p->id); const ProjectileMapPair& pp = it->second; eventHandler.ProjectileDestroyed(pp.first, pp.second); syncedProjectileIDs.erase(it); if (p->id != 0) { freeIDs.push_back(p->id); } } //! push_back this projectile for deletion pci = pc.erase_delete_synced(pci); } else { assert(!synced); pci = pc.erase_delete(pci); } } else { p->Update(); GML_GET_TICKS(p->lastProjUpdate); ++pci; } } }
void CProjectileHandler::UpdateProjectileContainer(ProjectileContainer& pc, bool synced) { ProjectileContainer::iterator pci = pc.begin(); #define VECTOR_SANITY_CHECK(v) \ assert(!math::isnan(v.x) && !math::isinf(v.x)); \ assert(!math::isnan(v.y) && !math::isinf(v.y)); \ assert(!math::isnan(v.z) && !math::isinf(v.z)); #define MAPPOS_SANITY_CHECK(v) \ assert(v.x >= -(float3::maxxpos * 16.0f)); \ assert(v.x <= (float3::maxxpos * 16.0f)); \ assert(v.z >= -(float3::maxzpos * 16.0f)); \ assert(v.z <= (float3::maxzpos * 16.0f)); \ assert(v.y >= -MAX_PROJECTILE_HEIGHT); \ assert(v.y <= MAX_PROJECTILE_HEIGHT); #define PROJECTILE_SANITY_CHECK(p) \ VECTOR_SANITY_CHECK(p->pos); \ MAPPOS_SANITY_CHECK(p->pos); while (pci != pc.end()) { CProjectile* p = *pci; if (p->deleteMe) { ProjectileMap::iterator pIt; if (p->synced) { //! iterator is always valid pIt = syncedProjectileIDs.find(p->id); eventHandler.ProjectileDestroyed((pIt->second).first, (pIt->second).second); syncedProjectileIDs.erase(pIt); freeSyncedIDs.push_back(p->id); //! push_back this projectile for deletion pci = pc.erase_delete_synced(pci); } else { #if UNSYNCED_PROJ_NOEVENT eventHandler.UnsyncedProjectileDestroyed(p); #else pIt = unsyncedProjectileIDs.find(p->id); eventHandler.ProjectileDestroyed((pIt->second).first, (pIt->second).second); unsyncedProjectileIDs.erase(pIt); freeUnsyncedIDs.push_back(p->id); #endif #if DETACH_SYNCED pci = pc.erase_detach(pci); #else pci = pc.erase_delete(pci); #endif } } else { PROJECTILE_SANITY_CHECK(p); p->Update(); qf->MovedProjectile(p); PROJECTILE_SANITY_CHECK(p); GML_GET_TICKS(p->lastProjUpdate); ++pci; } } }