Exemplo n.º 1
0
void CInterceptHandler::AddShieldInterceptableProjectile(CWeaponProjectile* p)
{
	for (std::list<CPlasmaRepulser*>::iterator wi = repulsors.begin(); wi != repulsors.end(); ++wi) {
		CPlasmaRepulser* shield = *wi;
		if (shield->weaponDef->shieldInterceptType & p->weaponDef->interceptedByShieldType) {
			shield->NewProjectile(p);
		}
	}
}
Exemplo n.º 2
0
float CInterceptHandler::AddShieldInterceptableBeam(CWeapon* emitter, const float3& start, const float3& dir, float length, float3& newDir, CPlasmaRepulser*& repulsedBy)
{
	float minRange = 99999999;
	float3 tempDir;

	for (std::list<CPlasmaRepulser*>::iterator wi = plasmaRepulsors.begin(); wi != plasmaRepulsors.end(); ++wi) {
		CPlasmaRepulser* shield = *wi;
		if(shield->weaponDef->shieldInterceptType & emitter->weaponDef->interceptedByShieldType){
			float dist = shield->NewBeam(emitter, start, dir, length, tempDir);
			if ((dist > 0) && (dist < minRange)) {
				minRange = dist;
				newDir = tempDir;
				repulsedBy = shield;
			}
		}
	}
	return minRange;
}
Exemplo n.º 3
0
float CInterceptHandler::AddShieldInterceptableBeam(CWeapon* emitter, const float3& start, const float3& dir, float length, float3& newDir, CPlasmaRepulser*& repulsedBy)
{
	float minRange = std::numeric_limits<float>::max();
	float3 tempDir;

	for (std::list<CPlasmaRepulser*>::iterator wi = repulsors.begin(); wi != repulsors.end(); ++wi) {
		CPlasmaRepulser* shield = *wi;

		if ((shield->weaponDef->shieldInterceptType & emitter->weaponDef->interceptedByShieldType) == 0)
			continue;

		const float dist = shield->NewBeam(emitter, start, dir, length, tempDir);

		if (dist <=     0.0f) continue;
		if (dist >= minRange) continue;

		minRange = dist;
		newDir = tempDir;
		repulsedBy = shield;
	}

	return minRange;
}
void CLightningCannon::Fire(void)
{
	float3 dir=targetPos-weaponMuzzlePos;
	dir.Normalize();
	dir+=(gs->randVector()*sprayAngle+salvoError)*(1-owner->limExperience*0.5f);
	dir.Normalize();
	CUnit* u=0;
	float r=helper->TraceRay(weaponMuzzlePos,dir,range,0,owner,u,collisionFlags);

	float3 newDir;
	CPlasmaRepulser* shieldHit;
	float shieldLength=interceptHandler.AddShieldInterceptableBeam(this,weaponMuzzlePos,dir,range,newDir,shieldHit);
	if(shieldLength<r){
		r=shieldLength;
		if(shieldHit) {
			shieldHit->BeamIntercepted(this);
		}
	}

//	if(u)
//		u->DoDamage(damages,owner,ZeroVector);

	// Dynamic Damage
	DamageArray dynDamages;
	if (weaponDef->dynDamageExp > 0)
		dynDamages = weaponDefHandler->DynamicDamages(weaponDef->damages, weaponMuzzlePos, targetPos, weaponDef->dynDamageRange>0?weaponDef->dynDamageRange:weaponDef->range, weaponDef->dynDamageExp, weaponDef->dynDamageMin, weaponDef->dynDamageInverted);

	helper->Explosion(weaponMuzzlePos+dir*r,weaponDef->dynDamageExp>0?dynDamages:weaponDef->damages,areaOfEffect,weaponDef->edgeEffectiveness,weaponDef->explosionSpeed,owner,false,0.5f,true,false,weaponDef->explosionGenerator, u,dir, weaponDef->id);

	SAFE_NEW CLightningProjectile(weaponMuzzlePos,
		weaponMuzzlePos + dir * (r + 10), owner, color, weaponDef, 10, this);

	if (fireSoundId && (!weaponDef->soundTrigger || salvoLeft == salvoSize - 1))
		sound->PlaySample(fireSoundId, owner, fireSoundVolume);

}
Exemplo n.º 5
0
void CLightningCannon::FireImpl()
{
	float3 dir = targetPos - weaponMuzzlePos;
	dir.ANormalize();
	dir += (gs->randVector() * sprayAngle + salvoError) * (1.0f - owner->limExperience * 0.5f);
	dir.ANormalize();

	CUnit* u = 0;
	float r = helper->TraceRay(weaponMuzzlePos, dir, range, 0, owner, u, collisionFlags);

	float3 newDir;
	CPlasmaRepulser* shieldHit = 0;
	const float shieldLength = interceptHandler.AddShieldInterceptableBeam(this, weaponMuzzlePos, dir, range, newDir, shieldHit);

	if (shieldLength < r) {
		r = shieldLength;
		if (shieldHit) {
			shieldHit->BeamIntercepted(this);
		}
	}

	if (u) {
		if (u->unitDef->usePieceCollisionVolumes) {
			u->SetLastAttackedPiece(u->localmodel->pieces[0], gs->frameNum);
		}
	}

	// Dynamic Damage
	DamageArray dynDamages;
	if (weaponDef->dynDamageExp > 0) {
		dynDamages = weaponDefHandler->DynamicDamages(
			weaponDef->damages,
			weaponMuzzlePos,
			targetPos,
			weaponDef->dynDamageRange > 0?
				weaponDef->dynDamageRange:
				weaponDef->range,
			weaponDef->dynDamageExp,
			weaponDef->dynDamageMin,
			weaponDef->dynDamageInverted
		);
	}

	helper->Explosion(
		weaponMuzzlePos + dir * r,
		weaponDef->dynDamageExp > 0?
			dynDamages:
			weaponDef->damages,
		areaOfEffect,
		weaponDef->edgeEffectiveness,
		weaponDef->explosionSpeed,
		owner,
		false,
		0.5f,
		true,
		false,
		weaponDef->explosionGenerator,
		u,
		dir,
		weaponDef->id
	);

	new CLightningProjectile(
		weaponMuzzlePos,
		weaponMuzzlePos + dir * (r + 10),
		owner,
		color,
		weaponDef,
		10,
		this
	);
}
Exemplo n.º 6
0
void CLightningCannon::FireImpl()
{
	float3 dir(targetPos - weaponMuzzlePos);
	dir.Normalize();
	dir +=
		(gs->randVector() * sprayAngle + salvoError) *
		(1.0f - owner->limExperience * weaponDef->ownerExpAccWeight);
	dir.Normalize();

	CUnit* u = NULL;
	CFeature* f = NULL;
	float r = TraceRay::TraceRay(weaponMuzzlePos, dir, range, collisionFlags, owner, u, f);

	float3 newDir;
	CPlasmaRepulser* shieldHit = NULL;
	const float shieldLength = interceptHandler.AddShieldInterceptableBeam(this, weaponMuzzlePos, dir, range, newDir, shieldHit);

	if (shieldLength < r) {
		r = shieldLength;
		if (shieldHit) {
			shieldHit->BeamIntercepted(this);
		}
	}

	if (u) {
		if (u->unitDef->usePieceCollisionVolumes) {
			u->SetLastAttackedPiece(u->localmodel->GetRoot(), gs->frameNum);
		}
	}

	// Dynamic Damage
	DamageArray damageArray;
	if (weaponDef->dynDamageExp > 0) {
		damageArray = weaponDefHandler->DynamicDamages(
			weaponDef->damages,
			weaponMuzzlePos,
			targetPos,
			weaponDef->dynDamageRange > 0?
				weaponDef->dynDamageRange:
				weaponDef->range,
			weaponDef->dynDamageExp,
			weaponDef->dynDamageMin,
			weaponDef->dynDamageInverted
		);
	} else {
		damageArray = weaponDef->damages;
	}

	CGameHelper::ExplosionParams params = {
		weaponMuzzlePos + dir * r,
		dir,
		damageArray,
		weaponDef,
		owner,
		u,                                                // hitUnit
		f,                                                // hitFeature
		areaOfEffect,
		weaponDef->edgeEffectiveness,
		weaponDef->explosionSpeed,
		0.5f,                                             // gfxMod
		weaponDef->impactOnly,
		weaponDef->noExplode || weaponDef->noSelfDamage,  // ignoreOwner
		false                                             // damageGround
	};

	helper->Explosion(params);

	new CLightningProjectile(
		weaponMuzzlePos,
		weaponMuzzlePos + dir * (r + 10),
		owner,
		color,
		weaponDef,
		10,
		this
	);
}
Exemplo n.º 7
0
void CUnitScript::SetUnitVal(int val, int param)
{
	// may happen in case one uses Spring.SetUnitCOBValue (Lua) on a unit with CNullUnitScript
	if (!unit) {
		ShowUnitScriptError("Error: no unit (in SetUnitVal)");
		return;
	}

#ifndef _CONSOLE
	switch (val) {
		case ACTIVATION: {
			if(unit->unitDef->onoffable) {
				Command c(CMD_ONOFF, 0, (param == 0) ? 0 : 1);
				unit->commandAI->GiveCommand(c);
			}
			else {
				if(param == 0) {
					unit->Deactivate();
				}
				else {
					unit->Activate();
				}
			}
			break;
		}
		case STANDINGMOVEORDERS: {
			if (param >= 0 && param <= 2) {
				Command c(CMD_MOVE_STATE, 0, param);
				unit->commandAI->GiveCommand(c);
			}
			break;
		}
		case STANDINGFIREORDERS: {
			if (param >= 0 && param <= 2) {
				Command c(CMD_FIRE_STATE, 0, param);
				unit->commandAI->GiveCommand(c);
			}
			break;
		}
		case HEALTH: {
			break;
		}
		case INBUILDSTANCE: {
			unit->inBuildStance = (param != 0);
			break;
		}
		case BUSY: {
			busy = (param != 0);
			break;
		}
		case PIECE_XZ: {
			break;
		}
		case PIECE_Y: {
			break;
		}
		case UNIT_XZ: {
			break;
		}
		case UNIT_Y: {
			break;
		}
		case UNIT_HEIGHT: {
			break;
		}
		case XZ_ATAN: {
			break;
		}
		case XZ_HYPOT: {
			break;
		}
		case ATAN: {
			break;
		}
		case HYPOT: {
			break;
		}
		case GROUND_HEIGHT: {
			break;
		}
		case GROUND_WATER_HEIGHT: {
			break;
		}
		case BUILD_PERCENT_LEFT: {
			break;
		}
		case YARD_OPEN: {
			if (unit->blockMap != NULL) {
				// note: if this unit is a factory, engine-controlled
				// OpenYard() and CloseYard() calls can interfere with
				// the yardOpen state (they probably should be removed
				// at some point)
				if (param == 0) {
					if (groundBlockingObjectMap->CanCloseYard(unit)) {
						groundBlockingObjectMap->CloseBlockingYard(unit);
					}
				} else {
					if (groundBlockingObjectMap->CanOpenYard(unit)) {
						groundBlockingObjectMap->OpenBlockingYard(unit);
					}
				}
			}
			break;
		}
		case BUGGER_OFF: {
			if (param != 0) {
				CGameHelper::BuggerOff(unit->pos + unit->frontdir * unit->radius, unit->radius * 1.5f, true, false, unit->team, NULL);
			}
			break;
		}
		case ARMORED: {
			if (param) {
				unit->curArmorMultiple = unit->armoredMultiple;
			} else {
				unit->curArmorMultiple = 1;
			}
			unit->armoredState = (param != 0);
			break;
		}
		case VETERAN_LEVEL: {
			unit->experience = param * 0.01f;
			break;
		}
		case MAX_SPEED: {
			// interpret negative values as non-persistent changes
			unit->commandAI->SetScriptMaxSpeed(std::max(param, -param) / float(COBSCALE), (param >= 0));
			break;
		}
		case CLOAKED: {
			unit->wantCloak = !!param;
			break;
		}
		case WANT_CLOAK: {
			unit->wantCloak = !!param;
			break;
		}
		case UPRIGHT: {
			unit->upright = !!param;
			break;
		}
		case HEADING: {
			unit->heading = param % COBSCALE;
			unit->UpdateDirVectors(!unit->upright);
			unit->UpdateMidAndAimPos();
		} break;
		case LOS_RADIUS: {
			unit->ChangeLos(param, unit->realAirLosRadius);
			unit->realLosRadius = param;
			break;
		}
		case AIR_LOS_RADIUS: {
			unit->ChangeLos(unit->realLosRadius, param);
			unit->realAirLosRadius = param;
			break;
		}
		case RADAR_RADIUS: {
			unit->ChangeSensorRadius(&unit->radarRadius, param);
			break;
		}
		case JAMMER_RADIUS: {
			unit->ChangeSensorRadius(&unit->jammerRadius, param);
			break;
		}
		case SONAR_RADIUS: {
			unit->ChangeSensorRadius(&unit->sonarRadius, param);
			break;
		}
		case SONAR_JAM_RADIUS: {
			unit->ChangeSensorRadius(&unit->sonarJamRadius, param);
			break;
		}
		case SEISMIC_RADIUS: {
			unit->ChangeSensorRadius(&unit->seismicRadius, param);
			break;
		}
		case CURRENT_FUEL: {
			unit->currentFuel = param / (float) COBSCALE;
			break;
		}
		case SHIELD_POWER: {
			if (unit->shieldWeapon != NULL) {
				CPlasmaRepulser* shield = static_cast<CPlasmaRepulser*>(unit->shieldWeapon);
				shield->SetCurPower(std::max(0.0f, float(param) / float(COBSCALE)));
			}
			break;
		}
		case STEALTH: {
			unit->stealth = !!param;
			break;
		}
		case SONAR_STEALTH: {
			unit->sonarStealth = !!param;
			break;
		}
		case CRASHING: {
			AAirMoveType* amt = dynamic_cast<AAirMoveType*>(unit->moveType);
			if (amt != NULL) {
				if (!!param) {
					amt->SetState(AAirMoveType::AIRCRAFT_CRASHING);
				} else {
					amt->SetState(AAirMoveType::AIRCRAFT_FLYING);
				}
			}
			break;
		}
		case CHANGE_TARGET: {
			if (param <                     0) { return; }
			if (param >= unit->weapons.size()) { return; }

			unit->weapons[param]->avoidTarget = true;
			break;
		}
		case CEG_DAMAGE: {
			unit->cegDamage = param;
			break;
		}
		case FLANK_B_MODE:
			unit->flankingBonusMode = param;
			break;
		case FLANK_B_MOBILITY_ADD:
			unit->flankingBonusMobilityAdd = (param / (float)COBSCALE);
			break;
		case FLANK_B_MAX_DAMAGE: {
			float mindamage = unit->flankingBonusAvgDamage - unit->flankingBonusDifDamage;
			unit->flankingBonusAvgDamage = (param / (float)COBSCALE + mindamage)*0.5f;
			unit->flankingBonusDifDamage = (param / (float)COBSCALE - mindamage)*0.5f;
			break;
		 }
		case FLANK_B_MIN_DAMAGE: {
			float maxdamage = unit->flankingBonusAvgDamage + unit->flankingBonusDifDamage;
			unit->flankingBonusAvgDamage = (maxdamage + param / (float)COBSCALE)*0.5f;
			unit->flankingBonusDifDamage = (maxdamage - param / (float)COBSCALE)*0.5f;
			break;
		}
		default: {
			if ((val >= GLOBAL_VAR_START) && (val <= GLOBAL_VAR_END)) {
				globalVars[val - GLOBAL_VAR_START] = param;
			}
			else if ((val >= TEAM_VAR_START) && (val <= TEAM_VAR_END)) {
				teamVars[unit->team][val - TEAM_VAR_START] = param;
			}
			else if ((val >= ALLY_VAR_START) && (val <= ALLY_VAR_END)) {
				allyVars[unit->allyteam][val - ALLY_VAR_START] = param;
			}
			else if ((val >= UNIT_VAR_START) && (val <= UNIT_VAR_END)) {
				unitVars[val - UNIT_VAR_START] = param;
			}
			else {
				LOG_L(L_ERROR, "CobError: Unknown set constant %d", val);
			}
		}
	}
#endif
}
Exemplo n.º 8
0
void CLightningCannon::FireImpl()
{
	float3 dir(targetPos - weaponMuzzlePos);
	dir.Normalize();
	dir +=
		(gs->randVector() * sprayAngle + salvoError) *
		(1.0f - owner->limExperience * weaponDef->ownerExpAccWeight);
	dir.Normalize();

	CUnit* u = NULL;
	CFeature* f = NULL;
	float r = 0.0f;

	{
		const CUnit* cu = NULL;
		const CFeature* cf = NULL;
		r = helper->TraceRay(weaponMuzzlePos, dir, range, 0, (const CUnit*)owner, cu, collisionFlags, &cf);
		u = const_cast<CUnit*>(cu);
		f = const_cast<CFeature*>(cf);
	}


	float3 newDir;
	CPlasmaRepulser* shieldHit = NULL;
	const float shieldLength = interceptHandler.AddShieldInterceptableBeam(this, weaponMuzzlePos, dir, range, newDir, shieldHit);

	if (shieldLength < r) {
		r = shieldLength;
		if (shieldHit) {
			shieldHit->BeamIntercepted(this);
		}
	}

	if (u) {
		if (u->unitDef->usePieceCollisionVolumes) {
			u->SetLastAttackedPiece(u->localmodel->GetRoot(), gs->frameNum);
		}
	}

	// Dynamic Damage
	DamageArray dynDamages;
	if (weaponDef->dynDamageExp > 0) {
		dynDamages = weaponDefHandler->DynamicDamages(
			weaponDef->damages,
			weaponMuzzlePos,
			targetPos,
			weaponDef->dynDamageRange > 0?
				weaponDef->dynDamageRange:
				weaponDef->range,
			weaponDef->dynDamageExp,
			weaponDef->dynDamageMin,
			weaponDef->dynDamageInverted
		);
	}

	helper->Explosion(
		weaponMuzzlePos + dir * r,
		weaponDef->dynDamageExp > 0?
			dynDamages:
			weaponDef->damages,
		areaOfEffect,
		weaponDef->edgeEffectiveness,
		weaponDef->explosionSpeed,
		owner,
		false,
		0.5f,
		weaponDef->noExplode || weaponDef->noSelfDamage, /*true*/
		weaponDef->impactOnly,                           /*false*/
		weaponDef->explosionGenerator,
		u,
		dir,
		weaponDef->id,
		f
	);

	new CLightningProjectile(
		weaponMuzzlePos,
		weaponMuzzlePos + dir * (r + 10),
		owner,
		color,
		weaponDef,
		10,
		this
	);
}
Exemplo n.º 9
0
void CBeamLaser::FireInternal(float3 dir, bool sweepFire)
{
	float rangeMod=1.3f;
#ifdef DIRECT_CONTROL_ALLOWED
	if(owner->directControl)
		rangeMod=0.95f;
#endif

	float maxLength=range*rangeMod;
	float curLength=0;
	float3 curPos=weaponPos;
	float3 hitPos;

	bool tryAgain=true;
	CUnit* hit;

	// increase range if targets are searched for in a cylinder
	if (cylinderTargetting > 0.01) {
		//const float3 up(0, owner->radius*cylinderTargetting, 0);
		//const float uplen = up.dot(dir);
		const float uplen = owner->radius*cylinderTargetting * dir.y;
		maxLength = sqrt(maxLength*maxLength + uplen*uplen);
	}

	// increase range if targetting edge of hitsphere
	if (targetType == Target_Unit && targetUnit && targetBorder != 0) {
		maxLength += targetUnit->radius*targetBorder;
	}

	for(int tries=0;tries<5 && tryAgain;++tries){
		tryAgain=false;
		hit=0;
		float length=helper->TraceRay(curPos,dir,maxLength-curLength,damages[0],owner,hit);

		if(hit && hit->allyteam == owner->allyteam && sweepFire){	//never damage friendlies with sweepfire
			lastFireFrame = 0;
			return;
		}

		float3 newDir;
		CPlasmaRepulser* shieldHit;
		float shieldLength=interceptHandler.AddShieldInterceptableBeam(this,curPos,dir,length,newDir,shieldHit);
		if(shieldLength<length){
			length=shieldLength;
			bool repulsed=shieldHit->BeamIntercepted(this);
			if(repulsed){
				tryAgain=true;
			}
		}

		hitPos=curPos+dir*length;

		float baseAlpha=weaponDef->intensity*255;
		float startAlpha=(1-curLength/(range*1.3f))*baseAlpha;
		float endAlpha=(1-(curLength+length)/(range*1.3f))*baseAlpha;

		if(weaponDef->largeBeamLaser)
			SAFE_NEW CLargeBeamLaserProjectile(curPos, hitPos, color, weaponDef->visuals.color2, owner,weaponDef);
		else
			SAFE_NEW CBeamLaserProjectile(curPos,hitPos,startAlpha,endAlpha,color,weaponDef->visuals.color2, owner,weaponDef->thickness,weaponDef->corethickness, weaponDef->laserflaresize, weaponDef);

		curPos=hitPos;
		curLength+=length;
		dir=newDir;
	}

	// fix negative damage when hitting big spheres
	float actualRange = range;
	if (hit && targetBorder > 0) {
		actualRange += hit->radius*targetBorder;
	}
	// make it possible to always hit with some minimal intensity (melee weapons have use for that)
	float intensity=max(minIntensity, 1-(curLength)/(actualRange*2));

	if(curLength<maxLength) {
		// Dynamic Damage
		DamageArray dynDamages;
		if (weaponDef->dynDamageExp > 0)
			dynDamages = weaponDefHandler->DynamicDamages(weaponDef->damages, weaponPos, curPos, weaponDef->dynDamageRange>0?weaponDef->dynDamageRange:weaponDef->range, weaponDef->dynDamageExp, weaponDef->dynDamageMin, weaponDef->dynDamageInverted);
		helper->Explosion(hitPos, weaponDef->dynDamageExp>0?dynDamages*(intensity*damageMul):weaponDef->damages*(intensity*damageMul), areaOfEffect, weaponDef->edgeEffectiveness, weaponDef->explosionSpeed,owner, true, 1.0f, false, weaponDef->explosionGenerator, hit, dir, weaponDef->id);
	}

	if(targetUnit)
		lastFireFrame = gs->frameNum;
}
Exemplo n.º 10
0
void CBeamLaser::FireInternal(float3 dir, bool sweepFire)
{
	// fix negative damage when hitting big spheres
	float actualRange = range;
	float rangeMod = 1.0f;

	if (dynamic_cast<CBuilding*>(owner) == NULL) {
		// help units fire while chasing
		rangeMod = 1.3f;
	}

	if (owner->fpsControlPlayer != NULL) {
		rangeMod = 0.95f;
	}

	float maxLength = range * rangeMod;
	float curLength = 0.0f;

	float3 curPos = weaponMuzzlePos;
	float3 hitPos;

	dir +=
		((gs->randVector() * sprayAngle *
		(1.0f - owner->limExperience * weaponDef->ownerExpAccWeight)));
	dir.SafeNormalize();

	bool tryAgain = true;

	// increase range if targets are searched for in a cylinder
	if (cylinderTargetting > 0.01f) {
		const float verticalDist = owner->radius * cylinderTargetting * dir.y;
		const float maxLengthModSq = maxLength * maxLength + verticalDist * verticalDist;

		maxLength = math::sqrt(maxLengthModSq);
	}


	// increase range if targetting edge of hitsphere
	if (targetType == Target_Unit && targetUnit && targetBorder != 0) {
		maxLength += (targetUnit->radius * targetBorder);
	}


	// unit at the end of the beam
	CUnit* hitUnit = NULL;
	CFeature* hitFeature = NULL;
	CPlasmaRepulser* hitShield = NULL;

	for (int tries = 0; tries < 5 && tryAgain; ++tries) {
		tryAgain = false;

		float length = TraceRay::TraceRay(curPos, dir, maxLength - curLength, collisionFlags, owner, hitUnit, hitFeature);

		if (hitUnit && teamHandler->AlliedTeams(hitUnit->team, owner->team) && sweepFire) {
			// never damage friendlies with sweepfire
			lastFireFrame = 0;
			return;
		}

		float3 newDir;
		const float shieldLength = interceptHandler.AddShieldInterceptableBeam(this, curPos, dir, length, newDir, hitShield);

		if (shieldLength < length) {
			length = shieldLength;
			tryAgain = hitShield->BeamIntercepted(this, damageMul); // repulsed
		}

		hitPos = curPos + dir * length;

		const float baseAlpha  = weaponDef->intensity * 255.0f;
		const float startAlpha = (1.0f - (curLength         ) / (range * 1.3f)) * baseAlpha;
		const float endAlpha   = (1.0f - (curLength + length) / (range * 1.3f)) * baseAlpha;

		if (weaponDef->largeBeamLaser) {
			new CLargeBeamLaserProjectile(curPos, hitPos, color, weaponDef->visuals.color2, owner, weaponDef);
		} else {
			new CBeamLaserProjectile(curPos, hitPos, startAlpha, endAlpha, color, owner, weaponDef);
		}

		curPos = hitPos;
		curLength += length;
		dir = newDir;
	}

	if (hitUnit) {
		if (hitUnit->unitDef->usePieceCollisionVolumes) {
			// getting the actual piece here is probably overdoing it
			// TODO change this if we really need propper flanking bonus support
			// for beam-lasers
			hitUnit->SetLastAttackedPiece(hitUnit->localmodel->GetRoot(), gs->frameNum);
		}

		if (targetBorder > 0) {
			actualRange += hitUnit->radius * targetBorder;
		}
	}

	// make it possible to always hit with some minimal intensity (melee weapons have use for that)
	const float hitIntensity = std::max(minIntensity, 1.0f - (curLength) / (actualRange * 2));

	if (curLength < maxLength) {
		// Dynamic Damage
		DamageArray dynDamages;

		if (weaponDef->dynDamageExp > 0) {
			dynDamages = weaponDefHandler->DynamicDamages(
				weaponDef->damages,
				weaponMuzzlePos,
				curPos,
				weaponDef->dynDamageRange > 0?
					weaponDef->dynDamageRange:
					weaponDef->range,
				weaponDef->dynDamageExp,
				weaponDef->dynDamageMin,
				weaponDef->dynDamageInverted
			);
		}

		DamageArray damageArray = weaponDef->dynDamageExp > 0?
			dynDamages * (hitIntensity * damageMul):
			weaponDef->damages * (hitIntensity * damageMul);
		CGameHelper::ExplosionParams params = {
			hitPos,
			dir,
			damageArray,
			weaponDef,
			owner,
			hitUnit,
			hitFeature,
			areaOfEffect,
			weaponDef->edgeEffectiveness,
			weaponDef->explosionSpeed,
			1.0f,                                             // gfxMod
			weaponDef->impactOnly,
			weaponDef->noExplode || weaponDef->noSelfDamage,  // ignoreOwner
			true                                              // damageGround
		};

		helper->Explosion(params);
	}

	if (targetUnit) {
		lastFireFrame = gs->frameNum;
	}
}
Exemplo n.º 11
0
void CBeamLaser::FireInternal(float3 dir, bool sweepFire)
{
	float rangeMod = 1.0f;

	if (dynamic_cast<CBuilding*>(owner) == NULL) {
		// help units fire while chasing
		rangeMod = 1.3f;
	}

	if (owner->directControl) {
		rangeMod = 0.95f;
	}

	float maxLength = range * rangeMod;
	float curLength = 0.0f;

	float3 curPos = weaponMuzzlePos;
	float3 hitPos;

	dir += gs->randVector() * sprayAngle * (1 - owner->limExperience * 0.7f);
	dir.ANormalize();

	bool tryAgain = true;
	// unit at the end of the beam
	CUnit* hit = 0;

	// increase range if targets are searched for in a cylinder
	if (cylinderTargetting > 0.01f) {
		// const float3 up(0, owner->radius*cylinderTargetting, 0);
		// const float uplen = up.dot(dir);
		const float uplen = owner->radius * cylinderTargetting * dir.y;
		maxLength = streflop::sqrtf(maxLength * maxLength + uplen * uplen);
	}

	// increase range if targetting edge of hitsphere
	if (targetType == Target_Unit && targetUnit && targetBorder != 0) {
		maxLength += targetUnit->radius * targetBorder;
	}

	for (int tries = 0; tries < 5 && tryAgain; ++tries) {
		tryAgain = false;
		hit = 0;

		float length = helper->TraceRay(
			curPos,
			dir,
			maxLength - curLength,
			weaponDef->damages[0],
			owner,
			hit,
			collisionFlags
		);

		if (hit && hit->allyteam == owner->allyteam && sweepFire) {
			// never damage friendlies with sweepfire
			lastFireFrame = 0;
			return;
		}

		float3 newDir;
		CPlasmaRepulser* shieldHit = 0;
		const float shieldLength = interceptHandler.AddShieldInterceptableBeam(this, curPos, dir, length, newDir, shieldHit);

		if (shieldLength < length) {
			length = shieldLength;

			if (shieldHit->BeamIntercepted(this, damageMul)) {
				// repulsed
				tryAgain = true;
			}
		}

		hitPos = curPos + dir * length;

		const float baseAlpha  = weaponDef->intensity * 255.0f;
		const float startAlpha = (1.0f - (curLength         ) / (range * 1.3f)) * baseAlpha;
		const float endAlpha   = (1.0f - (curLength + length) / (range * 1.3f)) * baseAlpha;

		if (weaponDef->largeBeamLaser) {
			new CLargeBeamLaserProjectile(curPos, hitPos, color, weaponDef->visuals.color2, owner, weaponDef);
		} else {
			new CBeamLaserProjectile(
				curPos, hitPos,
				startAlpha, endAlpha,
				color, weaponDef->visuals.color2,
				owner,
				weaponDef->thickness,
				weaponDef->corethickness,
				weaponDef->laserflaresize,
				weaponDef,
				weaponDef->visuals.beamttl,
				weaponDef->visuals.beamdecay
			);
		}

		curPos = hitPos;
		curLength += length;
		dir = newDir;
	}

	// fix negative damage when hitting big spheres
	float actualRange = range;
	if (hit) {
		if (hit->unitDef->usePieceCollisionVolumes) {
			// getting the actual piece here is probably overdoing it
			hit->SetLastAttackedPiece(hit->localmodel->pieces[0], gs->frameNum);
		}

		if (targetBorder > 0) {
			actualRange += hit->radius * targetBorder;
		}
	}

	// make it possible to always hit with some minimal intensity (melee weapons have use for that)
	const float intensity = std::max(minIntensity, 1.0f - (curLength) / (actualRange * 2));

	if (curLength < maxLength) {
		// Dynamic Damage
		DamageArray dynDamages;

		if (weaponDef->dynDamageExp > 0) {
			dynDamages = weaponDefHandler->DynamicDamages(
				weaponDef->damages,
				weaponMuzzlePos,
				curPos,
				weaponDef->dynDamageRange > 0?
					weaponDef->dynDamageRange:
					weaponDef->range,
				weaponDef->dynDamageExp,
				weaponDef->dynDamageMin,
				weaponDef->dynDamageInverted
			);
		}

		helper->Explosion(
			hitPos,
			weaponDef->dynDamageExp > 0?
				dynDamages * (intensity * damageMul):
				weaponDef->damages * (intensity * damageMul),
			areaOfEffect,
			weaponDef->edgeEffectiveness,
			weaponDef->explosionSpeed,
			owner,
			true,
			1.0f,
			weaponDef->noExplode || weaponDef->noSelfDamage, /*false*/
			weaponDef->impactOnly,                           /*false*/
			weaponDef->explosionGenerator,
			hit,
			dir,
			weaponDef->id
		);
	}

	if (targetUnit) {
		lastFireFrame = gs->frameNum;
	}
}
Exemplo n.º 12
0
void CBeamLaser::FireInternal(float3 curDir)
{
	float actualRange = range;
	float rangeMod = 1.0f;

	if (!owner->unitDef->IsImmobileUnit()) {
		// help units fire while chasing
		rangeMod = 1.3f;
	}
	if (owner->UnderFirstPersonControl()) {
		rangeMod = 0.95f;
	}

	bool tryAgain = true;
	bool doDamage = true;

	float maxLength = range * rangeMod;
	float curLength = 0.0f;

	float3 curPos = weaponMuzzlePos;
	float3 hitPos;
	float3 newDir;

	// objects at the end of the beam
	CUnit* hitUnit = NULL;
	CFeature* hitFeature = NULL;
	CPlasmaRepulser* hitShield = NULL;
	CollisionQuery hitColQuery;

	if (!sweepFireState.IsSweepFiring()) {
		curDir += (gs->randVector() * SprayAngleExperience());
		curDir.SafeNormalize();

		// increase range if targets are searched for in a cylinder
		if (cylinderTargeting > 0.01f) {
			const float verticalDist = owner->radius * cylinderTargeting * curDir.y;
			const float maxLengthModSq = maxLength * maxLength + verticalDist * verticalDist;

			maxLength = math::sqrt(maxLengthModSq);
		}

		// adjust range if targetting edge of hitsphere
		if (targetType == Target_Unit && targetUnit != NULL && targetBorder != 0.0f) {
			maxLength += (targetUnit->radius * targetBorder);
		}
	} else {
		// restrict the range when sweeping
		maxLength = std::min(maxLength, sweepFireState.GetTargetDist3D() * 1.125f);
	}

	for (int tries = 0; tries < 5 && tryAgain; ++tries) {
		float beamLength = TraceRay::TraceRay(curPos, curDir, maxLength - curLength, collisionFlags, owner, hitUnit, hitFeature, &hitColQuery);

		if (hitUnit != NULL && teamHandler->AlliedTeams(hitUnit->team, owner->team)) {
			if (sweepFireState.IsSweepFiring() && !sweepFireState.DamageAllies()) {
				doDamage = false; break;
			}
		}

		if (!weaponDef->waterweapon) {
			// terminate beam at water surface if necessary
			if ((curDir.y < 0.0f) && ((curPos.y + curDir.y * beamLength) <= 0.0f)) {
				beamLength = curPos.y / -curDir.y;
			}
		}

		// if the beam gets intercepted, this modifies newDir
		//
		// we do more than one trace-iteration and set dir to
		// newDir only in the case there is a shield in our way
		const float shieldLength = interceptHandler.AddShieldInterceptableBeam(this, curPos, curDir, beamLength, newDir, hitShield);

		if (shieldLength < beamLength) {
			beamLength = shieldLength;
			tryAgain = hitShield->BeamIntercepted(this, salvoDamageMult);
		} else {
			tryAgain = false;
		}

		// same as hitColQuery.GetHitPos() if no water or shield in way
		hitPos = curPos + curDir * beamLength;

		{
			const float baseAlpha  = weaponDef->intensity * 255.0f;
			const float startAlpha = (1.0f - (curLength             ) / maxLength);
			const float endAlpha   = (1.0f - (curLength + beamLength) / maxLength);

			ProjectileParams pparams = GetProjectileParams();
			pparams.pos = curPos;
			pparams.end = hitPos;
			pparams.ttl = weaponDef->beamLaserTTL;
			pparams.startAlpha = Clamp(startAlpha * baseAlpha, 0.0f, 255.0f);
			pparams.endAlpha = Clamp(endAlpha * baseAlpha, 0.0f, 255.0f);

			WeaponProjectileFactory::LoadProjectile(pparams);
		}

		curPos = hitPos;
		curDir = newDir;
		curLength += beamLength;
	}

	if (!doDamage)
		return;

	if (hitUnit != NULL) {
		hitUnit->SetLastAttackedPiece(hitColQuery.GetHitPiece(), gs->frameNum);

		if (targetBorder > 0.0f) {
			actualRange += (hitUnit->radius * targetBorder);
		}
	}

	if (curLength < maxLength) {
		const DamageArray& baseDamages = (weaponDef->dynDamageExp <= 0.0f)?
			weaponDef->damages:
			weaponDefHandler->DynamicDamages(
				weaponDef->damages,
				weaponMuzzlePos,
				curPos,
				(weaponDef->dynDamageRange > 0.0f)?
					weaponDef->dynDamageRange:
					weaponDef->range,
				weaponDef->dynDamageExp,
				weaponDef->dynDamageMin,
				weaponDef->dynDamageInverted
			);

		// make it possible to always hit with some minimal intensity (melee weapons have use for that)
		const float hitIntensity = std::max(minIntensity, 1.0f - curLength / (actualRange * 2.0f));

		const DamageArray damages = baseDamages * (hitIntensity * salvoDamageMult);
		const CGameHelper::ExplosionParams params = {
			hitPos,
			curDir,
			damages,
			weaponDef,
			owner,
			hitUnit,
			hitFeature,
			craterAreaOfEffect,
			damageAreaOfEffect,
			weaponDef->edgeEffectiveness,
			weaponDef->explosionSpeed,
			1.0f,                                             // gfxMod
			weaponDef->impactOnly,
			weaponDef->noExplode || weaponDef->noSelfDamage,  // ignoreOwner
			true,                                             // damageGround
			-1u                                               // projectileID
		};

		helper->Explosion(params);
	}
}
Exemplo n.º 13
0
void CLightningCannon::FireImpl(bool scriptCall)
{
	float3 curPos = weaponMuzzlePos;
	float3 curDir = (targetPos - curPos).Normalize();
	float3 newDir = curDir;

	curDir +=
		(gs->randVector() * SprayAngleExperience() + SalvoErrorExperience());
	curDir.Normalize();

	CUnit* hitUnit = NULL;
	CFeature* hitFeature = NULL;
	CPlasmaRepulser* hitShield = NULL;
	CollisionQuery hitColQuery;

	float boltLength = TraceRay::TraceRay(curPos, curDir, range, collisionFlags, owner, hitUnit, hitFeature, &hitColQuery);

	if (!weaponDef->waterweapon) {
		// terminate bolt at water surface if necessary
		if ((curDir.y < 0.0f) && ((curPos.y + curDir.y * boltLength) <= 0.0f)) {
			boltLength = curPos.y / -curDir.y;
		}
	}

	const float shieldLength = interceptHandler.AddShieldInterceptableBeam(this, curPos, curDir, range, newDir, hitShield);

	if (shieldLength < boltLength) {
		boltLength = shieldLength;
		hitShield->BeamIntercepted(this);
	}

	if (hitUnit != NULL) {
		hitUnit->SetLastAttackedPiece(hitColQuery.GetHitPiece(), gs->frameNum);
	}

	const DamageArray& damageArray = (weaponDef->dynDamageExp <= 0.0f)?
		weaponDef->damages:
		weaponDefHandler->DynamicDamages(
			weaponDef->damages,
			weaponMuzzlePos,
			targetPos,
			(weaponDef->dynDamageRange > 0.0f)?
				weaponDef->dynDamageRange:
				weaponDef->range,
			weaponDef->dynDamageExp,
			weaponDef->dynDamageMin,
			weaponDef->dynDamageInverted
		);

	const CGameHelper::ExplosionParams params = {
		curPos + curDir * boltLength,                     // hitPos (same as hitColQuery.GetHitPos() if no water or shield in way)
		curDir,
		damageArray,
		weaponDef,
		owner,
		hitUnit,
		hitFeature,
		craterAreaOfEffect,
		damageAreaOfEffect,
		weaponDef->edgeEffectiveness,
		weaponDef->explosionSpeed,
		0.5f,                                             // gfxMod
		weaponDef->impactOnly,
		weaponDef->noExplode || weaponDef->noSelfDamage,  // ignoreOwner
		false,                                            // damageGround
		-1u                                               // projectileID
	};

	helper->Explosion(params);

	ProjectileParams pparams = GetProjectileParams();
	pparams.pos = curPos;
	pparams.end = curPos + curDir * (boltLength + 10.0f);
	pparams.ttl = 10;

	WeaponProjectileFactory::LoadProjectile(pparams);
}
Exemplo n.º 14
0
void CLightningCannon::FireImpl()
{
	float3 curPos = weaponMuzzlePos;
	float3 hitPos;
	float3 curDir = (targetPos - curPos).Normalize();
	float3 newDir = curDir;

	curDir +=
		(gs->randVector() * sprayAngle + salvoError) *
		(1.0f - owner->limExperience * weaponDef->ownerExpAccWeight);
	curDir.Normalize();

	CUnit* hitUnit = NULL;
	CFeature* hitFeature = NULL;
	CPlasmaRepulser* hitShield = NULL;

	float boltLength = TraceRay::TraceRay(curPos, curDir, range, collisionFlags, owner, hitUnit, hitFeature);

	if (!weaponDef->waterweapon) {
		// terminate bolt at water surface if necessary
		if ((curDir.y < 0.0f) && ((curPos.y + curDir.y * boltLength) <= 0.0f)) {
			boltLength = curPos.y / -curDir.y;
		}
	}

	const float shieldLength = interceptHandler.AddShieldInterceptableBeam(this, curPos, curDir, range, newDir, hitShield);

	if (shieldLength < boltLength) {
		boltLength = shieldLength;
		hitShield->BeamIntercepted(this);
	}

	hitPos = curPos + curDir * boltLength;

	if (hitUnit != NULL) {
		hitUnit->SetLastAttackedPiece(hitUnit->localModel->GetRoot(), gs->frameNum);
	}


	const DamageArray& damageArray = (weaponDef->dynDamageExp <= 0.0f)?
		weaponDef->damages:
		weaponDefHandler->DynamicDamages(
			weaponDef->damages,
			weaponMuzzlePos,
			targetPos,
			(weaponDef->dynDamageRange > 0.0f)?
				weaponDef->dynDamageRange:
				weaponDef->range,
			weaponDef->dynDamageExp,
			weaponDef->dynDamageMin,
			weaponDef->dynDamageInverted
		);

	const CGameHelper::ExplosionParams params = {
		hitPos,
		curDir,
		damageArray,
		weaponDef,
		owner,
		hitUnit,
		hitFeature,
		craterAreaOfEffect,
		damageAreaOfEffect,
		weaponDef->edgeEffectiveness,
		weaponDef->explosionSpeed,
		0.5f,                                             // gfxMod
		weaponDef->impactOnly,
		weaponDef->noExplode || weaponDef->noSelfDamage,  // ignoreOwner
		false                                             // damageGround
	};

	helper->Explosion(params);

	ProjectileParams pparams = GetProjectileParams();
	pparams.pos = curPos;
	pparams.end = curPos + curDir * (boltLength + 10.0f);
	pparams.ttl = 10;
	new CLightningProjectile(pparams, color);
}