Пример #1
0
void CDestructibleModel::DoExplosion(char* pTargetName)
{
	CWeapons weapons;
	weapons.Init(m_hObject);
	weapons.ObtainWeapon(m_nExplosionWeaponId);
	weapons.ChangeWeapon(m_nExplosionWeaponId);

	CWeapon* pWeapon = weapons.GetCurWeapon();
	if (!pWeapon) return;

	weapons.SetAmmo(pWeapon->GetAmmoId());

	pWeapon->SetDamageFactor(m_fDamageFactor);

	LTRotation rRot;
	g_pLTServer->GetObjectRotation(m_hObject, &rRot);

	LTVector vF, vPos;
	g_pLTServer->GetObjectPos(m_hObject, &vPos);
	vF = rRot.Forward();

	// Just blow up in place if we're not supposed to fire along
	// forward vector and we don't have a target...

	if (!m_bFireAlongForward)
	{
		pWeapon->SetLifetime(0.0f);
		VEC_SET(vF, 0.0f, -1.0f, 0.0f);  // Fire down
	}

	// See if we have a target...If so, point at it.

	if (pTargetName)
	{
		ObjArray <HOBJECT, MAX_OBJECT_ARRAY_SIZE> objArray;
		g_pLTServer->FindNamedObjects(pTargetName, objArray);

		if (objArray.NumObjects())
		{
			LTVector vObjPos;
			g_pLTServer->GetObjectPos(objArray.GetObject(0), &vObjPos);
			vF = vObjPos - vPos;
			vF.Normalize();

			rRot = LTRotation(vF, LTVector(0.0f, 1.0f, 0.0f));
			g_pLTServer->SetObjectRotation(m_hObject, &rRot);
		}
	}

	WeaponFireInfo weaponFireInfo;
	weaponFireInfo.hFiredFrom	= m_hObject;
	weaponFireInfo.vPath		= vF;
	weaponFireInfo.vFirePos	= vPos;
	weaponFireInfo.vFlashPos	= vPos;

	pWeapon->Fire(weaponFireInfo);
}
Пример #2
0
void CUnitScript::EmitSfx(int sfxType, int piece)
{
#ifndef _CONSOLE
	if (!PieceExists(piece)) {
		ShowScriptError("Invalid piecenumber for emit-sfx");
		return;
	}

	if (ph->particleSaturation > 1.0f && sfxType < SFX_CEG) {
		// skip adding (unsynced!) particles when we have too many
		return;
	}

	// Make sure wakes are only emitted on water
	if ((sfxType >= SFX_WAKE) && (sfxType <= SFX_REVERSE_WAKE_2)) {
		if (ground->GetApproximateHeight(unit->pos.x, unit->pos.z) > 0.0f) {
			return;
		}
	}

	float3 relPos = ZeroVector;
	float3 relDir = UpVector;

	if (!GetEmitDirPos(piece, relPos, relDir)) {
		ShowScriptError("emit-sfx: GetEmitDirPos failed");
		return;
	}

	relDir.SafeNormalize();

	const float3 pos =
		unit->pos +
		unit->frontdir * relPos.z +
		unit->updir    * relPos.y +
		unit->rightdir * relPos.x;
	const float3 dir =
		unit->frontdir * relDir.z +
		unit->updir    * relDir.y +
		unit->rightdir * relDir.x;

	float alpha = 0.3f + gu->usRandFloat() * 0.2f;
	float alphaFalloff = 0.004f;
	float fadeupTime = 4;

	const UnitDef* ud = unit->unitDef;
	const MoveDef* md = ud->moveDef;

	// hovercraft need special care
	if (md != NULL && md->moveType == MoveDef::Hover_Move) {
		fadeupTime = 8.0f;
		alpha = 0.15f + gu->usRandFloat() * 0.2f;
		alphaFalloff = 0.008f;
	}

	switch (sfxType) {
		case SFX_REVERSE_WAKE:
		case SFX_REVERSE_WAKE_2: {  //reverse wake
			new CWakeProjectile(
				pos + gu->usRandVector() * 2.0f,
				dir * 0.4f,
				6.0f + gu->usRandFloat() * 4.0f,
				0.15f + gu->usRandFloat() * 0.3f,
				unit,
				alpha, alphaFalloff, fadeupTime
			);
			break;
		}

		case SFX_WAKE_2:  //wake 2, in TA it lives longer..
		case SFX_WAKE: {  //regular ship wake
			new CWakeProjectile(
				pos + gu->usRandVector() * 2.0f,
				dir * 0.4f,
				6.0f + gu->usRandFloat() * 4.0f,
				0.15f + gu->usRandFloat() * 0.3f,
				unit,
				alpha, alphaFalloff, fadeupTime
			);
			break;
		}

		case SFX_BUBBLE: {  //submarine bubble. does not provide direction through piece vertices..
			float3 pspeed = gu->usRandVector() * 0.1f;
				pspeed.y += 0.2f;

			new CBubbleProjectile(
				pos + gu->usRandVector() * 2.0f,
				pspeed,
				40.0f + gu->usRandFloat() * 30.0f,
				1.0f + gu->usRandFloat() * 2.0f,
				0.01f,
				unit,
				0.3f + gu->usRandFloat() * 0.3f
			);
		} break;

		case SFX_WHITE_SMOKE:  //damaged unit smoke
			new CSmokeProjectile(pos, gu->usRandVector() * 0.5f + UpVector * 1.1f, 60, 4, 0.5f, unit, 0.5f);
			break;
		case SFX_BLACK_SMOKE:  //damaged unit smoke
			new CSmokeProjectile(pos, gu->usRandVector() * 0.5f + UpVector * 1.1f, 60, 4, 0.5f, unit, 0.6f);
			break;
		case SFX_VTOL: {
			const float3 speed =
				unit->speed    * 0.7f +
				unit->frontdir * 0.5f *       relDir.z  +
				unit->updir    * 0.5f * -math::fabs(relDir.y) +
				unit->rightdir * 0.5f *       relDir.x;

			CHeatCloudProjectile* hc = new CHeatCloudProjectile(
				pos,
				speed,
				10 + gu->usRandFloat() * 5,
				3 + gu->usRandFloat() * 2,
				unit
			);
			hc->size = 3;
			break;
		}
		default: {
			if (sfxType & SFX_CEG) {
				// emit defined explosiongenerator
				const unsigned index = sfxType - SFX_CEG;
				if (index >= unit->unitDef->sfxExplGens.size() || unit->unitDef->sfxExplGens[index] == NULL) {
					ShowScriptError("Invalid explosion generator index for emit-sfx");
					break;
				}

				IExplosionGenerator* explGen = unit->unitDef->sfxExplGens[index];
				explGen->Explosion(0, pos, unit->cegDamage, 1, unit, 0, 0, dir);
			}
			else if (sfxType & SFX_FIRE_WEAPON) {
				// make a weapon fire from the piece
				const unsigned index = sfxType - SFX_FIRE_WEAPON;
				if (index >= unit->weapons.size() || unit->weapons[index] == NULL) {
					ShowScriptError("Invalid weapon index for emit-sfx");
					break;
				}

				CWeapon* weapon = unit->weapons[index];

				const float3 targetPos = weapon->targetPos;
				const float3 weaponMuzzlePos = weapon->weaponMuzzlePos;

				weapon->targetPos = pos + dir;
				weapon->weaponMuzzlePos = pos;
				weapon->Fire();
				weapon->weaponMuzzlePos = weaponMuzzlePos;
				weapon->targetPos = targetPos;
			}
			else if (sfxType & SFX_DETONATE_WEAPON) {
				const unsigned index = sfxType - SFX_DETONATE_WEAPON;
				if (index >= unit->weapons.size() || unit->weapons[index] == NULL) {
					ShowScriptError("Invalid weapon index for emit-sfx");
					break;
				}

				// detonate weapon from piece
				const WeaponDef* weaponDef = unit->weapons[index]->weaponDef;

				CGameHelper::ExplosionParams params = {
					pos,
					ZeroVector,
					weaponDef->damages,
					weaponDef,
					unit,                              // owner
					NULL,                              // hitUnit
					NULL,                              // hitFeature
					weaponDef->craterAreaOfEffect,
					weaponDef->damageAreaOfEffect,
					weaponDef->edgeEffectiveness,
					weaponDef->explosionSpeed,
					1.0f,                              // gfxMod
					weaponDef->impactOnly,
					weaponDef->noSelfDamage,           // ignoreOwner
					true,                              // damageGround
				};

				helper->Explosion(params);
			}
		} break;
	}


#endif
}
Пример #3
0
void CUnitScript::EmitSfx(int type, int piece)
{
#ifndef _CONSOLE
	if (!PieceExists(piece)) {
		ShowScriptError("Invalid piecenumber for emit-sfx");
		return;
	}

	if (ph->particleSaturation > 1 && type < 1024) {
		// skip adding (unsynced!) particles when we have too many
		return;
	}

	float3 relPos = ZeroVector;
	float3 relDir = UpVector;
	if (!GetEmitDirPos(piece, relPos, relDir)) {
		ShowScriptError("emit-sfx: GetEmitDirPos failed");
		return;
	}

	const float3 pos =
		unit->pos +
		unit->frontdir * relPos.z +
		unit->updir    * relPos.y +
		unit->rightdir * relPos.x;
	const float3 dir =
		unit->frontdir * relDir.z +
		unit->updir    * relDir.y +
		unit->rightdir * relDir.x;

	float alpha = 0.3f + gu->usRandFloat() * 0.2f;
	float alphaFalloff = 0.004f;
	float fadeupTime = 4;

	// Hovers need special care
	if (unit->unitDef->canhover) {
		fadeupTime = 8.0f;
		alpha = 0.15f + gu->usRandFloat() * 0.2f;
		alphaFalloff = 0.008f;
	}

	//Make sure wakes are only emitted on water
	if ((type >= 2) && (type <= 5)) {
		if (ground->GetApproximateHeight(unit->pos.x, unit->pos.z) > 0) {
			return;
		}
	}

	switch (type) {
		case SFX_REVERSE_WAKE:
		case SFX_REVERSE_WAKE_2: {  //reverse wake
			relDir *= -0.2f;

			new CWakeProjectile(
				pos + gu->usRandVector() * 2.0f,
				dir * 0.4f,
				6.0f + gu->usRandFloat() * 4.0f,
				0.15f + gu->usRandFloat() * 0.3f,
				unit,
				alpha, alphaFalloff, fadeupTime
			);
			break;
		}

		case SFX_WAKE_2:  //wake 2, in TA it lives longer..
		case SFX_WAKE: {  //regular ship wake
			relDir *= 0.2f;

			new CWakeProjectile(
				pos + gu->usRandVector() * 2.0f,
				dir * 0.4f,
				6.0f + gu->usRandFloat() * 4.0f,
				0.15f + gu->usRandFloat() * 0.3f,
				unit,
				alpha, alphaFalloff, fadeupTime
			);
			break;
		}

		case SFX_BUBBLE: {  //submarine bubble. does not provide direction through piece vertices..
			float3 pspeed = gu->usRandVector() * 0.1f;
				pspeed.y += 0.2f;

			new CBubbleProjectile(
				pos + gu->usRandVector() * 2.0f,
				pspeed,
				40.0f + gu->usRandFloat() * 30.0f,
				1.0f + gu->usRandFloat() * 2.0f,
				0.01f,
				unit,
				0.3f + gu->usRandFloat() * 0.3f
			);
		} break;

		case SFX_WHITE_SMOKE:  //damaged unit smoke
			new CSmokeProjectile(pos, gu->usRandVector() * 0.5f + UpVector * 1.1f, 60, 4, 0.5f, unit, 0.5f);
			break;
		case SFX_BLACK_SMOKE:  //damaged unit smoke
			new CSmokeProjectile(pos, gu->usRandVector() * 0.5f + UpVector * 1.1f, 60, 4, 0.5f, unit, 0.6f);
			break;
		case SFX_VTOL: {  //vtol
			relDir *= 0.2f;

			const float3 udir =
				unit->frontdir * relDir.z +
				unit->updir    * -fabs(relDir.y) +
				unit->rightdir * relDir.x;

			CHeatCloudProjectile* hc = new CHeatCloudProjectile(
				pos,
				unit->speed * 0.7f + udir * 0.5f,
				10 + gu->usRandFloat() * 5,
				3 + gu->usRandFloat() * 2,
				unit
			);
			hc->size = 3;
			break;
		}
		default: {
			if (type & SFX_CEG) {
				// emit defined explosiongenerator
				const unsigned index = type - SFX_CEG;
				if (index >= unit->unitDef->sfxExplGens.size() || unit->unitDef->sfxExplGens[index] == NULL) {
					ShowScriptError("Invalid explosion generator index for emit-sfx");
					break;
				}

				float3 ndir = dir; 

				CExplosionGenerator* explGen = unit->unitDef->sfxExplGens[index];
				explGen->Explosion(pos, unit->cegDamage, 1, unit, 0, 0, ndir.SafeNormalize());
			}
			else if (type & SFX_FIRE_WEAPON) {
				// make a weapon fire from the piece
				const unsigned index = type - SFX_FIRE_WEAPON;
				if (index >= unit->weapons.size() || unit->weapons[index] == NULL) {
					ShowScriptError("Invalid weapon index for emit-sfx");
					break;
				}

				CWeapon* weapon = unit->weapons[index];

				const float3 targetPos = weapon->targetPos;
				const float3 weaponMuzzlePos = weapon->weaponMuzzlePos;

				float3 ndir = dir;

				// don't override the weapon's target position
				// if it was not set internally (so that force-
				// fire keeps working as expected)
				if (!weapon->haveUserTarget) {
					weapon->targetPos = pos + ndir.SafeNormalize();
				}

				weapon->weaponMuzzlePos = pos;
				weapon->Fire();
				weapon->weaponMuzzlePos = weaponMuzzlePos;

				weapon->targetPos = targetPos;
			}
			else if (type & SFX_DETONATE_WEAPON) {
				const unsigned index = type - SFX_DETONATE_WEAPON;
				if (index >= unit->weapons.size() || unit->weapons[index] == NULL) {
					ShowScriptError("Invalid weapon index for emit-sfx");
					break;
				}

				// detonate weapon from piece
				const WeaponDef* weaponDef = unit->weapons[index]->weaponDef;

				if (weaponDef->soundhit.getID(0) > 0) {
					Channels::Battle.PlaySample(weaponDef->soundhit.getID(0), unit, weaponDef->soundhit.getVolume(0));
				}

				helper->Explosion(
					pos, weaponDef->damages, weaponDef->areaOfEffect, weaponDef->edgeEffectiveness,
					weaponDef->explosionSpeed, unit, true, 1.0f, weaponDef->noSelfDamage, weaponDef->impactOnly, weaponDef->explosionGenerator,
					NULL, float3(0, 0, 0), weaponDef->id
				);
			}
		} break;
	}


#endif
}
Пример #4
0
void CUnitScript::EmitSfx(int sfxType, int piece)
{
#ifndef _CONSOLE
	if (!PieceExists(piece)) {
		ShowUnitScriptError("Invalid piecenumber for emit-sfx");
		return;
	}

	if (projectileHandler->GetParticleSaturation() > 1.0f && sfxType < SFX_CEG) {
		// skip adding (unsynced!) particles when we have too many
		return;
	}

	// Make sure wakes are only emitted on water
	if ((sfxType >= SFX_WAKE) && (sfxType <= SFX_REVERSE_WAKE_2)) {
		if (CGround::GetApproximateHeight(unit->pos.x, unit->pos.z) > 0.0f) {
			return;
		}
	}

	float3 relPos = ZeroVector;
	float3 relDir = UpVector;

	if (!GetEmitDirPos(piece, relPos, relDir)) {
		ShowUnitScriptError("emit-sfx: GetEmitDirPos failed");
		return;
	}

	relDir.SafeNormalize();

	const float3 pos = unit->GetObjectSpacePos(relPos);
	const float3 dir = unit->GetObjectSpaceVec(relDir);

	float alpha = 0.3f + gu->RandFloat() * 0.2f;
	float alphaFalloff = 0.004f;
	float fadeupTime = 4;

	const UnitDef* ud = unit->unitDef;
	const MoveDef* md = unit->moveDef;

	// hovercraft need special care
	if (md != NULL && md->speedModClass == MoveDef::Hover) {
		fadeupTime = 8.0f;
		alpha = 0.15f + gu->RandFloat() * 0.2f;
		alphaFalloff = 0.008f;
	}

	switch (sfxType) {
		case SFX_REVERSE_WAKE:
		case SFX_REVERSE_WAKE_2: {  //reverse wake
			new CWakeProjectile(
				unit,
				pos + gu->RandVector() * 2.0f,
				dir * 0.4f,
				6.0f + gu->RandFloat() * 4.0f,
				0.15f + gu->RandFloat() * 0.3f,
				alpha, alphaFalloff, fadeupTime
			);
			break;
		}

		case SFX_WAKE_2:  //wake 2, in TA it lives longer..
		case SFX_WAKE: {  //regular ship wake
			new CWakeProjectile(
				unit,
				pos + gu->RandVector() * 2.0f,
				dir * 0.4f,
				6.0f + gu->RandFloat() * 4.0f,
				0.15f + gu->RandFloat() * 0.3f,
				alpha, alphaFalloff, fadeupTime
			);
			break;
		}

		case SFX_BUBBLE: {  //submarine bubble. does not provide direction through piece vertices..
			float3 pspeed = gu->RandVector() * 0.1f;
				pspeed.y += 0.2f;

			new CBubbleProjectile(
				unit,
				pos + gu->RandVector() * 2.0f,
				pspeed,
				40.0f + gu->RandFloat() * GAME_SPEED,
				1.0f + gu->RandFloat() * 2.0f,
				0.01f,
				0.3f + gu->RandFloat() * 0.3f
			);
		} break;

		case SFX_WHITE_SMOKE:  //damaged unit smoke
			new CSmokeProjectile(unit, pos, gu->RandVector() * 0.5f + UpVector * 1.1f, 60, 4, 0.5f, 0.5f);
			break;
		case SFX_BLACK_SMOKE:  //damaged unit smoke
			new CSmokeProjectile(unit, pos, gu->RandVector() * 0.5f + UpVector * 1.1f, 60, 4, 0.5f, 0.6f);
			break;
		case SFX_VTOL: {
			const float3 speed =
				unit->speed    * 0.7f +
				unit->frontdir * 0.5f *       relDir.z  +
				unit->updir    * 0.5f * -math::fabs(relDir.y) +
				unit->rightdir * 0.5f *       relDir.x;

			CHeatCloudProjectile* hc = new CHeatCloudProjectile(
				unit,
				pos,
				speed,
				10 + gu->RandFloat() * 5,
				3 + gu->RandFloat() * 2
			);
			hc->size = 3;
			break;
		}
		default: {
			if (sfxType & SFX_CEG) {
				// emit defined explosion-generator (can only be custom, not standard)
				// index is made valid by callee, an ID of -1 means CEG failed to load
				explGenHandler->GenExplosion(ud->GetModelExplosionGeneratorID(sfxType - SFX_CEG), pos, dir, unit->cegDamage, 1.0f, 0.0f, unit, NULL);
			}
			else if (sfxType & SFX_FIRE_WEAPON) {
				// make a weapon fire from the piece
				const unsigned index = sfxType - SFX_FIRE_WEAPON;
				if (index >= unit->weapons.size()) {
					ShowUnitScriptError("Invalid weapon index for emit-sfx");
					break;
				}
				CWeapon* w = unit->weapons[index];
				const SWeaponTarget origTarget = w->GetCurrentTarget();
				const float3 origWeaponMuzzlePos = w->weaponMuzzlePos;
				w->SetAttackTarget(SWeaponTarget(pos + dir));
				w->weaponMuzzlePos = pos;
				w->Fire(true);
				w->weaponMuzzlePos = origWeaponMuzzlePos;
				bool origRestored = w->Attack(origTarget);
				assert(origRestored);
			}
			else if (sfxType & SFX_DETONATE_WEAPON) {
				const unsigned index = sfxType - SFX_DETONATE_WEAPON;
				if (index >= unit->weapons.size()) {
					ShowUnitScriptError("Invalid weapon index for emit-sfx");
					break;
				}

				// detonate weapon from piece
				const WeaponDef* weaponDef = unit->weapons[index]->weaponDef;

				CGameHelper::ExplosionParams params = {
					pos,
					ZeroVector,
					weaponDef->damages,
					weaponDef,
					unit,                              // owner
					NULL,                              // hitUnit
					NULL,                              // hitFeature
					weaponDef->craterAreaOfEffect,
					weaponDef->damageAreaOfEffect,
					weaponDef->edgeEffectiveness,
					weaponDef->explosionSpeed,
					1.0f,                              // gfxMod
					weaponDef->impactOnly,
					weaponDef->noSelfDamage,           // ignoreOwner
					true,                              // damageGround
					-1u                                // projectileID
				};

				helper->Explosion(params);
			}
		} break;
	}


#endif
}