CFireProjectile::CFireProjectile(const float3& pos,const float3& speed,CUnit* owner,int emitTtl,float emitRadius,int particleTtl,float particleSize)
: CProjectile(pos,speed,owner),
	ttl(emitTtl),
	emitPos(pos),
	emitRadius(emitRadius),
	particleTime(particleTtl),
	particleSize(particleSize)
{
	drawRadius=emitRadius+particleTime*speed.Length();
	checkCol=false;
	this->pos.y+=particleTime*speed.Length()*0.5;
	ageSpeed=1.0/particleTime;

	alwaysVisible=true;
	castShadow=true;
}
Пример #2
0
static float GetCamDistOfGrassBlock(const int x, const int y, const bool square = false)
{
	float3 quadCenter = float3(x, 0.f, y) * gSSsq;
	quadCenter.y = CGround::GetHeightReal(quadCenter.x, quadCenter.z, false);
	const float3 dif = camera->GetPos() - quadCenter;
	return (square) ? dif.SqLength() : dif.Length();
}
Пример #3
0
/** For reference, see http://realtimecollisiondetection.net/blog/?p=20 . */
Sphere Sphere::FitThroughPoints(const float3 &a, const float3 &b, const float3 &c)
{
	Sphere sphere;

	float3 ab = b-a;
	float3 ac = c-a;

	float s, t;
	bool success = FitSphereThroughPoints(ab, ac, s, t);
	if (!success)
	{
		LOGW("Sphere::FitThroughPoints(a,b,c) failed! The three input points are collinear!");
		sphere.SetDegenerate();
		return sphere;
	}

	const float3 p = s*ab + t*ac;

	// In our translated coordinate space, the origin lies on the sphere, so the distance of p from origin 
	// gives the radius of the sphere.
	sphere.r = p.Length(); 

	// Translate back to original coordinate space.
	sphere.pos = a + p;

	return sphere;
}
Пример #4
0
CTorpedoProjectile::CTorpedoProjectile(
		const float3& pos, const float3& speed,
		CUnit* owner,
		float areaOfEffect, float maxSpeed,
		float tracking, int ttl,
		CUnit* target,
		const WeaponDef* weaponDef)
	: CWeaponProjectile(pos, speed, owner, target, ZeroVector, weaponDef, NULL, ttl),
	tracking(tracking),
	maxSpeed(maxSpeed),
	areaOfEffect(areaOfEffect),
	target(target),
	nextBubble(4)
{
	projectileType = WEAPON_TORPEDO_PROJECTILE;
	curSpeed = speed.Length();
	dir = speed / curSpeed;

	if (target) {
		AddDeathDependence(target);
	}

	SetRadius(0.0f);
	drawRadius = maxSpeed * 8;

//	const float3 camDir = (pos - camera->pos).Normalize();
	texx = projectileDrawer->torpedotex->xstart - (projectileDrawer->torpedotex->xend - projectileDrawer->torpedotex->xstart) * 0.5f;
	texy = projectileDrawer->torpedotex->ystart - (projectileDrawer->torpedotex->yend - projectileDrawer->torpedotex->ystart) * 0.5f;
#ifdef TRACE_SYNC
	tracefile << "New projectile: ";
	tracefile << pos.x << " " << pos.y << " " << pos.z << " " << speed.x << " " << speed.y << " " << speed.z << "\n";
#endif

	cegID = gCEG->Load(explGenHandler, cegTag);
}
CLaserProjectile::CLaserProjectile(const float3& pos, const float3& speed,
		CUnit* owner, float length, const float3& color, const float3& color2,
		float intensity, const WeaponDef *weaponDef, int ttl GML_PARG_C)
