void CCannon::FireImpl(const bool scriptCall) { float3 diff = currentTargetPos - weaponMuzzlePos; float3 dir = (diff.SqLength() > 4.0f) ? GetWantedDir(diff) : diff; // prevent vertical aim when emit-sfx firing the weapon dir += (gsRNG.NextVector() * SprayAngleExperience() + SalvoErrorExperience()); dir.SafeNormalize(); int ttl = 0; const float sqSpeed2D = dir.SqLength2D() * projectileSpeed * projectileSpeed; const int predict = math::ceil((sqSpeed2D == 0.0f) ? (-2.0f * projectileSpeed * dir.y / gravity): math::sqrt(diff.SqLength2D() / sqSpeed2D)); if (weaponDef->flighttime > 0) { ttl = weaponDef->flighttime; } else if (weaponDef->selfExplode) { ttl = (predict + gsRNG.NextFloat() * 2.5f - 0.5f); } else if ((weaponDef->groundBounce || weaponDef->waterBounce) && weaponDef->numBounce > 0) { ttl = (predict * (1 + weaponDef->numBounce * weaponDef->bounceRebound)); } else { ttl = predict * 2; } ProjectileParams params = GetProjectileParams(); params.pos = weaponMuzzlePos; params.end = currentTargetPos; params.speed = dir * projectileSpeed; params.ttl = ttl; params.gravity = gravity; WeaponProjectileFactory::LoadProjectile(params); }
void CCannon::FireImpl() { float3 diff = targetPos - weaponMuzzlePos; float3 dir = (diff.SqLength() > 4.0) ? GetWantedDir(diff) : diff; // prevent vertical aim when emit-sfx firing the weapon dir += (gs->randVector() * sprayAngle + salvoError) * (1.0f - owner->limExperience * weaponDef->ownerExpAccWeight); dir.SafeNormalize(); int ttl = 0; float sqSpeed2D = dir.SqLength2D() * projectileSpeed * projectileSpeed; int predict = (int)math::ceil((sqSpeed2D == 0) ? (-2 * projectileSpeed * dir.y / gravity) : math::sqrt(diff.SqLength2D() / sqSpeed2D)); if(weaponDef->flighttime > 0) { ttl = weaponDef->flighttime; } else if(selfExplode) { ttl = (int)(predict + gs->randFloat() * 2.5f - 0.5f); } else if((weaponDef->groundBounce || weaponDef->waterBounce) && weaponDef->numBounce > 0) { ttl = (int)(predict * (1 + weaponDef->numBounce * weaponDef->bounceRebound)); } else { ttl=predict*2; } ProjectileParams params = GetProjectileParams(); params.pos = weaponMuzzlePos; params.speed = dir * projectileSpeed; params.ttl = ttl; new CExplosiveProjectile(params, damageAreaOfEffect, gravity); }
void CCannon::FireImpl(void) { float3 diff = targetPos-weaponMuzzlePos; float3 dir=(diff.SqLength() > 4.0) ? GetWantedDir(diff) : diff; //prevent vertical aim when emit-sfx firing the weapon dir+=(gs->randVector()*sprayAngle+salvoError)*(1-owner->limExperience*0.9f); dir.Normalize(); int ttl = 0; float sqSpeed2D = dir.SqLength2D() * projectileSpeed * projectileSpeed; int predict = (int)ceil((sqSpeed2D == 0) ? (-2 * projectileSpeed * dir.y / gravity) : sqrt(diff.SqLength2D() / sqSpeed2D)); if(weaponDef->flighttime > 0) { ttl = weaponDef->flighttime; } else if(selfExplode) { ttl = (int)(predict + gs->randFloat() * 2.5f - 0.5f); } else if((weaponDef->groundBounce || weaponDef->waterBounce) && weaponDef->numBounce > 0) { ttl = (int)(predict * (1 + weaponDef->numBounce * weaponDef->bounceRebound)); } else { ttl=predict*2; } new CExplosiveProjectile(weaponMuzzlePos, dir * projectileSpeed, owner, weaponDef, ttl, areaOfEffect, gravity); }
void CCannon::Fire(void) { float3 diff = targetPos-weaponMuzzlePos; float3 dir=(diff.Length() > 2.0) ? GetWantedDir(diff) : diff; //prevent vertical aim when emit-sfx firing the weapon dir+=(gs->randVector()*sprayAngle+salvoError)*(1-owner->limExperience*0.9f); dir.Normalize(); #ifdef TRACE_SYNC tracefile << "Cannon fire: "; tracefile << owner->pos.x << " " << dir.x << " " << targetPos.x << " " << targetPos.y << " " << targetPos.z << "\n"; #endif int ttl = 0; float sqSpeed2D = dir.SqLength2D() * projectileSpeed * projectileSpeed; int predict = (int)ceil((sqSpeed2D == 0) ? (-2 * projectileSpeed * dir.y / gravity) : sqrt(diff.SqLength2D() / sqSpeed2D)); if(weaponDef->flighttime > 0) { ttl = weaponDef->flighttime; } else if(selfExplode) { ttl = (int)(predict + gs->randFloat() * 2.5f - 0.5f); } else if((weaponDef->groundBounce || weaponDef->waterBounce) && weaponDef->numBounce > 0) { ttl = (int)(predict * (1 + weaponDef->numBounce * weaponDef->bounceRebound)); } else { ttl=predict*2; } SAFE_NEW CExplosiveProjectile(weaponMuzzlePos, dir * projectileSpeed, owner, weaponDef, ttl, areaOfEffect, gravity); if(fireSoundId && (!weaponDef->soundTrigger || salvoLeft==salvoSize-1)) sound->PlaySample(fireSoundId,owner,fireSoundVolume); // if(weaponMuzzlePos.y < 30) // water->AddExplosion(weaponMuzzlePos, weaponDef->damages[0] * 0.1f, sqrt(weaponDef->damages[0]) + 80); }
bool CCannon::TryTarget(const float3 &pos, bool userTarget, CUnit* unit) { if (!CWeapon::TryTarget(pos, userTarget, unit)) { return false; } if (!weaponDef->waterweapon) { if (unit) { if (unit->isUnderWater) { return false; } } else { if (pos.y < 0) { return false; } } } if (projectileSpeed == 0) { return true; } float3 dif(pos - weaponMuzzlePos); float3 dir(GetWantedDir(dif)); if (dir.SqLength() == 0) { return false; } float3 flatdir(dif.x, 0, dif.z); float flatlength = flatdir.Length(); if (flatlength == 0) { return true; } flatdir /= flatlength; float gc = ground->TrajectoryGroundCol(weaponMuzzlePos, flatdir, flatlength - 10, dir.y , gravity / (projectileSpeed * projectileSpeed) * 0.5f); if (gc > 0) { return false; } const float quadratic = gravity / (projectileSpeed * projectileSpeed) * 0.5f; const float spread = ((accuracy + sprayAngle) * 0.6f) * ((1.0f - owner->limExperience * weaponDef->ownerExpAccWeight) * 0.9f); if (avoidFriendly && helper->TestTrajectoryCone(weaponMuzzlePos, flatdir, flatlength - 30, dir.y, quadratic, spread, 3, owner, CGameHelper::TEST_ALLIED)) { return false; } if (avoidNeutral && helper->TestTrajectoryCone(weaponMuzzlePos, flatdir, flatlength - 30, dir.y, quadratic, spread, 3, owner, CGameHelper::TEST_NEUTRAL)) { return false; } return true; }
void CCannon::Update() { if(targetType!=Target_None){ weaponPos=owner->pos + owner->frontdir*relWeaponPos.z + owner->updir*relWeaponPos.y + owner->rightdir*relWeaponPos.x; weaponMuzzlePos=owner->pos + owner->frontdir*relWeaponMuzzlePos.z + owner->updir*relWeaponMuzzlePos.y + owner->rightdir*relWeaponMuzzlePos.x; float3 diff = targetPos-weaponPos; wantedDir = GetWantedDir(diff); float speed2D = wantedDir.Length2D() * projectileSpeed; predict = ((speed2D == 0) ? 1 : (diff.Length2D()/speed2D)); } else { predict=0; } CWeapon::Update(); }
void CCannon::Update() { if (targetType != Target_None) { weaponPos = owner->GetObjectSpacePos(relWeaponPos); weaponMuzzlePos = owner->GetObjectSpacePos(relWeaponMuzzlePos); const float3 targetVec = targetPos - weaponPos; const float speed2D = (wantedDir = GetWantedDir(targetVec)).Length2D() * projectileSpeed; predict = ((speed2D == 0.0f) ? 1.0f : (targetVec.Length2D() / speed2D)); } else { predict = 0.0f; } CWeapon::Update(); }
void CCannon::Fire(void) { float3 diff = targetPos-weaponMuzzlePos; float3 dir=GetWantedDir(diff); dir+=(gs->randVector()*sprayangle+salvoError)*(1-owner->limExperience*0.9f); dir.Normalize(); #ifdef TRACE_SYNC tracefile << "Cannon fire: "; tracefile << owner->pos.x << " " << dir.x << " " << targetPos.x << " " << targetPos.y << " " << targetPos.z << "\n"; #endif int ttl = 0; float sqSpeed2D = dir.SqLength2D() * projectileSpeed * projectileSpeed; int predict = (int)ceil((sqSpeed2D == 0) ? (-2 * projectileSpeed * dir.y / gravity) : sqrt(diff.SqLength2D() / sqSpeed2D)); if(weaponDef->flighttime > 0) { ttl = weaponDef->flighttime; } else if(selfExplode) { ttl = (int)(predict + gs->randFloat() * 2.5f - 0.5f); } else if((weaponDef->groundBounce || weaponDef->waterBounce) && weaponDef->numBounce > 0) { ttl = (int)(predict * (1 + weaponDef->numBounce * weaponDef->bounceRebound)); } else { ttl=predict*2; } SAFE_NEW CExplosiveProjectile(weaponMuzzlePos, dir * projectileSpeed, owner, weaponDef, ttl, areaOfEffect, gravity); //CWeaponProjectile::CreateWeaponProjectile(weaponPos,owner->speed,owner, NULL, float3(0,0,0), weaponDef); // SAFE_NEW CSmokeProjectile(weaponPos,dir*0.01f,90,0.1f,0.02f,owner,0.6f); // CHeatCloudProjectile* p=SAFE_NEW CHeatCloudProjectile(weaponPos,dir*0.02f,8,0.6f,owner); // p->Update(); // p->maxheat=p->heat; if(fireSoundId && (!weaponDef->soundTrigger || salvoLeft==salvoSize-1)) sound->PlaySample(fireSoundId,owner,fireSoundVolume); // if(weaponMuzzlePos.y < 30) // water->AddExplosion(weaponMuzzlePos, weaponDef->damages[0] * 0.1f, sqrt(weaponDef->damages[0]) + 80); }
void CCannon::UpdateWantedDir() { const float3 targetVec = currentTargetPos - aimFromPos; wantedDir = GetWantedDir(targetVec); }
bool CCannon::TryTarget(const float3 &pos, bool userTarget, CUnit* unit) { if (!CWeapon::TryTarget(pos, userTarget, unit)) { return false; } if (!weaponDef->waterweapon) { if (unit) { if (unit->isUnderWater) { return false; } } else { if (pos.y < 0) { return false; } } } if (projectileSpeed == 0) { return true; } float3 dif(pos - weaponMuzzlePos); float3 dir(GetWantedDir(dif)); if (dir.SqLength() == 0) { return false; } float3 flatdir(dif.x, 0, dif.z); float flatlength = flatdir.Length(); if (flatlength == 0) { return true; } flatdir /= flatlength; const float linear = dir.y; const float quadratic = gravity / (projectileSpeed * projectileSpeed) * 0.5f; const float gc = ((collisionFlags & Collision::NOGROUND) == 0)? ground->TrajectoryGroundCol(weaponMuzzlePos, flatdir, flatlength - 10, linear, quadratic): -1.0f; if (gc > 0.0f) { return false; } const float spread = ((accuracy + sprayAngle) * 0.6f) * ((1.0f - owner->limExperience * weaponDef->ownerExpAccWeight) * 0.9f); if (avoidFriendly && TraceRay::TestTrajectoryAllyCone(weaponMuzzlePos, flatdir, flatlength - 30, dir.y, quadratic, spread, 3, owner->allyteam, owner)) { return false; } if (avoidNeutral && TraceRay::TestTrajectoryNeutralCone(weaponMuzzlePos, flatdir, flatlength - 30, dir.y, quadratic, spread, 3, owner)) { return false; } return true; }
bool CCannon::TryTarget(const float3 &pos,bool userTarget,CUnit* unit) { if(!CWeapon::TryTarget(pos,userTarget,unit)) { return false; } if(!weaponDef->waterweapon) { if(unit) { if(unit->isUnderWater) { return false; } } else { if(pos.y<0) { return false; } } } if (projectileSpeed == 0) { return true; } float3 dif(pos-weaponMuzzlePos); float3 dir(GetWantedDir(dif)); if(dir.SqLength() == 0){ return false; } float3 flatdir(dif.x,0,dif.z); float flatlength=flatdir.Length(); if(flatlength==0) { return true; } flatdir/=flatlength; float gc=ground->TrajectoryGroundCol(weaponMuzzlePos, flatdir, flatlength-10, dir.y , gravity / (projectileSpeed * projectileSpeed) * 0.5f); if(gc>0) { return false; } /* gc=ground->LineGroundCol(wpos+dir*(length*0.5f),pos,false); if(gc>0 && gc<length*0.40f) return false; */ if(avoidFriendly && helper->TestTrajectoryCone(weaponMuzzlePos, flatdir, flatlength-30, dir.y, gravity / (projectileSpeed * projectileSpeed) * 0.5f, (accuracy+sprayangle) * 0.6f * (1-owner->limExperience * 0.9f) * 0.9f, 3, owner->allyteam, owner)) { return false; } /* if(helper->TestCone(weaponPos,dir,length*0.5f,(accuracy+sprayangle)*1.2f*(1-owner->limExperience*0.9f)*0.9f,owner->allyteam,owner)){ return false; } float3 dir2(dif); dir2.y+=predictTime*predictTime*gs->gravity; //compensate for the earlier up prediction dir2.Normalize(); if(helper->TestCone(weaponPos+dir*(length*0.5f),dir2,length*0.5f,(accuracy+sprayangle)*!userTarget*(1-owner->limExperience*0.9f)*0.6f,owner->allyteam,owner)){ return false; }*/ return true; }