void Triangle::computeForces(Vector3 &airVelocity) { this->airVelocity = airVelocity; Vector3 velocity = (p1->velocity + p2->velocity + p3->velocity) / 3; Vector3 realVelocity = velocity - airVelocity; if (realVelocity.Mag() > 0) { Vector3 *one = new Vector3(); Vector3 *two = new Vector3(); one->Cross(p2->position - p1->position, p3->position - p1->position); two->Cross(p2->position - p1->position, p3->position - p1->position); one->Normalize(); normal = *one; float a0 = 0.5 * two->Mag(); float a = a0 * (realVelocity.Dot(normal) / realVelocity.Mag()); Vector3 fAero = -0.5 * density * realVelocity.Mag2() *a *normal; Vector3 fAeroParticle = fAero / 3; if (!p1->pinned) p1->applyForce(fAeroParticle); if (!p2->pinned) p2->applyForce(fAeroParticle); if (!p3->pinned) p3->applyForce(fAeroParticle); delete one; delete two; } }
Vector3 Entity::PushFromCliffs( Vector3 const &pos, Vector3 const &oldPos ) { Vector3 horiz = ( pos - oldPos ); horiz.y = 0.0; double horizDistance = horiz.Mag(); double gradient = (pos.y - oldPos.y) / horizDistance; Vector3 result = pos; if( gradient > 1.0 ) { double distance = 0.0; while( distance < 50.0 ) { double angle = distance * 2.0 * M_PI; Vector3 offset( iv_cos(angle) * distance, 0.0, iv_sin(angle) * distance ); Vector3 newPos = result + offset; newPos.y = g_app->m_location->m_landscape.m_heightMap->GetValue( newPos.x, newPos.z ); horiz = ( newPos - oldPos ); horiz.y = 0.0; horizDistance = horiz.Mag(); double newGradient = ( newPos.y - oldPos.y ) / horizDistance; if( newGradient < 1.0 ) { result = newPos; break; } distance += 0.2; } } return result; }
void pTriangle::ComputeForce(Vector3 vair) { //find the tirangle velocity velocity = (p1->getVelocity() + p2->getVelocity() + p3->getVelocity()) / 3 ; //assume no air velocity for now Vector3 v = velocity - vair; Vector3 r1 = p1->getPosition(); Vector3 r2 = p2->getPosition(); Vector3 r3 = p3->getPosition(); //find triangle unnormalized normal, n* Vector3 ra = (r2 - r1); Vector3 rb = (r3 - r1); Vector3 ncross; ncross.Cross(ra, rb); //constants float p = 1.225f; float cd = 1.225f; //force = -1/2 * p * |v|^2 * cd * a * n Vector3 v2an = ( (v.Mag()*v.Dot(ncross))/(2.0f*ncross.Mag()) ) * ncross; Vector3 aeroForce = (-1.0f/2.0f) * p * cd * v2an; aeroForce = aeroForce / 3; p1->ApplyForce(aeroForce); p2->ApplyForce(aeroForce); p3->ApplyForce(aeroForce); normal = ncross.Normalize(); }
Quaternion RotationBetweenVectors3(Vector3 v1, Vector3 v2) { const float epsilon = 0.0000001; double length1 = v1.Mag(); double length2 = v2.Mag(); double cosangle = (v1 * v2) / (length1 * length2); if (fabs(cosangle-1.0) < epsilon) { // near co-linear vectors return Quaternion(0.0, 0.0, 0.0, 1.0); } else if (fabs(cosangle+1.0) < epsilon) { // vectors are opposite, so we need to find an orthogonal vector to v1 // around which to rotate Vector3 tmp; if (fabs(v1.x)<fabs(v1.y)) if (fabs(v1.x)<fabs(v1.z)) tmp = Vector3(1.0,0.0,0.0); // use x axis. else tmp = Vector3(0.0,0.0,1.0); else if (fabs(v1.y)<fabs(v1.z)) tmp = Vector3(0.0,1.0,0.0); else tmp = Vector3(0.0,0.0,1.0); // find orthogonal axis. Vector3 axis = v2^tmp; axis.Normalize(); // cos of half angle of PI is zero. return QuatFromAxis(axis, 0.0); } else { // this is the usual case: take a cross-product of v1 and v2 // and that is the axis around which to rotate Vector3 axis = v1^v2; double angle = acos( cosangle ); return QuatFromAxis(axis, angle); } }
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; }
void ParticleSystem::computePressure(){ float h2 = h*h; for(int i = 0; i < NumParticles; i++){ std::vector<Particle *> neighbors = GetNeighbors(Particles[i]); Vector3 pi = Particles[i]->getPosition(); Vector3 vi = Particles[i]->getVelocity(); float pressure_i = Particles[i]->getPressure(); Vector3 sumPressure = Vector3(0, 0, 0); Vector3 sumViscosity = Vector3(0, 0, 0); for(int j = 0; j < neighbors.size(); j++){ Vector3 pj = neighbors[j]->getPosition(); Vector3 vj = neighbors[j]->getVelocity(); float pressure_j = neighbors[j]->getPressure(); float density_j = neighbors[j]->getDensity(); Vector3 diff = pi - pj; float rad = diff.Mag(); float rad2 = rad * rad; if(h2 > rad2 && EPSILON <= rad2){ float sqr = h - rad; sumPressure += diff/rad * ((pressure_i+pressure_j)/(2*density_j)) * sqr * sqr; sumViscosity += (vj - vi)/density_j * sqr; } } Particles[i]->addForce(sumPressure * (float(particle_mass) * mSpikyKernel * -1.0f)); Particles[i]->addForce(sumViscosity * float(fluid_viscosity*particle_mass)*mViscosityKernel); } }
void Entity::FollowRoute() { AppDebugAssert(m_routeId != -1); Route *route = g_app->m_location->m_levelFile->GetRoute(m_routeId); if( g_app->Multiplayer() ) route = g_app->m_location->m_routingSystem.GetRoute( m_routeId ); if(!route) { m_routeId = -1; return; } if (m_routeWayPointId == -1) { m_routeWayPointId = 0; } WayPoint *waypoint = route->m_wayPoints.GetData(m_routeWayPointId); if( !waypoint ) { m_routeId = -1; return; } SetWaypoint ( waypoint->GetPos() ); Vector3 targetVect = waypoint->GetPos() - m_pos; m_spawnPoint = waypoint->GetPos(); if (waypoint->m_type != WayPoint::TypeBuilding && targetVect.Mag() < m_routeTriggerDistance ) { m_routeWayPointId++; if (m_routeWayPointId >= route->m_wayPoints.Size()) { m_routeWayPointId = -1; m_routeId = -1; } } // // If its a building instead of a 3D pos, this unit will never // get to the next waypoint. A new unit is created when the unit // enters the teleport, and taht new unit will automatically // continue towards the next waypoint instead. // }
bool pTriangle::TestSegment(const Segment &s, Intersection &i) { Vector3 v0 = p1->getPosition(); Vector3 v1 = p2->getPosition(); Vector3 v2 = p3->getPosition(); float da = (s.A - v0).Dot(normal); float db = (s.B - v0).Dot(normal); //on same side of triangle if (da > 0 && db > 0) return false; //inside, place on surface if (da < 0 && db < 0) return false; //avoid divide by 0 if ((da - db) == 0) return false; Vector3 x = ((da*s.B)-(db*s.B)) / (da - db); //convert to barycentric coordinates Vector3 xPrime = x - v0; Vector3 e1 = v1 - v0; Vector3 e2 = v2 - v0; float denom = e1.Dot(e2); //avoid divide by 0 if (denom == 0) return false; float alpha = (xPrime.Dot(e2)) / denom; float beta = (xPrime.Dot(e1)) / denom; if (alpha < 0 || beta < 0 || (alpha+beta) > 1) return false; Vector3 temp = s.B - v0; float d = temp.Dot(normal); if (d < 0) { //point is behind the triangle face d = -d; x = x * (1- d/x.Mag()); } i.Position = x; i.Normal = normal; return true; }
void Entity::AdvanceInWater( Unit *_unit ) { m_inWater += SERVER_ADVANCE_PERIOD; if( m_inWater > 10.0 /* && m_type != TypeInsertionSquadie */ ) { ChangeHealth( -500 ); } Vector3 targetPos; if( _unit ) { targetPos = _unit->GetWayPoint(); targetPos.y = 0.0; Vector3 offset = _unit->GetFormationOffset(Unit::FormationRectangle, m_id.GetIndex() ); targetPos += offset; } if( targetPos != g_zeroVector ) { Vector3 distance = targetPos - m_pos; distance.y = 0.0; m_vel = distance; m_vel.Normalise(); m_front = m_vel; m_vel *= m_stats[StatSpeed] * 0.3; if (distance.Mag() < m_vel.Mag() * SERVER_ADVANCE_PERIOD) { m_vel = distance / SERVER_ADVANCE_PERIOD; } } m_vel.SetLength( 5.0 ); m_pos += m_vel * SERVER_ADVANCE_PERIOD; m_pos.y = 0.0 - iv_sin(m_inWater * 3.0) - 4.0; double groundLevel = g_app->m_location->m_landscape.m_heightMap->GetValue(m_pos.x, m_pos.z); if( groundLevel > 0.0 ) { m_inWater = -1; } }
void SoundLibrary3dSoftware::CalcChannelVolumes(int _channelIndex, float *_left, float *_right) { SoftwareChannel *channel = &m_channels[_channelIndex]; float calculatedVolume = -(5.0f - channel->m_volume * 0.5f); calculatedVolume += m_masterVolume * 0.001f; if( calculatedVolume < -10.0f ) calculatedVolume = -10.0f; if( calculatedVolume > 0.0f ) calculatedVolume = 0.0f; calculatedVolume = expf(calculatedVolume); if (channel->m_3DMode == SoundLibrary3d::Mode3dPositioned) { Vector3 to = channel->m_pos - m_listenerPos; float dist = to.Mag(); // DEF: Fixes ambrosia bug # 1371 // if distance equals zero we don't divide b/c we're right on top of the sound. if(dist != 0) to /= dist; // END DEF float dotRight = to * m_listenerRight; *_right = (dotRight + 1.0f) * 0.5f; *_left = 1.0f - *_right; if (dist > channel->m_minDist) { float dropOff = channel->m_minDist / dist; *_left *= dropOff; *_right *= dropOff; } } else { *_left = 1.0f; *_right = 1.0f; } *_left *= calculatedVolume; *_right *= calculatedVolume; }
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 DrawGrid(Vector3 const &_camPos) { float camPosMag = _camPos.Mag(); int scale = log(camPosMag); float multiplier = exp(scale) * 0.1f; glScalef(multiplier, multiplier, multiplier); glColor3ub(99,99,99); glLineWidth(1.0f); glBegin(GL_LINES); for (int x = -10; x < 10; x++) { for (int y = -10; y < 10; y++) { glVertex3f(x, 0, y); glVertex3f(x+1, 0, y); } } for (int x = -10; x < 10; x++) { for (int y = -10; y < 10; y++) { glVertex3f(x, 0, y); glVertex3f(x, 0, y + 1); } } glEnd(); glColor3ub(255,255,255); glLineWidth(2.0f); glBegin(GL_LINES); glVertex3f(-10, 0, 0); glVertex3f(10, 0, 0); glVertex3f(0, 0, -10); glVertex3f(0, 0, 10); glEnd(); glScalef(1/multiplier, 1/multiplier, 1/multiplier); }
bool OfficerOrders::Advance() { if( m_arrivedTimer >= 0.0f ) { // We are already here, so just fade out m_vel.Zero(); m_arrivedTimer += SERVER_ADVANCE_PERIOD; if( m_arrivedTimer > 1.0f ) return true; } else { float speed = m_vel.Mag(); speed *= 1.1f; speed = max( speed, 30.0f ); speed = min( speed, 150.0f ); Vector3 toWaypoint = ( m_wayPoint - m_pos ); toWaypoint.y = 0.0f; float distance = toWaypoint.Mag(); toWaypoint.Normalise(); m_vel = toWaypoint * speed; Vector3 oldPos = m_pos; m_pos += m_vel * SERVER_ADVANCE_PERIOD; float landHeight = g_app->m_location->m_landscape.m_heightMap->GetValue( m_pos.x, m_pos.z ); m_pos.y = landHeight + 2.0f; m_vel = ( m_pos - oldPos ) / SERVER_ADVANCE_PERIOD; g_app->m_particleSystem->CreateParticle( oldPos, g_zeroVector, Particle::TypeMuzzleFlash, 30.0f ); if( m_vel.Mag() * SERVER_ADVANCE_PERIOD > distance ) m_arrivedTimer = 0.0f; if( distance < 3.0f ) m_arrivedTimer = 0.0f; } return false; }
Vector3 cartesianToSpherical(Vector3 v) { // http://en.wikipedia.org/wiki/Spherical_coordinate_system // but modified, since ground ref is the XY plane double azim, elev, dist; dist = v.Mag(); azim = atan2(v.y,v.x) - M_PI/2; // put in range of [-pi,pi] if (azim > M_PI) azim -= 2 * M_PI; else if (azim < -M_PI) azim += 2 * M_PI; if (dist > 0.000001) elev = M_PI/2 - acos(v.z/dist); else elev = 0.0; return Vector3(azim, elev, dist); }
Vector3 Entity::PushFromEachOther( Vector3 const &_pos ) { Vector3 result = _pos; int numFound; g_app->m_location->m_entityGrid->GetNeighbours( s_neighbours, _pos.x, _pos.z, 2.0, &numFound ); for( int i = 0; i < numFound; ++i ) { WorldObjectId id = s_neighbours[i]; if( !( id == m_id ) ) { WorldObject *obj = g_app->m_location->GetEntity( id ); // double distance = (obj->m_pos - thisPos).Mag(); // while( distance < 1.0 ) // { // Vector3 pushForce = (obj->m_pos - thisPos).Normalise() * 0.1; // if( obj->m_pos == thisPos ) pushForce = Vector3(0.0,0.0,1.0); // thisPos -= pushForce; // distance = (obj->m_pos - thisPos).Mag(); // } Vector3 diff = ( _pos - obj->m_pos ); double force = 0.1 / diff.Mag(); diff.Normalise(); Vector3 thisDiff = ( diff * force ); result += thisDiff; } } result.y = g_app->m_location->m_landscape.m_heightMap->GetValue( result.x, result.z ); return result; }
void LocationEditor::Render() { // // Render our buildings g_app->m_renderer->SetObjectLighting(); LevelFile *levelFile = g_app->m_location->m_levelFile; for( int i = 0; i < levelFile->m_buildings.Size(); ++i ) { if( levelFile->m_buildings.ValidIndex(i) ) { Building *b = levelFile->m_buildings.GetData(i); b->Render(0.0); } } g_app->m_renderer->UnsetObjectLighting(); if (m_mode == ModeBuilding) { for( int i = 0; i < levelFile->m_buildings.Size(); ++i ) { if( levelFile->m_buildings.ValidIndex(i) ) { Building *b = levelFile->m_buildings.GetData(i); b->RenderAlphas(0.0); b->RenderLink(); } } } // // Render camera mounts { g_app->m_renderer->SetObjectLighting(); Shape *camShape = g_app->m_resource->GetShape("camera.shp"); Matrix34 mat; for (int i = 0; i < g_app->m_location->m_levelFile->m_cameraMounts.Size(); ++i) { CameraMount *mount = g_app->m_location->m_levelFile->m_cameraMounts[i]; Vector3 camToMount = g_app->m_camera->GetPos() - mount->m_pos; if (camToMount.Mag() < 20.0) continue; mat.OrientFU(mount->m_front, mount->m_up); mat.pos = mount->m_pos; camShape->Render(0.0, mat); } g_app->m_renderer->UnsetObjectLighting(); } g_app->m_renderer->UnsetObjectLighting(); // // Render our instant units for (int i = 0; i < levelFile->m_instantUnits.Size(); ++i) { InstantUnit *iu = levelFile->m_instantUnits.GetData(i); RenderUnit(iu); } switch (m_mode) { case ModeLandTile: RenderModeLandTile(); break; case ModeLandFlat: RenderModeLandFlat(); break; case ModeBuilding: RenderModeBuilding(); break; case ModeLight: break; case ModeInstantUnit: RenderModeInstantUnit(); break; case ModeCameraMount: RenderModeCameraMount(); break; } // // Render axes float sizeX = g_app->m_location->m_landscape.GetWorldSizeX() / 2; float sizeZ = g_app->m_location->m_landscape.GetWorldSizeZ() / 2; RenderArrow(Vector3(10, 200, 0), Vector3(sizeX, 200, 0), 4.0); glBegin(GL_LINES); glVertex3f(sizeX, 250, 0); glVertex3f(sizeX + 90, 150, 0); glVertex3f(sizeX, 150, 0); glVertex3f(sizeX + 90, 250, 0); glEnd(); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); RenderArrow(Vector3(0, 200, 10), Vector3(0, 200, sizeZ), 4.0); glBegin(GL_LINES); glVertex3f(0, 250, sizeZ); glVertex3f(0, 250, sizeZ + 90); glVertex3f(0, 250, sizeZ); glVertex3f(0, 150, sizeZ + 90); glVertex3f(0, 150, sizeZ); glVertex3f(0, 150, sizeZ + 90); glEnd(); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); // // Render targetting crosshair g_app->m_renderer->SetupMatricesFor2D(); glColor3ub(255,255,255); glLineWidth( 1.0 ); glBegin( GL_LINES ); glVertex2i( g_app->m_renderer->ScreenW()/2, g_app->m_renderer->ScreenH()/2 - 30 ); glVertex2i( g_app->m_renderer->ScreenW()/2, g_app->m_renderer->ScreenH()/2 + 30 ); glVertex2i( g_app->m_renderer->ScreenW()/2 - 30, g_app->m_renderer->ScreenH()/2 ); glVertex2i( g_app->m_renderer->ScreenW()/2 + 30, g_app->m_renderer->ScreenH()/2 ); glEnd(); g_app->m_renderer->SetupMatricesFor3D(); CHECK_OPENGL_STATE(); }
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(); } } } }