예제 #1
0
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();
		}
	}
}
예제 #2
0
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();
			}
		}
	}
}
예제 #3
0
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);
		}
	}
}
예제 #4
0
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;
		}
	}
}
예제 #5
0
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;
		}
	}
}