bool SoulDestroyer::SearchForRandomPosition() { Vector3 toSpawnPoint = ( m_pos - m_spawnPoint ); toSpawnPoint.y = 0.0; double distToSpawnPoint = toSpawnPoint.Mag(); double chanceOfReturn = ( distToSpawnPoint / m_roamRange ); if( chanceOfReturn >= 1.0 || syncfrand(1.0) <= chanceOfReturn ) { // We have strayed too far from our spawn point // So head back there now Vector3 targetPos = m_spawnPoint; targetPos.y = g_app->m_location->m_landscape.m_heightMap->GetValue( targetPos.x, targetPos.z ); targetPos.y += 100.0 + syncsfrand( 100.0 ); Vector3 returnVector = ( targetPos - m_pos ); returnVector.SetLength( 160.0 ); m_targetPos = m_pos + returnVector; } else { double distance = 160.0; double angle = syncsfrand(2.0 * M_PI); m_targetPos = m_pos + Vector3( iv_sin(angle) * distance, 0.0, iv_cos(angle) * distance ); m_targetPos.y = g_app->m_location->m_landscape.m_heightMap->GetValue( m_targetPos.x, m_targetPos.z ); m_targetPos.y += (100.0 + syncsfrand( 100.0 )); } return true; }
/** * @brief * Initializes a particle */ void PGLeaf::InitParticle(Particle &cParticle) const { // Initialize all particles to a random but valued state cParticle.vPos.x = (Math::GetRandNegFloat()*Radius) + GetTransform().GetPosition().x; cParticle.vPos.z = (Math::GetRandNegFloat()*Radius) + GetTransform().GetPosition().z; cParticle.vPos.y = (Math::GetRandFloat()*Height) + GetTransform().GetPosition().y; Vector3 vN(Math::GetRandNegFloat(), Math::GetRandNegFloat(), Math::GetRandNegFloat()); vN.SetLength(1.0f); if (!cParticle.pRot) cParticle.pRot = new Quaternion(); EulerAngles::ToQuaternion(static_cast<float>(vN.x*Math::RadToDeg), static_cast<float>(vN.y*Math::RadToDeg), static_cast<float>(vN.z*Math::RadToDeg), *cParticle.pRot); cParticle.bDistorted = true; cParticle.fCustom1 = cParticle.fSize = LeafSize + LeafSizeVariation*Math::GetRandNegFloat(); cParticle.vVelocity.x = Math::GetRandNegFloat(); cParticle.vVelocity.y = Math::GetRandNegFloat(); cParticle.vVelocity.z = Math::GetRandNegFloat(); cParticle.nCustom1 = ((static_cast<int>(Math::GetRandNegFloat()*255.0f*2.0f))<<8)|0xff; Vector3 vD = Vector3::UnitY.CrossProduct(vN); vD.SetLength(cParticle.fSize); cParticle.vDistortion.x = vD.x; cParticle.vDistortion.y = vD.y; cParticle.vDistortion.z = vD.z; cParticle.vFixPos.x = cParticle.vColor[0] = 0.8f; cParticle.vFixPos.y = cParticle.vColor[1] = 0.5f+Math::GetRandFloat()*0.5f; cParticle.vFixPos.z = cParticle.vColor[2] = 0.5f+Math::GetRandFloat()*0.5f; cParticle.vColor[3] = 1.0f; }
bool SmokeMarker::Advance() { for( int i = 0; i < 3; ++i ) { Vector3 vel = g_upVector; vel.x += sfrand(0.4f); vel.z += sfrand(0.4f); vel.SetLength( 50.0f ); float size = 200.0f + frand(100.0f); g_app->m_particleSystem->CreateParticle( m_pos, vel, Particle::TypeMissileTrail, size ); } return false; }
void AntHill::Damage ( float _damage ) { Building::Damage( _damage ); if( m_health > 0 ) { int healthBandBefore = int(m_health / 20.0f); m_health += _damage; int healthBandAfter = int(m_health / 20.0f); if( healthBandAfter != healthBandBefore ) { Matrix34 mat( m_front, g_upVector, m_pos ); g_explosionManager.AddExplosion( m_shape, mat, 1.0f - (float)m_health/100.0f ); g_app->m_soundSystem->TriggerBuildingEvent( this, "Damage" ); } if( m_health <= 0 ) { Matrix34 mat( m_front, g_upVector, m_pos ); g_explosionManager.AddExplosion( m_shape, mat ); int numSpirits = m_numAntsInside + m_numSpiritsInside; for( int i = 0; i < numSpirits; ++i ) { Vector3 pos = m_pos; float radius = syncfrand(20.0f); float theta = syncfrand(M_PI * 2); pos.x += radius * sinf(theta); pos.z += radius * cosf(theta); Vector3 vel = ( pos - m_pos ); vel.SetLength( syncfrand(50.0f) ); g_app->m_location->SpawnSpirit( pos, vel, m_id.GetTeamId(), WorldObjectId() ); } g_app->m_soundSystem->TriggerBuildingEvent( this, "Explode" ); m_health = 0; } } }
void Tripod::AdvanceAttack() { START_PROFILE(g_app->m_profiler, "AdvanceAttack"); // Consider mode switch float timeInAttack = g_gameTime - m_modeStartTime; if (timeInAttack > ATTACK_DURATION) { m_mode = ModePostAttack; m_modeStartTime = g_gameTime; END_PROFILE(g_app->m_profiler, "AdvanceAttack"); return; } // m_up = CalcAttackUpVector(); Vector3 right = m_up ^ g_upVector; // m_front = m_up ^ right; // m_front.Normalise(); if (timeInAttack > 1.0f) { int t2 = (int)(timeInAttack * 10.0f); if (t2 & 1) { Vector3 toEnemy = m_attackTarget - m_pos; toEnemy.Normalise(); float const speed = 80.0f; right.SetLength(4.0f); Vector3 pos = m_pos + right; toEnemy.x += syncsfrand(0.1f); toEnemy.z += syncsfrand(0.1f); g_app->m_location->FireLaser(pos + toEnemy * 5.0f, toEnemy * speed, m_id.GetTeamId()); pos = m_pos - right; g_app->m_location->FireLaser(pos + toEnemy * 5.0f, toEnemy * speed, m_id.GetTeamId()); } } END_PROFILE(g_app->m_profiler, "AdvanceAttack"); }
bool SoulDestroyer::AdvanceToTargetPosition() { double amountToTurn = SERVER_ADVANCE_PERIOD * 2.0; Vector3 targetDir = (m_targetPos - m_pos).Normalise(); if( !m_targetEntity.IsValid() ) { Vector3 right1 = m_front ^ m_up; targetDir.RotateAround( right1 * iv_sin(GetNetworkTime() * 6.0) * 1.5 ); } // Look ahead to see if we're about to hit the ground Vector3 forwardPos = m_pos + targetDir * 50.0; double landHeight = g_app->m_location->m_landscape.m_heightMap->GetValue(forwardPos.x, forwardPos.z); if( forwardPos.y <= landHeight ) { targetDir = g_upVector; } Vector3 actualDir = m_front * (1.0 - amountToTurn) + targetDir * amountToTurn; actualDir.Normalise(); double speed = m_stats[StatSpeed]; speed = 130.0; Vector3 oldPos = m_pos; Vector3 newPos = m_pos + actualDir * speed * SERVER_ADVANCE_PERIOD; landHeight = g_app->m_location->m_landscape.m_heightMap->GetValue( newPos.x, newPos.z ); //newPos.y = max( newPos.y, landHeight ); Vector3 moved = newPos - oldPos; if( moved.Mag() > speed * SERVER_ADVANCE_PERIOD ) moved.SetLength( speed * SERVER_ADVANCE_PERIOD ); newPos = m_pos + moved; m_pos = newPos; m_vel = ( m_pos - oldPos ) / SERVER_ADVANCE_PERIOD; m_front = actualDir; Vector3 right = m_front ^ g_upVector; m_up = right ^ m_front; return ( m_pos - m_targetPos ).Mag() < 40.0; }
void LaserFence::Spark() { Vector3 sparkPos = m_pos; sparkPos.y += frand( m_scale*50.0f ); LaserFence *nextFence = (LaserFence *) g_app->m_location->GetBuilding( m_nextLaserFenceId ); int numSparks = 5.0f + frand(5.0f); for( int i = 0; i < numSparks; ++i ) { Vector3 particleVel; if( nextFence ) particleVel = ( m_pos - nextFence->m_pos ) ^ g_upVector; else particleVel = Vector3( sfrand(10.0f), sfrand(5.0f), sfrand(10.0f) ); particleVel.SetLength( 40.0f+frand(20.0f) ); particleVel += Vector3( frand() * 20.0f, sfrand() * 20.0f, sfrand() * 20.0f ); float size = 25.0f + frand(25.0f); g_app->m_particleSystem->CreateParticle( sparkPos, particleVel, Particle::TypeSpark, size ); } g_app->m_soundSystem->TriggerBuildingEvent( this, "Spark" ); }
/** * @brief * Called when the scene node needs to be updated */ void PGLeaf::OnUpdate() { // If this scene node wasn't drawn at the last frame, we can skip some update stuff if ((GetFlags() & ForceUpdate) || m_bUpdate) { m_bUpdate = false; // If there are free particles, create new particles Particle *pParticle = AddParticle(); while (pParticle) { InitParticle(*pParticle); // Next particle, please pParticle = AddParticle(); } { // Update particles float fTimeDiff = Timing::GetInstance()->GetTimeDifference(); Iterator<Particle> cIterator = GetParticleIterator(); while (cIterator.HasNext()) { Particle &cParticle = cIterator.Next(); // Update forces // One: gravity cParticle.vVelocity[1] -= fTimeDiff*(cParticle.vPos[1]-FloorHeight)/5; // Two wind (dot wind vector normal) Vector3 vRot; EulerAngles::FromQuaternion(*cParticle.pRot, vRot.x, vRot.y, vRot.z); vRot.x *= static_cast<float>(Math::RadToDeg); vRot.y *= static_cast<float>(Math::RadToDeg); vRot.z *= static_cast<float>(Math::RadToDeg); cParticle.vVelocity += Wind.Get()*fTimeDiff*Math::Abs(vRot.DotProduct(Wind.Get())); // Four collision (just check whether leaf would end up on wrong side) if (cParticle.vPos.y + cParticle.vVelocity.y*fTimeDiff < FloorHeight) { // Random bouncy and some friction cParticle.vVelocity.y *= -1.0; cParticle.vVelocity.z *= Math::GetRandNegFloat(); cParticle.vVelocity.x *= Math::GetRandNegFloat(); cParticle.nCustom1 = ((static_cast<int>(Math::GetRandNegFloat()*255.0f*8.0f))<<8) | (cParticle.nCustom1&0xff); } // Five check whether particle has left area and can die... if it is outside, let it die float fDistx = GetTransform().GetPosition().x - cParticle.vPos.x; float fDisty = GetTransform().GetPosition().z - cParticle.vPos.z; float fDistToCenter = fDistx*fDistx + fDisty*fDisty; uint32 nStart = cParticle.nCustom1 & 0xff; if (nStart < 0xff) { // It is being spawned nStart += static_cast<uint32>(fTimeDiff*512.0f + 0.5f); if (nStart > 0xff) nStart = 0xff; // Clamp cParticle.nCustom1 = (cParticle.nCustom1&0xffffff00)|nStart; // Write to lower 8 bits } if (fDistToCenter > Radius*Radius) { // Start dying... set alpha according to how far it is away fDistToCenter = 255 - (Math::Sqrt(fDistToCenter) - Radius)*3.0f; cParticle.fSize = static_cast<float>(static_cast<int>(fDistToCenter*(cParticle.nCustom1 & 0xff))>>8)/255*cParticle.fCustom1; if (cParticle.fSize < 0.2f) InitParticle(cParticle); } else { cParticle.fSize = static_cast<float>(cParticle.nCustom1 &0xff)/255*cParticle.fCustom1; } // Update position cParticle.vPos += cParticle.vVelocity*fTimeDiff*cParticle.fSize/2; // Update spin Vector3 vAxis = cParticle.vVelocity; vAxis.SetLength(1); // Transform normal and distortion vAxis *= ((static_cast<float>(cParticle.nCustom1>>8))/255.0f)*fTimeDiff/10; Quaternion qRotInc; EulerAngles::ToQuaternion(static_cast<float>(vAxis.x*Math::DegToRad), static_cast<float>(vAxis.y*Math::DegToRad), static_cast<float>(vAxis.z*Math::DegToRad), qRotInc); *cParticle.pRot *= qRotInc; Vector3 d = cParticle.vDistortion; d.SetLength(cParticle.fSize); cParticle.vDistortion = (*cParticle.pRot)*d; // Update color EulerAngles::FromQuaternion(*cParticle.pRot, vRot.x, vRot.y, vRot.z); vRot.x *= static_cast<float>(Math::RadToDeg); vRot.y *= static_cast<float>(Math::RadToDeg); vRot.z *= static_cast<float>(Math::RadToDeg); vAxis = vRot.Normalize(); fDistx = vAxis.x+vAxis.y*2+vAxis.z*3; if (fDistx > 1.0f) fDistx = 1.0f; if (fDistx < 0.5f) fDistx = 0.5f; cParticle.vColor[0] = cParticle.vFixPos.x*fDistx; cParticle.vColor[1] = cParticle.vFixPos.y*fDistx; cParticle.vColor[2] = cParticle.vFixPos.z*fDistx; }
void PowerBuilding::RenderAlphas ( float _predictionTime ) { Building::RenderAlphas( _predictionTime ); Building *powerLink = g_app->m_location->GetBuilding( m_powerLink ); if( powerLink ) { // // Render the power line itself PowerBuilding *powerBuilding = (PowerBuilding *) powerLink; Vector3 ourPos = GetPowerLocation(); Vector3 theirPos = powerBuilding->GetPowerLocation(); Vector3 camToOurPos = g_app->m_camera->GetPos() - ourPos; Vector3 ourPosRight = camToOurPos ^ ( theirPos - ourPos ); ourPosRight.SetLength( 2.0f ); Vector3 camToTheirPos = g_app->m_camera->GetPos() - theirPos; Vector3 theirPosRight = camToTheirPos ^ ( theirPos - ourPos ); theirPosRight.SetLength( 2.0f ); glDisable ( GL_CULL_FACE ); glEnable ( GL_BLEND ); glBlendFunc ( GL_SRC_ALPHA, GL_ONE ); glDepthMask ( false ); glColor4f ( 0.9f, 0.9f, 0.5f, 1.0f ); glEnable ( GL_TEXTURE_2D ); glBindTexture ( GL_TEXTURE_2D, g_app->m_resource->GetTexture( "textures/laser.bmp" ) ); glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); glBegin( GL_QUADS ); glTexCoord2f(0.1f, 0); glVertex3fv( (ourPos - ourPosRight).GetData() ); glTexCoord2f(0.1f, 1); glVertex3fv( (ourPos + ourPosRight).GetData() ); glTexCoord2f(0.9f, 1); glVertex3fv( (theirPos + theirPosRight).GetData() ); glTexCoord2f(0.9f, 0); glVertex3fv( (theirPos - theirPosRight).GetData() ); glEnd(); // // Render any surges glEnable ( GL_TEXTURE_2D ); glBindTexture ( GL_TEXTURE_2D, g_app->m_resource->GetTexture( "textures/starburst.bmp" ) ); float surgeSize = 25.0f; glColor4f( 0.5f, 0.5f, 1.0f, 1.0f ); Vector3 camUp = g_app->m_camera->GetUp() * surgeSize; Vector3 camRight = g_app->m_camera->GetRight() * surgeSize; glBegin( GL_QUADS ); for( int i = 0; i < m_surges.Size(); ++i ) { float thisSurge = m_surges[i]; thisSurge += _predictionTime * 2; if( thisSurge < 0.0f ) thisSurge = 0.0f; if( thisSurge > 1.0f ) thisSurge = 1.0f; Vector3 thisSurgePos = ourPos + (theirPos-ourPos) * thisSurge; glTexCoord2i( 0, 0 ); glVertex3fv( (thisSurgePos - camUp - camRight).GetData() ); glTexCoord2i( 1, 0 ); glVertex3fv( (thisSurgePos - camUp + camRight).GetData() ); glTexCoord2i( 1, 1 ); glVertex3fv( (thisSurgePos + camUp + camRight).GetData() ); glTexCoord2i( 0, 1 ); glVertex3fv( (thisSurgePos + camUp - camRight).GetData() ); } glEnd(); glDisable ( GL_TEXTURE_2D ); glDepthMask ( true ); glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glDisable ( GL_BLEND ); glEnable ( GL_CULL_FACE ); } }
bool DustBall::Advance() { double speed = DUSTBALL_SPEED; if( s_vortexPos != g_zeroVector ) { /*double speed = DUSTBALL_SPEED / 5.0; speed /= (m_pos.y / 1000.0); speed = max( speed, 100.0 ); speed = min( speed, 500.0 ); Vector3 thisVortexPos = s_vortexPos; thisVortexPos.y = m_pos.y; Vector3 oldPos = m_pos; double amountToTurn = SERVER_ADVANCE_PERIOD * (1.0 / (m_pos.y / 1000.0)); Vector3 targetDir = (thisVortexPos - m_pos).Normalise(); Vector3 actualDir = m_vel.Normalise() * (1.0 - amountToTurn) + targetDir * amountToTurn; actualDir.Normalise(); Vector3 newPos = m_pos + actualDir * speed * SERVER_ADVANCE_PERIOD; Vector3 moved = newPos - oldPos; if( moved.Mag() > speed * SERVER_ADVANCE_PERIOD ) moved.SetLength( speed * SERVER_ADVANCE_PERIOD ); newPos = m_pos + moved;*/ Vector3 vortexPos = s_vortexPos; double timeIndex = GetNetworkTime() + m_id.GetUniqueId() * 20; double radius = (300.0 * (m_pos.y / 1000.0) ); Vector3 targetPos = vortexPos; targetPos.x += iv_cos( timeIndex ) * radius; targetPos.z += iv_sin( timeIndex ) * radius; targetPos.y = m_pos.y; Vector3 oldPos = m_pos; Vector3 actualDir = (targetPos - m_pos).Normalise(); Vector3 newPos = m_pos + (actualDir * speed * SERVER_ADVANCE_PERIOD); Vector3 moved = newPos - oldPos; if( moved.Mag() > speed * SERVER_ADVANCE_PERIOD ) moved.SetLength( speed * SERVER_ADVANCE_PERIOD ); m_pos = newPos; m_vel = ( m_pos - oldPos ) / SERVER_ADVANCE_PERIOD; } else { Vector3 oldPos = m_pos; Vector3 target = m_pos + g_app->m_location->m_windDirection * 2000.0; double amountToTurn = SERVER_ADVANCE_PERIOD * 3.0; Vector3 targetDir = (target - m_pos).Normalise(); Vector3 actualDir = m_vel.Normalise() * (1.0 - amountToTurn) + targetDir * amountToTurn; actualDir.Normalise(); Vector3 newPos = m_pos + actualDir * speed * SERVER_ADVANCE_PERIOD; Vector3 moved = newPos - oldPos; if( moved.Mag() > speed * SERVER_ADVANCE_PERIOD ) moved.SetLength( speed * SERVER_ADVANCE_PERIOD ); newPos = m_pos + moved; m_pos = newPos; m_vel = ( m_pos - oldPos ) / SERVER_ADVANCE_PERIOD; } if( m_pos.x > g_app->m_location->m_landscape.GetWorldSizeX() || m_pos.z > g_app->m_location->m_landscape.GetWorldSizeZ() || m_pos.x < 0.0 || m_pos.z < 0.0 ) { return true; } return false; }
void SoulDestroyer::Attack( Vector3 const &_pos ) { int numFound; g_app->m_location->m_entityGrid->GetEnemies( s_neighbours, _pos.x, _pos.z, SOULDESTROYER_DAMAGERANGE, &numFound, m_id.GetTeamId() ); for( int i = 0; i < numFound; ++i ) { WorldObjectId id = s_neighbours[i]; Entity *entity = (Entity *) g_app->m_location->GetEntity( id ); bool killed = false; Vector3 pushVector = ( entity->m_pos - _pos ); double distance = pushVector.Mag(); if( distance < SOULDESTROYER_DAMAGERANGE ) { g_app->m_soundSystem->TriggerEntityEvent( this, "Attack" ); pushVector.SetLength( SOULDESTROYER_DAMAGERANGE - distance ); g_app->m_location->m_entityGrid->RemoveObject( id, entity->m_pos.x, entity->m_pos.z, entity->m_radius ); entity->m_pos += pushVector; g_app->m_location->m_entityGrid->AddObject( id, entity->m_pos.x, entity->m_pos.z, entity->m_radius ); bool dead = entity->m_dead; entity->ChangeHealth( (SOULDESTROYER_DAMAGERANGE - distance) * -50.0 ); if( !dead && entity->m_dead ) killed = true; } if( killed ) { // Eat the spirit int spiritIndex = g_app->m_location->GetSpirit( id ); if( spiritIndex != -1 ) { g_app->m_location->m_spirits.RemoveData( spiritIndex ); if( m_spirits.NumUsed() < SOULDESTROYER_MAXSPIRITS ) { m_spirits.PutData( (double) GetHighResTime() ); } else { // Doesnt need to be sync safe int index = AppRandom() % SOULDESTROYER_MAXSPIRITS; m_spirits.PutData( (double) GetHighResTime(), index ); } } if(entity->m_type == TypeDarwinian ) { // Create a zombie Zombie *zombie = new Zombie(); zombie->m_pos = entity->m_pos; zombie->m_front = entity->m_front; zombie->m_up = g_upVector; zombie->m_up.RotateAround( zombie->m_front * syncsfrand(1) ); zombie->m_vel = m_vel * 0.5; zombie->m_vel.y = 20.0 + syncfrand(25.0); int index = g_app->m_location->m_effects.PutData( zombie ); zombie->m_id.Set( id.GetTeamId(), UNIT_EFFECTS, index, -1 ); zombie->m_id.GenerateUniqueId(); } } } }
Vector3 Entity::PushFromObstructions( Vector3 const &pos, bool killem ) { Vector3 result = pos; if( m_onGround ) { result.y = g_app->m_location->m_landscape.m_heightMap->GetValue( result.x, result.z ); } Matrix34 transform( m_front, g_upVector, result ); // // Push from Water if( result.y <= 1.0 ) { double pushAngle = syncsfrand(1.0); double distance = 0.0; while( distance < 50.0 ) { double angle = distance * pushAngle * M_PI; Vector3 offset( iv_cos(angle) * distance, 0.0, iv_sin(angle) * distance ); Vector3 newPos = result + offset; double height = g_app->m_location->m_landscape.m_heightMap->GetValue( newPos.x, newPos.z ); if( height > 1.0 ) { result = newPos; result.y = height; break; } distance += 1.0; } } // // Push from buildings LList<int> *buildings = g_app->m_location->m_obstructionGrid->GetBuildings( result.x, result.z ); for( int b = 0; b < buildings->Size(); ++b ) { int buildingId = buildings->GetData(b); Building *building = g_app->m_location->GetBuilding( buildingId ); if( building ) { bool hit = false; if( m_shape && building->DoesShapeHit( m_shape, transform ) ) hit = true; if( (!m_shape || m_type == TypeOfficer ) && building->DoesSphereHit( result, 1.0 ) ) hit = true; // cheap hack, but no point overriding the entire function for this one line if( !hit ) { Vector3 oldPos = m_pos - m_vel * SERVER_ADVANCE_PERIOD; if( building->DoesRayHit( oldPos, m_front, (m_pos - oldPos).Mag() ) ) hit = true; } if( hit ) { if( building->m_type == Building::TypeLaserFence && killem && ((LaserFence *) building)->IsEnabled()) { if( !g_app->m_location->IsFriend(building->m_id.GetTeamId(), m_id.GetTeamId() ) ) { ChangeHealth( -9999 ); ((LaserFence *) building)->Electrocute( m_pos ); } } else { Vector3 pushForce = (building->m_pos - result); pushForce.y = 0.0f; pushForce.SetLength(4.0f); while( building->DoesSphereHit( result, 2.0f ) ) { result -= pushForce; //result.y = g_app->m_location->m_landscape.m_heightMap->GetValue( result.x, result.z ); } } } } } return result; }
void Nuke::RenderHistory( double _predictionTime ) { if( m_history.Size() > 0 && m_id.GetTeamId() != 255 ) { glBindTexture( GL_TEXTURE_2D, g_app->m_resource->GetTexture( "textures/laser.bmp" ) ); Vector3 predictedPos = m_pos + m_vel * SERVER_ADVANCE_PERIOD; Vector3 lastPos = predictedPos; RGBAColour colour = g_app->m_location->m_teams[m_id.GetTeamId()]->m_colour; if( m_id.GetTeamId() == g_app->m_location->GetMonsterTeamId() ) { glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR ); colour.Set( 255, 255, 255, 0 ); } for( int i = 0; i < m_history.Size(); ++i ) { Vector3 historyPos, thisPos; thisPos = historyPos = *m_history[i]; Vector3 diff = thisPos - lastPos; lastPos += diff * 0.1f; if( m_id.GetTeamId() != g_app->m_location->GetMonsterTeamId() ) { colour.a = 255 - 255 * (float) i / (float) m_history.Size(); } glColor4ubv( colour.GetData() ); Vector3 lengthVector = (thisPos - lastPos).Normalise(); lengthVector.SetLength((thisPos - lastPos).Mag()); Vector3 fromPos = lastPos; Vector3 toPos = thisPos;//lastPos - lengthVector; Vector3 midPoint = fromPos + (toPos - fromPos)/2.0f; Vector3 camToMidPoint = g_app->m_camera->GetPos() - midPoint; float camDistSqd = camToMidPoint.MagSquared(); Vector3 rightAngle = (camToMidPoint ^ ( midPoint - toPos )).Normalise(); //rightAngle *= 0.8f; rightAngle.SetLength(5.0f); glBegin( GL_QUADS ); glTexCoord2i(0,0); glVertex3dv( (fromPos - rightAngle).GetData() ); glTexCoord2i(0,1); glVertex3dv( (fromPos + rightAngle).GetData() ); glTexCoord2i(1,1); glVertex3dv( (toPos + rightAngle).GetData() ); glTexCoord2i(1,0); glVertex3dv( (toPos - rightAngle).GetData() ); glTexCoord2i(0,0); glVertex3dv( (fromPos - rightAngle).GetData() ); glTexCoord2i(0,1); glVertex3dv( (fromPos + rightAngle).GetData() ); glTexCoord2i(1,1); glVertex3dv( (toPos + rightAngle).GetData() ); glTexCoord2i(1,0); glVertex3dv( (toPos - rightAngle).GetData() ); glTexCoord2i(0,0); glVertex3dv( (fromPos - rightAngle).GetData() ); glTexCoord2i(0,1); glVertex3dv( (fromPos + rightAngle).GetData() ); glTexCoord2i(1,1); glVertex3dv( (toPos + rightAngle).GetData() ); glTexCoord2i(1,0); glVertex3dv( (toPos - rightAngle).GetData() ); glEnd(); lastPos = historyPos; } } }
void Nuke::Render( double _predictionTime ) { if( m_renderMarker ) { RenderGroundMarker(); } RenderSub( _predictionTime ); if( m_exploded ) { //RenderDeaths(); } else { if( !m_launched ) return; Vector3 front = m_front; front.RotateAroundY( M_PI / 2.0f ); Vector3 predictedPos = m_pos + m_vel * _predictionTime;; Vector3 entityUp = m_front; Vector3 entityRight (front ^ entityUp); Vector3 lengthVector = m_vel; lengthVector.SetLength( 10.0f ); Vector3 fromPos = predictedPos; Vector3 toPos = predictedPos - lengthVector; Vector3 midPoint = fromPos + (toPos - fromPos)/2.0f; Vector3 camToMidPoint = g_app->m_camera->GetPos() - midPoint; float camDistSqd = camToMidPoint.MagSquared(); Vector3 rightAngle = (camToMidPoint ^ ( midPoint - toPos )).Normalise(); entityRight = rightAngle; float size = 10.0f; size *= (1.0f + 0.03f * (( m_id.GetIndex() * m_id.GetUniqueId() ) % 10)); entityRight *= size; entityUp *= size * 2.0f; glDepthMask ( false ); glEnable ( GL_BLEND ); glBlendFunc ( GL_SRC_ALPHA, GL_ONE ); glEnable ( GL_TEXTURE_2D ); glBindTexture( GL_TEXTURE_2D, g_app->m_resource->GetTexture( "sprites/nuke.bmp" ) ); RGBAColour colour = g_app->m_location->m_teams[m_id.GetTeamId()]->m_colour; if( m_id.GetTeamId() == g_app->m_location->GetMonsterTeamId() ) { glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR ); colour.Set( 255, 255, 255, 0 ); } glColor4ubv(colour.GetData()); glBegin(GL_QUADS); glTexCoord2i(0, 1); glVertex3dv( (predictedPos - entityRight + entityUp).GetData() ); glTexCoord2i(1, 1); glVertex3dv( (predictedPos + entityRight + entityUp).GetData() ); glTexCoord2i(1, 0); glVertex3dv( (predictedPos + entityRight).GetData() ); glTexCoord2i(0, 0); glVertex3dv( (predictedPos - entityRight).GetData() ); glEnd(); RenderHistory( _predictionTime ); glShadeModel ( GL_FLAT ); glDisable ( GL_TEXTURE_2D ); glDepthMask ( true ); } }