Beispiel #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();
		}
	}
}
void CGround::CheckCol(CProjectileHandler* ph)
{
    Projectile_List::iterator psi;

    for (psi = ph->ps.begin(); psi != ph->ps.end(); ++psi) {
        CProjectile* p = *psi;
        if (p->checkCol) {
            if (GetHeight(p->pos.x, p->pos.z) > p->pos.y /* - p->radius*/) {
                // too many projectiles seem to hit the ground before hitting
                // so remove the radius till a better fix is done
                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();
			}
		}
	}
}
Beispiel #4
0
void CProjectileHandler::CheckGroundCollisions(ProjectileContainer& pc)
{
	for (size_t i = 0; i < pc.size(); ++i) {
		CProjectile* p = pc[i];

		if (!p->checkCol)
			continue;

		// NOTE:
		//   if <p> is a MissileProjectile and does not have
		//   selfExplode set, tbis will cause it to never be
		//   removed (!)
		if (p->GetCollisionFlags() & Collision::NOGROUND)
			continue;

		// don't collide with ground yet if last update scheduled a bounce
		if (p->weapon && static_cast<const CWeaponProjectile*>(p)->HasScheduledBounce())
			continue;

		// NOTE:
		//   don't add p->radius to groundHeight, or most (esp. modelled)
		//   projectiles will collide with the ground one or more frames
		//   too early
		const float groundHeight = CGround::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 can not live, adjust it and explode us now
			// (if the projectile does not set deleteMe = true, it
			// will keep hugging the terrain)
			p->SetPosition(p->pos * XZVector + UpVector * groundHeight * belowGround);
			p->Collision();
		}
	}
}
Beispiel #5
0
void CProjectileHandler::CheckUnitCol()
{
	Projectile_List::iterator psi;

	static std::vector<CUnit*> tempUnits(uh->MaxUnits(), NULL);
	static std::vector<CFeature*> tempFeatures(uh->MaxUnits(), NULL);
	CollisionQuery q;

	for (psi = ps.begin(); psi != ps.end(); ++psi) {
		CProjectile* p = (*psi);

		if (p->checkCol && !p->deleteMe) {
			const float3 ppos0 = p->pos;
			const float3 ppos1 = p->pos + p->speed;

			float speedf = p->speed.Length();

			CUnit** endUnit = &tempUnits[0];
			CFeature** endFeature = &tempFeatures[0];
			qf->GetUnitsAndFeaturesExact(p->pos, p->radius + speedf, endUnit, endFeature);

			for (CUnit** ui = &tempUnits[0]; ui != endUnit; ++ui) {
				CUnit* unit = *ui;
				const bool friendlyShot = (p->owner() && (unit->allyteam == p->owner()->allyteam));
				const bool raytraced =
					(unit->collisionVolume &&
					unit->collisionVolume->GetTestType() == COLVOL_TEST_CONT);

				// if this unit fired this projectile or (this unit is in the
				// same allyteam as the unit that shot this projectile and we
				// are ignoring friendly collisions)
				if (p->owner() == unit || !unit->collisionVolume ||
					((p->collisionFlags & COLLISION_NOFRIENDLY) && friendlyShot)) {
					continue;
				}

				if (p->collisionFlags & COLLISION_NONEUTRAL) {
					if (unit->IsNeutral()) {
						continue;
					}
				}

				if (CCollisionHandler::DetectHit(unit, ppos0, ppos1, &q)) {
					// this projectile won't reach the raytraced surface impact pos
					// until Update() is called (right after we return, same frame)
					// which is a problem when dealing with fast low-AOE projectiles
					// since they would do almost no damage if detonated outside the
					// volume, so smuggle a bit ("rolling back" its pos in Update()
					// and waiting for the next-frame CheckUnitCol() is problematic
					// for noExplode projectiles)

					// const float3& pimpp = (q.b0)? q.p0: q.p1;
					const float3 pimpp =
						(q.b0 && q.b1)? (q.p0 + q.p1) * 0.5f:
						(q.b0        )? (q.p0 + ppos1) * 0.5f:
						                (ppos0 + q.p1) * 0.5f;

					p->pos = (raytraced)? pimpp: ppos0;
					p->Collision(unit);
					p->pos = (raytraced)? ppos0: p->pos;
					break;
				}
			}

			if (!(p->collisionFlags & COLLISION_NOFEATURE)) {
				for (CFeature** fi = &tempFeatures[0]; fi != endFeature; ++fi) {
					CFeature* feature = *fi;
					const bool raytraced =
						(feature->collisionVolume &&
						feature->collisionVolume->GetTestType() == COLVOL_TEST_CONT);

					// geothermals do not have a collision volume, skip them
					if (!feature->blocking || feature->def->geoThermal || !feature->collisionVolume) {
						continue;
					}

					if (CCollisionHandler::DetectHit(feature, ppos0, ppos1, &q)) {
						const float3 pimpp =
							(q.b0 && q.b1)? (q.p0 + q.p1) * 0.5f:
							(q.b0        )? (q.p0 + ppos1) * 0.5f:
							                (ppos0 + q.p1) * 0.5f;

						p->pos = (raytraced)? pimpp: ppos0;
						p->Collision(feature);
						p->pos = (raytraced)? ppos0: p->pos;
						break;
					}
				}
			}
		}
	}
}