: CWeaponProjectile(pos,speed,owner,0,ZeroVector,weaponDef,0, true,  ttl GML_PARG_P),
	color(color),
	color2(color2),
	length(length),
	curLength(0),
	stayTime(0),
	intensity(intensity),
	intensityFalloff(weaponDef?intensity*weaponDef->falloffRate:0)
{
	dir=speed;
	dir.Normalize();
	speedf=speed.Length();

	if (weaponDef) SetRadius(weaponDef->collisionSize);
	drawRadius=length;
	if (weaponDef)midtexx = weaponDef->visuals.texture2->xstart + (weaponDef->visuals.texture2->xend-weaponDef->visuals.texture2->xstart)*0.5f;
#ifdef TRACE_SYNC
	tracefile << "New laser: ";
	tracefile << pos.x << " " << pos.y << " " << pos.z << " " << speed.x << " " << speed.y << " " << speed.z << "\n";
#endif

	if (cegTag.size() > 0) {
		ceg.Load(explGenHandler, cegTag);
	}
}
void CGameHelper::DoExplosionDamage(
	CFeature* feature,
	const float3& expPos,
	float expRad,
	const DamageArray& damages,
	const int weaponDefID
) {
	const CollisionVolume* cv = feature->collisionVolume;

	if (cv) {
		const float3 dif = (feature->midPos + cv->GetOffsets()) - expPos;

		float expDist = std::max(dif.Length(), 0.1f);
		float expMod = (expRad - expDist) / expRad;
		float dmgScale = (damages.GetDefaultDamage() + damages.impulseBoost);

		// always do some damage with explosive stuff
		// (DDM wreckage etc. is too big to normally
		// be damaged otherwise, even by BB shells)
		// NOTE: this will also be only approximate
		// for non-spherical volumes
		if ((expRad > SQUARE_SIZE) && (expDist < (cv->GetBoundingRadius() * 1.1f)) && (expMod < 0.1f)) {
			expMod = 0.1f;
		}

		if (expMod > 0.0f) {
			const DamageArray modDamages = damages * expMod;
			const float3& modImpulse = dif * (damages.impulseFactor * expMod / expDist * dmgScale);

			feature->DoDamage(modDamages, modImpulse, NULL, weaponDefID);
		}
	}
}
Пример #7
0
static float GetCamDistOfGrassBlock(const int x, const int y, const bool square = false)
{
	const float qx = x * gSSsq;
	const float qz = y * gSSsq;
	const float3 mid = float3(qx, CGround::GetHeightReal(qx, qz, false), qz);
	const float3 dif = camera->GetPos() - mid;
	return (square) ? dif.SqLength() : dif.Length();
}
CMissileProjectile::CMissileProjectile(const float3& pos,const float3& speed,CUnit* owner,const DamageArray& damages,float areaOfEffect,float maxSpeed, int ttl,CUnit* target, WeaponDef *weaponDef,float3 targetPos)
: CWeaponProjectile(pos,speed,owner,target,ZeroVector,weaponDef,0),
	damages(damages),
	ttl(ttl),
	maxSpeed(maxSpeed),
	target(target),
	dir(speed),
	oldSmoke(pos),
	age(0),
	drawTrail(true),
	numParts(0),
	areaOfEffect(areaOfEffect),
	decoyTarget(0),
	targPos(targetPos),
	wobbleTime(1),
	wobbleDir(0,0,0),
	wobbleDif(0,0,0),
	isWobbling(weaponDef->wobble>0),
	extraHeightTime(0)
{
	curSpeed=speed.Length();
	dir.Normalize();
	oldDir=dir;
	if(target)
		AddDeathDependence(target);

	SetRadius(0.0);
	if(!weaponDef->visuals.modelName.empty()){
		S3DOModel* model = modelParser->Load3DO(string("objects3d/")+weaponDef->visuals.modelName,1,0);
		if(model){
			SetRadius(model->radius);
		}
	}

	drawRadius=radius+maxSpeed*8;
	ENTER_MIXED;
	float3 camDir=(pos-camera->pos).Normalize();
	if(camera->pos.distance(pos)*0.2+(1-fabs(camDir.dot(dir)))*3000 < 200)
		drawTrail=false;
	ENTER_SYNCED;
	castShadow=true;
#ifdef TRACE_SYNC
	tracefile << "New missile: ";
	tracefile << pos.x << " " << pos.y << " " << pos.z << " " << speed.x << " " << speed.y << " " << speed.z << "\n";
#endif
	if(target)
		target->IncomingMissile(this);

	if(weaponDef->trajectoryHeight>0){
		float dist=pos.distance(targPos);
		extraHeight=dist*weaponDef->trajectoryHeight;
		if(dist<maxSpeed)
			dist=maxSpeed;
		extraHeightTime=(int)(dist/*+pos.distance(targPos+UpVector*dist))*0.5*//maxSpeed);
		extraHeightDecay=extraHeight/extraHeightTime;
	}
}
Пример #9
0
CFireProjectile::CFireProjectile(const float3& pos, const float3& speed, CUnit* owner, int emitTtl, float emitRadius, int particleTtl, float particleSize):
	//! these are synced, but neither weapon nor piece
	//! (only burning features create instances of them)
	CProjectile(pos, speed, owner, true, false, false),
	ttl(emitTtl),
	emitPos(pos),
	emitRadius(emitRadius),
	particleTime(particleTtl),
	particleSize(particleSize)
{
	drawRadius = emitRadius + particleTime * speed.Length();
	checkCol = false;
	this->pos.y += particleTime * speed.Length() * 0.5f;
	ageSpeed = 1.0f / particleTime;

	alwaysVisible = true;
	castShadow = true;
}
CFlameProjectile::CFlameProjectile(const float3& pos,const float3& speed,const float3& spread,CUnit* owner,const DamageArray& damages, WeaponDef *weaponDef, int ttl)
: CWeaponProjectile(pos,speed,owner,0,ZeroVector,weaponDef,damages,0),
	spread(spread),
	curTime(0)
{
	invttl=1.0/ttl;

	SetRadius(speed.Length()*0.9);
}
Пример #11
0
void COrbitController::Init(const float3& p, const float3& tar)
{
	CCamera* cam = camera;

	const float l = (tar == ZeroVector)?
		std::max(ground->LineGroundCol(p, p + cam->forward * 1024.0f), 512.0f):
		(p - tar).Length();

	const float3 t = (tar == ZeroVector)? (p + cam->forward * l): tar;
	const float3 v = (t - p);
	const float3 w = (v / v.Length()); // do not normalize v in-place

	const float d = v.Length();
	const float e = RAD2DEG(acos(v.Length2D() / d));
	const float r = RAD2DEG(acos(w.x));

	distance  = cDistance = d;
	elevation = cElevation = e;
	rotation  = cRotation = (v.z > 0.0f)? 180.0f + r: 180.0f - r;
	cen       = t;
}
CStarburstProjectile::CStarburstProjectile(const float3& pos,const float3& speed,CUnit* owner,float3 targetPos,const DamageArray& damages,float areaOfEffect,float maxSpeed,float tracking, int uptime,CUnit* target, WeaponDef *weaponDef, CWeaponProjectile* interceptTarget)
: CWeaponProjectile(pos,speed,owner,target,targetPos,weaponDef,damages,interceptTarget),
	ttl(200),
	maxSpeed(maxSpeed),
	tracking(tracking),
	dir(speed),
	oldSmoke(pos),
	age(0),
	drawTrail(true),
	numParts(0),
	doturn(true),
	curCallback(0),
	numCallback(0),
	missileAge(0),
	areaOfEffect(areaOfEffect)
{
	this->uptime=uptime;
	ttl=(int)min(3000.f,uptime+weaponDef->range/maxSpeed+100);

	maxGoodDif=cos(tracking*0.6);
	curSpeed=speed.Length();
	dir.Normalize();
	oldSmokeDir=dir;

	drawRadius=maxSpeed*8;
	ENTER_MIXED;
	numCallback=new int;
	*numCallback=0;
	float3 camDir=(pos-camera->pos).Normalize();
	if(camera->pos.distance(pos)*0.2+(1-fabs(camDir.dot(dir)))*3000 < 200)
		drawTrail=false;
	ENTER_SYNCED;

	for(int a=0;a<5;++a){
		oldInfos[a]=new OldInfo;
		oldInfos[a]->dir=dir;
		oldInfos[a]->pos=pos;
		oldInfos[a]->speedf=curSpeed;
	}
	castShadow=true;

#ifdef TRACE_SYNC
	tracefile << "New starburst rocket: ";
	tracefile << pos.x << " " << pos.y << " " << pos.z << " " << speed.x << " " << speed.y << " " << speed.z << "\n";
#endif

}
Пример #13
0
int CAdvTreeDrawer::AddFallingTree(float3 pos, float3 dir, int type)
{
	GML_STDMUTEX_LOCK(tree); // AddFallingTree

	FallingTree ft;

	ft.pos=pos;
	dir.y=0;
	float s=dir.Length();
	if(s>500)
		return 0;
	ft.dir=dir/s;
	ft.speed=std::max(0.01f,s*0.0004f);
	ft.type=type;
	ft.fallPos=0;

	fallingTrees.push_back(ft);
	return 0;
}
Пример #14
0
CLaserProjectile::CLaserProjectile(
    const float3& pos,
    const float3& speed,
    CUnit* owner,
    float length,
    const float3& color,
    const float3& color2,
    float intensity,
    const WeaponDef* weaponDef,
    int ttl):

    CWeaponProjectile(pos, speed, owner, NULL, ZeroVector, weaponDef, NULL, ttl),
    intensity(intensity),
    color(color),
    color2(color2),
    length(length),
    curLength(0.0f),
    intensityFalloff(weaponDef ? (intensity * weaponDef->falloffRate) : 0.0f),
    stayTime(0)
{
    projectileType = WEAPON_LASER_PROJECTILE;

    speedf = speed.Length();
    dir = speed / speedf;

    if (weaponDef) {
        SetRadiusAndHeight(weaponDef->collisionSize, 0.0f);

        midtexx =
            (weaponDef->visuals.texture2->xstart +
             (weaponDef->visuals.texture2->xend - weaponDef->visuals.texture2->xstart) * 0.5f);
    }

    drawRadius = length;

#ifdef TRACE_SYNC
    tracefile << "New laser: ";
    tracefile << pos.x << " " << pos.y << " " << pos.z << " " << speed.x << " " << speed.y << " " << speed.z << "\n";
#endif

    cegID = gCEG->Load(explGenHandler, (weaponDef != NULL)? weaponDef->cegTag: "");
}
Пример #15
0
bool CCamera::InView(const float3 &p, float radius)
{
	const float3 t = (p - pos);
	const float  l = t.Length();

	if (l < 50.0f) {
		return true;
	}
	else if (l > gu->viewRange) {
		return false;
	}
	
	if ((t.dot(rightside) > radius) ||
	    (t.dot(leftside)  > radius) ||
	    (t.dot(bottom)    > radius) ||
	    (t.dot(top)       > radius)) {
		return false;
	}

	return true;
}
CLaserProjectile::CLaserProjectile(const float3& pos,const float3& speed,CUnit* owner,const DamageArray& damages,float length,const float3& color,float intensity, WeaponDef *weaponDef, int ttl)
: CWeaponProjectile(pos,speed,owner,0,ZeroVector,weaponDef,0),
	damages(damages),
	ttl(ttl),
	color(color),
	length(length),
	curLength(0),
	intensity(intensity),
	intensityFalloff(intensity*0.1)
{
	dir=speed;
	dir.Normalize();
	speedf=speed.Length();

	SetRadius(0.5);
	drawRadius=length;
#ifdef TRACE_SYNC
	tracefile << "New laser: ";
	tracefile << pos.x << " " << pos.y << " " << pos.z << " " << speed.x << " " << speed.y << " " << speed.z << "\n";
#endif
}
CLaserProjectile::CLaserProjectile(const float3& pos,const float3& speed,CUnit* owner,const DamageArray& damages,float length,const float3& color, const float3& color2, float intensity, WeaponDef *weaponDef, int ttl)
: CWeaponProjectile(pos,speed,owner,0,ZeroVector,weaponDef,damages,0),
	ttl(ttl),
	color(color),
	color2(color2),
	length(length),
	curLength(0),
	intensity(intensity),
	intensityFalloff(intensity*0.1)
{
	dir=speed;
	dir.Normalize();
	speedf=speed.Length();

	SetRadius(weaponDef->collisionSize);
	drawRadius=length;
	midtexx = weaponDef->visuals.texture2->xstart + (weaponDef->visuals.texture2->xend-weaponDef->visuals.texture2->xstart)*0.5;
#ifdef TRACE_SYNC
	tracefile << "New laser: ";
	tracefile << pos.x << " " << pos.y << " " << pos.z << " " << speed.x << " " << speed.y << " " << speed.z << "\n";
#endif
}
Пример #18
0
/** For reference, see http://realtimecollisiondetection.net/blog/?p=20 . */
Sphere Sphere::FitThroughPoints(const float3 &a, const float3 &b, const float3 &c, const float3 &d)
{
	Sphere sphere;

	float s,t,u;
	const float3 ab = b-a;
	const float3 ac = c-a;
	const float3 ad = d-a;
	bool success = FitSphereThroughPoints(ab, ac, ad, s, t, u);
	if (success)
	{
		const float3 center = s*ab + t*ac + u*ad;
		sphere.r = center.Length();
		sphere.pos = a + center;
	}
	else
	{
		LOGW("Sphere::FitThroughPoints through four points failed! The points lie on the same plane!");
		sphere.SetDegenerate();
	}

	return sphere;
}
CTorpedoProjectile::CTorpedoProjectile(const float3& pos,const float3& speed,CUnit* owner,const DamageArray& damages,float areaOfEffect,float maxSpeed,float tracking, int ttl,CUnit* target, WeaponDef *weaponDef)
: CWeaponProjectile(pos,speed,owner,target,ZeroVector,weaponDef,0),
	damages(damages),
	ttl(ttl),
	maxSpeed(maxSpeed),
	tracking(tracking),
	target(target),
	dir(speed),
	areaOfEffect(areaOfEffect),
	nextBubble(4)
{
	curSpeed=speed.Length();
	dir.Normalize();
	if(target)
		AddDeathDependence(target);

	SetRadius(0.0);
	drawRadius=maxSpeed*8;
	float3 camDir=(pos-camera->pos).Normalize();
#ifdef TRACE_SYNC
	tracefile << "New projectile: ";
	tracefile << pos.x << " " << pos.y << " " << pos.z << " " << speed.x << " " << speed.y << " " << speed.z << "\n";
#endif
}
Пример #20
0
void AAirMoveType::CheckForCollision()
{
	if (!collide)
		return;

	const SyncedFloat3& pos = owner->midPos;
	const SyncedFloat3& forward = owner->frontdir;

	const float3 midTestPos = pos + forward * 121.0f;
	const std::vector<CUnit*>& others = quadField->GetUnitsExact(midTestPos, 115.0f);

	float dist = 200.0f;

	if (lastColWarning) {
		DeleteDeathDependence(lastColWarning, DEPENDENCE_LASTCOLWARN);
		lastColWarning = NULL;
		lastColWarningType = 0;
	}

	for (CUnit* unit: others) {
		if (unit == owner || !unit->unitDef->canfly) {
			continue;
		}

		const SyncedFloat3& op = unit->midPos;
		const float3 dif = op - pos;
		const float3 forwardDif = forward * (forward.dot(dif));

		if (forwardDif.SqLength() >= (dist * dist)) {
			continue;
		}

		const float3 ortoDif = dif - forwardDif;
		const float frontLength = forwardDif.Length();
		// note: radii are multiplied by two
		const float minOrtoDif = (unit->radius + owner->radius) * 2.0f + frontLength * 0.1f + 10;

		if (ortoDif.SqLength() < (minOrtoDif * minOrtoDif)) {
			dist = frontLength;
			lastColWarning = const_cast<CUnit*>(unit);
		}
	}

	if (lastColWarning != NULL) {
		lastColWarningType = 2;
		AddDeathDependence(lastColWarning, DEPENDENCE_LASTCOLWARN);
		return;
	}

	for (CUnit* u: others) {
		if (u == owner)
			continue;
		if ((u->midPos - pos).SqLength() < (dist * dist)) {
			lastColWarning = u;
		}
	}

	if (lastColWarning != NULL) {
		lastColWarningType = 1;
		AddDeathDependence(lastColWarning, DEPENDENCE_LASTCOLWARN);
	}
}
Пример #21
0
// problems: giving reclaim order on moving target causes commander
// to walk (messing up subsequent dgun order if target still moving)
// and does not take commander torso rotation time into account
//
void CDGunController::TrackAttackTarget(unsigned int currentFrame) {
	if (currentFrame - state.targetSelectionFrame == 5) {
		// five sim-frames have passed since selecting target, attack
		const UnitDef* udef = ai->cb->GetUnitDef(state.targetID);

		const float3 curTargetPos = ai->cb->GetUnitPos(state.targetID);              // current target position
		const float3 commanderPos = ai->cb->GetUnitPos(commanderID);                 // current commander position

		const float3 targetDif    = (commanderPos - curTargetPos);
		const float  targetDist   = targetDif.Length();                              // distance to target
		const float3 targetVel    = (curTargetPos - state.oldTargetPos);

		float3 targetMoveDir   = targetVel;
		float  targetMoveSpeed = 0.0f;

		if (targetVel != ZeroVector) {
			targetMoveSpeed = targetVel.Length() / 5.0f;                             // target speed per sim-frame during tracking interval
			targetMoveDir   = targetVel / (targetMoveSpeed * 5.0f);                  // target direction of movement
		}

		const float  dgunDelay    = targetDist / commanderWD->projectilespeed;       // sim-frames needed for dgun to reach target position
		const float3 leadPos      = targetMoveDir * (targetMoveSpeed * dgunDelay);
		const float3 dgunPos      = curTargetPos + leadPos;                          // position where target will be in <dgunDelay> frames
		const float  maxRange     = ai->cb->GetUnitMaxRange(commanderID);

		bool haveClearShot = true;
		int orderType = -1;

		AIHCTraceRay rayData = {
			commanderPos,
			targetDif / targetDist, // direction
			maxRange,
			commanderID,
			-1,
			0
		};

		ai->cb->HandleCommand(AIHCTraceRayId, &rayData);

		if (rayData.hitUID != -1) {
			// note: still fails when allied structure is between us and enemy
			// can also fail if enemy is in front of allied structure and both
			// are within the d-gun's range
			haveClearShot = (ai->cb->GetUnitAllyTeam(rayData.hitUID) != ai->cb->GetMyAllyTeam());

			// TODO: get DGun weapon properties & check if it can pass through
			// a unit, if yes then allow executing the code below
			if(haveClearShot) {
				// check if there is a unit next to hit unit on DGun path...
				const float3 enemyPos = ai->cb->GetUnitPos(rayData.hitUID);
				const float segmentLeft = maxRange - commanderPos.distance(enemyPos);

				if(segmentLeft > 0.0) {
					AIHCTraceRay rayData2 = {
						enemyPos,
						targetDif / targetDist,
						segmentLeft,
						rayData.hitUID,
						-1,
						0
					};

					ai->cb->HandleCommand(AIHCTraceRayId, &rayData2);

					if(rayData2.hitUID != -1) {
						haveClearShot = (ai->cb->GetUnitAllyTeam(rayData2.hitUID) != ai->cb->GetMyAllyTeam());
					}
				}
			}
		}

		// multiply by 0.9 to ensure commander does not have to walk
		if ((commanderPos - dgunPos).Length() < maxRange * 0.9f) {
			bool canDGun =
				(ai->cb->GetEnergy() >= DGUN_MIN_ENERGY_LEVEL)
				&& haveClearShot
				&& (udef != NULL && !udef->weapons.empty());

			if(canDGun) {
				IssueOrder(dgunPos, orderType = CMD_DGUN, 0);
			} else {
				bool bDanger = ai->tm->ThreatAtThisPoint(commanderPos/*curTargetPos*/) > ai->tm->GetAverageThreat();
				if(bDanger) {
					state.Reset(currentFrame, true);
				} else {
					if (ai->cb->GetUnitHealth(state.targetID) < ai->cb->GetUnitMaxHealth(state.targetID) * 0.5f) {
						IssueOrder(state.targetID, orderType = CMD_RECLAIM, 0);
					} else {
						IssueOrder(state.targetID, orderType = CMD_CAPTURE, 0);
					}
				}
			}

			if (orderType == CMD_DGUN   ) { state.dgunOrderFrame    = ai->cb->GetCurrentFrame(); }
			if (orderType == CMD_RECLAIM) { state.reclaimOrderFrame = ai->cb->GetCurrentFrame(); }
			if (orderType == CMD_CAPTURE) { state.captureOrderFrame = ai->cb->GetCurrentFrame(); }
		} else {
			state.Reset(currentFrame, true);
		}
	}

	state.Reset(currentFrame, false);
}
Пример #22
0
// problems: giving reclaim order on moving target causes commander
// to walk (messing up subsequent dgun order if target still moving)
// and does not take commander torso rotation time into account
//
void CDGunController::TrackAttackTarget(unsigned int currentFrame) {
	if (currentFrame - state.targetSelectionFrame == 5) {
		// five sim-frames have passed since selecting target, attack
		const UnitDef* udef = ai->cb->GetUnitDef(state.targetID);

		const float3 curTargetPos = ai->cb->GetUnitPos(state.targetID);              // current target position
		const float3 commanderPos = ai->cb->GetUnitPos(commanderID);                 // current commander position

		const float3 targetDif    = (commanderPos - curTargetPos);
		const float  targetDist   = targetDif.Length();                              // distance to target
		const float3 targetVel    = (curTargetPos - state.oldTargetPos);

		float3 targetMoveDir   = targetVel;
		float  targetMoveSpeed = 0.0f;

		if (targetVel != ZeroVector) {
			targetMoveSpeed = targetVel.Length() / 5.0f;                             // target speed per sim-frame during tracking interval
			targetMoveDir   = targetVel / (targetMoveSpeed * 5.0f);                  // target direction of movement
		}

		const float  dgunDelay    = targetDist / commanderWD->projectilespeed;       // sim-frames needed for dgun to reach target position
		const float3 leadPos      = targetMoveDir * (targetMoveSpeed * dgunDelay);
		const float3 dgunPos      = curTargetPos + leadPos;                          // position where target will be in <dgunDelay> frames
		const float  maxRange     = ai->cb->GetUnitMaxRange(commanderID);

		bool haveClearShot = true;
		int numSegments = 0;


		AIHCTraceRay rayData;
		float  rayLen = maxRange * 1.1f;
		float3 rayPos = commanderPos;
		float3 rayDir = targetDif / targetDist;
			rayDir.y = 0.0f;

		while (haveClearShot && (rayLen >= 1.0f)) {
			rayData.rayPos = rayPos;
			rayData.rayDir = targetDif / targetDist;
			rayData.rayLen = rayLen;
			rayData.srcUID = commanderID;
			rayData.hitUID = -1;
			rayData.flags  = 0;

			// modifies hitUID and rayLen
			ai->ccb->HandleCommand(AIHCTraceRayId, &rayData);

			// note: even if hitUnitID is -1, we can still end up destroying
			// our own units because dgun projectiles keep hugging the ground
			// rather than being absorbed by it on impact (which is assumed by
			// the trace)
			if (rayData.hitUID != -1) {
				if (ai->cb->GetUnitAllyTeam(rayData.hitUID) == ai->cb->GetMyAllyTeam()) {
					// hitUID is an allied unit
					haveClearShot = false;
				} else {
					// hitUID is an enemy unit
					rayPos = ai->ccb->GetUnitPos(rayData.hitUID);
				}
			}

			// make sure we always terminate
			rayLen -= rayData.rayLen;
		}


		// multiply by 0.9 to ensure commander does not have to walk
		if ((commanderPos - dgunPos).Length() < maxRange * 0.9f) {
			bool canDGun =
				(ai->cb->GetEnergy() >= DGUN_MIN_ENERGY_LEVEL)
				&& haveClearShot
				&& (udef != NULL && !udef->weapons.empty());

			if (canDGun) {
				IssueOrder(dgunPos, CMD_DGUN, 0);
			} else {
				bool bDanger = ai->tm->ThreatAtThisPoint(commanderPos/*curTargetPos*/) > ai->tm->GetAverageThreat();

				if (bDanger) {
					state.Reset(currentFrame, true);
				} else {
					if (ai->cb->GetUnitHealth(state.targetID) < ai->cb->GetUnitMaxHealth(state.targetID) * 0.5f) {
						IssueOrder(state.targetID, CMD_RECLAIM, 0);
					} else {
						IssueOrder(state.targetID, CMD_CAPTURE, 0);
					}
				}
			}
		} else {
			state.Reset(currentFrame, true);
		}
	}

	state.Reset(currentFrame, false);
}
Пример #23
0
CStarburstProjectile::CStarburstProjectile(
	const float3& pos, const float3& speed,
	CUnit* owner,
	float3 targetPos,
	float areaOfEffect, float maxSpeed,
	float tracking, int uptime,
	CUnit* target,
	const WeaponDef* weaponDef,
	CWeaponProjectile* interceptTarget,
	float maxdistance, float3 aimError):

	CWeaponProjectile(pos, speed, owner, target, targetPos, weaponDef, interceptTarget, 200),
	tracking(tracking),
	maxSpeed(maxSpeed),
	areaOfEffect(areaOfEffect),
	age(0),
	oldSmoke(pos),
	aimError(aimError),
	drawTrail(true),
	numParts(0),
	doturn(true),
	curCallback(0),
	numCallback(0),
	missileAge(0),
	distanceToTravel(maxdistance)
{
	projectileType = WEAPON_STARBURST_PROJECTILE;
	this->uptime = uptime;

	if (weaponDef) {
		if (weaponDef->flighttime == 0) {
			ttl = (int) std::min(3000.0f, uptime + weaponDef->range / maxSpeed + 100);
		} else {
			ttl = weaponDef->flighttime;
		}
	}
	maxGoodDif = cos(tracking * 0.6f);
	curSpeed = speed.Length();
	dir = speed / curSpeed;
	oldSmokeDir = dir;

	drawRadius = maxSpeed * 8;
	numCallback = new int;
	*numCallback = 0;

	float3 camDir=(pos-camera->pos).Normalize();
	if(camera->pos.distance(pos)*0.2f+(1-fabs(camDir.dot(dir)))*3000 < 200)
		drawTrail=false;

	for(int a = 0; a < 5; ++a) {
		oldInfos[a]=new OldInfo;
		oldInfos[a]->dir=dir;
		oldInfos[a]->pos=pos;
		oldInfos[a]->speedf=curSpeed;
		for(float aa = 0; aa < curSpeed + 0.6f; aa += 0.15f) {
			float ageMod = 1.0f;
			oldInfos[a]->ageMods.push_back(ageMod);
		}
	}
	castShadow = true;

#ifdef TRACE_SYNC
	tracefile << "New starburst rocket: ";
	tracefile << pos.x << " " << pos.y << " " << pos.z << " " << speed.x << " " << speed.y << " " << speed.z << "\n";
#endif

	if (!cegTag.empty()) {
		ceg.Load(explGenHandler, cegTag);
	}
}
Пример #24
0
CMissileProjectile::CMissileProjectile(
		const float3& pos, const float3& speed,
		CUnit* owner,
		float areaOfEffect, float maxSpeed, int ttl,
		CUnit* target, const WeaponDef* weaponDef,
		float3 targetPos)
	: CWeaponProjectile(pos, speed, owner, target, targetPos, weaponDef, NULL, ttl)
	, maxSpeed(maxSpeed)
	, areaOfEffect(areaOfEffect)
	, age(0)
	, oldSmoke(pos)
	, target(target)
	, decoyTarget(NULL)
	, drawTrail(true)
	, numParts(0)
	, targPos(targetPos)
	, isWobbling(weaponDef? (weaponDef->wobble > 0): false)
	, wobbleDir(ZeroVector)
	, wobbleTime(1)
	, wobbleDif(ZeroVector)
	, isDancing(weaponDef? (weaponDef->dance > 0): false)
	, danceTime(1)
	, danceMove(ZeroVector)
	, danceCenter(ZeroVector)
	, extraHeightTime(0)
{
	projectileType = WEAPON_MISSILE_PROJECTILE;
	curSpeed = speed.Length();
	dir = speed / curSpeed;
	oldDir = dir;

	if (target) {
		AddDeathDependence(target);
	}

	SetRadius(0.0f);

	if (weaponDef) {
		model = LoadModel(weaponDef);
		if (model) {
			SetRadius(model->radius);
		}
	}

	drawRadius = radius + maxSpeed * 8;

	float3 camDir = (pos - camera->pos).Normalize();
	if ((camera->pos.distance(pos) * 0.2f + (1 - fabs(camDir.dot(dir))) * 3000) < 200) {
		drawTrail = false;
	}

	castShadow = true;

#ifdef TRACE_SYNC
	tracefile << "New missile: ";
	tracefile << pos.x << " " << pos.y << " " << pos.z << " " << speed.x << " " << speed.y << " " << speed.z << "\n";
#endif

	if (target) {
		target->IncomingMissile(this);
	}

	if ((weaponDef) && (weaponDef->trajectoryHeight > 0)) {
		float dist = pos.distance(targPos);
		extraHeight = (dist * weaponDef->trajectoryHeight);

		if (dist < maxSpeed) {
			dist = maxSpeed;
		}

		extraHeightTime = (int)(dist / maxSpeed);
		extraHeightDecay = extraHeight / extraHeightTime;
	}


	cegID = gCEG->Load(explGenHandler, cegTag);
}
Пример #25
0
float3 float3::Reflect(const float3 &normal) const
{
	assume2(normal.IsNormalized(), normal.SerializeToCodeString(), normal.Length());
	return 2.f * this->ProjectToNorm(normal) - *this;
}
Пример #26
0
bool float3::IsPerpendicular(const float3 &other, float epsilon) const
{
	return fabs(Dot(other)) <= epsilon * Length() * other.Length();
}
Пример #27
0
void CFreeController::Update()
{
    if (!globalRendering->active) {
        vel  = ZeroVector;
        avel = ZeroVector;
        prevVel  = vel;
        prevAvel = avel;
        return;
    }

    // safeties
    velTime  = max(0.1f,  velTime);
    avelTime = max(0.1f, avelTime);

    // save some old state
    const float ctrlVelY = vel.y;
    const float3 prevPos = pos;

    // setup the time fractions
    const float ft = globalRendering->lastFrameTime;
    const float nt = (ft / velTime); // next time factor
    const float pt = (1.0f - nt);    // prev time factor
    const float ant = (ft / avelTime); // next time factor
    const float apt = (1.0f - ant);    // prev time factor

    // adjustment to match the ground slope
    float autoTiltVel = 0.0f;
    if (gndLock && (autoTilt > 0.0f)) {
        const float gndHeight = ground->GetHeightReal(pos.x, pos.z, false);
        if (pos.y < (gndHeight + gndOffset + 1.0f)) {
            float3 hDir;
            hDir.y = 0.0f;
            hDir.x = (float)math::sin(camera->rot.y);
            hDir.z = (float)math::cos(camera->rot.y);
            const float3 gndNormal = ground->GetSmoothNormal(pos.x, pos.z, false);
            const float dot = gndNormal.dot(hDir);
            const float gndRotX = (float)math::acos(dot) - (PI * 0.5f);
            const float rotXdiff = (gndRotX - camera->rot.x);
            autoTiltVel = (autoTilt * rotXdiff);
        }
    }

    // convert control velocity into position velocity
    if (!tracking) {
        if (goForward) {
            const float3 tmpVel((camera->forward * vel.x) +
                                (UpVector        * vel.y) +
                                (camera->right   * vel.z));
            vel = tmpVel;
        }
        else {
            float3 forwardNoY(camera->forward.x, 0.0f, camera->forward.z);
            forwardNoY.ANormalize();
            const float3 tmpVel((forwardNoY    * vel.x) +
                                (UpVector      * vel.y) +
                                (camera->right * vel.z));
            vel = tmpVel;
        }
    }

    // smooth the velocities
    vel  =  (vel * nt)  +  (prevVel * pt);
    avel = (avel * ant) + (prevAvel * apt);

    // no smoothing for gravity (still isn't right)
    if (gndLock) {
        const float dGrav = (gravity * ft);
        vel.y += dGrav;
        if (slide > 0.0f) {
            const float gndHeight = ground->GetHeightReal(pos.x, pos.z, false);
            if (pos.y < (gndHeight + gndOffset + 1.0f)) {
                const float3 gndNormal = ground->GetSmoothNormal(pos.x, pos.z, false);
                const float dotVal = gndNormal.y;
                const float scale = (dotVal * slide * -dGrav);
                vel.x += (gndNormal.x * scale);
                vel.z += (gndNormal.z * scale);
            }
        }
    }

    // set the new position/rotation
    if (!tracking) {
        pos           += (vel         * ft);
        camera->rot   += (avel        * ft);
        camera->rot.x += (autoTiltVel * ft); // note that this is not smoothed
    }
    else {
        // speed along the tracking direction varies with distance
        const float3 diff = (pos - trackPos);
        if (goForward) {
            const float dist = max(0.1f, diff.Length());
            const float nomDist = 512.0f;
            float speedScale = (dist / nomDist);
            speedScale = max(0.25f, min(16.0f, speedScale));
            const float delta = -vel.x * (ft * speedScale);
            const float newDist = max(trackRadius, (dist + delta));
            const float scale = (newDist / dist);
            pos = trackPos + (diff * scale);
            pos.y += (vel.y * ft);
        }
        else {
            const float dist = max(0.1f, diff.Length2D());
            const float nomDist = 512.0f;
            float speedScale = (dist / nomDist);
            speedScale = max(0.25f, min(16.0f, speedScale));
            const float delta = -vel.x * (ft * speedScale);
            const float newDist = max(trackRadius, (dist + delta));
            const float scale = (newDist / dist);
            pos.x = trackPos.x + (scale * diff.x);
            pos.z = trackPos.z + (scale * diff.z);
            pos.y += (vel.y * ft);
        }

        // convert the angular velocity into its positional change
        const float3 diff2 = (pos - trackPos);
        const float deltaRad = (avel.y * ft);
        const float cos_val = math::cos(deltaRad);
        const float sin_val = math::sin(deltaRad);
        pos.x = trackPos.x + ((cos_val * diff2.x) + (sin_val * diff2.z));
        pos.z = trackPos.z + ((cos_val * diff2.z) - (sin_val * diff2.x));
    }

    // setup ground lock
    const float gndHeight = ground->GetHeightReal(pos.x, pos.z, false);

    if (keyInput->IsKeyPressed(SDLK_LSHIFT)) {
        if (ctrlVelY > 0.0f) {
            gndLock = false;
        } else if ((gndOffset > 0.0f) && (ctrlVelY < 0.0f) &&
                   (pos.y < (gndHeight + gndOffset))) {
            gndLock = true;
        }
    }

    // positional clamps
    if (gndOffset < 0.0f) {
        pos.y = (gndHeight - gndOffset);
        vel.y = 0.0f;
    }
    else if (gndLock && (gravity >= 0.0f)) {
        pos.y = (gndHeight + gndOffset);
        vel.y = 0.0f;
    }
    else if (gndOffset > 0.0f) {
        const float minHeight = (gndHeight + gndOffset);
        if (pos.y < minHeight) {
            pos.y = minHeight;
            if (gndLock) {
                vel.y = min(math::fabs(scrollSpeed), ((minHeight - prevPos.y) / ft));
            } else {
                vel.y = 0.0f;
            }
        }
    }

    // angular clamps
    const float xRotLimit = (PI * 0.4999f);
    if (camera->rot.x > xRotLimit) {
        camera->rot.x = xRotLimit;
        avel.x = 0.0f;
    }
    else if (camera->rot.x < -xRotLimit) {
        camera->rot.x = -xRotLimit;
        avel.x = 0.0f;
    }
    camera->rot.y = math::fmod(camera->rot.y, PI * 2.0f);

    // setup for the next loop
    prevVel  = vel;
    prevAvel = avel;
    vel  = ZeroVector;
    avel = ZeroVector;

    tracking = false;
}
Пример #28
0
float4 float4::Reflect3(const float3 &normal) const
{
	assume2(normal.IsNormalized(), normal.SerializeToCodeString(), normal.Length());
	assume(EqualAbs(w, 0));
	return 2.f * this->ProjectToNorm3(normal) - *this;
}