void GhostChoose(struct Player *g) { if(g->intel==G_TRYING) { g->intel=g->lastint; Stupid(g); } else if(g->intel==G_EYES) { g->intel=G_TRYING; g->lastint=G_EYES; HomeIn(g,HomeX*BITMAP_X,HomeY*BITMAP_Y); } else if(g->intel==G_SMART) { g->intel=G_TRYING; g->lastint=G_SMART; HomeIn(g,Pac.zx,Pac.zy); } else if(g->intel==G_SCARED) { g->intel=G_TRYING; g->lastint=G_SCARED; Avoid(g,Pac.zx,Pac.zy); } }
/** * Invoked each server tick */ void CFish::Update( float deltaT ) { Vector deltaPos = GetAbsOrigin() - m_poolOrigin; const float safetyMargin = 5.0f; // pass relative position to the client // clamp them here to cover the rare cases where a fish's high velocity skirts the range limit m_x = clamp( deltaPos.x, -255.0f, 255.0f ); m_y = clamp( deltaPos.y, -255.0f, 255.0f ); m_z = m_poolOrigin->z; // // Dead fish just coast to a stop. All floating to the // surface and bobbing motion is handled client-side. // if (m_lifeState == LIFE_DEAD) { // don't allow fish to leave maximum range of pool if (deltaPos.IsLengthGreaterThan( m_pool->GetMaxRange() - safetyMargin )) { SetAbsVelocity( Vector( 0, 0, 0 ) ); } else { // decay movement speed to zero Vector vel = GetAbsVelocity(); const float drag = 1.0f; vel -= drag * vel * deltaT; SetAbsVelocity( vel ); } return; } // // Living fish behavior // // periodically change our turning preference if (m_turnTimer.IsElapsed()) { m_turnTimer.Start( RandomFloat( 10.0f, 30.0f ) ); m_turnClockwise = !m_turnClockwise; } if (m_panicTimer.GetRemainingTime() > 0.0f) { // panicking m_desiredSpeed = m_panicSpeed; } else if (m_moveTimer.GetRemainingTime() > 0.0f) { // normal movement m_desiredSpeed = m_calmSpeed; } else if (m_goTimer.IsElapsed()) { // move every so often m_goTimer.Start( RandomFloat( 10.0f, 60.0f ) ); m_moveTimer.Start( RandomFloat( 2.0f, 10.0 ) ); m_desiredSpeed = m_calmSpeed; } // avoid obstacles float danger = Avoid(); // flock towards visible fish for( int i=0; i<m_visible.Count(); ++i ) { FlockTo( m_visible[i], (1.0f - danger) ); } // flock towards center of pool FlockTo( NULL, (1.0f - danger) ); // // Update orientation // // limit rate of angular change - proportional to movement rate const float maxAngleChange = (25.0f + 175.0f * (m_speed/m_panicSpeed)) * deltaT; if (m_angleChange > maxAngleChange) { m_angleChange = maxAngleChange; } else if (m_angleChange < -maxAngleChange) { m_angleChange = -maxAngleChange; } m_angle += m_angleChange; m_angleChange = 0.0f; m_forward.x = cos( m_angle * M_PI/180.0f ); m_forward.y = sin( m_angle * M_PI/180.0f ); m_forward.z = 0.0f; m_perp.x = -m_forward.y; m_perp.y = m_forward.x; m_perp.z = 0.0f; // // Update speed // const float rate = 2.0f; m_speed += rate * (m_desiredSpeed - m_speed) * deltaT; // decay desired speed if done moving if (m_moveTimer.IsElapsed()) { const float decayRate = 1.0f; m_desiredSpeed -= decayRate * deltaT; if (m_desiredSpeed < 0.0f) { m_desiredSpeed = 0.0f; } } Vector vel = m_speed * m_forward; // don't allow fish to leave maximum range of pool if (deltaPos.IsLengthGreaterThan( m_pool->GetMaxRange() - safetyMargin )) { Vector toCenter = -deltaPos; float radial = DotProduct( toCenter, vel ); if (radial < 0.0f) { // heading out of range, zero the radial velocity component toCenter.NormalizeInPlace(); Vector perp( -toCenter.y, toCenter.x, 0.0f ); float side = DotProduct( perp, vel ); vel = side * perp; } } SetAbsVelocity( vel ); m_flSpeed = m_speed; }