void float3::Orthonormalize(float3 &a, float3 &b) { assume(!a.IsZero()); assume(!b.IsZero()); a.Normalize(); b -= b.ProjectToNorm(a); b.Normalize(); }
Dirlight::Dirlight(float3 dir,float3 color,bool enabled) { this->dir = dir.Normalize(); this->color = color; this->enabled = enabled; up = float3(0.0f,1.0f,0.0f); lookat = float3(0.0f,0.0f,0.0f); castshadows = false; // slow, so off by default scene->lights->AddDirlight(this); // add to global dump }
void CBeamLaser::FireInternal(float3 dir, bool sweepFire) { float rangeMod=1.0f; CBuilding* building = dynamic_cast<CBuilding*>(owner); if (!building) { rangeMod=1.3f; //help units fire while chasing } #ifdef DIRECT_CONTROL_ALLOWED if(owner->directControl) rangeMod=0.95f; #endif float maxLength=range*rangeMod; float curLength=0; float3 curPos=weaponMuzzlePos; float3 hitPos; dir += gs->randVector() * sprayAngle * (1 - owner->limExperience * 0.7f); dir.Normalize(); 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, 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; float shieldLength=interceptHandler.AddShieldInterceptableBeam(this,curPos,dir,length,newDir,shieldHit); if(shieldLength<length){ length=shieldLength; bool repulsed=shieldHit->BeamIntercepted(this, damageMul); 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, weaponDef->visuals.beamttl, weaponDef->visuals.beamdecay); 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 = std::max(minIntensity, 1-(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, false, false, weaponDef->explosionGenerator, hit, dir, weaponDef->id); } if(targetUnit) lastFireFrame = gs->frameNum; }