Пример #1
0
void CGameHelper::Update()
{
	std::list<WaitingDamage*>* wd = &waitingDamages[gs->frameNum & 127];

	while (!wd->empty()) {
		WaitingDamage* w = wd->back();
		wd->pop_back();

		CUnit* attackee = unitHandler->units[w->target];
		CUnit* attacker = (w->attacker == -1)? NULL: unitHandler->units[w->attacker];

		if (attackee != NULL)
			attackee->DoDamage(w->damage, w->impulse, attacker, w->weaponID, w->projectileID);

		delete w;
	}
}
void CTransportUnit::KillUnit(bool selfDestruct, bool reclaimed, CUnit* attacker, bool)
{
	std::list<TransportedUnit>::iterator ti;
	for (ti = transported.begin(); ti != transported.end(); ++ti) {
		CUnit* u = ti->unit;

		u->transporter = 0;
		u->DeleteDeathDependence(this);

		// prevent a position teleport on the next movetype update if
		// the transport died in a place that the unit being carried
		// could not get to on its own
		if (!u->pos.IsInBounds()) {
			u->KillUnit(false, false, 0x0, false);
			continue;
		} else {
			const float gh = ground->GetHeight2(u->pos.x, u->pos.z);

			if (gh < -u->unitDef->maxWaterDepth || gh > -u->unitDef->minWaterDepth) {
				// note: should also check movedef restraints?
				u->KillUnit(false, false, 0x0, false);
				continue;
			}
		}


		if (!unitDef->releaseHeld) {
			if (!selfDestruct) {
				// we don't want it to leave a corpse
				u->DoDamage(DamageArray() * 1000000, 0, ZeroVector);
			}
			u->KillUnit(selfDestruct, reclaimed, attacker);
		} else {
			u->stunned = (u->paralyzeDamage > u->health);
			if (CGroundMoveType* mt = dynamic_cast<CGroundMoveType*>(u->moveType)) {
				mt->StartFlying();
			}
			u->speed = speed;

			eventHandler.UnitUnloaded(u, this);
		}
	}

	CUnit::KillUnit(selfDestruct, reclaimed, attacker);
}
Пример #3
0
void CRifle::FireImpl()
{
	float3 dir = (targetPos - weaponMuzzlePos).Normalize();
	dir +=
		((gs->randVector() * sprayAngle + salvoError) *
		(1.0f - owner->limExperience * weaponDef->ownerExpAccWeight));
	dir.Normalize();

	CUnit* hitUnit;
	CFeature* hitFeature;
	float length = TraceRay::TraceRay(weaponMuzzlePos, dir, range, 0, owner, hitUnit, hitFeature);

	if (hitUnit) {
		hitUnit->DoDamage(weaponDef->damages, owner, ZeroVector, weaponDef->id);
		new CHeatCloudProjectile(weaponMuzzlePos + dir*length, hitUnit->speed*0.9f, 30, 1, owner);
	}
	new CTracerProjectile(weaponMuzzlePos, dir*projectileSpeed, length, owner);
	new CSmokeProjectile(weaponMuzzlePos, float3(0,0,0), 70, 0.1f, 0.02f, owner, 0.6f);
}
Пример #4
0
void CRifle::Fire(void)
{
	float3 dir=targetPos-weaponMuzzlePos;
	dir.Normalize();
	dir+=(gs->randVector()*sprayangle+salvoError)*(1-owner->limExperience*0.9f);
	dir.Normalize();
#ifdef TRACE_SYNC
	tracefile << "Rifle fire: ";
	tracefile << owner->pos.x << " " << dir.x << " " << targetPos.x << " " << targetPos.y << " " << targetPos.z << "\n";
#endif
	CUnit* hit;
	float length=helper->TraceRay(weaponMuzzlePos, dir, range, weaponDef->damages[0], owner, hit, collisionFlags);
	if(hit) {
		hit->DoDamage(weaponDef->damages, owner, ZeroVector, weaponDef->id);
		SAFE_NEW CHeatCloudProjectile(weaponMuzzlePos + dir * length, hit->speed*0.9f, 30, 1, owner);
	}
	SAFE_NEW CTracerProjectile(weaponMuzzlePos,dir*projectileSpeed,length,owner);
	SAFE_NEW CSmokeProjectile(weaponMuzzlePos,float3(0,0.0f,0),70,0.1f,0.02f,owner,0.6f);
	if(fireSoundId)
		sound->PlaySample(fireSoundId,owner,fireSoundVolume);
}
Пример #5
0
void CTransportUnit::KillUnit(bool selfDestruct, bool reclaimed, CUnit* attacker, bool)
{
	if (!isDead) {
		// guard against recursive invocation via
		//     transportee->KillUnit
		//     helper->Explosion
		//     helper->DoExplosionDamage
		//     unit->DoDamage
		//     unit->KillUnit
		// in the case that unit == this
		isDead = true;

		// ::KillUnit might be called multiple times while !deathScriptFinished,
		// but it makes no sense to kill/detach our transportees more than once
		std::list<TransportedUnit>::iterator ti;

		for (ti = transportedUnits.begin(); ti != transportedUnits.end(); ++ti) {
			CUnit* transportee = ti->unit;
			assert(transportee != this);

			if (transportee->isDead)
				continue;

			const float gh = ground->GetHeightReal(transportee->pos.x, transportee->pos.z);

			transportee->transporter = NULL;
			transportee->DeleteDeathDependence(this, DEPENDENCE_TRANSPORTER);

			// prevent a position teleport on the next movetype update if
			// the transport died in a place that the unit being carried
			// could not get to on its own
			if (!transportee->pos.IsInBounds()) {
				transportee->KillUnit(false, false, NULL, false);
				continue;
			} else {
				// immobile units can still be transported
				// via script trickery, guard against this
				if (!transportee->unitDef->IsAllowedTerrainHeight(gh)) {
					transportee->KillUnit(false, false, NULL, false);
					continue;
				}
			}

			if (!unitDef->releaseHeld) {
				if (!selfDestruct) {
					// we don't want it to leave a corpse
					transportee->DoDamage(DamageArray(1e6f), ZeroVector, NULL, -DAMAGE_EXTSOURCE_KILLED);
				}

				transportee->KillUnit(selfDestruct, reclaimed, attacker);
			} else {
				// place unit near the place of death of the transport
				// if it's a ground transport and uses a piece-in-ground method
				// to hide units
				if (transportee->pos.y < gh) {
					const float k = (transportee->radius + radius) * std::max(unitDef->unloadSpread, 1.0f);

					// try to unload in a presently unoccupied spot
					// unload on a wreck if suitable position not found
					for (int i = 0; i < 10; ++i) {
						float3 pos = transportee->pos;
						pos.x += (gs->randFloat() * 2 * k - k);
						pos.z += (gs->randFloat() * 2 * k - k);
						pos.y = ground->GetHeightReal(transportee->pos.x, transportee->pos.z);

						if (qf->GetUnitsExact(pos, transportee->radius + 2).empty()) {
							transportee->Move3D(pos, false);
							break;
						}
					}
				} else if (CGroundMoveType* mt = dynamic_cast<CGroundMoveType*>(transportee->moveType)) {
					mt->StartFlying();
				}

				transportee->moveType->SlowUpdate();
				transportee->moveType->LeaveTransport();

				// issue a move order so that unit won't try to return to pick-up pos in IdleCheck()
				if (unitDef->canfly && transportee->unitDef->canmove) {
					Command c(CMD_MOVE);
					c.params.push_back(transportee->pos.x);
					c.params.push_back(ground->GetHeightAboveWater(transportee->pos.x, transportee->pos.z));
					c.params.push_back(transportee->pos.z);
					transportee->commandAI->GiveCommand(c);
				}

				transportee->stunned = (transportee->paralyzeDamage > (modInfo.paralyzeOnMaxHealth? transportee->maxHealth: transportee->health));
				transportee->speed = speed * (0.5f + 0.5f * gs->randFloat());

				if (CBuilding* building = dynamic_cast<CBuilding*>(transportee)) {
					// this building may end up in a strange position, so kill it
					building->KillUnit(selfDestruct, reclaimed, attacker);
				}

				eventHandler.UnitUnloaded(transportee, this);
			}
		}

		transportedUnits.clear();

		// make sure CUnit::KillUnit does not return early
		isDead = false;
	}

	CUnit::KillUnit(selfDestruct, reclaimed, attacker);
}
void CTransportUnit::KillUnit(bool selfDestruct, bool reclaimed, CUnit* attacker, bool)
{
	std::list<TransportedUnit>::iterator ti;
	for (ti = transported.begin(); ti != transported.end(); ++ti) {
		CUnit* u = ti->unit;
		const float gh = ground->GetHeight2(u->pos.x, u->pos.z);

		u->transporter = 0;
		u->DeleteDeathDependence(this);

		// prevent a position teleport on the next movetype update if
		// the transport died in a place that the unit being carried
		// could not get to on its own
		if (!u->pos.IsInBounds()) {
			u->KillUnit(false, false, NULL, false);
			continue;
		} else {
			// immobile units can still be transported
			// via script trickery, guard against this
			if (u->unitDef->movedata != NULL && gh < -u->unitDef->movedata->depth) {
				// always treat depth as maxWaterDepth (fails if
				// the transportee is a ship, but so does using
				// UnitDef::{min, max}WaterDepth)
				u->KillUnit(false, false, NULL, false);
				continue;
			}
		}


		if (!unitDef->releaseHeld) {
			if (!selfDestruct) {
				// we don't want it to leave a corpse
				u->DoDamage(DamageArray() * 1000000, 0, ZeroVector);
			}
			u->KillUnit(selfDestruct, reclaimed, attacker);
		} else {
			// place unit near the place of death of the transport
			// if it's a ground transport and uses a piece-in-ground method
			// to hide units
			if (u->pos.y < gh) {
				const float k = (u->radius + radius)*std::max(unitDef->unloadSpread, 1.f);
				// try to unload in a presently unoccupied spot
				// unload on a wreck if suitable position not found
				for (int i = 0; i<10; ++i) {
					float3 pos = u->pos;
					pos.x += gs->randFloat()*2*k - k;
					pos.z += gs->randFloat()*2*k - k;
					pos.y = ground->GetHeight2(u->pos.x, u->pos.z);
					if (qf->GetUnitsExact(pos, u->radius + 2).empty()) {
						u->pos = pos;
						break;
					}
				}
				u->UpdateMidPos();
			} else if (CGroundMoveType* mt = dynamic_cast<CGroundMoveType*>(u->moveType)) {
				mt->StartFlying();
			}

			u->stunned = (u->paralyzeDamage > u->health);
			u->moveType->LeaveTransport();
			u->speed = speed*(0.5f + 0.5f*gs->randFloat());

			eventHandler.UnitUnloaded(u, this);
		}
	}

	CUnit::KillUnit(selfDestruct, reclaimed, attacker);
}