gCycle Class Reference

#include <gCycle.h>

Inheritance diagram for gCycle:

Inheritance graph
[legend]
Collaboration diagram for gCycle:

Collaboration graph
[legend]

List of all members.

Public Member Functions

virtual void Die (REAL time)
 dies at the specified time
void KillAt (const eCoord &pos)
 kill this cycle at the given position and take care of scoring
int WindingNumber () const
 returns the current winding number
virtual bool Vulnerable () const
 returns whether the cycle can be killed
virtual void InitAfterCreation ()
 shared initialization routine
 gCycle (eGrid *grid, const eCoord &pos, const eCoord &dir, ePlayerNetID *p=NULL)
REAL MaxWallsLength () const
 the maximum total length of the walls (including max effect of rubber growth)
REAL ThisWallsLength () const
 the maximum total length of this cycle's wall (including rubber shrink)
REAL WallEndSpeed () const
 the speed the end of the trail is receeding with right now
bool IsMe (eGameObject const *other) const
 checks whether the passed pointer is logically identical with this cycle
 gCycle (nMessage &m)
virtual void WriteCreate (nMessage &m)
virtual void WriteSync (nMessage &m)
virtual void ReadSync (nMessage &m)
virtual void RequestSyncOwner ()
 requests special syncs to the owner on important points (just passed an enemy trail end safely...)
virtual void RequestSyncAll ()
 requests special syncs to everyone on important points (just passed an enemy trail end safely...)
virtual void SyncEnemy (const eCoord &begWall)
 handle sync message for enemy cycles
virtual void ReceiveControl (REAL time, uActionPlayer *Act, REAL x)
virtual void PrintName (tString &s) const
virtual bool ActionOnQuit ()
virtual nDescriptorCreatorDescriptor () const
virtual bool SyncIsNew (nMessage &m)
virtual bool Timestep (REAL currentTime)
 advance to the given time
virtual bool TimestepCore (REAL currentTime, bool calculateAcceleration=true)
 core physics simulation routine
virtual void InteractWith (eGameObject *target, REAL time, int recursion=1)
virtual bool EdgeIsDangerous (const eWall *w, REAL time, REAL a) const
 returns whether a given wall is dangerous to this cycle
virtual void PassEdge (const eWall *w, REAL time, REAL a, int recursion=1)
virtual REAL PathfindingModifier (const eWall *w) const
virtual bool Act (uActionPlayer *Act, REAL x)
virtual bool DoTurn (int dir)
 turns the cycle in the given direction
void DropWall (bool buildNew=true)
 Drops the current wall and builds a new one.
virtual void Kill ()
 destroys the gameobject (in the game)
const eTempEdgeEdge ()
const gPlayerWallCurrentWall ()
virtual void Render (const eCamera *cam)
 draws object to the screen using OpenGL
virtual void Render2D (tCoord scale) const
virtual void RenderName (const eCamera *cam)
virtual bool RenderCockpitFixedBefore (bool primary=true)
virtual eCoord CamPos () const
virtual eCoord PredictPosition () const
virtual eCoord CamTop () const
virtual eCoord CamDir () const
virtual eCoord Direction () const
 returns the current driving direction
virtual void RightBeforeDeath (int numTries)
 called when the cycle is very close to a wall and about to crash

Static Public Member Functions

static void SetWallsStayUpDelay (REAL delay)
 the time the cycle walls stay up ( negative values: they stay up forever )
static void SetWallsLength (REAL length)
 the maximum total length of the walls
static void SetExplosionRadius (REAL radius)
 the radius of the holes blewn in by an explosion
static REAL WallsStayUpDelay ()
 the time the cycle walls stay up ( negative values: they stay up forever )
static REAL WallsLength ()
 the default total length of the walls
static REAL ExplosionRadius ()
 the radius of the holes blewn in by an explosion
static void PrivateSettings ()

Public Attributes

eCoord lastGoodPosition_
REAL skew
REAL skewDot
bool mp
rModelbody
rModelfront
rModelrear
rModelcustomModel
gTextureCyclewheelTex
gTextureCyclebodyTex
gTextureCyclecustomTexture
eCoord rotationFrontWheel
eCoord rotationRearWheel
REAL heightFrontWheel
REAL heightRearWheel
gCycleMemory memory
gRealColor color_
gRealColor trailColor_
eCoord correctPosSmooth
eCoord predictPosition_
 the best guess of where the cycle is at at display time
REAL correctDistanceSmooth

Static Public Attributes

static uActionPlayer s_brake

Protected Member Functions

virtual ~gCycle ()
virtual void OnRemoveFromGame ()
 called on RemoveFromGame(). Call base class implementation, too, in your implementation. Must keep the object alive.
virtual void OnRoundEnd ()
 called when the round ends
virtual bool DoIsDestinationUsed (const gDestination *dest) const
 returns whether the given destination is in active use

Private Member Functions

void TransferPositionCorrectionToDistanceCorrection ()
 tCHECKED_PTR (gNetPlayerWall) currentWall
 the wall that currenly is attached to the cycle
 tCHECKED_PTR (gNetPlayerWall) lastWall
 the last wall that was attached to this cycle
 tCHECKED_PTR (gNetPlayerWall) lastNetWall
 the last wall received over the network
void ResetExtrapolator ()
bool Extrapolate (REAL dt)
void SyncFromExtrapolator ()
virtual void OnNotifyNewDestination (gDestination *dest)
 called when a destination is successfully inserted into the destination list
virtual void OnDropTempWall (gPlayerWall *wall, eCoord const &position, eCoord const &direction)
 called when another cycle grinds a wall; this cycle should then drop its current wall if the grinding is too close.
void MyInitAfterCreation ()
 private shared initialization code
void SetCurrentWall (gNetPlayerWall *w)
void PreparePredictPosition (gPredictPositionData &data)
 prepares CalculatePredictPosition() call, requesting a raycast to the front
REAL CalculatePredictPosition (gPredictPositionData &data)
 Calculates predictPosition_.

Private Attributes

REAL spawnTime_
 time the cycle spawned at
REAL lastTimeAnim
 last time animation was simulated at
REAL timeCameIntoView
std::auto_ptr< gCycleChatBotchatBot_
bool dropWallRequested_
 flag indicating that someone requested a wall drop
gCycleWallsDisplayListManager displayList_
 display list manager
SyncData lastSyncMessage_
tJUST_CONTROLLED_PTR
< gCycleExtrapolator
extrapolator_
bool resimulate_
nTimeRolling nextSync
nTimeRolling nextSyncOwner
gJoystickjoystick_
 joystick control

Static Private Attributes

static REAL wallsStayUpDelay = 8.0f
 the time the cycle walls stay up ( negative values: they stay up forever )
static REAL wallsLength = -1.0f
 the maximum total length of the walls
static REAL explosionRadius = 4.0f
 the radius of the holes blewn in by an explosion

Friends

class gPlayerWall
class gNetPlayerWall
class gDestination
class gCycleWallRenderer
class gCycleChatBot


Detailed Description

Definition at line 149 of file gCycle.h.


Constructor & Destructor Documentation

gCycle::~gCycle (  )  [protected, virtual]

Definition at line 2331 of file gCycle.cpp.

References body, bodyTex, customModel, customTexture, CYCLE_MOTOR, front, eSoundMixer::GetMixer(), mp, rear, eSoundMixer::RemoveContinuous(), eGameObject::RemoveFromGame(), and wheelTex.

02332                {
02333 #ifdef DEBUG
02334     //  con << "deleting cylce...\n";
02335 #endif
02336     // clear the destination list
02337 
02338     eSoundMixer* mixer = eSoundMixer::GetMixer();
02339     mixer->RemoveContinuous(CYCLE_MOTOR, this);
02340 
02341     this->RemoveFromGame();
02342 
02343     if (mp){
02344         delete customModel;
02345         delete customTexture;
02346     }
02347     else{
02348         delete body;
02349         delete front;
02350         delete rear;
02351         delete wheelTex;
02352         delete bodyTex;
02353     }
02354 #ifdef DEBUG
02355     //con << "Deleted cycle.\n";
02356 #endif
02357     /*
02358       delete currentPos;
02359       delete last_turn;
02360     */

Here is the call graph for this function:

gCycle::gCycle ( eGrid grid,
const eCoord &  pos,
const eCoord &  dir,
ePlayerNetID p = NULL 
)

Definition at line 2308 of file gCycle.cpp.

References eGameObject::deathTime, eGameObject::dir, gCycleMovement::dirDrive, eGrid::DirectionWinding(), eGrid::GetDirection(), eGameObject::Grid(), MyInitAfterCreation(), NULL, sg_ArchiveCoord(), sg_ArchiveReal(), gCycleMovement::windingNumber_, and gCycleMovement::windingNumberWrapped_.

02310         :gCycleMovement(grid, pos,d,p,false),
02311         skew(0),skewDot(0),
02312         rotationFrontWheel(1,0),rotationRearWheel(1,0),heightFrontWheel(0),heightRearWheel(0),
02313         currentWall(NULL),
02314         lastWall(NULL)
02315 {
02316     windingNumberWrapped_ = windingNumber_ = Grid()->DirectionWinding(dirDrive);
02317     dirDrive = Grid()->GetDirection(windingNumberWrapped_);
02318     dir = dirDrive;
02319 
02320     deathTime=0;
02321 
02322     lastNetWall=lastWall=currentWall=NULL;
02323 
02324     MyInitAfterCreation();
02325 
02326     sg_ArchiveCoord( this->dirDrive, 1 );
02327     sg_ArchiveCoord( this->dir, 1 );
02328     sg_ArchiveCoord( this->pos, 1 );
02329     sg_ArchiveReal( this->verletSpeed_, 1 );

Here is the call graph for this function:

gCycle::gCycle ( nMessage m  ) 

Definition at line 4878 of file gCycle.cpp.

References gRealColor::b, color_, correctDistanceSmooth, eGameObject::deathTime, eGameObject::dir, gCycleMovement::dirDrive, eGrid::DirectionWinding(), gCycleMovement::dirSpawn, EPS, gRealColor::g, eGrid::GetDirection(), eGameObject::Grid(), eGameObject::lastTime, lastTimeAnim, nextSync, nextSyncOwner, NULL, gRealColor::r, gCycleMovement::rubber, se_GameTime(), se_MakeColorValid(), spawnTime_, trailColor_, gCycleMovement::windingNumber_, and gCycleMovement::windingNumberWrapped_.

04878                          :
04879 gCycle::gCycle(nMessage &m)
04880         :gCycleMovement(m),
04881         skew(0),skewDot(0),
04882         rotationFrontWheel(1,0),rotationRearWheel(1,0),heightFrontWheel(0),heightRearWheel(0),
04883         currentWall(NULL),
04884         lastWall(NULL)
04885 {
04886     deathTime=0;
04887     lastNetWall=lastWall=currentWall=NULL;
04888     windingNumberWrapped_ = windingNumber_ = Grid()->DirectionWinding(dirDrive);
04889     dirDrive = Grid()->GetDirection(windingNumberWrapped_);
04890     dir = dirDrive;
04891 
04892     rubber=0;
04893     //correctTimeSmooth =0;
04894     correctDistanceSmooth =0;
04895     //correctSpeedSmooth =0;
04896 
04897     deathTime = 0;
04898     spawnTime_ = se_GameTime() + 100;
04899     dirSpawn = dirDrive;
04900 
04901 
04902     m >> color_.r;
04903     m >> color_.g;
04904     m >> color_.b;
04905 
04906     trailColor_ = color_;
04907 
04908     se_MakeColorValid( color_.r, color_.g, color_.b, 1.0f );
04909     se_MakeColorValid( trailColor_.r, trailColor_.g, trailColor_.b, .5f );
04910 
04911     // set last time so that the first read_sync will not think this is old
04912     lastTimeAnim = lastTime = -EPS;
04913 
04914     nextSync = nextSyncOwner = -1;
}

Here is the call graph for this function:


Member Function Documentation

void gCycle::TransferPositionCorrectionToDistanceCorrection (  )  [private]

Definition at line 5158 of file gCycle.cpp.

References correctDistanceSmooth, correctPosSmooth, gCycleMovement::dirDrive, gCycleMovement::distance, and REAL.

Referenced by Die(), SyncFromExtrapolator(), and TimestepCore().

05160 {
05161     REAL newCorrectDist = eCoord::F( correctPosSmooth, dirDrive );
05162     distance += newCorrectDist - correctDistanceSmooth;
05163     correctDistanceSmooth = newCorrectDist;

Here is the caller graph for this function:

gCycle::tCHECKED_PTR ( gNetPlayerWall   )  [private]

the wall that currenly is attached to the cycle

gCycle::tCHECKED_PTR ( gNetPlayerWall   )  [private]

the last wall that was attached to this cycle

gCycle::tCHECKED_PTR ( gNetPlayerWall   )  [private]

the last wall received over the network

void gCycle::ResetExtrapolator (  )  [private]

Definition at line 5055 of file gCycle.cpp.

References eGameObject::dir, extrapolator_, lastSyncMessage_, eGameObject::pos, resimulate_, and tNEW.

Referenced by PassEdge(), and Timestep().

05057 {
05058     resimulate_ = false;
05059     if (!extrapolator_)
05060     {
05061         extrapolator_ = tNEW( gCycleExtrapolator )(grid, pos, dir );
05062     }
05063 
05064     extrapolator_->CopyFrom( lastSyncMessage_, *this );
05065 
05066     // simulate a bit, only to get current rubberSpeedFactor and acceleration
05067     extrapolator_->TimestepCore( extrapolator_->LastTime(), true );

Here is the caller graph for this function:

bool gCycle::Extrapolate ( REAL  dt  )  [private]

Definition at line 5070 of file gCycle.cpp.

References eCoord, extrapolator_, eGameObject::lastTime, gDestination::list, REAL, tASSERT, and eGameObject::TimestepThis().

Referenced by PassEdge(), and Timestep().

05072 {
05073     tASSERT( extrapolator_ );
05074 
05075     eCoord posBefore = extrapolator_->Position();
05076 
05077     // calculate target time
05078     REAL newTime = extrapolator_->LastTime() + dt;
05079 
05080     bool ret = false;
05081 
05082     // clamp: don't simulate further than our current time
05083     if ( newTime >= lastTime )
05084     {
05085         // simulate extrapolator until now
05086         eGameObject::TimestepThis( lastTime, extrapolator_ );
05087 
05088         // test if there are real (the check for list does that) destinations left; we cannot call it finished if there are.
05089         gDestination* unhandledDestination = extrapolator_->GetCurrentDestination();
05090         ret = !unhandledDestination || !unhandledDestination->list;
05091 
05092         newTime = lastTime;
05093     }
05094     else
05095     {
05096         // simulate extrapolator as requested
05097         eGameObject::TimestepThis( newTime, extrapolator_ );
05098     }
05099 
05100     //eCoord posAfter = extrapolator_->Position();
05101     //eDebugLine::SetTimeout( 1.0 );
05102     //eDebugLine::SetColor( 1,0,0 );
05103     //eDebugLine::Draw( posBefore, 8, posAfter, 4 );
05104     //eDebugLine::Draw( posBefore, 4, posAfter, 4 );
05105 
05106     return ret;

Here is the call graph for this function:

Here is the caller graph for this function:

void gCycle::SyncFromExtrapolator (  )  [private]

Definition at line 5166 of file gCycle.cpp.

References gCycleMovement::CopyFrom(), correctDistanceSmooth, correctPosSmooth, gCycleMovement::distance, dt, eCoord, extrapolator_, eGameObject::LastTime(), gCycleMovement::lastTurnPos_, gPlayerWallCoord::Pos, eGameObject::pos, REAL, resimulate_, sg_cycleWallTime, spawnTime_, tASSERT, and TransferPositionCorrectionToDistanceCorrection().

Referenced by Timestep().

05168 {
05169     // store old position
05170     eCoord oldPos = pos;
05171 
05172     // con << "Copy: " << LastTime() << ", " << extrapolator_->LastTime() << ", " << extrapolator_->Position() << ", " << pos << "\n";
05173 
05174     tASSERT( extrapolator_ );
05175 
05176     // delegate
05177     CopyFrom( *extrapolator_ );
05178 
05179     // adjust current wall (not essential, don't do it for the first wall)
05180     if ( currentWall && currentWall->tBeg > spawnTime_ + sg_cycleWallTime + .01f )
05181     {
05182         // update start position
05183         currentWall->beg = extrapolator_->GetLastTurnPos();
05184 
05185         // set begin distance as well
05186         REAL dBeg = extrapolator_->GetDistance() - eCoord::F( extrapolator_->Direction(), extrapolator_->Position() - extrapolator_->GetLastTurnPos() );
05187 
05188         currentWall->dbegin = dBeg;
05189         currentWall->coords_[0].Pos = dBeg;
05190 
05191         // and care for consistency
05192         int i;
05193         for ( i = currentWall->coords_.Len() -1 ; i>=0; --i )
05194         {
05195             gPlayerWallCoord & coord = currentWall->coords_( i );
05196             if ( coord.Pos <= dBeg )
05197                 coord.Pos = dBeg;
05198         }
05199     }
05200 
05201     // transfer last turn position
05202     lastTurnPos_ = extrapolator_->GetLastTurnPos();
05203 
05204     // smooth position correction
05205     correctPosSmooth = correctPosSmooth + oldPos - pos;
05206 
05207 #ifdef DEBUG
05208     if ( correctPosSmooth.NormSquared() > .1f )
05209     {
05210         std::cout << "Lag slide! " << correctPosSmooth << "\n";
05211         resimulate_ = true;
05212     }
05213 #endif
05214 
05215     // calculate time difference between this cycle and extrapolator
05216     REAL dt = this->LastTime() - extrapolator_->LastTime();
05217 
05218     // extrapolate true distance ( the best estimate we have for the distance on the server )
05219     REAL trueDistance = extrapolator_->trueDistance_ + extrapolator_->Speed() * dt;
05220 
05221     // update distance correction
05222     // con <<   correctDistanceSmooth << "," << trueDistance << "," << distance << "\n";
05223     // correctDistanceSmooth = trueDistance - distance;
05224     distance = trueDistance;
05225     correctDistanceSmooth=0;
05226 
05227     // split away part in driving direction
05228     TransferPositionCorrectionToDistanceCorrection();
05229 
05230     // make sure correction does not bring us to the wrong side of a wall
05231     // se_SanifyDisplacement( this, correctPosSmooth );
05232 
05233     //eDebugLine::SetTimeout( 1.0 );
05234     //eDebugLine::SetColor( 0,1,0 );
05235     //eDebugLine::Draw( pos, 4, pos + dirDrive * 10, 14 );
05236 
05237     // delete extrapolator
05238     extrapolator_ = 0;

Here is the call graph for this function:

Here is the caller graph for this function:

void gCycle::OnNotifyNewDestination ( gDestination dest  )  [private, virtual]

called when a destination is successfully inserted into the destination list

Reimplemented from gCycleMovement.

Definition at line 1428 of file gCycle.cpp.

References gCycleMovement::acceleration, BroadCastNewDestination(), gCycleMovement::dirDrive, gDestination::distance, gCycleMovement::distance, EPS, extrapolator_, gDestination::gameTime, eNetGameObject::Lag(), eGameObject::lastTime, nCLIENT, nSERVER, gCycleMovement::OnNotifyNewDestination(), nNetObject::Owner(), eNetGameObject::Player(), eGameObject::pos, gDestination::position, REAL, eLag::Report(), gCycleMovement::rubber, gCycleMovement::rubberSpeedFactor, se_GameTime(), sg_gnuplotDebug, sg_RubberValues(), sn_GetNetState(), sn_myNetID, st_Breakpoint(), eLag::TakeCredit(), TimestepCore(), tSysTimeFloat(), and gCycleMovement::verletSpeed_.

01429 {
01430 #ifdef DELAYEDTURN_DEBUG
01431     sg_turnReceivedTime = tSysTimeFloat();
01432 #endif
01433 
01434 #ifdef GNUPLOT_DEBUG
01435     if ( sg_gnuplotDebug && Player() )
01436     {
01437         std::ofstream f( Player()->GetUserName() + "_sync", std::ios::app );
01438         f << dest->position.x << " " << dest->position.y << "\n";
01439     }
01440 #endif
01441 
01442     gCycleMovement::OnNotifyNewDestination( dest );
01443 
01444     //  if (sn_GetNetState()==nSERVER || ::sn_myNetID == owner)
01445     if (sn_GetNetState()==nCLIENT && ::sn_myNetID == Owner())
01446         BroadCastNewDestination(this,dest);
01447 
01448     if ( extrapolator_ )
01449     {
01450         // add destination and try to squeeze it into the schedule.
01451         extrapolator_->NotifyNewDestination( dest );
01452     }
01453 
01454     // start a new simulation in any case. The server may simulate the movement a bit differently at the turn.
01455     // resimulate_ = ( sn_GetNetState() == nCLIENT );
01456 
01457     // detect lag slides
01458     if( sn_GetNetState() == nSERVER )
01459     {
01460         // see how far we should be simulated in an ideal world
01461         REAL simTime=se_GameTime() - Lag();
01462 
01463         REAL lag = simTime - dest->gameTime;  // the real lag
01464         REAL lagOffset = simTime - lastTime;  // difference between real lag and practical lag (what we need to compensate)
01465         if ( lag > 0 && sn_GetNetState() == nSERVER )
01466         {
01467             eLag::Report( Owner(), lag );
01468             if ( currentWall && currentWall->Wall() && rubberSpeedFactor >= 1-EPS )
01469             {
01470                 lag -= lagOffset; // switch to practical lag
01471 
01472                 // no compensation? Just quit.
01473                 if ( lag < 0 )
01474                     return;
01475 
01476                 // see how much we can go back
01477                 REAL minDist   = currentWall->Wall()->Pos(0);
01478                 REAL maxGoBack = ( distance - minDist ) * .8;
01479 
01480                 // see how much we should go back
01481                 REAL stepBack = distance - dest->distance;
01482 
01483                 if ( rubberSpeedFactor < 1-EPS )
01484                 {
01485                     // make the correction distance based so we don't loosen a grind
01486                     maxGoBack = stepBack;
01487                 }
01488 
01489                 // clamp so we don't go back too far
01490                 if ( stepBack > maxGoBack )
01491                 {
01492                     stepBack = maxGoBack;
01493                     lag = rubberSpeedFactor*stepBack/verletSpeed_;
01494                 }
01495 
01496                 // ask lag compensation how much we are allowed to go back; switch to real lag
01497                 // for the credit
01498                 lag = eLag::TakeCredit( Owner(), lag + lagOffset ) - lagOffset;
01499 
01500                 // no compensation? Just quit.
01501                 if ( lag < 0 )
01502                     return;
01503 
01504                 // go back in time
01505                 if ( rubberSpeedFactor >= 1-EPS )
01506                 {
01507                     // rubber is inactive, basic timestep is enough
01508                     TimestepCore( lastTime - lag );
01509                 }
01510                 else if ( 0 )
01511                 {
01512                     // rubber is active. Take care!
01513 
01514                     // just extrapolate the movement backwards
01515                     REAL step = lag * verletSpeed_;
01516                     lastTime -= lag;
01517 
01518                     // rubber is a bit tricker, we need the effectiveness
01519                     REAL rubberGranted, rubberEffectiveness;
01520                     sg_RubberValues( player, verletSpeed_, rubberGranted, rubberEffectiveness );
01521                     if ( rubberEffectiveness > 0 )
01522                         rubber -= step/rubberEffectiveness;
01523 
01524                     if ( rubber < 0 )
01525                         rubber = 0;
01526 
01527                     // position and distance are easy
01528                     step *= rubberSpeedFactor;
01529                     distance -= step;
01530                     pos = pos - dirDrive * step;
01531 
01532                     // undo acceleration
01533                     verletSpeed_ -= acceleration * lag;
01534                 }
01535 
01536                 // see if we went back too far (should almost never happen)
01537                 if ( distance < minDist )
01538                 {
01539                     st_Breakpoint();
01540                     TimestepCore( lastTime + ( minDist - distance )/verletSpeed_ );
01541                 }
01542             }
01543         }
01544     }
01545 }

Here is the call graph for this function:

void gCycle::OnDropTempWall ( gPlayerWall wall,
eCoord const &  position,
eCoord const &  dir 
) [private, virtual]

called when another cycle grinds a wall; this cycle should then drop its current wall if the grinding is too close.

Parameters:
wall the wall the other cycle is grinding
pos the position of the grind
dir the direction the raycast triggering the gridding comes from

Reimplemented from gCycleMovement.

Definition at line 1560 of file gCycle.cpp.

References tRecorderSync< DATA >::Archive(), dropWallRequested_, nNetObject::ID(), gCycleMovement::lastDirDrive, gPlayerWall::NetWall(), REAL, sg_minDropInterval, tASSERT, and gCycleMovement::verletSpeed_.

01561 {
01562     tASSERT( wall );
01563 
01564     unsigned short idrec = ID();
01565     tRecorderSync< unsigned short >::Archive( "_ON_DROP_WALL", 8, idrec );
01566 
01567     // determine if the grinded wall is current enough
01568     bool wallRight = ( currentWall && ( wall->NetWall() == currentWall || wall->NetWall() == currentWall ) );
01569 
01570     // don't drop if we already dropped a short time ago
01571     if ( wallRight && currentWall->Edge()->Vec().NormSquared() < verletSpeed_ * verletSpeed_ * sg_minDropInterval * sg_minDropInterval )
01572         wallRight = false;
01573 
01574     tRecorderSync< bool >::Archive( "_ON_DROP_WALL_RIGHT", 8, wallRight );
01575 
01576     // drop the current wall if eiter this or the last wall is grinded
01577     // gNetPlayerWall * nw = wall->NetWall();
01578     if ( wallRight )
01579     {
01580         // calculate relative position of grinding in wall; if alpha is positive, it's already too late
01581         REAL alpha = currentWall->Edge()->Edge(0)->Ratio( position );
01582         tRecorderSync< REAL >::Archive( "_ON_DROP_WALL_ALPHA", 8, alpha );
01583         if ( alpha > -.5 )
01584         {
01585             unsigned short idrec = ID();
01586             tRecorderSync< unsigned short >::Archive( "_ON_DROP_WALL_DROP", 8, idrec );
01587 
01588             // just request the drop, Timestep() will execute it later
01589             dropWallRequested_ = true;
01590 
01591             // bend last driving direction to -dir. That way, should the grinder overtake this cycle,
01592             // it will end up on the right side of his wall.
01593             lastDirDrive = -dir;
01594         }
01595     }
01596 }

Here is the call graph for this function:

void gCycle::MyInitAfterCreation ( void   )  [private]

private shared initialization code

Reimplemented from gCycleMovement.

Definition at line 2114 of file gCycle.cpp.

References eGameObject::AddToList(), gRealColor::b, body, gCycleVisuals::bodyModel, bodyTex, gCycleVisuals::bodyTexture, color_, con, correctDistanceSmooth, correctPosSmooth, gCycleVisuals::customModel, customModel, gCycleVisuals::customTexture, customTexture, CYCLE_MOTOR, eGameObject::dir, gCycleMovement::dirDrive, gCycleMovement::dirSpawn, dropWallRequested_, eCoord, front, gCycleVisuals::frontModel, gRealColor::g, gCycleWallRenderer, eSoundMixer::GetMixer(), joystick_, lastGoodPosition_, eGameObject::lastTime, lastTimeAnim, gCycleVisuals::LoadModel(), mp, gCycleVisuals::mpType, nCLIENT, nextSync, nextSyncOwner, NULL, eSoundMixer::PlayContinuous(), eNetGameObject::Player(), eGameObject::pos, predictPosition_, gRealColor::r, REAL, rear, gCycleVisuals::rearModel, gCycleMovement::RequestSync(), resimulate_, rotationFrontWheel, rotationRearWheel, se_MakeColorValid(), sg_cycleFirstSpawnProtection, sg_gnuplotDebug, sg_MoviePack(), skew, skewDot, sn_GetNetState(), spawnTime_, sqrt(), tASSERT, tERR_ERROR, timeCameIntoView, tNEW, trailColor_, tSysTimeFloat(), wheelTex, and gCycleVisuals::wheelTexture.

Referenced by gCycle(), and InitAfterCreation().

02114                                 {
02115 #ifndef DEDICATED
02116     joystick_ = tNEW( gJoystick( this ) );
02117 #else
02118     joystick_ = NULL;
02119 #endif
02120 
02121 // create wall renderer
02122 #ifndef DEDICATED
02123     new gCycleWallRenderer( this );
02124 #endif
02125 
02126     dropWallRequested_ = false;
02127     lastGoodPosition_ = pos;
02128 
02129 #ifdef DEBUG
02130     // con << "creating cycle.\n";
02131 #endif
02132     eSoundMixer* mixer = eSoundMixer::GetMixer();
02133     mixer->PlayContinuous(CYCLE_MOTOR, this);
02134 
02135     //correctDistSmooth=correctTimeSmooth=correctSpeedSmooth=0;
02136     correctDistanceSmooth = 0;
02137 
02138     resimulate_ = false;
02139 
02140     mp=sg_MoviePack();
02141 
02142     lastTimeAnim = 0;
02143     timeCameIntoView = 0;
02144 
02145     customModel = NULL;
02146     body = NULL;
02147     front = NULL;
02148     rear = NULL;
02149     wheelTex = NULL;
02150     bodyTex = NULL;
02151     customTexture = NULL;
02152 
02153     correctPosSmooth=eCoord(0,0);
02154 
02155     rotationFrontWheel=rotationRearWheel=eCoord(1,0);
02156 
02157     skew=skewDot=0;
02158 
02159     {
02160         dir=dirDrive;
02161         REAL dirLen=dir.NormSquared();
02162         if ( dirLen > 0 )
02163         {
02164             dir = dir * (1/sqrt( dirLen ));
02165         }
02166     }
02167 
02168     if (sn_GetNetState()!=nCLIENT){
02169         if(!player)
02170         { // distribute AI colors
02171             // con << current_ai << ':' << take_ai << ':' << maxmindist <<  "\n\n\n";
02172             color_.r=1;
02173             color_.g=1;
02174             color_.b=1;
02175 
02176             trailColor_.r=1;
02177             trailColor_.g=1;
02178             trailColor_.b=1;
02179         }
02180         else
02181         {
02182             player->Color(color_.r,color_.g,color_.b);
02183             player->TrailColor(trailColor_.r,trailColor_.g,trailColor_.b);
02184         }
02185 
02186         se_MakeColorValid( color_.r, color_.g, color_.b, 1.0f );
02187         se_MakeColorValid( trailColor_.r, trailColor_.g, trailColor_.b, .5f );
02188     }
02189 
02190     // load model and texture
02191 #ifndef DEDICATED
02192     gCycleVisuals visuals( color_ );
02193     if ( !visuals.LoadModel( mp ) )
02194     {
02195         tERR_ERROR( "Neither classic style nor moviepack style model and textures found. "
02196                     "The folders \"textures\" and \"moviepack\" need to contain either "
02197                     "cycle.ase and bike.png or body.mod, front.mod, rear.mod, cycle_body.png and cycle_wheel.png." );
02198     }
02199 
02200     mp = visuals.mpType;
02201 
02202     // transfer models and textures
02203     if ( mp )
02204     {
02205         // use moviepack style body and texture
02206         customModel = visuals.customModel;
02207         visuals.customModel = 0;
02208         customTexture = visuals.customTexture;
02209         visuals.customTexture = 0;
02210     }
02211     else
02212     {
02213         // use classic style body and texture
02214         body = visuals.bodyModel;
02215         visuals.bodyModel = 0;
02216         front = visuals.frontModel;
02217         visuals.frontModel = 0;
02218         rear = visuals.rearModel;
02219         visuals.rearModel = 0;
02220         bodyTex = visuals.bodyTexture;
02221         visuals.bodyTexture = 0;
02222         wheelTex = visuals.wheelTexture;
02223         visuals.wheelTexture = 0;
02224 
02225         tASSERT ( body && front && rear && bodyTex && wheelTex );
02226 
02227         mp = false;
02228     }
02229 #endif // DEDICATED
02230 
02231     /*
02232       the old, less flexible, loading code
02233 
02234     if (mp)
02235     {
02236         customModel=new rModel("moviepack/cycle.ASE","moviepack/cycle.ase");
02237     }
02238     else{
02239         body=new rModel("models/cycle_body.mod");
02240         front=new rModel("models/cycle_front.mod");
02241         rear=new rModel("models/cycle_rear.mod");
02242     }
02243 
02244     if (mp)
02245     {
02246         // static rSurface bike(lala_bikeTexture);
02247         static rSurface bike("moviepack/bike.png");
02248         customTexture=new gTextureCycle(bike,color_,0,0);
02249     }
02250     else{
02251         static rSurface body("textures/cycle_body.png");
02252         static rSurface wheel("textures/cycle_wheel.png");
02253         //static rSurface body((const char*) lala_bodyTexture);
02254         //static rSurface wheel((const char*) lala_wheelTexture);
02255         wheelTex=new gTextureCycle(wheel,color_,0,0,true);
02256         bodyTex=new gTextureCycle(body,color_,0,0);
02257     }
02258     */
02259 
02260 #ifdef DEBUG
02261     con << "Created cycle.\n";
02262 #endif
02263     nextSyncOwner=nextSync=tSysTimeFloat()-1;
02264 
02265     if (sn_GetNetState()!=nCLIENT)
02266         RequestSync();
02267 
02268     grid->AddGameObjectInteresting(this);
02269 
02270     spawnTime_=lastTimeAnim=lastTime;
02271     // set spawn time to infinite past if this is the first spawn
02272     if ( !sg_cycleFirstSpawnProtection && spawnTime_ <= 1.0 )
02273     {
02274         spawnTime_ = -1E+20;
02275     }
02276     dirSpawn = dirDrive;
02277 
02278     // add to game grid
02279     this->AddToList();
02280 
02281     predictPosition_ = pos;
02282 
02283 #ifdef GNUPLOT_DEBUG
02284     if ( sg_gnuplotDebug && Player() )
02285     {
02286         std::ofstream f( Player()->GetUserName() + "_step" );
02287         f << pos.x << " " << pos.y << "\n";
02288         std::ofstream g( Player()->GetUserName() + "_sync" );
02289         g << pos.x << " " << pos.y << "\n";
02290         std::ofstream h( Player()->GetUserName() + "_turn" );
02291         h << pos.x << " " << pos.y << "\n";
02292     }
02293 #endif

Here is the call graph for this function:

Here is the caller graph for this function:

void gCycle::SetCurrentWall ( gNetPlayerWall w  )  [private]

void gCycle::PreparePredictPosition ( gPredictPositionData data  )  [private]

prepares CalculatePredictPosition() call, requesting a raycast to the front

Parameters:
data data to be passed to CalculatePredictPosition() later

Definition at line 2442 of file gCycle.cpp.

References eGameObject::GetMaxLazyLag(), eGameObject::lastTime, eGameObject::MaxSimulateAhead(), gCycleMovement::maxSpaceMaxCast_, gPredictPositionData::maxSpaceReport, REAL, gCycleMovement::RubberSpeed(), gCycleMovement::rubberSpeedFactor, se_PredictTime(), sg_predictWalls, and gCycleMovement::verletSpeed_.

Referenced by Timestep().

02444 {
02445     // don't cast a ray by default
02446     data.maxSpaceReport = 0;
02447 #ifdef DEDICATED
02448     if ( sg_predictWalls )
02449     {
02450         // predict to the maximum time anyone else may be simulated up to
02451         REAL maxTime = lastTime + MaxSimulateAhead() + GetMaxLazyLag();
02452         REAL predictDT = maxTime - lastTime;
02453         REAL lookAhead = predictDT * verletSpeed_;
02454 
02455         // see how far we can go before rubber kicks in
02456         data.rubberStart = verletSpeed_ / RubberSpeed();
02457 
02458         // store max lookahead plus rubber safety
02459         data.maxSpaceReport = lookAhead + data.rubberStart;
02460     }
02461 #else
02462     data.maxSpaceReport = verletSpeed_ * se_PredictTime() * rubberSpeedFactor;
02463 #endif
02464 
02465     // request a raycast of the right length
02466     maxSpaceMaxCast_ = data.maxSpaceReport;

Here is the call graph for this function:

Here is the caller graph for this function:

REAL gCycle::CalculatePredictPosition ( gPredictPositionData data  )  [private]

Calculates predictPosition_.

Parameters:
data data from PreparePredictPosition()
Returns:
the time up to which the cycle's position was predicted

Definition at line 2479 of file gCycle.cpp.

References correctPosSmooth, gCycleMovement::dirDrive, gCycleMovement::GetMaxSpaceAhead(), eGameObject::lastTime, gPredictPositionData::maxSpaceReport, eGameObject::pos, predictPosition_, REAL, se_PredictTime(), sg_predictWalls, and gCycleMovement::verletSpeed_.

Referenced by Timestep().

02481 {
02482     // predict position
02483     REAL predictTime = lastTime;
02484     {
02485 #ifdef DEDICATED
02486         predictPosition_ = pos;
02487 
02488         if ( sg_predictWalls )
02489         {
02490             REAL spaceAhead = GetMaxSpaceAhead( data.maxSpaceReport );
02491             spaceAhead -= data.rubberStart;
02492 
02493             if ( spaceAhead > 0 )
02494             {
02495                 // store consistent prediction position and  time
02496                 predictPosition_ = pos + dirDrive * spaceAhead;
02497                 predictTime = lastTime + spaceAhead/verletSpeed_;
02498             }
02499         }
02500 #else
02501         // predict half a frame time
02502         predictTime += se_PredictTime();
02503         predictPosition_ = pos+correctPosSmooth + dirDrive * GetMaxSpaceAhead( data.maxSpaceReport );
02504 #endif
02505     }
02506 
02507     return predictTime;

Here is the call graph for this function:

Here is the caller graph for this function:

void gCycle::OnRemoveFromGame (  )  [protected, virtual]

called on RemoveFromGame(). Call base class implementation, too, in your implementation. Must keep the object alive.

Reimplemented from gCycleMovement.

Definition at line 2362 of file gCycle.cpp.

References gCycleMovement::Alive(), Die(), joystick_, eGameObject::lastTime, nSERVER, NULL, gCycleMovement::OnRemoveFromGame(), gCycleMovement::RequestSync(), sn_GetNetState(), and gCycleMovement::Turn().

02364 {
02365     // keep this cycle alive during this function
02366     tJUST_CONTROLLED_PTR< gCycle > keep;
02367 
02368     if ( this->GetRefcount() > 0 )
02369     {
02370         keep = this;
02371 
02372         this->Turn(0);
02373 
02374         if ( sn_GetNetState() == nSERVER )
02375             RequestSync();
02376     }
02377 
02378     // make sure we're dead, so our walls know they need to time out.
02379     if ( Alive() )
02380     {
02381         Die( lastTime );
02382     }
02383 
02384     if (currentWall)
02385         currentWall->CopyIntoGrid(0);
02386     currentWall=NULL;
02387     lastWall=NULL;
02388 
02389     gCycleMovement::OnRemoveFromGame();
02390 
02391     delete joystick_;
02392     joystick_ = NULL;

Here is the call graph for this function:

void gCycle::OnRoundEnd (  )  [protected, virtual]

called when the round ends

Reimplemented from eGameObject.

Definition at line 2395 of file gCycle.cpp.

References ePlayerNetID::AddScore(), gCycleMovement::Alive(), eNetGameObject::Player(), and score_survive.

02397 {
02398     // give survival bonus
02399     if ( Alive() && player )
02400     {
02401         Player()->AddScore( score_survive, tOutput("$player_win_survive"), tOutput() );
02402     }

Here is the call graph for this function:

void gCycle::Die ( REAL  time  )  [virtual]

dies at the specified time

Parameters:
time the time of death

Reimplemented from gCycleMovement.

Definition at line 3097 of file gCycle.cpp.

References correctPosSmooth, gNetPlayerWall::Cycle(), gCycleMovement::Die(), eCoord, nSERVER, eGameObject::pos, predictPosition_, gNetPlayerWall::Preliminary(), gNetPlayerWall::real_CopyIntoGrid(), gCycleMovement::RequestSync(), sg_netPlayerWalls, sn_GetNetState(), and TransferPositionCorrectionToDistanceCorrection().

Referenced by Kill(), OnRemoveFromGame(), ReadSync(), Timestep(), and TimestepCore().

03099 {
03100     if ( sn_GetNetState() == nSERVER )
03101     {
03102         // request one last sync
03103         RequestSync( true );
03104     }
03105 
03106     gCycleMovement::Die( time );
03107 
03108     // reset smoothing
03109     correctPosSmooth = eCoord();
03110     TransferPositionCorrectionToDistanceCorrection();
03111     predictPosition_ = pos;
03112 
03113     // delete all temporary walls of this cycle
03114     for ( int i = sg_netPlayerWalls.Len()-1; i >= 0; --i )
03115     {
03116         gNetPlayerWall * wall = sg_netPlayerWalls(i);
03117         if ( wall->Cycle() == this && wall->Preliminary() )
03118         {
03119             wall->real_CopyIntoGrid(grid);
03120         }
03121     }

Here is the call graph for this function:

Here is the caller graph for this function:

void gCycle::KillAt ( const eCoord &  pos  ) 

kill this cycle at the given position and take care of scoring

Definition at line 3123 of file gCycle.cpp.

References gStatList::add(), ePlayerNetID::AddScore(), gCycleMovement::Alive(), tColoredString::ColorString(), ePlayerNetID::CurrentTeam(), gStatistics::deaths, gCycleMovement::enemyInfluence, gEnemyInfluence::GetEnemy(), ePlayerNetID::GetName(), gEnemyInfluence::GetTime(), ePlayerNetID::GetUserName(), gStats, ePlayerNetID::IsHuman(), Kill(), gStatistics::kills, eGameObject::LastTime(), eGameObject::lastTime, gCycleMovement::MoveSafely(), nCLIENT, NULL, ePlayerNetID::Object(), eNetGameObject::Player(), eGameObject::pos, score_die, score_kill, score_suicide, se_SaveToLadderLog(), se_sendEventNotification(), tOutput::SetTemplateParameter(), sg_suicideTimeout, sn_ConsoleOut(), sn_GetNetState(), and Vulnerable().

Referenced by PassEdge(), sg_TopologyPoliceCheck(), Timestep(), and TimestepCore().

03124                                           {
03125     // don't kill invulnerable cycles
03126     if ( !Vulnerable() )
03127     {
03128         MoveSafely( deathPos, lastTime, lastTime );
03129         return;
03130     }
03131 
03132     // find the killer from the enemy influence storage
03133     ePlayerNetID const * constHunter = enemyInfluence.GetEnemy();
03134     ePlayerNetID * hunter = Player();
03135 
03136     // cast away const the safe way
03137     if ( constHunter && constHunter->Object() )
03138         hunter = constHunter->Object()->Player();
03139 
03140     // only take it if it is not too old
03141     if ( LastTime() - enemyInfluence.GetTime() > sg_suicideTimeout )
03142         hunter = NULL;
03143 
03144     // suicide?
03145     if ( !hunter )
03146         hunter = Player();
03147 
03148 
03149     if (!Alive() || sn_GetNetState()==nCLIENT)
03150         return;
03151 
03152 #ifdef KRAWALL_SERVER_LEAGUE
03153     if (    hunter           && Player()          &&
03154             !dynamic_cast<gAIPlayer*>(hunter)     &&
03155             !dynamic_cast<gAIPlayer*>(Player())             &&
03156             hunter->IsAuth() && Player()->IsAuth())
03157         nKrawall::ServerFrag(hunter->GetUserName(), Player()->GetUserName());
03158 #endif
03159 
03160     if (hunter==Player())
03161     {
03162         if (hunter)
03163         {
03164             tString ladderLog;
03165             ladderLog << "DEATH_SUICIDE " << hunter->GetUserName() << "\n";
03166             se_SaveToLadderLog( ladderLog );
03167             tString notificationMessage(hunter->GetUserName());
03168             notificationMessage << " commited suicide";
03169             se_sendEventNotification(tString("Death suicide"), notificationMessage);
03170 
03171             if ( score_suicide )
03172                 hunter->AddScore(score_suicide, tOutput(), "$player_lose_suicide" );
03173             else
03174             {
03175                 tColoredString hunterName;
03176                 hunterName << *hunter << tColoredString::ColorString(1,1,1);
03177                 sn_ConsoleOut( tOutput( "$player_free_suicide", hunterName ) );
03178             }
03179         }
03180     }
03181     else{
03182         if (hunter)
03183         {
03184             tOutput lose;
03185             tOutput win;
03186             if (Player())
03187             {
03188                 tColoredString preyName;
03189                 preyName << *Player();
03190                 preyName << tColoredString::ColorString(1,1,1);
03191                 if (Player()->CurrentTeam() != hunter->CurrentTeam()) {
03192                     tString ladderLog;
03193                     ladderLog << "DEATH_FRAG " << Player()->GetUserName() << " " << hunter->GetUserName()  << "\n";
03194                     se_SaveToLadderLog( ladderLog );
03195                     tString notificationMessage(hunter->GetUserName());
03196                     notificationMessage << " core dumped " << Player()->GetUserName();
03197                     se_sendEventNotification(tString("Death frag"), notificationMessage);
03198 
03199                     win.SetTemplateParameter(3, preyName);
03200                     win << "$player_win_frag";
03201                     if ( score_kill != 0 )
03202                         hunter->AddScore(score_kill, win, lose );
03203                     else
03204                     {
03205                         tColoredString hunterName;
03206                         hunterName << *hunter << tColoredString::ColorString(1,1,1);
03207                         sn_ConsoleOut( tOutput( "$player_free_frag", hunterName, preyName ) );
03208                     }
03209                 }
03210                 else {
03211                     tString ladderLog;
03212                     ladderLog << "DEATH_TEAMKILL " << Player()->GetUserName() << " " << hunter->GetUserName()  << "\n";
03213                     se_SaveToLadderLog( ladderLog );
03214                     tString notificationMessage(hunter->GetUserName());
03215                     notificationMessage << " teamkilled " << Player()->GetUserName();
03216                     se_sendEventNotification(tString("Death teamkill"), notificationMessage);
03217 
03218                     tColoredString hunterName;
03219                     hunterName << *hunter << tColoredString::ColorString(1,1,1);
03220                     sn_ConsoleOut( tOutput( "$player_teamkill", hunterName, preyName ) );
03221                 }
03222             }
03223             else
03224             {
03225                 win << "$player_win_frag_ai";
03226                 hunter->AddScore(score_kill, win, lose);
03227             }
03228         }
03229         //      if (prey->player && (prey->player->CurrentTeam() != hunter->player->CurrentTeam()))
03230         if (Player())
03231             Player()->AddScore(score_die,tOutput(),"$player_lose_frag");
03232     }
03233 
03234     //collect stats! huzzah!
03235     if (Player() && hunter && gStats)
03236     {
03237         //always a death
03238         if (Player()->IsHuman())
03239         {
03240             gStats->deaths->add(Player()->GetName(), 1);
03241         }
03242         if (hunter != Player() && hunter->IsHuman()) //but a kill too?
03243         {
03244             gStats->kills->add(hunter->GetName(), 1);
03245         }
03246     }
03247 
03248     // set position to death position so the explosion is at the right place (I dimly remember this caused problems in an earlier attempt)
03249     this->pos = deathPos;
03250 
03251     Kill();

Here is the call graph for this function:

Here is the caller graph for this function:

int gCycle::WindingNumber ( void   )  const [inline]

returns the current winding number

Returns:
number of right turns taken minus the number of left turns

Reimplemented from gCycleMovement.

Definition at line 243 of file gCycle.h.

References gCycleMovement::windingNumber_.

Referenced by gAIPlayer::EmergencySurvive().

00243 {return windingNumber_;}

Here is the caller graph for this function:

bool gCycle::Vulnerable (  )  const [virtual]

returns whether the cycle can be killed

Returns:
the distance driven since the last turn

the distance driven since the last turn

true if the cycle is vulnerable

Reimplemented from gCycleMovement.

Definition at line 6076 of file gCycle.cpp.

References gCycleMovement::Alive(), eGameObject::lastTime, sg_cycleInvulnerableTime, and spawnTime_.

Referenced by EdgeIsDangerous(), KillAt(), PassEdge(), and Render().

06078 {
06079     return Alive() && lastTime > spawnTime_ + sg_cycleInvulnerableTime;

Here is the call graph for this function:

Here is the caller graph for this function:

void gCycle::InitAfterCreation ( void   )  [virtual]

shared initialization routine

Reimplemented from gCycleMovement.

Definition at line 2295 of file gCycle.cpp.

References gCycleMovement::InitAfterCreation(), MyInitAfterCreation(), gCycleMovement::Speed(), and st_Breakpoint().

02296                               {
02297 #ifdef DEBUG
02298     if (!finite(Speed()))
02299         st_Breakpoint();
02300 #endif
02301     gCycleMovement::InitAfterCreation();
02302 #ifdef DEBUG
02303     if (!finite(Speed()))
02304         st_Breakpoint();
02305 #endif
02306     MyInitAfterCreation();

Here is the call graph for this function:

void gCycle::SetWallsStayUpDelay ( REAL  delay  )  [static]

the time the cycle walls stay up ( negative values: they stay up forever )

Definition at line 1607 of file gCycle.cpp.

References nConfItem< T >::Set().

Referenced by _wrap_GCycle_set_walls_stay_up_delay(), and sg_copySettings().

01608 {
01609     c_pwsud->Set( delay );
01610 }

Here is the call graph for this function:

Here is the caller graph for this function:

void gCycle::SetWallsLength ( REAL  length  )  [static]

the maximum total length of the walls

Definition at line 1700 of file gCycle.cpp.

References c_pwl.

Referenced by _wrap_GCycle_set_walls_length(), and sg_copySettings().

01701 {
01702     c_pwl->Set( length );
01703 }

Here is the caller graph for this function:

void gCycle::SetExplosionRadius ( REAL  radius  )  [static]

the radius of the holes blewn in by an explosion

Definition at line 1706 of file gCycle.cpp.

References c_per.

Referenced by _wrap_GCycle_set_explosion_radius(), and sg_copySettings().

01707 {
01708     c_per->Set( radius );
01709 }

Here is the caller graph for this function:

static REAL gCycle::WallsStayUpDelay (  )  [inline, static]

the time the cycle walls stay up ( negative values: they stay up forever )

Definition at line 256 of file gCycle.h.

References wallsStayUpDelay.

Referenced by _wrap_GCycle_walls_stay_up_delay(), gCycleWallsDisplayListManager::CannotHaveList(), cWidget::Map::DrawWalls(), gNetPlayerWall::IsDangerousAnywhere(), gNetPlayerWall::IsDangerousApartFromHoles(), gNetPlayerWall::RenderBegin(), and gNetPlayerWall::RenderNormal().

Here is the caller graph for this function:

static REAL gCycle::WallsLength (  )  [inline, static]

the default total length of the walls

Definition at line 257 of file gCycle.h.

References wallsLength.

Referenced by _wrap_GCycle_walls_length(), cWidget::Map::DrawWalls(), gNetPlayerWall::IsDangerousAnywhere(), gNetPlayerWall::IsDangerousApartFromHoles(), gNetPlayerWall::RenderList(), and sg_CycleWallLengthFromDist().

Here is the caller graph for this function:

REAL gCycle::MaxWallsLength (  )  const

the maximum total length of the walls (including max effect of rubber growth)

Definition at line 1681 of file gCycle.cpp.

References gCycleMovement::distance, REAL, sg_cycleDistWallShrink, sg_cycleRubberWallShrink, sg_CycleWallLengthFromDist(), sg_rubberCycle, and wallsLength.

Referenced by gCycleWallsDisplayListManager::RenderAll().

01682 {
01683     REAL len = sg_CycleWallLengthFromDist( distance );
01684 
01685     // exception: if the wall grows faster than it receeds, take the maximum, because the wall will
01686     // grow backwards
01687     if ( sg_cycleDistWallShrink > 1 )
01688     {
01689         len = wallsLength;
01690     }
01691 
01692     // if the wall grows from rubber use, add the maximal growth
01693     if ( sg_cycleRubberWallShrink >= 0 || sg_rubberCycle < 0 )
01694         return len;
01695     else
01696         return len - sg_cycleRubberWallShrink * sg_rubberCycle;
01697 }

Here is the call graph for this function:

Here is the caller graph for this function:

REAL gCycle::ThisWallsLength (  )  const

the maximum total length of this cycle's wall (including rubber shrink)

Definition at line 1649 of file gCycle.cpp.

References gCycleMovement::distance, gCycleMovement::GetRubber(), REAL, sg_cycleRubberWallShrink, and sg_CycleWallLengthFromDist().

Referenced by gCycleWallsDisplayListManager::CannotHaveList(), cWidget::Map::DrawWalls(), PassEdge(), and gCycleWallsDisplayListManager::RenderAll().

01650 {
01651     // get distance influence
01652     REAL len = sg_CycleWallLengthFromDist( distance );
01653 
01654     // apply rubber shortening
01655     return len - GetRubber() * sg_cycleRubberWallShrink;
01656 }

Here is the call graph for this function:

Here is the caller graph for this function:

REAL gCycle::WallEndSpeed (  )  const

the speed the end of the trail is receeding with right now

Definition at line 1660 of file gCycle.cpp.

References d, gCycleMovement::distance, REAL, gCycleMovement::rubberSpeedFactor, sg_cycleDistWallShrink, sg_cycleDistWallShrinkOffset, sg_cycleRubberWallShrink, sg_RubberValues(), and gCycleMovement::Speed().

01661 {
01662     REAL rubberMax, rubberEffectiveness;
01663     sg_RubberValues( player, Speed(), rubberMax, rubberEffectiveness );
01664 
01665     // basic speed from cycle movement
01666     REAL speed = rubberSpeedFactor * Speed();
01667 
01668     // take distance shrinking into account
01669     REAL d = sg_cycleDistWallShrinkOffset - distance;
01670     if ( d > 0 )
01671         speed *= ( 1 - sg_cycleDistWallShrink );
01672 
01673     // speed from rubber usage and shringing
01674     if ( rubberEffectiveness > 0 )
01675         speed += Speed() * ( 1 - rubberSpeedFactor ) * sg_cycleRubberWallShrink / rubberEffectiveness;
01676 
01677     return speed;
01678 }

Here is the call graph for this function:

static REAL gCycle::ExplosionRadius (  )  [inline, static]

the radius of the holes blewn in by an explosion

Definition at line 261 of file gCycle.h.

References explosionRadius.

Referenced by _wrap_GCycle_explosion_radius(), gExplosion::OnNewWall(), and gExplosion::Timestep().

Here is the caller graph for this function:

bool gCycle::IsMe ( eGameObject const *  other  )  const

checks whether the passed pointer is logically identical with this cycle

Definition at line 1419 of file gCycle.cpp.

References extrapolator_.

Referenced by gSensor::PassEdge().

01420 {
01421     return other == this || other == extrapolator_;
01422 }

Here is the caller graph for this function:

void gCycle::WriteCreate ( nMessage m  )  [virtual]

Reimplemented from eNetGameObject.

Definition at line 4917 of file gCycle.cpp.

References gRealColor::b, color_, gRealColor::g, gRealColor::r, and eNetGameObject::WriteCreate().

04918                                    {
04919     eNetGameObject::WriteCreate(m);
04920     m << color_.r;
04921     m << color_.g;
04922     m << color_.b;

Here is the call graph for this function:

void gCycle::WriteSync ( nMessage m  )  [virtual]

Reimplemented from eNetGameObject.

Definition at line 4926 of file gCycle.cpp.

References gCycleMovement::Alive(), gCycleMovement::braking, gCycleMovement::brakingReservoir, compressZeroOne, eGameObject::deathTime, Direction(), gCycleMovement::distance, gCycleMovement::GetLastTurnPos(), gCycleMovement::lastDestination, eGameObject::lastTime, gDestination::messageID, eGameObject::Position(), REAL, gCycleMovement::rubber, gCycleMovement::rubberMalus, sg_rubberCycle, sg_verletIntegration, gCycleMovement::Speed(), nVersionFeature::Supported(), gCycleMovement::turns, gCycleMovement::verletSpeed_, gFloatCompressor::Write(), nMessage::Write(), and x.

04927                                  {
04928     //  eNetGameObject::WriteSync(m);
04929 
04930     if ( Alive() )
04931     {
04932         m << lastTime;
04933     }
04934     else
04935     {
04936         m << deathTime;
04937     }
04938     m << Direction();
04939     m << Position();
04940 
04941     REAL speed = verletSpeed_;
04942     // if the clients understand it, send them the real current speed
04943     if ( sg_verletIntegration.Supported() )
04944         speed = Speed();
04945 
04946     if ( speed > 15 )
04947     {
04948         int x;
04949         x = 0;
04950     }
04951 
04952     m << speed;
04953     m << short( Alive() ? 1 : 0 );
04954     m << distance;
04955     if (!currentWall || currentWall->preliminary)
04956         m.Write(0);
04957     else
04958         m.Write(currentWall->ID());
04959 
04960     m.Write(turns);
04961     m.Write(braking);
04962 
04963     // write last turn position
04964     m << GetLastTurnPos();
04965 
04966     // write rubber
04967     compressZeroOne.Write( m, rubber/( sg_rubberCycle + .1 ) );
04968     compressZeroOne.Write( m, 1/( 1 + rubberMalus ) );
04969 
04970     // write last clientside sync message ID
04971     unsigned short lastMessageID = 0;
04972     if ( lastDestination )
04973         lastMessageID = lastDestination->messageID;
04974     m.Write(lastMessageID);
04975 
04976     // write brake
04977     compressZeroOne.Write( m, brakingReservoir );
04978 
04979     // set new sync times
04980     // nextSync=tSysTimeFloat()+sg_syncIntervalEnemy;
04981     // nextSyncOwner=tSysTimeFloat()+sg_GetSyncIntervalSelf( this );

Here is the call graph for this function:

void gCycle::ReadSync ( nMessage m  )  [virtual]

Reimplemented from eNetGameObject.

Definition at line 5254 of file gCycle.cpp.

References gCycleMovement::AccelerationDiscontinuity(), gCycleMovement::Alive(), eSensor::before_hit, gCycleMovement::braking, gCycleMovement::SyncData::braking, gCycleMovement::brakingReservoir, gCycleMovement::SyncData::brakingReservoir, ClampForward(), color_, compressZeroOne, con, correctDistanceSmooth, correctPosSmooth, eGameObject::deathTime, gCycleMovement::destinationList, eSensor::detect(), Die(), eGameObject::dir, gCycleMovement::SyncData::dir, gCycleMovement::dirDrive, Direction(), gCycleMovement::dirSpawn, gDestination::distance, gCycleMovement::distance, gCycleMovement::SyncData::distance, DropWall(), eCoord, nMessage::End(), extrapolator_, eGameObject::FindCurrentFace(), gDestination::gameTime, gCycleMovement::GetDestinationBefore(), eGrid::GetDirection(), eGameObject::GOID(), eGameObject::Grid(), gCycleMovement::lastDirDrive, lastGoodPosition_, lastSyncMessage_, eGameObject::lastTime, gCycleMovement::SyncData::lastTurn, gCycleMovement::lastTurnPos_, gCycleMovement::SyncData::messageID, gCycleMovement::MoveSafely(), gDestination::next, NULL, nNetObject::Owner(), gCycleMovement::SyncData::pos, eGameObject::pos, gDestination::position, predictPosition_, gFloatCompressor::Read(), nMessage::Read(), REAL, resimulate_, gCycleMovement::rubber, gCycleMovement::SyncData::rubber, gCycleMovement::SyncData::rubberMalus, gCycleMovement::SetWindingNumberWrapped(), sg_cycleFirstSpawnProtection, sg_rubberCycle, skew, skewDot, sn_myNetID, sn_Update(), spawnTime_, gCycleMovement::Speed(), gCycleMovement::SyncData::speed, sqrt(), SyncEnemy(), gCycleMovement::SyncData::time, tNEW, gCycleMovement::turns, gCycleMovement::SyncData::turns, gCycleMovement::verletSpeed_, gCycleMovement::windingNumberWrapped_, and x.

05256 {
05257     // data from sync message
05258     SyncData sync;
05259 
05260     short sync_alive;               // is this cycle alive?
05261     unsigned short sync_wall=0;     // ID of wall
05262 
05263     eCoord new_pos = pos;       // the extrapolated position
05264 
05265     // warning: depends on the implementation of eNetGameObject::WriteSync
05266     // since we don't call eNetGameObject::ReadSync.
05267     m >> sync.time;
05268 
05269     // reset values not sent with old protocol messages
05270     sync.rubber = rubber;
05271     sync.turns = turns;
05272     sync.braking = braking;
05273     sync.messageID = 1;
05274 
05275     m >> sync.dir;
05276     m >> sync.pos;
05277 
05278     //eDebugLine::SetTimeout( 1.0 );
05279     //eDebugLine::SetColor( 1,1,1 );
05280     //eDebugLine::Draw( lastSyncMessage_.pos, 0, lastSyncMessage_.pos, 20 );
05281 
05282     m >> sync.speed;
05283     m >> sync_alive;
05284     m >> sync.distance;
05285     m.Read(sync_wall);
05286     if (!m.End())
05287         m.Read(sync.turns);
05288     if (!m.End())
05289         m.Read(sync.braking);
05290 
05291     if ( !m.End() )
05292     {
05293         m >> sync.lastTurn;
05294     }
05295     else if ( currentWall )
05296     {
05297         sync.lastTurn = currentWall->beg;
05298     }
05299 
05300     bool canUseExtrapolatorMethod = false;
05301 
05302     bool rubberSent = false;
05303     if ( !m.End() )
05304     {
05305         rubberSent = true;
05306 
05307         // read rubber
05308         REAL preRubber, preRubberMalus;
05309         preRubber = compressZeroOne.Read( m );
05310         preRubberMalus = compressZeroOne.Read( m );
05311 
05312         // read last message ID
05313         m.Read(sync.messageID);
05314 
05315         // read braking reservoir
05316         sync.brakingReservoir = compressZeroOne.Read( m );
05317         // std::cout << "sync: " << sync.brakingReservoir << ":" << sync.braking << "\n";
05318 
05319         // undo skewing
05320         sync.rubber = preRubber * ( sg_rubberCycle + .1 );
05321         sync.rubberMalus = 1/preRubberMalus - 1;
05322 
05323         // extrapolation is probably safe
05324         canUseExtrapolatorMethod = sg_useExtrapolatorSync && lastTime > 0;
05325     }
05326     else
05327     {
05328         // try to extrapolate brake status backwards in time
05329         sync.brakingReservoir = brakingReservoir;
05330         if ( brakingReservoir > 0 && sync.braking )
05331             sync.brakingReservoir += ( lastTime - sync.time ) * sg_cycleBrakeDeplete;
05332         else if ( brakingReservoir < 1 && !sync.braking )
05333             sync.brakingReservoir -= ( lastTime - sync.time ) * sg_cycleBrakeRefill;
05334 
05335         if ( sync.brakingReservoir < 0 )
05336             sync.brakingReservoir = 0;
05337         else if ( sync.brakingReservoir > 1 )
05338             sync.brakingReservoir = 1;
05339     }
05340 
05341     // abort if sync is not new
05342     if ( lastSyncMessage_.time >= sync.time && lastSyncMessage_.turns >= sync.turns && sync_alive > 0 )
05343     {
05344         //eDebugLine::SetTimeout( 5 );
05345         //eDebugLine::SetColor( 1,1,0);
05346         //eDebugLine::Draw( lastSyncMessage_.pos, 1.5, lastSyncMessage_.pos, 5.0 );
05347         return;
05348     }
05349     lastSyncMessage_ = sync;
05350 
05351     // store last known good position: a bit before the last position confirmed by the server
05352     lastGoodPosition_ = sync.pos + ( sync.lastTurn - sync.pos ) *.01;
05353     // offset it a tiny bit by our last driving direction
05354     if ( eCoord::F( dirDrive, sync.dir ) > .99f*dirDrive.NormSquared() )
05355         lastGoodPosition_ = lastGoodPosition_ - this->lastDirDrive * .0001;
05356 
05357     //eDebugLine::SetTimeout( 2 );
05358     //eDebugLine::SetColor( 0,1,0);
05359     //eDebugLine::Draw( lastSyncMessage_.pos, 1.5, lastSyncMessage_.pos, 5.0 );
05360 
05361     // con << "Sync: " << lastTime << ", " << lastSyncMessage_.time << ", " << lastSyncMessage_.pos << ", " << pos << "\n";
05362 
05363     if ( canUseExtrapolatorMethod )
05364     {
05365         // reset extrapolator if information from server is more up to date
05366         if ( extrapolator_ && extrapolator_->LastTime() < lastSyncMessage_.time )
05367         {
05368             extrapolator_ = 0;
05369         }
05370     }
05371 
05372     // killed?
05373     if (Alive() && sync_alive!=1 && GOID() >= 0 && grid )
05374     {
05375         Die( lastSyncMessage_.time );
05376         MoveSafely( lastSyncMessage_.pos, lastTime, deathTime );
05377         distance=lastSyncMessage_.distance;
05378         correctDistanceSmooth=0;
05379         DropWall( false );
05380 
05381         tNEW(gExplosion)( grid, lastSyncMessage_.pos, lastSyncMessage_.time ,color_, this );
05382 
05383         return;
05384     }
05385 
05386     // no point going on if you're not alive
05387     if (!Alive())
05388     {
05389 #ifdef DEBUG
05390         con << "Received duplicate death sync message; those things confuse old clients!\n";
05391 #endif
05392         return;
05393     }
05394 
05395     gDestination emergency_aft(*this);
05396 
05397     // all the data was read. check where it fits in our destination list:
05398     gDestination *bef= GetDestinationBefore( lastSyncMessage_, destinationList );
05399     gDestination *aft=NULL;
05400     if (bef){
05401         aft=bef->next;
05402         if (!aft)
05403             aft=&emergency_aft;
05404 
05405         //eDebugLine::SetTimeout(1);
05406         //eDebugLine::SetColor( 1,0,0 );
05407         //eDebugLine::Draw( bef->position, 1.5, lastSyncMessage_.pos, 3.0 );
05408         //eDebugLine::SetColor( 0,1,0 );
05409         //eDebugLine::Draw( lastSyncMessage_.pos, 3.0, aft->position, 5.0 );
05410 
05411     }
05412 
05413 
05414     // detect local tunneling by casting a ray from the server certified position
05415     // to the next known client position
05416     if ( lastTime > 0 )
05417     {
05418         eCoord position = pos;
05419         if ( bef )
05420             position = bef->position;
05421         eSensor tunnel( this, lastSyncMessage_.pos, position - lastSyncMessage_.pos );
05422         tunnel.detect( 1 );
05423 
05424         // use extrapolation to undo local tunneling
05425         if ( tunnel.ehit )
05426         {
05427             canUseExtrapolatorMethod = true;
05428             if ( 0 )
05429             {
05430                 con << "possible local tunneling detected\n";
05431                 eSensor tunnel( this, lastSyncMessage_.pos, position - lastSyncMessage_.pos );
05432                 tunnel.detect( 1 );
05433             }
05434         }
05435     }
05436     else
05437     {
05438         // first sync. Accept the position without questioning it.
05439         pos = sync.pos;
05440         FindCurrentFace();
05441     }
05442 
05443     // determine whether we can use the distance based interpolating sync method here
05444     bool distanceBased = aft && aft != &emergency_aft && Owner() == sn_myNetID;
05445 
05446     if ( canUseExtrapolatorMethod && Owner()==sn_myNetID )
05447     {
05448         // exactlu resimulate from sync position for cycles controlled by this client
05449         resimulate_ = true;
05450 
05451         return;
05452     }
05453 
05454     rubber = lastSyncMessage_.rubber;
05455 
05456     // bool fullSync = false;
05457 
05458     // try to get a distance value closer to the client's data by calculating the distance from the sync position to the next destination
05459     REAL interpolatedDistance = lastSyncMessage_.distance;
05460     if ( aft )
05461     {
05462         interpolatedDistance = aft->distance - sqrt((lastSyncMessage_.pos-aft->position).NormSquared());
05463     }
05464 
05465     // determine true lag
05466     // REAL lag = 1;
05467     //if ( player )
05468     //    lag = player->ping;
05469 
05470     if ( distanceBased )
05471     {
05472         // new way: correct our time and speed
05473 
05474 #ifdef DEBUG
05475         // destination *save = bef;
05476 #endif
05477 
05478         REAL ratio = (interpolatedDistance - bef->distance)/
05479                      (aft->distance - bef->distance);
05480 
05481         if (!finite(ratio))
05482             ratio = 0;
05483 
05484         // interpolate when the cycle was at the position the sync message was sent
05485         REAL interpolatedTime = bef->gameTime * (1-ratio) + aft->gameTime * ratio;
05486         // REAL interpolatedSpeed = bef->speed   * (1-ratio) + aft->speed    * ratio;
05487 
05488         // calculate deltas
05489         REAL correctTime  = ( lastSyncMessage_.time     - interpolatedTime     );
05490         // REAL correctSpeed = ( lastSyncMessage_.speed    - interpolatedSpeed    );
05491         REAL correctDist  = ( lastSyncMessage_.distance - interpolatedDistance );
05492 
05493         // don't trust high ratios too much; they may be skewed by rubber application
05494         {
05495             REAL factor = (1 - ratio) * 5;
05496             if ( factor < 1 )
05497             {
05498                 if ( factor < 0 )
05499                     factor = 0;
05500                 correctTime *= factor;
05501                 correctDist *= factor;
05502             }
05503         }
05504 
05505         //if (correctTime > 0)
05506         //{
05507         //    correctTime*=.5;
05508         //    correctSpeed*=.5;
05509         //    correctDist*=.5;
05510         //}
05511 
05512         //correctTimeSmooth       += correctTime;
05513         //correctSpeedSmooth      += correctSpeed;
05514         // correctDistanceSmooth   += correctDist;
05515 
05516         // correctDistanceSmooth   += correctDist;
05517 
05518         // con << ratio << ", " << correctDist << ", " << correctTime << "\n";
05519 
05520         // correct distances according to sync
05521         {
05522             distance += correctDist;
05523             gDestination * run = bef;
05524             while ( run )
05525             {
05526                 run->distance += correctDist;
05527                 run = run->next;
05528             }
05529         }
05530 
05531         // correct time by adapting position and distance
05532         eCoord newPos = pos - Direction() * Speed() * correctTime;
05533         if ( currentWall )
05534         {
05535             ClampForward( newPos, currentWall->beg, Direction() );
05536         }
05537 
05538         // don't tunnel through walls
05539         {
05540             const eCoord & safePos = pos; // aft->position
05541             gSensor test( this, safePos , newPos - safePos );
05542             test.detect(1);
05543             if ( test.ehit )
05544             {
05545                 newPos = test.before_hit;
05546 
05547                 // something bad must be going on, better recheck with accurate extrapolation
05548                 resimulate_ = true;
05549             }
05550         }
05551 
05552         correctPosSmooth = correctPosSmooth + pos - newPos;
05553         distance += eCoord::F( newPos - pos, Direction() )/Direction().NormSquared();
05554 
05555         MoveSafely( newPos, lastTime, lastTime );
05556 
05557         /*
05558         REAL ts = lastSyncMessage_.time - lastTime;
05559 
05560         //        eCoord intPos = pos + dirDrive * (ts * speed + .5 * ts*ts*acceleration);
05561         eCoord intPos = pos + dirDrive * ( ts * ( speed + lastSyncMessage_.speed ) * .5 );
05562         REAL  int_speed = speed + acceleration*ts;
05563 
05564         dirDrive = lastSyncMessage_.dir;
05565 
05566         correctPosSmooth = lastSyncMessage_.pos - intPos;
05567 
05568         distance = lastSyncMessage_.distance - speed * ts - acceleration * ts*ts*.5;
05569 
05570         //correctTimeSmooth = 0;
05571         */
05572     }
05573     else
05574     {
05575         // direct sync
05576         if ( Owner() != sn_myNetID )
05577         {
05578             // direct extrapolation for cycles of other clients or if no turn is newer than the sync
05579             SyncEnemy( lastSyncMessage_.lastTurn );
05580 
05581             // update beginning of current wall
05582             if ( currentWall )
05583             {
05584                 currentWall->beg = lastSyncMessage_.lastTurn;
05585             }
05586 
05587             // update brake status
05588             AccelerationDiscontinuity();
05589             braking = lastSyncMessage_.braking;
05590 
05591             // store last turn
05592             lastTurnPos_ = lastSyncMessage_.lastTurn;
05593         }
05594         else
05595         {
05596             // same algorithm, but update smooth position correction so that there is no immediate visual change
05597             eCoord oldPos = pos + correctPosSmooth;
05598             SyncEnemy( lastSyncMessage_.lastTurn );
05599             correctPosSmooth = oldPos - pos;
05600         }
05601 
05602         // restore rubber meter
05603         if ( !rubberSent )
05604         {
05605             rubber = lastSyncMessage_.rubber;
05606         }
05607     }
05608 
05609     // if this happens during creation, ignore position correction
05610     if ( this->ID() == 0 )
05611     {
05612         correctPosSmooth = eCoord();
05613 
05614         // some other stuff that should happen on the first sync
05615 
05616         // estimate time of spawning (HACK)
05617         spawnTime_=lastTime;
05618         if ( verletSpeed_ > 0 )
05619             spawnTime_ -= distance/verletSpeed_;
05620 
05621         // set spawn time to infinite past if this is the first spawn
05622         if ( !sg_cycleFirstSpawnProtection && spawnTime_ <= 1.0 )
05623         {
05624             spawnTime_ = -1E+20;
05625         }
05626         dirSpawn = dirDrive;
05627 
05628         // reset position and direction
05629         predictPosition_ = pos;
05630         dir = dirDrive;
05631         skew = skewDot = 0;
05632         lastDirDrive=dirDrive;
05633         lastTurnPos_=pos;
05634     }
05635 #ifdef DEBUG
05636     else
05637         if ( correctPosSmooth.NormSquared() > .1f && lastTime > 0.0 )
05638         {
05639             std::cout << "Lag slide! " << correctPosSmooth << "\n";
05640             int x;
05641             x = 0;
05642         }
05643 #endif
05644 
05645     sn_Update(turns,lastSyncMessage_.turns);
05646 
05647     //if (fabs(correctTimeSmooth > 5))
05648     //    st_Breakpoint();
05649 
05650     // calculate new winding number. Try to change it as little as possible.
05651     this->SetWindingNumberWrapped( Grid()->DirectionWinding(dirDrive) );
05652 
05653     // Resnap to the axis
05654     dirDrive = Grid()->GetDirection(windingNumberWrapped_);

Here is the call graph for this function:

void gCycle::RequestSyncOwner (  )  [virtual]

requests special syncs to the owner on important points (just passed an enemy trail end safely...)

Definition at line 5012 of file gCycle.cpp.

References gCycleMovement::Alive(), nextSyncOwner, nSERVER, nNetObject::Owner(), REAL, gCycleMovement::RequestSync(), sg_GetSyncIntervalSelf(), sn_GetNetState(), and tSysTimeFloat().

Referenced by PassEdge(), and TimestepCore().

05014 {
05015     // no more syncs when you're dead
05016     if ( !Alive() )
05017     {
05018         return;
05019     }
05020 
05021     // nothing to do on the client or if the cycle belongs to an AI
05022     if ( sn_GetNetState() != nSERVER || Owner() == 0 )
05023         return;
05024 
05025     REAL syncInterval = sg_GetSyncIntervalSelf( this );
05026     if ( nextSyncOwner < tSysTimeFloat() + syncInterval * 2.0 )
05027     {
05028         // postpone next sync so the notal number of syncs stays the same
05029         RequestSync( Owner(), false );
05030         nextSyncOwner += syncInterval;
05031     }

Here is the call graph for this function:

Here is the caller graph for this function:

void gCycle::RequestSyncAll (  )  [virtual]

requests special syncs to everyone on important points (just passed an enemy trail end safely...)

Definition at line 5033 of file gCycle.cpp.

References gCycleMovement::Alive(), nextSync, nSERVER, nNetObject::Owner(), REAL, gCycleMovement::RequestSync(), sg_syncIntervalEnemy, sn_GetNetState(), and tSysTimeFloat().

Referenced by PassEdge().

05035 {
05036     // no more syncs when you're dead
05037     if ( !Alive() )
05038     {
05039         return;
05040     }
05041 
05042     // nothing to do on the client or if the cycle belongs to an AI
05043     if ( sn_GetNetState() != nSERVER || Owner() == 0 )
05044         return;
05045 
05046     REAL syncInterval = sg_syncIntervalEnemy;
05047     if ( nextSync < tSysTimeFloat() + syncInterval * 2.0 )
05048     {
05049         // postpone next sync so the notal number of syncs stays the same
05050         RequestSync( false );
05051         nextSync += syncInterval;
05052     }

Here is the call graph for this function:

Here is the caller graph for this function:

void gCycle::SyncEnemy ( const eCoord &  begWall  )  [virtual]

handle sync message for enemy cycles

Definition at line 5656 of file gCycle.cpp.

References b, gCycleMovement::SyncData::brakingReservoir, gCycleMovement::brakingReservoir, eNetGameObject::clientside_action(), correctDistanceSmooth, CYCLE_TURN, gCycleMovement::SyncData::dir, gCycleMovement::dirDrive, gCycleMovement::SyncData::distance, gCycleMovement::distance, eDebugLine::Draw(), eCoord, EPS, eSoundMixer::GetMixer(), gNetPlayerWall, eNetGameObject::laggometer, eNetGameObject::laggometerSmooth, gCycleMovement::lastDirDrive, lastSyncMessage_, eGameObject::lastTime, lastTimeAnim, gCycleMovement::lastTimestep_, gCycleMovement::MoveSafely(), nCLIENT, NULL, nNetObject::Owner(), eGameObject::pos, gCycleMovement::SyncData::pos, eSoundMixer::PushButton(), REAL, resimulate_, gCycleMovement::SyncData::rubber, gCycleMovement::rubber, se_GameTime(), eDebugLine::SetColor(), eDebugLine::SetTimeout(), sg_cycleWallTime, skewDot, sn_GetNetState(), sn_myNetID, spawnTime_, gCycleMovement::SyncData::speed, tASSERT, gCycleMovement::SyncData::time, eGameObject::TimestepThis(), gCycleMovement::SyncData::turns, gCycleMovement::turns, and gCycleMovement::verletSpeed_.

Referenced by ReadSync().

05658 {
05659     // keep this cycle alive
05660     tJUST_CONTROLLED_PTR< gCycle > keep( this->GetRefcount()>0 ? this : 0 );
05661 
05662     resimulate_ = false;
05663 
05664     // calculate turning
05665     bool turned = false;
05666     REAL turnDirection=( dirDrive*lastSyncMessage_.dir );
05667     REAL notTurned=eCoord::F( dirDrive, lastSyncMessage_.dir )/dirDrive.NormSquared();
05668 
05669     // the last known time
05670     REAL lastKnownTime = lastTime;
05671 
05672     // calculate the position of the last turn from the sync data
05673     if ( distance > 0 && ( notTurned < .99 || this->turns < lastSyncMessage_.turns ) )
05674     {
05675         // update old wall as good as we can
05676         eCoord crossPos = lastSyncMessage_.pos;
05677         REAL crossDist = lastSyncMessage_.distance;
05678         REAL crossTime = lastSyncMessage_.time;
05679 
05680         // calculate intersection of old and new trajectory (if only one turn was made)
05681         // the second condition is for old servers that don't send the turn count; they
05682         // don't support multiple axes, so we can possibly detect missed turns if
05683         // the dot product of the current and last direction is negative.
05684         if (this->turns+1 >= lastSyncMessage_.turns && ( lastSyncMessage_.turns > 0 || notTurned > -.5 ) )
05685         {
05686             if ( fabs( turnDirection ) > .01 )
05687             {
05688                 REAL b = ( crossPos - pos ) * dirDrive;
05689                 REAL distplace = b/turnDirection;
05690                 crossPos = crossPos + lastSyncMessage_.dir * distplace;
05691                 crossDist += distplace;
05692                 if ( lastSyncMessage_.speed > 0 )
05693                     crossTime += distplace / lastSyncMessage_.speed;
05694 
05695                 tASSERT( fabs ( ( crossPos - pos ) * dirDrive ) < 1 );
05696                 tASSERT( fabs ( ( crossPos - lastSyncMessage_.pos ) * lastSyncMessage_.dir ) < 1 );
05697 
05698                 // update the old wall
05699                 if (currentWall) {
05700                     currentWall->Update(crossTime,crossPos);
05701 
05702                     eSoundMixer* mixer = eSoundMixer::GetMixer();
05703                     mixer->PushButton(CYCLE_TURN, crossPos);
05704                 }
05705             }
05706         }
05707         else
05708         {
05709             // a turn sync was dropped for whatever reason. The last wall is not reliable.
05710             // make it disappear immediately.
05711             if (currentWall)
05712             {
05713                 currentWall->real_CopyIntoGrid(grid);
05714             }
05715         }
05716 
05717         eDebugLine::SetTimeout(5);
05718         eDebugLine::SetColor( 1,0,0 );
05719         eDebugLine::Draw( crossPos, 0, crossPos, 8 );
05720 
05721         // drop old wall
05722         if(currentWall){
05723             lastWall=currentWall;
05724             currentWall->CopyIntoGrid( grid );
05725             tControlledPTR< gNetPlayerWall > bounce( currentWall );
05726             currentWall=NULL;
05727         }
05728 
05729         // create new wall at sync location
05730         distance = lastSyncMessage_.distance;
05731         correctDistanceSmooth=0;
05732 
05733         REAL startBuildWallAt = spawnTime_ + sg_cycleWallTime;
05734         if ( crossTime > startBuildWallAt )
05735             currentWall=new gNetPlayerWall
05736                         (this,crossPos,lastSyncMessage_.dir,crossTime,crossDist);
05737 
05738         turned = true;
05739 
05740         // save last driving direction
05741         lastDirDrive = dirDrive;
05742 
05743         // move to cross position
05744         MoveSafely( crossPos, lastTime, crossTime );
05745         lastKnownTime = crossTime;
05746     }
05747 
05748     // side bending
05749     skewDot+=4*turnDirection;
05750 
05751     // calculate timestep
05752     // REAL ts = lastSyncMessage_.time - lastTime;
05753 
05754     // backup current time
05755     REAL oldTime = lastTime;
05756 
05757     // update position, speed, distance and direction
05758     MoveSafely( lastSyncMessage_.pos, lastKnownTime, lastSyncMessage_.time );
05759     verletSpeed_  = lastSyncMessage_.speed;
05760     lastTimestep_ = 0;
05761     distance = lastSyncMessage_.distance;
05762     correctDistanceSmooth=0;
05763     dirDrive = lastSyncMessage_.dir;
05764     rubber = lastSyncMessage_.rubber;
05765     brakingReservoir = lastSyncMessage_.brakingReservoir;
05766 
05767     // update time to values from sync
05768     lastTime = lastSyncMessage_.time;
05769     if ( oldTime < 0 )
05770         oldTime = lastTime;
05771     clientside_action();
05772 
05773     // bend last driving direction if it is antiparallel to the current one
05774     if ( lastDirDrive * dirDrive < EPS && eCoord::F( lastDirDrive, dirDrive ) < 0 )
05775     {
05776         lastDirDrive = dirDrive.Turn(0,1);
05777     }
05778 
05779     // correct laggometer to actual facts
05780     if (Owner() != sn_myNetID )
05781     {
05782         // calculate lag from sync delay
05783         REAL lag = se_GameTime() - lastSyncMessage_.time;
05784         if ( lag < 0 )
05785             lag = 0;
05786 
05787         // try not to let the lag jump
05788         REAL maxLag = laggometer * 1.2;
05789         REAL minLag = laggometer * .8;
05790 
05791         // store it
05792         laggometer = lag;
05793 
05794         // clamp smooth laggometer to it (or set it if a turn was made)
05795         //if ( laggometerSmooth > lag )
05796         //    laggometerSmooth = lag;
05797 
05798         // For the client and without prediction:
05799         // do not simulate if a turn was made, just accept sync as it is
05800         // (so turns don't look awkward)
05801         if (
05802             sn_GetNetState()==nCLIENT && turned )
05803         {
05804             laggometerSmooth = lag;
05805 
05806             // but at least update the current wall
05807             if ( currentWall )
05808                 currentWall->Update(lastTime,pos);
05809 
05810             // and reset the animation time
05811             lastTimeAnim=lastTime;
05812 
05813             return;
05814         }
05815         else
05816         {
05817             // sanity check: the lag should not jump up suddenly
05818             // (and if it does, we'll catch up at the next turn)
05819             // REAL maxLag = 1.2 * laggometerSmooth;
05820             if ( laggometer > maxLag )
05821                 laggometer = maxLag;
05822             if ( laggometer < minLag )
05823                 laggometer = minLag;
05824         }
05825     }
05826 
05827     // simulate to extrapolate, but don't touch the smooth laggometer
05828     {
05829         REAL laggometerSmoothBackup = this->laggometerSmooth;
05830         TimestepThis(oldTime, this);
05831         this->laggometerSmooth = laggometerSmoothBackup;
05832     }

Here is the call graph for this function:

Here is the caller graph for this function:

void gCycle::ReceiveControl ( REAL  time,
uActionPlayer Act,
REAL  x 
) [virtual]

Reimplemented from eNetGameObject.

Definition at line 5931 of file gCycle.cpp.

References Act(), and eGameObject::TimestepThis().

05932                                                               {
05933     //forceTime=true;
05934     TimestepThis(time,this);
05935     Act(act,x);
05936     //forceTime=false;

Here is the call graph for this function:

void gCycle::PrintName ( tString s  )  const [virtual]

Reimplemented from nNetObject.

Definition at line 5938 of file gCycle.cpp.

References nNetObject::ID().

Referenced by sg_TopologyPoliceKill().

05940 {
05941     s << "gCycle nr. " << ID();
05942     if ( this->player )
05943     {
05944         s << " owned by ";
05945         this->player->PrintName( s );
05946     }

Here is the call graph for this function:

Here is the caller graph for this function:

bool gCycle::ActionOnQuit (  )  [virtual]

Reimplemented from eNetGameObject.

Definition at line 5948 of file gCycle.cpp.

References Kill(), nSERVER, sn_GetNetState(), and nNetObject::TakeOwnership().

Referenced by _wrap_GCycle_action_on_quit().

05950 {
05951     //  currentWall = NULL;
05952     //  lastWall = NULL;
05953     if ( sn_GetNetState() == nSERVER )
05954     {
05955         TakeOwnership();
05956         Kill();
05957         return false;
05958     }
05959     else
05960     {
05961         return true;
05962     }

Here is the call graph for this function:

Here is the caller graph for this function:

nDescriptor & gCycle::CreatorDescriptor ( void   )  const [virtual]

Implements nNetObject.

Definition at line 5965 of file gCycle.cpp.

References cycle_init.

Referenced by _wrap_GCycle_creator_descriptor().

05966                                             {
05967     return cycle_init;

Here is the caller graph for this function:

bool gCycle::SyncIsNew ( nMessage m  )  [virtual]

Reimplemented from eNetGameObject.

Definition at line 4983 of file gCycle.cpp.

References con, nMessage::Read(), REAL, and eNetGameObject::SyncIsNew().

04984                                  {
04985     bool ret=eNetGameObject::SyncIsNew(m);
04986 
04987 
04988     REAL dummy2;
04989     short al;
04990     unsigned short Turns;
04991 
04992     m >> dummy2;
04993     m >> al;
04994     m >> dummy2;
04995     m.Read(Turns);
04996 
04997 #ifdef DEBUG_X
04998     con << "received sync for player " << player->GetName() << "  ";
04999     if (ret || al!=1){
05000         con << "accepting..\n";
05001         return true;
05002     }
05003     else
05004     {
05005         con << "rejecting..\n";
05006         return false;
05007     }
05008 #endif
05009 
05010     return ret || al!=1;

Here is the call graph for this function:

bool gCycle::Timestep ( REAL  currentTime  )  [virtual]

advance to the given time

Parameters:
currentTime the time to simulate up to
Returns:
true if the cycle is to be deleted

Reimplemented from gCycleMovement.

Definition at line 2509 of file gCycle.cpp.

References gCycleChatBot::Activate(), gCycleMovement::Alive(), tRecorderSync< DATA >::Archive(), CalculatePredictPosition(), chatBot_, gCycleMovement::currentDestination, gCycleMovement::destinationList, Die(), gDestination::distance, dropWallRequested_, dt, Extrapolate(), extrapolator_, gCycleChatBot::Get(), nNetObject::ID(), gDestination::InsertIntoList(), KillAt(), eGameObject::lastTime, gCycleMovement::maxSpaceHit_, gDestination::messageID, nCLIENT, gCycleMovement::pendingTurns, eNetGameObject::Player(), eGameObject::pos, gCycleDeath::pos_, PredictPosition(), PreparePredictPosition(), REAL, ResetExtrapolator(), resimulate_, sg_ArchiveCoord(), sg_ArchiveReal(), sg_chatBotAlwaysActive, sg_gnuplotDebug, sg_minDropInterval, sg_syncFF, sg_syncFFSteps, sn_GetNetState(), sn_myNetID, SyncFromExtrapolator(), gCycleMovement::Timestep(), tNEW, tSysTimeFloat(), and gCycleMovement::verletSpeed_.

Referenced by sg_CreateWinDeathZone().

02510                                      {
02511     // clear out dangerous info when we're done
02512     gMaxSpaceAheadHitInfoClearer hitInfoClearer( maxSpaceHit_ );
02513 
02514     // if ( Owner() == sn_myNetID )
02515     //    con << pos << ',' << distance << ',' << eCoord::F( dirDrive, pos ) - distance << '\n';
02516 
02517     // request the right space ahead for wall extrapolation
02518     gPredictPositionData predictPositionData;
02519     PreparePredictPosition( predictPositionData );
02520 
02521     // drop current wall if it was requested
02522     if ( dropWallRequested_ )
02523     {
02524         // but don't do so too often globally (performance)
02525         static double nextDrop = 0;
02526         double time = tSysTimeFloat();
02527         if ( time >= nextDrop )
02528         {
02529             unsigned short idrec = ID();
02530             tRecorderSync< unsigned short >::Archive( "_PARTIAL_COPY_GRID", 8, idrec );
02531 
02532             nextDrop = time + sg_minDropInterval;
02533             if ( currentWall )
02534             {
02535                 currentWall->Update(lastTime,pos);
02536                 currentWall->PartialCopyIntoGrid( grid );
02537             }
02538             dropWallRequested_ = false;
02539         }
02540     }
02541 
02542 #ifdef GNUPLOT_DEBUG
02543     if ( sg_gnuplotDebug && Player() )
02544     {
02545         std::ofstream f( Player()->GetUserName() + "_step", std::ios::app );
02546         f << pos.x << " " << pos.y << "\n";
02547     }
02548 #endif
02549     // timewarp test debug code
02550     //if ( Player() && Player()->IsHuman() )
02551     //    currentTime -= .1;
02552 
02553     // don't timestep when you're dead
02554     if ( !Alive() )
02555     {
02556         // die completely
02557         Die( lastTime );
02558 
02559         // and let yourself be removed from the lists so we don't have to go
02560         // through this again.
02561         return true;
02562     }
02563 
02564     // Debug archive position and speed
02565     sg_ArchiveCoord( pos, 7 );
02566     sg_ArchiveReal( verletSpeed_, 7 );
02567 
02568     if ( !destinationList && sn_GetNetState() == nCLIENT )
02569     {
02570         // insert emergency first destination without broadcasting it
02571         gDestination* dest = tNEW(gDestination)(*this);
02572         dest->messageID = 0;
02573         dest->distance = -.001;
02574         dest->InsertIntoList(&destinationList);
02575     }
02576 
02577     // start new extrapolation
02578     if ( !extrapolator_ && resimulate_ )
02579         ResetExtrapolator();
02580 
02581     // extrapolate state from server and copy state when finished
02582     if ( extrapolator_ )
02583     {
02584         REAL dt = ( currentTime - lastTime ) * sg_syncFF / sg_syncFFSteps;
02585 #ifdef DEBUG
02586         // dt *= 10.101;
02587         //if ( !resimulate_ )
02588         //      dt *= .1;
02589 #endif
02590         for ( int i = sg_syncFFSteps - 1; i>= 0; --i )
02591         {
02592             if ( Extrapolate( dt ) )
02593             {
02594                 SyncFromExtrapolator();
02595                 break;
02596             }
02597         }
02598     }
02599 
02600     bool ret = false;
02601 
02602     // nothing special if simulating backwards
02603     if (currentTime < lastTime)
02604     {
02605         ret = gCycleMovement::Timestep(currentTime);
02606     }
02607     // no targets are given
02608     else if ( !currentDestination && pendingTurns.empty() )
02609     {
02610         // chatting? activate chatbot
02611         if ( bool(player) &&
02612                 player->IsHuman() &&
02613                 ( sg_chatBotAlwaysActive || player->IsChatting() ) &&
02614                 player->Owner() == sn_myNetID )
02615         {
02616             gCycleChatBot & bot = gCycleChatBot::Get( this );
02617             bot.Activate( currentTime );
02618         }
02619         else if ( &(*chatBot_) )
02620         {
02621             chatBot_->nextChatAI_ = 0;
02622         }
02623 
02624         bool simulate=Alive();
02625 
02626         if ( !pendingTurns.empty() || currentDestination )
02627             simulate=true;
02628 
02629         if (simulate)
02630         {
02631             try
02632             {
02633                 ret = gCycleMovement::Timestep(currentTime);
02634             }
02635             catch ( gCycleDeath const & death )
02636             {
02637                 KillAt( death.pos_ );
02638                 return false;
02639             }
02640         }
02641         else
02642             ret = !Alive();
02643     }
02644     else
02645     {
02646         // just basic movement to do: let base class handle that.
02647         try
02648         {
02649             gCycleMovement::Timestep(currentTime);
02650         }
02651         catch ( gCycleDeath const & death )
02652         {
02653             KillAt( death.pos_ );
02654             return false;
02655         }
02656     }
02657 
02658     // do the rest of the timestep
02659     try
02660     {
02661         if ( currentTime > lastTime )
02662             ret = gCycleMovement::Timestep(currentTime);
02663     }
02664     catch ( gCycleDeath const & death )
02665     {
02666         KillAt( death.pos_ );
02667         return false;
02668     }
02669 
02670     REAL predictTime = CalculatePredictPosition( predictPositionData );
02671 
02672     if ( Alive() && currentWall )
02673     {
02674         // z-man: the next two lines are a very bad idea. This lets walls stick out on the other side while you're using up your rubber.
02675         //if ( sn_GetNetState() != nSERVER )
02676         //    wallEndPos = pos + dirDrive * ( verletSpeed_ * se_PredictTime() );
02677 
02678         // but using the predicted position which halts at walls may work
02679         currentWall->Update(predictTime, PredictPosition() );
02680     }
02681 
02682     return ret;

Here is the call graph for this function:

Here is the caller graph for this function:

bool gCycle::TimestepCore ( REAL  currentTime,
bool  calculateAcceleration = true 
) [virtual]

core physics simulation routine

Parameters:
currentTime time to simulate up to
Returns:
true if the cycle is to be killed

Reimplemented from gCycleMovement.

Definition at line 2738 of file gCycle.cpp.

References gCycleMovement::Alive(), gRealColor::b, clamp(), ClampDisplacement(), color_, correctDistanceSmooth, correctPosSmooth, crash_sparks, gPlayerWall::Cycle(), DecaySmooth(), Die(), eGameObject::dir, gCycleMovement::dirDrive, gCycleMovement::dirSpawn, DropWall(), eCoord, EPS, fr, gRealColor::g, gCycleMovement::GetMaxSpaceAhead(), joystick_, KillAt(), eGameObject::lastTime, lastTimeAnim, gCycleMovement::lastTurnPos_, gCycleMovement::MoveSafely(), nextSync, nextSyncOwner, nSERVER, nNetObject::Owner(), eGameObject::pos, gCycleDeath::pos_, gRealColor::r, REAL, gCycleMovement::RequestSync(), RequestSyncOwner(), rotate(), rotationFrontWheel, rotationRearWheel, gCycleMovement::rubberSpeedFactor, sg_ArchiveCoord(), sg_ArchiveReal(), sg_avoidBadOldClientSync, sg_cycleSyncSmoothMinSpeed, sg_cycleSyncSmoothThreshold, sg_cycleSyncSmoothTime, sg_cycleWallTime, sg_GetSparksDistance(), sg_GetSyncIntervalSelf(), sg_NoLocalTunnelOnSync, sg_syncIntervalEnemy, skew, skewDot, sn_Connections, sn_GetNetState(), spawnTime_, gCycleMovement::Speed(), sqrt(), nVersionFeature::Supported(), gCycleMovement::TimestepCore(), TransferPositionCorrectionToDistanceCorrection(), ts, tSysTimeFloat(), gJoystick::Turn(), nBandwidthControl::Usage_Planning, and gCycleMovement::verletSpeed_.

Referenced by OnNotifyNewDestination().

02739                                                                       {
02740     if (!finite(skew))
02741         skew=0;
02742     if (!finite(skewDot))
02743         skewDot=0;
02744 
02745     eCoord oldpos=pos;
02746 
02747     // let the joystick execute delayed turns
02748     if ( joystick_ )
02749     {
02750         joystick_->Turn();
02751     }
02752 
02753     // archive rubber speed for later comparison
02754     REAL rubberSpeedFactorBack = rubberSpeedFactor;
02755 
02756     REAL ts=(currentTime-lastTime);
02757 
02758     clamp(ts, -10, 10);
02759     //clamp(correctTimeSmooth, -100, 100);
02760     clamp(correctDistanceSmooth, -100, 100);
02761     //clamp(correctSpeedSmooth, -100, 100);
02762 
02763     // scale factor for smoothing. It is always used as
02764     // value += smooth * smooth_correction;
02765     // smooth_correction -= smooth * smooth_correction;
02766 
02767     REAL smooth = 0;
02768 
02769     if ( ts > 0 )
02770     {
02771         // go a bit of the way
02772         smooth = 1 - 1/( 1 + ts / sg_cycleSyncSmoothTime );
02773     }
02774 
02775     //if ( smooth > 0)
02776     //{
02777     //    REAL scd = correctDistanceSmooth * smooth;
02778     //    distance += scd;
02779     //    correctDistanceSmooth -= scd;
02780     // }
02781 
02782     // handle distance correction
02783     TransferPositionCorrectionToDistanceCorrection();
02784 
02785     // apply smooth position correction
02786     // smooth = .5f;
02787     //correctPosSmooth = eCoord(0,0);
02788 
02789     // correctPosSmooth = correctPosSmooth * ( 1 - smooth );
02790 
02791     //if ( 0 )
02792 
02793     REAL animts=currentTime-lastTimeAnim;
02794     if (animts<0 || !finite(animts))
02795         animts=0;
02796     else
02797         lastTimeAnim=currentTime;
02798 
02799     // handle decaying of smooth position correction
02800     {
02801         // let components of smooth position correction decay
02802         REAL minSpeed = sg_cycleSyncSmoothMinSpeed * Speed() * animts;
02803         REAL clamp    = sg_cycleSyncSmoothThreshold * Speed();
02804 
02805         DecaySmooth( correctPosSmooth.x, smooth, minSpeed, clamp );
02806         DecaySmooth( correctPosSmooth.y, smooth, minSpeed, clamp );
02807 
02808         // do sanity checks
02809         if ( correctPosSmooth.NormSquared() > EPS )
02810         {
02811             // cast ray to make sure corrected position lies on the right side of walls
02812             ClampDisplacement( this, correctPosSmooth, correctPosSmooth * 2, pos );
02813 
02814             // same for negative direction, players should see it when they are close to a wall
02815             ClampDisplacement( this, correctPosSmooth, -correctPosSmooth, pos );
02816 
02817             // cast another some rays into the future
02818             eCoord lookahead = dirDrive * ( 2 * correctPosSmooth.Norm() );
02819             ClampDisplacement( this, correctPosSmooth, lookahead, pos );
02820         }
02821     }
02822 
02823     if (animts>.2)
02824         animts=.2;
02825 
02826     rotate(rotationFrontWheel,2*verletSpeed_*animts/.43);
02827     rotate(rotationRearWheel,2*verletSpeed_*animts/.73);
02828 
02829     REAL sparksDistance = sg_GetSparksDistance();
02830     REAL extension = .25;
02831     if ( extension < sparksDistance )
02832         extension = sparksDistance;
02833 
02834     //    REAL step=speed*ts; // +.5*acceleration*ts*ts;
02835 
02836     // animate cycle direction
02837     {
02838         // move it a bit closer to dirDrive
02839         dir=dir+dirDrive*animts*verletSpeed_*3;
02840 
02841         // if it's too far away from dirDrive, clamp it
02842         eCoord dirDistance = dir - dirDrive;
02843         REAL dist = dirDistance.NormSquared();
02844         const REAL maxDist = .8;
02845         if (dirDistance.NormSquared() > maxDist)
02846             dir = dirDrive + dirDistance* (1/sqrt(dist/maxDist));
02847 
02848         // normalize
02849         dir=dir*(1/sqrt(dir.NormSquared()));
02850     }
02851 
02852     {
02853         eCoord oldPos = pos;
02854 
02855         if ( Alive() ){
02856             // delegate core work to base class
02857             try
02858             {
02859                 // start building wall
02860                 REAL startBuildWallAt = spawnTime_ + sg_cycleWallTime;
02861                 if ( !currentWall && currentTime > startBuildWallAt  )
02862                 {
02863                     // simulate right to the spot where the wall should begin
02864                     if ( currentTime < startBuildWallAt )
02865                         if ( gCycleMovement::TimestepCore( startBuildWallAt, calculateAcceleration ) )
02866                             return true;
02867                     calculateAcceleration = true;
02868 
02869                     // build the wall, modifying the spawn time to make sure it happens
02870                     REAL lastSpawn = spawnTime_;
02871                     spawnTime_ += -1E+20;
02872                     DropWall();
02873                     spawnTime_ = lastSpawn;
02874                     dirSpawn = dirDrive;
02875                     lastTurnPos_ = pos; // hack last turn position to generate good wall
02876                 }
02877 
02878                 // simulate rest of frame
02879                 if ( gCycleMovement::TimestepCore( currentTime, calculateAcceleration ) )
02880                     return true;
02881             }
02882             catch ( gCycleDeath const & death )
02883             {
02884                 KillAt( death.pos_ );
02885 
02886                 // death exceptions are precise; we can safely take over the position from it
02887                 oldPos = death.pos_;
02888             }
02889         }
02890 
02891         // die where you started
02892         if ( !Alive() )
02893         {
02894             MoveSafely(oldPos,currentTime,currentTime);
02895             Die( currentTime );
02896         }
02897     }
02898 
02899     // Debug archive position and speed
02900     sg_ArchiveCoord( pos, 7 );
02901     sg_ArchiveReal( verletSpeed_, 7 );
02902 
02903     if (Alive()){
02904 #ifndef DEDICATED
02905         // animate skew
02906         gSensor fl(this,pos,dirDrive.Turn(1,1));
02907         gSensor fr(this,pos,dirDrive.Turn(1,-1));
02908 
02909         fl.detect(extension*4);
02910         fr.detect(extension*4);
02911 
02912         if (fl.hit > extension)
02913             fl.hit = extension;
02914 
02915         if (fr.hit > extension)
02916             fr.hit = extension;
02917 
02918         REAL lr=(fl.hit-fr.hit)/extension;
02919 
02920         // ODE for skew
02921         const REAL skewrelax=24;
02922         skewDot-=128*(skew+lr/2)*animts;
02923         skewDot/=1+skewrelax*animts;
02924         if (skew*skewDot>4) skewDot=4/skew;
02925         skew+=skewDot*animts;
02926 
02927         REAL fac = 0.5f;
02928         if ( skew > fr.hit * fac )
02929         {
02930             skew = fr.hit * fac;
02931         }
02932         if ( skew < -fl.hit * fac )
02933         {
02934             skew = -fl.hit * fac;
02935         }
02936 
02937         // generate sparks
02938         eCoord sparkpos,sparkdir;
02939 
02940         if (fl.ehit && fl.hit<=sparksDistance){
02941             sparkpos=pos+dirDrive.Turn(1,1)*fl.hit;
02942             sparkdir=dirDrive.Turn(0,-1);
02943         }
02944         if (fr.ehit && fr.hit<=sparksDistance){
02945             sparkpos=pos+dirDrive.Turn(1,-1)*fr.hit;
02946             sparkdir=dirDrive.Turn(0,1);
02947         }
02948 
02949         if (fabs(skew)<fabs(lr*.8) ){
02950             skewDot-=lr*1000*animts;
02951             if (crash_sparks && animts>0)
02952             {
02953                 gPlayerWall *tmpplayerWall=0;
02954 
02955                 if(fl.ehit) tmpplayerWall=dynamic_cast<gPlayerWall*>(fl.ehit->GetWall());
02956                 if(fr.ehit) tmpplayerWall=dynamic_cast<gPlayerWall*>(fr.ehit->GetWall());
02957 
02958                 if(tmpplayerWall) {
02959                     gCycle *tmpcycle = tmpplayerWall->Cycle();
02960 
02961                     if( tmpcycle )
02962                         new gSpark(grid, sparkpos-dirDrive*.1,sparkdir,currentTime,color_.r,color_.g,color_.b,tmpcycle->color_.r,tmpcycle->color_.g,tmpcycle->color_.b);
02963                 }
02964                 else
02965                     new gSpark(grid, sparkpos-dirDrive*.1,sparkdir,currentTime,color_.r,color_.g,color_.b,1,1,1);
02966             }
02967         }
02968 
02969         if (fabs(skew)<fabs(lr*.9) ){
02970             skewDot-=lr*100*animts;
02971             if (crash_sparks && animts>0)
02972             {
02973                 gPlayerWall *tmpplayerWall=0;
02974 
02975                 if(fl.ehit) tmpplayerWall=dynamic_cast<gPlayerWall*>(fl.ehit->GetWall());
02976                 if(fr.ehit) tmpplayerWall=dynamic_cast<gPlayerWall*>(fr.ehit->GetWall());
02977 
02978                 if(tmpplayerWall) {
02979                     gCycle *tmpcycle = tmpplayerWall->Cycle();
02980 
02981                     if( tmpcycle )
02982                         new gSpark(grid, sparkpos-dirDrive*.1,sparkdir,currentTime,color_.r,color_.g,color_.b,tmpcycle->color_.r,tmpcycle->color_.g,tmpcycle->color_.b);
02983                 }
02984                 else
02985                     new gSpark(grid, sparkpos-dirDrive*.1,sparkdir,currentTime,color_.r,color_.g,color_.b,1,1,1);
02986             }
02987         }
02988 #endif
02989         /*
02990           if (fl.hit+fr.hit<extension*.4)
02991           Kill();
02992         */
02993     }
02994 
02995     // clamp skew
02996     if (skew>.5){
02997         skew=.5;
02998         skewDot=0;
02999     }
03000 
03001     if (skew<-.5){
03002         skew=-.5;
03003         skewDot=0;
03004     }
03005 
03006     // checkpoint wall when rubber starts to get used
03007     if ( currentWall )
03008     {
03009         if ( rubberSpeedFactor >= .99 && rubberSpeedFactorBack < .99 )
03010         {
03011             currentWall->Checkpoint();
03012         }
03013 
03014         if ( rubberSpeedFactor < .99 && rubberSpeedFactorBack >= .99 )
03015         {
03016             currentWall->Checkpoint();
03017         }
03018 
03019         if ( rubberSpeedFactor < .1 && rubberSpeedFactorBack >= .1 )
03020         {
03021             currentWall->Checkpoint();
03022         }
03023 
03024         if ( rubberSpeedFactor < .01 && rubberSpeedFactorBack >= .01 )
03025         {
03026             currentWall->Checkpoint();
03027         }
03028     }
03029 
03030 
03031     if ( sn_GetNetState()==nSERVER )
03032     {
03033         // do an emergency sync when rubber starts to get used, it may come unexpected to clients
03034         if ( rubberSpeedFactor < .99 && rubberSpeedFactorBack >= .99 )
03035         {
03036             RequestSyncOwner();
03037         }
03038 
03039         if (nextSync < tSysTimeFloat() )
03040         {
03041             // delay syncs for old clients when there is a wall ahead; they would tunnel locally
03042             REAL lookahead = Speed() * sg_syncIntervalEnemy*.5;
03043             if ( !sg_avoidBadOldClientSync || sg_NoLocalTunnelOnSync.Supported( Owner() ) || GetMaxSpaceAhead( lookahead ) >= lookahead )
03044             {
03045                 RequestSync(false);
03046 
03047                 // checkpoint wall for better collision accuracy, only required on the server
03048                 if ( currentWall )
03049                     currentWall->Checkpoint();
03050             }
03051 
03052             nextSync=tSysTimeFloat()+sg_syncIntervalEnemy;
03053             nextSyncOwner=tSysTimeFloat()+sg_GetSyncIntervalSelf( this );
03054         }
03055         else if ( nextSyncOwner < tSysTimeFloat() &&
03056                   Owner() != 0 &&
03057                   sn_Connections[Owner()].bandwidthControl_.Control( nBandwidthControl::Usage_Planning ) > 200 )
03058         {
03059             // sync only to the owner (provided there is enough bandwidth available)
03060             RequestSyncOwner();
03061         }
03062     }
03063 
03064     return (!Alive());

Here is the call graph for this function:

Here is the caller graph for this function:

void gCycle::InteractWith ( eGameObject target,
REAL  time,
int  recursion = 1 
) [virtual]

Reimplemented from eGameObject.

Definition at line 3067 of file gCycle.cpp.

03068                                                      {
03069     /*
03070       if (alive && target->type()==ArmageTron_CYCLE){
03071          gCycle *c=(gCycle *)target;
03072          if (c->alive){
03073       const eEdge *current_eEdge=Edge();
03074       const eEdge *other_eEdge=c->Edge();
03075       if(current_eEdge && other_eEdge){
03076       ePoint *meet=current_eEdge->IntersectWith(other_eEdge);
03077       if (meet){ // somebody is going to die!
03078       REAL ratio=current_eEdge->Ratio(*meet);
03079       REAL time=CurrentWall()->Time(ratio);
03080       PassEdge(other_eEdge,time,other_eEdge->Ratio(*meet),0);
03081       }
03082       }
03083          }
03084       }
03085     */

bool gCycle::EdgeIsDangerous ( const eWall wall,
REAL  time,
REAL  alpha 
) const [virtual]

returns whether a given wall is dangerous to this cycle

Parameters:
wall the wall to check for danger
time the time of the possible collision
alpha the local wall coordinate of the collision
Returns:
true if the wall is dangerous

Reimplemented from gCycleMovement.

Definition at line 3264 of file gCycle.cpp.

References gPlayerWall::Cycle(), gPlayerWall::CycleMovement(), gCycleMovement::EdgeIsDangerous(), gJustChecking::justChecking, gPlayerWall::NetWall(), nNetObject::Owner(), sn_myNetID, eGameObject::Team(), gPlayerWall::Time(), and Vulnerable().

Referenced by PassEdge().

03265                                                                     {
03266     gPlayerWall const * w = dynamic_cast< gPlayerWall const * >( ww );
03267     if ( w )
03268     {
03269         if ( !Vulnerable() )
03270             return false;
03271 
03272         gNetPlayerWall *nw = w->NetWall();
03273 
03274         // check whether the wall is one of the walls no real collision is
03275         // possible with. The lastNetWall is only checked for enemy cycles,
03276         // because it can be an arbitrary wall for your own cycle. But for
03277         // enemy cycles, it may be what lastWall should be, and the test
03278         // prevents enemy cycles from getting stuck right after a turn.
03279         if( nw == currentWall || nw == lastWall || ( nw == lastNetWall && Owner() != sn_myNetID ) )
03280             return false;
03281 
03282         // see if the wall is from another player and from the future.
03283         // if it is, it's not dangerous, this cycle was here first.
03284         // on passing the wall later, the other cycle will be pushed back
03285         // to the collision point or killed if that is no longer possible.
03286         // z-man notes: I've got the vaque feeling something like this was
03287         // here before, but got thrown out again for making problems.
03288         if ( gJustChecking::justChecking && w->CycleMovement() != static_cast< const gCycleMovement * >( this ) && w->Time(a) > time )
03289         {
03290             // One problem with this is that you kill teammates if they can't
03291             // be pushed back, whereas we'd just use our rubber to survive.
03292             // So we should first check whether the other player should be
03293             // protected.
03294             gCycle const * otherPlayer = w->Cycle();
03295             if ( !otherPlayer || // valididy
03296                     otherPlayer->Team() != this->Team() || // team protection
03297                     !otherPlayer->currentWall || w == otherPlayer->currentWall->Wall() // pushback protection, if the other player can be pushed back, it's all right as well
03298                )
03299                 return false;
03300         }
03301     }
03302 
03303     return gCycleMovement::EdgeIsDangerous( ww, time, a );

Here is the call graph for this function:

Here is the caller graph for this function:

void gCycle::PassEdge ( const eWall w,
REAL  time,
REAL  a,
int  recursion = 1 
) [virtual]

Reimplemented from eGameObject.

Definition at line 3338 of file gCycle.cpp.

References gExplosion::AccountForHole(), gEnemyInfluence::AddWall(), gCycleMovement::Alive(), ePlayerNetID::CurrentTeam(), gPlayerWall::Cycle(), d, gCycleMovement::dirDrive, gCycleMovement::distance, DropWall(), dropWallRequested_, dt, eCoord, EdgeIsDangerous(), gCycleMovement::enemyInfluence, EPS, Extrapolate(), extrapolator_, gCycleMovement::GetDistanceSinceLastTurn(), gCycleMovement::GetLastTurnPos(), eGameObject::GetMaxLazyLag(), gExplosion::GetOwner(), ePlayerNetID::GetUserName(), gPlayerWall::Holer(), KillAt(), eNetGameObject::Lag(), eGameObject::LastTime(), eGameObject::lastTime, max(), gCycleMovement::MoveSafely(), nCLIENT, eNetGameObject::Player(), eWall::Point(), eGameObject::pos, gPlayerWall::Pos(), REAL, RequestSyncAll(), RequestSyncOwner(), ResetExtrapolator(), gCycleMovement::rubber, score_hole, se_GameTime(), se_SaveToLadderLog(), sg_HoleScore(), sg_KillFutureWalls(), sg_RubberValues(), sn_GetNetState(), gCycleMovement::Speed(), ThisWallsLength(), gPlayerWall::Time(), gCycleMovement::verletSpeed_, and Vulnerable().

Referenced by sg_TopologyPoliceCheck().

03339                                                          {
03340     {
03341         // deactivate time check
03342         gJustChecking thisIsSerious;
03343 
03344         if (!EdgeIsDangerous(ww,time,a) || !Alive() )
03345         {
03346             // request a sync for everyone if this is a non-bogus wall passage, maybe not all clients know the wall is passable
03347             if ( ( !currentWall || ww != currentWall->Wall() ) && ( !lastWall || ww != lastWall->Wall() ) )
03348                 RequestSyncAll();
03349             
03350             // check whether we drove through a hole in an enemy wall made by a teammate
03351             gPlayerWall const * w = dynamic_cast< gPlayerWall const * >( ww );
03352             if ( w && score_hole )
03353             {
03354                 gExplosion * explosion = w->Holer( a, time );
03355                 if ( explosion )
03356                 {
03357                     gCycle * holer = explosion->GetOwner();
03358                     if ( holer && holer->Player() &&
03359                          Player() &&
03360                          w->Cycle() && w->Cycle()->Player() &&
03361                          holer->Player()->CurrentTeam() == Player()->CurrentTeam() &&       // holer must have been a teammate 
03362                          w->Cycle()->Player()->CurrentTeam() != Player()->CurrentTeam()  // wall must have been an enemy
03363                         )
03364                     {
03365                         // this test must come last, it resets the flag.
03366                         if ( explosion->AccountForHole() )
03367                         {
03368                             tString ladderLog;
03369                             ladderLog << "SACRIFICE " << Player()->GetUserName() << " " << holer->Player()->GetUserName() << " " << w->Cycle()->Player()->GetUserName() << "\n";
03370                             se_SaveToLadderLog( ladderLog );
03371                             if ( score_hole > 0 )
03372                             {
03373                                 // positive hole score goes to the holer
03374                                 sg_HoleScore( *holer );
03375                             }
03376                             else
03377                             {
03378                                 // negative hole score to the driver
03379                                 sg_HoleScore( *this );
03380 
03381                             }
03382                        }
03383                     }
03384                 }
03385             }
03386 
03387             return;
03388         }
03389 
03390 #ifdef DEBUG
03391         if (!EdgeIsDangerous(ww,time,a) || !Alive() )
03392             return;
03393 #endif
03394     }
03395 
03396     // request a sync to bring everyone up to date about the cycle passing/getting stuck on this wall
03397     RequestSyncOwner();
03398 
03399 #ifdef DEBUG_X
03400     // keep other cycle around
03401     tJUST_CONTROLLED_PTR<gCycleExtrapolator> keepOther( extrapolator_ );
03402 
03403     ResetExtrapolator();
03404 
03405     // extrapolate state from server and copy state when finished
03406     REAL dt = 1;
03407     for ( int i = 9; i>= 0; --i )
03408     {
03409         Extrapolate( dt );
03410     }
03411 
03412     extrapolator_ = keepOther;
03413 #endif
03414 
03415     eCoord collPos = ww->Point( a );
03416 
03417     const gPlayerWall *w = dynamic_cast<const gPlayerWall*>(ww);
03418 
03419     enemyInfluence.AddWall( ww, collPos, 0, this );
03420 
03421     if (w)
03422     {
03423         gCycle *otherPlayer=w->Cycle();
03424 
03425         REAL otherTime = w->Time(a);
03426         if(otherPlayer && time < otherTime*(1-EPS) )
03427         {
03428             // also send updates about the other cylce
03429             otherPlayer->RequestSyncOwner();
03430 
03431             // get the distance of the wall
03432             REAL wallDist = w->Pos(a);
03433             // get the distance the cycle is simulated up to
03434             REAL cycleDist = w->Cycle()->distance;
03435             // comparing these two gives an accurate criterion whether the wall is extrapolated
03436             if ( wallDist > cycleDist * (1 + EPS ) )
03437             {
03438                 static bool fix = false;
03439                 // it's an extrapolation wall, don't simulate further.
03440                 if ( fix && lastTime > se_GameTime() - 2 * Lag() - GetMaxLazyLag() )
03441                     throw gCycleStop();
03442                 else
03443                     return;
03444             }
03445 
03446             // we were first!
03447             if ( otherPlayer->Vulnerable() )
03448             {
03449                 static bool tryToSaveFutureWallOwner = true;
03450                 bool saved = false;
03451 
03452                 if ( tryToSaveFutureWallOwner && otherPlayer->currentWall && w == otherPlayer->currentWall->Wall() )
03453                 {
03454                     // teleport the other cycle back to the point before the collision; its next timestep
03455                     // will simulate the collision again from the right viewpoint
03456                     // determine the distance of the pushback
03457                     REAL d = otherPlayer->GetDistanceSinceLastTurn() * .001;
03458                     if ( d < .01 )
03459                         d = .01;
03460                     REAL maxd = eCoord::F( otherPlayer->dirDrive, collPos - otherPlayer->GetLastTurnPos() ) * .5/otherPlayer->dirDrive.NormSquared();
03461                     if ( d > maxd )
03462                         d = maxd;
03463                     if ( d > 0 )
03464                     {
03465                         saved = true;
03466 
03467                         // do the move
03468                         otherPlayer->MoveSafely( collPos-otherPlayer->dirDrive*d, otherPlayer->LastTime(), otherTime - d/otherPlayer->Speed() );
03469                         otherPlayer->currentWall->Update( otherPlayer->lastTime, otherPlayer->pos );
03470                         otherPlayer->dropWallRequested_ = false;
03471 
03472                         // drop our wall so collisions are more accurate
03473                         dropWallRequested_ = true;
03474                     }
03475                 }
03476 
03477                 // another possibility: if the walls are very short compared to rubber, we could
03478                 // get away with just accounding for some rubber on the cycle that we'd need to kill
03479                 // otherwise.
03480                 if ( !saved && verletSpeed_ >= 0 )
03481                 {
03482                     REAL dt = otherTime - time;
03483 
03484                     // this long would the other cycle have to sit in front of our wall
03485                     // before he's released by the end
03486                     REAL wallTimeLeft = this->ThisWallsLength()/verletSpeed_ - dt;
03487 
03488                     if ( wallTimeLeft < 0 )
03489                     {
03490                         // isn't hit at all
03491                         return;
03492                     }
03493 
03494                     // check how much rubber would be used
03495                     REAL max, effectiveness;
03496                     sg_RubberValues( otherPlayer->Player(), otherPlayer->verletSpeed_, max, effectiveness );
03497                     if ( effectiveness > 0 )
03498                     {
03499                         REAL rubberToEat = wallTimeLeft * otherPlayer->Speed()/effectiveness;
03500 
03501                         otherPlayer->rubber += rubberToEat;
03502                         if ( otherPlayer->rubber > max )
03503                             otherPlayer->rubber = max; // too much rubber used
03504                         else
03505                             saved = true;              // within bounds, he may survive
03506                     }
03507                 }
03508 
03509                 if ( !saved && sn_GetNetState() != nCLIENT )
03510                 {
03511                     // err, trouble. Can't push the other guy back far enough. Better kill him.
03512                     if ( currentWall )
03513                         otherPlayer->enemyInfluence.AddWall( currentWall->Wall(), lastTime, otherPlayer );
03514                     otherPlayer->distance = wallDist;
03515                     otherPlayer->DropWall();
03516                     otherPlayer->KillAt( collPos );
03517 
03518                     // get rid of future walls
03519                     sg_KillFutureWalls( otherPlayer );
03520                 }
03521             }
03522         }
03523         else // sad but true
03524         {
03525             // this cycle has to die here unless it has rubber left or is invulnerable (checked on catching the exception, and besides, this code path isn't called for invulnerable cycles)
03526             throw gCycleDeath( collPos );
03527 
03528             //                  REAL dist = w->Pos( a );
03529             //                  const_cast<gPlayerWall*>(w)->BlowHole( dist - explosionRadius, dist + explosionRadius );
03530         }
03531     }
03532     else
03533     {
03534         if (bool(player) && sn_GetNetState()!=nCLIENT && Alive() )
03535         {
03536             throw gCycleDeath( collPos );
03537         }
03538 
03539     }

Here is the call graph for this function:

Here is the caller graph for this function:

REAL gCycle::PathfindingModifier ( const eWall w  )  const [virtual]

Reimplemented from eGameObject.

Definition at line 3541 of file gCycle.cpp.

03543 {
03544     if (!w)
03545         return 1;
03546     if (dynamic_cast<const gPlayerWall*>(w))
03547         return .9f;
03548     else
03549         return 1;

bool gCycle::Act ( uActionPlayer Act,
REAL  x 
) [virtual]

Reimplemented from eGameObject.

Definition at line 3552 of file gCycle.cpp.

References gCycleMovement::AccelerationDiscontinuity(), gJoystick::Act(), gCycleMovement::AddDestination(), gCycleMovement::Alive(), gCycleMovement::braking, joystick_, nSERVER, gCycleMovement::RequestSync(), s_brake, s_brakeToggle, se_mainGameTimer, eGameObject::se_turnLeft, eGameObject::se_turnRight, sn_GetNetState(), eTimer::speed, eTimer::Time(), and gCycleMovement::Turn().

Referenced by ReceiveControl().

03553                                           {
03554     // delegate to joystick
03555     if ( joystick_ && joystick_->Act( Act, x ) )
03556     {
03557         return true;
03558     }
03559 
03560     // don't accept premature input
03561     if (se_mainGameTimer && ( se_mainGameTimer->speed <= 0 || se_mainGameTimer->Time() < -1 ) )
03562         return false;
03563 
03564     if (!Alive() && sn_GetNetState()==nSERVER)
03565         RequestSync(false);
03566 
03567     if(se_turnLeft==*Act && x>.5){
03568         //SendControl(lastTime,&se_turnLeft,1);
03569         Turn(-1);
03570         return true;
03571     }
03572     else if(se_turnRight==*Act && x>.5){
03573         //SendControl(lastTime,&se_turnRight,1);
03574         Turn(1);
03575         return true;
03576     }
03577     else if(s_brake==*Act){
03578         //SendControl(lastTime,&brake,x);
03579         unsigned short newBraking=(x>0);
03580         if ( braking != newBraking )
03581         {
03582             AccelerationDiscontinuity();
03583             braking = newBraking;
03584             AddDestination();
03585         }
03586         return true;
03587     }
03588     else if(s_brakeToggle==*Act){
03589         if ( x > 0 )
03590         {
03591             AccelerationDiscontinuity();
03592             braking = !braking;
03593             AddDestination();
03594         }
03595         return true;
03596     }
03597     return false;

Here is the call graph for this function:

Here is the caller graph for this function:

bool gCycle::DoTurn ( int  dir  )  [virtual]

turns the cycle in the given direction

Parameters:
dir +1 for right turns, -1 for left turns
Returns:
true of the turn could be executed right now, false if it was queued

Reimplemented from gCycleMovement.

Definition at line 3621 of file gCycle.cpp.

References gCycleMovement::AddDestination(), gCycleMovement::Alive(), eNetGameObject::clientside_action(), con, CYCLE_TURN, gCycleMovement::dirDrive, gCycleMovement::DoTurn(), DropWall(), eCoord, EPS, eGameObject::FindCurrentFace(), eSoundMixer::GetMixer(), gCycleMovement::lastDirDrive, nCLIENT, nSERVER, nNetObject::Owner(), eNetGameObject::Player(), eGameObject::pos, eGameObject::Position(), eSoundMixer::PushButton(), REAL, gCycleMovement::RequestSync(), sg_ArchiveCoord(), sg_gnuplotDebug, skewDot, sn_GetNetState(), sn_myNetID, tSysTimeFloat(), and gCycleMovement::turns.

03623 {
03624 #ifdef DELAYEDTURN_DEBUG
03625     REAL delay = tSysTimeFloat() - sg_turnReceivedTime;
03626     if ( delay > EPS && sn_GetNetState() == nSERVER && Owner() != 0 )
03627     {
03628         con << "Delayed turn execution! " << turns << "\n";
03629     }
03630 #endif
03631 
03632 #ifdef GNUPLOT_DEBUG
03633     if ( sg_gnuplotDebug && Player() )
03634     {
03635         std::ofstream f( Player()->GetUserName() + "_turn", std::ios::app );
03636         f << pos.x << " " << pos.y << "\n";
03637     }
03638 #endif
03639 
03640     if (d >  1) d =  1;
03641     if (d < -1) d = -1;
03642 
03643     if (Alive()){
03644         eSoundMixer* mixer = eSoundMixer::GetMixer();
03645         mixer->PushButton(CYCLE_TURN, Position());
03646 
03647         clientside_action();
03648 
03649         if ( gCycleMovement::DoTurn( d ) )
03650         {
03651             sg_ArchiveCoord( pos, 1 );
03652 
03653             skewDot+=4*d;
03654 
03655             if (sn_GetNetState() == nCLIENT && Owner() == ::sn_myNetID)
03656                 AddDestination();
03657 
03658             if (sn_GetNetState()!=nCLIENT)
03659             {
03660                 RequestSync();
03661             }
03662 
03663             // hack: while dropping the wall, turn around dirDrive.
03664             // this makes FindCurrentFace work better.
03665             {
03666                 FindCurrentFace();
03667                 REAL factor = -16;
03668                 eCoord dirDriveFake = dirDrive * factor;
03669                 eCoord lastDirDriveBack = lastDirDrive;
03670                 lastDirDrive = lastDirDrive * factor;
03671                 gFakeDirDriveSetter fakeSetter( dirDriveFake );
03672                 DropWall();
03673                 lastDirDrive = lastDirDriveBack;
03674             }
03675 
03676             return true;
03677         }
03678     }
03679 
03680     return false;

Here is the call graph for this function:

void gCycle::DropWall ( bool  buildNew = true  ) 

Drops the current wall and builds a new one.

Definition at line 3682 of file gCycle.cpp.

References c, eGameObject::CurrentFace(), gCycleMovement::dirDrive, gCycleMovement::distance, dropWallRequested_, eCoord, eGameObject::FindCurrentFace(), gNetPlayerWall, eDual::IsInGrid(), eGameObject::lastTime, NULL, eGameObject::pos, sg_cycleWallTime, sg_fakeDirDrive, and spawnTime_.

Referenced by DoTurn(), PassEdge(), ReadSync(), and TimestepCore().

03684 {
03685     // keep this cycle alive
03686     tJUST_CONTROLLED_PTR< gCycle > keep( this->GetRefcount()>0 ? this : 0 );
03687 
03688     // drop last net wall if it is outdated
03689     if ( lastWall && lastNetWall && lastWall->Time(.5) > lastNetWall->Time(0) )
03690         lastNetWall = 0;
03691 
03692     // update and drop current wall
03693     if(currentWall)
03694     {
03695         lastWall=currentWall;
03696         currentWall->Update(lastTime,pos);
03697         currentWall->CopyIntoGrid( grid );
03698         currentWall=NULL;
03699     }
03700 
03701     if ( buildNew && lastTime >= spawnTime_ + sg_cycleWallTime )
03702         currentWall=new gNetPlayerWall(this,pos,dirDrive,lastTime,distance);
03703 
03704     // grid datastructures change on inserting a wall, better recheck
03705     // all game objects. Temporarily override this cycle's driving direction.
03706     eCoord dirDriveBack = dirDrive;
03707     if ( sg_fakeDirDrive )
03708         dirDrive = *sg_fakeDirDrive;
03709 
03710     if ( grid )
03711     {
03712         for(int i=grid->GameObjects().Len()-1;i>=0;i--)
03713         {
03714             eGameObject * c = grid->GameObjects()(i);
03715             if (c->CurrentFace() && !c->CurrentFace()->IsInGrid() )
03716                 c->FindCurrentFace();
03717         }
03718     }
03719     dirDrive = dirDriveBack;
03720 
03721     // reset flag
03722     dropWallRequested_ = false;

Here is the call graph for this function:

Here is the caller graph for this function:

void gCycle::Kill (  )  [virtual]

destroys the gameobject (in the game)

Reimplemented from eGameObject.

Definition at line 3724 of file gCycle.cpp.

References gCycleMovement::Alive(), color_, Die(), gCycleMovement::distance, eGameObject::GOID(), eGameObject::lastTime, nCLIENT, NULL, eGameObject::pos, gCycleMovement::RequestSync(), sn_GetNetState(), and tNEW.

Referenced by ActionOnQuit(), gGame::Analysis(), KillAt(), gDeathZoneHack::OnEnter(), and sg_TopologyPoliceKill().

03725                  {
03726     // keep this cycle alive
03727     tJUST_CONTROLLED_PTR< gCycle > keep( this->GetRefcount()>0 ? this : 0 );
03728 
03729     if (sn_GetNetState()!=nCLIENT){
03730         RequestSync(true);
03731         if (Alive() && grid && GOID() >= 0 ){
03732             Die( lastTime );
03733             tNEW(gExplosion)(grid, pos,lastTime, color_, this );
03734             //   eEdge::SeethroughHasChanged();
03735 
03736             if ( currentWall )
03737             {
03738                 // z-man: updating the wall so it reflects exactly the position of death looks like
03739                 // a good idea, but unfortunately, the collision position reported from above
03740                 // is inaccurate. It's better not to use it at all, or the cycle's wall will stick out
03741                 // a bit on the other side of the wall it crashed into.
03742 
03743                 // but if prediction was active, do it anyway
03744                 if ( currentWall->Pos(1) > distance || currentWall->Time(1) > lastTime )
03745                     currentWall->Update( lastTime, pos );
03746 
03747                 // copy the wall into the grid, but not directly; the grid datastructures are probably currently traversed. Kill() is called from eGameObject::Move().
03748                 currentWall->CopyIntoGrid( 0 );
03749 
03750                 currentWall = NULL;
03751             }
03752         }
03753     }
03754     // z-man: another stupid idea. Why would we need a destination when we're dead?
03755     //    else if (Owner() == ::sn_myNetID)
03756     //        AddDestination();
03757     /*
03758       else if (owner!=::sn_myNetID)
03759       speed=-.01;
03760     */

Here is the call graph for this function:

Here is the caller graph for this function:

const eTempEdge * gCycle::Edge (  ) 

Definition at line 1889 of file gCycle.cpp.

References eTempEdge::Edge(), and NULL.

01889                              {
01890     if (currentWall)
01891         return currentWall->Edge();
01892     else
01893         return NULL;
01894 }

Here is the call graph for this function:

const gPlayerWall * gCycle::CurrentWall (  ) 

Definition at line 1896 of file gCycle.cpp.

References NULL.

01896                                       {
01897     if (currentWall)
01898         return currentWall->Wall();
01899     else
01900         return NULL;
01901 }

void gCycle::Render ( const eCamera cam  )  [virtual]

draws object to the screen using OpenGL

Reimplemented from eGameObject.

Definition at line 4141 of file gCycle.cpp.

References gCycleMovement::Alive(), gRealColor::b, BeginLineLoop(), BeginQuads(), BeginTriangles(), body, bodyTex, c, eCamera::CameraZ(), eCamera::Center(), color_, cos(), customModel, customTexture, cycle_shad, cycleprograminited, eGameObject::dir, eCoord, front, gRealColor::g, gCycleMovement::GetTurnDelay(), glMatrixMode, headlights, IdentityMatrix(), eNetGameObject::Lag(), eGameObject::lastTime, M_PI, ModelMatrix(), mp, nSERVER, nSTANDALONE, eGameObject::pos, PredictPosition(), gRealColor::r, REAL, rear, rModel::Render(), RenderEnd(), RenderName(), rFLOOR_GRID, rotationFrontWheel, rotationRearWheel, se_GameTime(), rITexture::Select(), sg_axesIndicator, sg_blinkFrequency, sg_laggometerScale, sg_laggometerThreshold, sin(), gArena::SizeMultiplier(), skew, sn_GetNetState(), spawnTime_, sqrt(), sr_alphaBlend, sr_DepthOffset(), sr_floorDetail, sr_laggometer, sr_predictObjects, st_Breakpoint(), rTextureGroups::TEX_FLOOR, TexMatrix(), rTextureGroups::TextureMode, tSysTimeFloat(), gCycleMovement::verletSpeed_, void(), Vulnerable(), wheelTex, x, and eGameObject::z.

04142                                      {
04143     // are we blinking from invulnerability?
04144     bool blinking = false;
04145     if ( lastTime > spawnTime_ && !Vulnerable() )
04146     {
04147         double time = tSysTimeFloat();
04148         double wrap = time - floor(time);
04149         int pulse = int ( 2 * wrap * sg_blinkFrequency );
04150         blinking = pulse & 1;
04151     }
04152 
04153 #ifdef USE_HEADLIGHT
04154 #ifdef LINUX
04155     typedef void (*glProgramStringARB_Func)(GLenum, GLenum, GLsizei, const void*);
04156     glProgramStringARB_Func glProgramStringARB_ptr = 0;
04157 
04158     typedef void (*glProgramLocalParameter4fARB_Func)(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
04159     glProgramLocalParameter4fARB_Func glProgramLocalParameter4fARB_ptr = 0;
04160 
04161     glProgramStringARB_ptr = (glProgramStringARB_Func) SDL_GL_GetProcAddress("glProgramStringARB");
04162     glProgramLocalParameter4fARB_ptr = (glProgramLocalParameter4fARB_Func) SDL_GL_GetProcAddress("glProgramLocalParameter4fARB");
04163 #endif
04164 #endif    
04165     if (!finite(z) || !finite(pos.x) ||!finite(pos.y)||!finite(dir.x)||!finite(dir.y)
04166             || !finite(skew))
04167         st_Breakpoint();
04168     if (Alive()){
04169         //con << "Drawing cycle at " << pos << '\n';
04170 
04171 #ifdef DEBUG
04172         /*     {
04173                    gDestination *l = destinationList;
04174                    glDisable(GL_LIGHTING);
04175                    glColor3f(1,1,1);
04176                    while(l){
04177                    if (l == currentDestination)
04178                    glColor3f(0,1,0);
04179 
04180                    glBegin(GL_LINES);
04181                    glVertex3f(l->position.x, l->position.y, 0);
04182                    glVertex3f(l->position.x, l->position.y, 100);
04183                    glEnd();
04184 
04185                    if (l == currentDestination)
04186                    glColor3f(0,1,1);
04187 
04188                    l=l->next;
04189                    }
04190                    } */
04191 #endif
04192 
04193         GLfloat color[4]={1,1,1,1};
04194         static GLfloat lposa[4] = { 320, 240, 200,0};
04195         static GLfloat lposb[4] = { -240, -100, 200,0};
04196         static GLfloat lighta[4] = { 1, .7, .7, 1 };
04197         static GLfloat lightb[4] = { .7, .7, 1, 1 };
04198 
04199         glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,color);
04200         glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,color);
04201 
04202         glLightfv(GL_LIGHT0, GL_DIFFUSE, lighta);
04203         glLightfv(GL_LIGHT0, GL_SPECULAR, lighta);
04204         glLightfv(GL_LIGHT0, GL_POSITION, lposa);
04205         glLightfv(GL_LIGHT1, GL_DIFFUSE, lightb);
04206         glLightfv(GL_LIGHT1, GL_SPECULAR, lightb);
04207         glLightfv(GL_LIGHT1, GL_POSITION, lposb);
04208 
04209 
04210         ModelMatrix();
04211         glPushMatrix();
04212         eCoord p = PredictPosition();
04213         glTranslatef(p.x,p.y,0);
04214         glScalef(.5f,.5f,.5f);
04215 
04216 
04217         eCoord ske(1,skew);
04218         ske=ske*(1/sqrt(ske.NormSquared()));
04219 
04220         GLfloat m[4][4]={{dir.x,dir.y,0,0},
04221                          {-dir.y,dir.x,0,0},
04222                          {0,0,1,0},
04223                          {0,0,0,1}};
04224         glMultMatrixf(&m[0][0]);
04225 
04226         glPushMatrix();
04227         //glTranslatef(-1.84,0,0);
04228         if (!mp)
04229             glTranslatef(-1.5,0,0);
04230 
04231         glPushMatrix();
04232 
04233         GLfloat sk[4][4]={{1,0,0,0},
04234                           {0,ske.x,ske.y,0},
04235                           {0,-ske.y,ske.x,0},
04236                           {0,0,0,1}};
04237 
04238         glMultMatrixf(&sk[0][0]);
04239 
04240 
04241         glEnable(GL_LIGHT0);
04242         glEnable(GL_LIGHT1);
04243         glEnable(GL_LIGHTING);
04244 
04245 
04246 
04247         TexMatrix();
04248         IdentityMatrix();
04249 
04250         if (mp){
04251 
04252             ModelMatrix();
04253             if ( !blinking )
04254             {
04255                 glPushMatrix();
04256                 customTexture->Select();
04257                 glColor3f(1,1,1);
04258                 customModel->Render();
04259                 glPopMatrix();
04260             }
04261 
04262             glPopMatrix();
04263             glTranslatef(-1.5,0,0);
04264         }
04265         else{
04266             glEnable(GL_TEXTURE_2D);
04267 
04268             ModelMatrix();
04269 
04270             if ( !blinking )
04271             {
04272                 bodyTex->Select();
04273                 body->Render();
04274 
04275                 wheelTex->Select();
04276                 
04277                 glPushMatrix();
04278                 glTranslatef(0,0,.73);
04279                 
04280                 GLfloat mr[4][4]={{rotationRearWheel.x,0,rotationRearWheel.y,0},
04281                                   {0,1,0,0},
04282                                   {-rotationRearWheel.y,0,rotationRearWheel.x,0},
04283                                   {0,0,0,1}};
04284                 
04285                 
04286                 glMultMatrixf(&mr[0][0]);
04287                 
04288                 rear->Render();
04289                 glPopMatrix();
04290 
04291                 glPushMatrix();
04292                 glTranslatef(1.84,0,.43);
04293 
04294                 GLfloat mf[4][4]={{rotationFrontWheel.x,0,rotationFrontWheel.y,0},
04295                                   {0,1,0,0},
04296                                   {-rotationFrontWheel.y,0,rotationFrontWheel.x,0},
04297                                   {0,0,0,1}};
04298                 
04299                 glMultMatrixf(&mf[0][0]);
04300 
04301                 front->Render();
04302                 glPopMatrix();
04303             }
04304             
04305             glPopMatrix();
04306         }
04307 
04308 
04309         //     TexMatrix();
04310         //     IdentityMatrix();
04311         ModelMatrix();
04312 
04313         /*
04314           glDisable(GL_TEXTURE_GEN_S);
04315           glDisable(GL_TEXTURE_GEN_T);
04316           glDisable(GL_TEXTURE_GEN_Q);
04317           glDisable(GL_TEXTURE_GEN_R);
04318         */
04319 
04320         glDisable(GL_LIGHT0);
04321         glDisable(GL_LIGHT1);
04322         glDisable(GL_LIGHTING);
04323 
04324         //glDisable(GL_TEXTURE);
04325         glDisable(GL_TEXTURE_2D);
04326         glColor3f(1,1,1);
04327 
04328         {
04329             bool renderPyramid = false;
04330             gRealColor colorPyramid;
04331             REAL alpha = 1;
04332             const REAL timeout = .5f;
04333 
04334             if ( bool(player) )
04335             {
04336                 if ( player->IsChatting() )
04337                 {
04338                     renderPyramid = true;
04339                     colorPyramid.b = 0.0f;
04340                 }
04341                 else if ( !player->IsActive() )
04342                 {
04343                     renderPyramid = true;
04344                     colorPyramid.b = 0.0f;
04345                     colorPyramid.g = 0.0f;
04346                 }
04347                 else if ( cam && cam->Center() == this && se_GameTime() < timeout && player->CurrentTeam() && player->CurrentTeam()->NumPlayers() > 1 )
04348                 {
04349                     renderPyramid = true;
04350                     alpha = timeout - se_GameTime();
04351                 }
04352             }
04353 
04354             if ( renderPyramid )
04355             {
04356                 GLfloat s=sin(lastTime);
04357                 GLfloat c=cos(lastTime);
04358 
04359                 GLfloat m[4][4]={{c,s,0,0},
04360                                  {-s,c,0,0},
04361                                  {0,0,1,0},
04362                                  {0,0,1,1}};
04363 
04364                 glPushMatrix();
04365 
04366                 glMultMatrixf(&m[0][0]);
04367                 glScalef(.5,.5,.5);
04368 
04369 
04370                 BeginTriangles();
04371 
04372                 glColor4f( colorPyramid.r,colorPyramid.g,colorPyramid.b, alpha );
04373                 glVertex3f(0,0,3);
04374                 glVertex3f(0,1,4.5);
04375                 glVertex3f(0,-1,4.5);
04376 
04377                 glColor4f( colorPyramid.r * .7f,colorPyramid.g * .7f,colorPyramid.b * .7f, alpha );
04378                 glVertex3f(0,0,3);
04379                 glVertex3f(1,0,4.5);
04380                 glVertex3f(-1,0,4.5);
04381 
04382                 RenderEnd();
04383 
04384                 glPopMatrix();
04385             }
04386         }
04387 
04388 #ifdef USE_HEADLIGHT
04389         // Headlight contributed by Jonathan
04390         if(headlights) {
04391             if(!cycleprograminited) { // set to false on every sr_InitDisplay, without it I lost my program when I switched to windowed
04392                 const char *program =
04393                     "!!ARBfp1.0\
04394                     \
04395                     PARAM normal = program.local[0];\
04396                     ATTRIB texcoord = fragment.texcoord;\
04397                     TEMP final, diffuse, distance;\
04398                     \
04399                     DP3 distance, texcoord, texcoord;\
04400                     RSQ diffuse, distance.w;\
04401                     RCP distance, distance.w;\
04402                     MUL diffuse, texcoord, diffuse;\
04403                     DP3 diffuse, diffuse, normal;\
04404                     MUL final, diffuse, distance;\
04405                     MOV result.color.w, fragment.color;\
04406                     MUL result.color.xyz, fragment.color, final;\
04407                     \
04408                     END";
04409 #ifdef LINUX
04410                 glProgramStringARB_ptr(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(program), program);
04411 #else
04412                 glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(program), program);
04413 #endif
04414                 cycleprograminited = true;
04415             }
04416 #ifdef LINUX
04417             glProgramLocalParameter4fARB_ptr(GL_FRAGMENT_PROGRAM_ARB, 0, 0, 0, verletSpeed_ * verletSpeed_, 0);
04418 #else                   
04419             glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, 0, 0, verletSpeed_ * verletSpeed_, 0);
04420 #endif
04421             glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // blend func and depth mask. Efficient or not, glPushAttrib/glPopAttrib is a quick way to manage state.
04422             glEnable(GL_FRAGMENT_PROGRAM_ARB); // doesn't check if it exists...
04423 
04424             const unsigned sensors = 32; // actually one more
04425             const double mul = 0.25 * M_PI / sensors;
04426             const double add = -0.125 * M_PI;
04427 
04428             double size = gArena::SizeMultiplier() * 500 * M_SQRT2; // is M_SQRT2 in your math.h?
04429             GLfloat array[sensors+2][5];
04430 
04431             array[0][0] = 0;
04432             array[0][1] = 0;
04433             array[0][2] = p.x;
04434             array[0][3] = p.y;
04435             array[0][4] = 0.125;
04436 
04437             for(unsigned i=0; i<=sensors; i++) {
04438                 gSensor sensor(this, p, dir.Turn(cos(i * mul + add), sin(i * mul + add)));
04439                 sensor.detect(size);
04440                 array[i][5] = sensor.before_hit.x - p.x;
04441                 array[i][6] = sensor.before_hit.y - p.y;
04442                 array[i][7] = sensor.before_hit.x;
04443                 array[i][8] = sensor.before_hit.y;
04444                 array[i][9] = 0.125;
04445             }
04446 
04447             glPushMatrix();
04448             glLoadIdentity();
04449 
04450             glMatrixMode(GL_TEXTURE);
04451             glPushMatrix();
04452             glTranslatef(0, 0, 1);
04453 
04454             glBlendFunc(GL_ONE, GL_ONE);
04455             glDepthMask(GL_FALSE);
04456 
04457             glColor3fv(reinterpret_cast<GLfloat *>(&color_)); // 8-)
04458             glEnableClientState(GL_VERTEX_ARRAY);
04459             glEnableClientState(GL_TEXTURE_COORD_ARRAY);
04460 
04461             glInterleavedArrays(GL_T2F_V3F, 0, array);
04462             glDrawArrays(GL_TRIANGLE_FAN, 0, sensors+2);
04463 
04464             glDisableClientState(GL_VERTEX_ARRAY);
04465             glDisableClientState(GL_TEXTURE_COORD_ARRAY);
04466 
04467             glDisable(GL_FRAGMENT_PROGRAM_ARB);
04468 
04469             glPopMatrix();
04470             glMatrixMode(GL_MODELVIEW);
04471 
04472             glPopMatrix();
04473             glPopAttrib();
04474         }
04475 #endif // USE_HEADLIGHT
04476         // Name
04477         RenderName( cam );
04478 
04479 
04480         // shadow:
04481 
04482         sr_DepthOffset(true);
04483 
04484 
04485         REAL h=0;//se_cameraZ*.005+.03;
04486 
04487         glEnable(GL_CULL_FACE);
04488 
04489         if(!blinking && sr_floorDetail>rFLOOR_GRID && rTextureGroups::TextureMode[rTextureGroups::TEX_FLOOR]>0 && sr_alphaBlend){
04490             glColor3f(0,0,0);
04491             cycle_shad.Select();
04492             BeginQuads();
04493             glTexCoord2f(0,1);
04494             glVertex3f(-.6,.4,h);
04495 
04496             glTexCoord2f(1,1);
04497             glVertex3f(-.6,-.4,h);
04498 
04499             glTexCoord2f(1,0);
04500             glVertex3f(2.1,-.4,h);
04501 
04502             glTexCoord2f(0,0);
04503             glVertex3f(2.1,.4,h);
04504 
04505             RenderEnd();
04506         }
04507 
04508         glDisable(GL_CULL_FACE);
04509 
04510         // sr_laggometer;
04511 
04512 
04513         REAL f=verletSpeed_;
04514 
04515         REAL l=Lag();
04516 
04517         glPopMatrix();
04518 
04519         h=cam->CameraZ()*.005+.03;
04520 
04521 #ifdef ENABLE_OLD_LAG_O_METER
04522         if(sg_laggometerUseOld) {
04523             if (sn_GetNetState() != nSTANDALONE && sr_laggometer && f*l>.5) {
04524                 //&& owner!=::sn_myNetID){
04525                 glPushMatrix();
04526 
04527                 glColor3f(1,1,1);
04528                 //glDisable(GL_TEXTURE);
04529                 glDisable(GL_TEXTURE_2D);
04530 
04531                 glTranslatef(0,0,h);
04532                 //glScalef(.5*f,.5*f,.5*f);
04533 
04534                 // compensate for the .5 scaling further up
04535                 f *= 2 * sg_laggometerScale;
04536 
04537                 glScalef(f,f,f);
04538 
04539                 // move the sr_laggometer ahead a bit
04540                 if (!sr_predictObjects || sn_GetNetState()==nSERVER)
04541                     glTranslatef(l,0,0);
04542 
04543 
04544                 BeginLineLoop();
04545 
04546 
04547                 glVertex2f(-l,-l);
04548                 glVertex2f(0,0);
04549                 glVertex2f(-l,l);
04550                 REAL delay = GetTurnDelay();
04551                 if(l> 2*delay){
04552                     glVertex2f(-2*l+delay,delay);
04553                     glVertex2f(-2*l+2*delay,0);
04554                     glVertex2f(-2*l+delay,-delay);
04555                 }
04556                 else if (l>delay){
04557                     glVertex2f(-2*l+delay,delay);
04558                     glVertex2f(-l,2*delay-l);
04559                     glVertex2f(-l,-(2*delay-l));
04560                     glVertex2f(-2*l+delay,-delay);
04561                 }
04562 
04563                 RenderEnd();
04564                 glPopMatrix();
04565             }
04566         } else
04567 #endif
04568         {
04569             glPushMatrix();
04570 
04571             //glDisable(GL_TEXTURE);
04572             glDisable(GL_TEXTURE_2D);
04573 
04574             glTranslatef(0,0,h);
04575             //glScalef(.5*f,.5*f,.5*f);
04576 
04577             // compensate for the .5 scaling further up
04578             f *= 2 * sg_laggometerScale;
04579 
04580             glScalef(f,f,f);
04581 
04582             // move the sr_laggometer back a bit
04583             if (sr_predictObjects || sn_GetNetState()==nSERVER) {
04584                 glTranslatef(-l,0,0);
04585             }
04586 
04587             if (f*l>sg_laggometerThreshold) {
04588                 if (sr_laggometer) {
04589                     gLaggometer::LagOMeterRenderer(this).render(l);
04590                 }
04591             } else if(sg_axesIndicator) {
04592                 gLaggometer::AxesIndicator(this).render();
04593             }
04594 
04595             glPopMatrix();
04596         }
04597         sr_DepthOffset(false);
04598 
04599         glPopMatrix();
04600 
04601     }

Here is the call graph for this function:

void gCycle::Render2D ( tCoord  scale  )  const [virtual]

Reimplemented from eGameObject.

Definition at line 4603 of file gCycle.cpp.

References gCycleMovement::Alive(), gRealColor::b, color_, eGameObject::DeathTime(), eGameObject::dir, Direction(), eCoord, gRealColor::g, glBegin, glEnd, eGameObject::pos, PredictPosition(), gRealColor::r, se_GameTime(), tCoord::x, and tCoord::y.

04604                                         {
04605     double alpha = 1;
04606     if(!Alive()) {
04607         alpha -= 2 * (se_GameTime() - DeathTime());
04608         if(alpha <= 0) return;
04609     }
04610     glColor4f(color_.r, color_.g, color_.b, alpha);
04611     eCoord pos = PredictPosition(), dir = Direction();
04612     tCoord p = pos;
04613     glPushMatrix();
04614     GLfloat m[16] = {
04615                         scale.x * dir.x, scale.y * dir.y, 0, 0,
04616                         -scale.x * dir.y, scale.y * dir.x, 0, 0,
04617                         0, 0, 1, 0,
04618                         pos.x, pos.y, 0, 1
04619                     };
04620     glMultMatrixf(m);
04621     glBegin(GL_TRIANGLES);
04622     glVertex2f(.5, 0);
04623     glVertex2f(-.5, .5);
04624     glVertex2f(-.5, -.5);
04625     glEnd();
04626     glPopMatrix();

Here is the call graph for this function:

void gCycle::RenderName ( const eCamera cam  )  [virtual]

Definition at line 4641 of file gCycle.cpp.

References DisplayText(), ModelMatrix(), eCamera::Player(), ProjMatrix(), rCHEIGHT_NORMAL, REAL, cCockpit::Render(), eCamera::RenderingMain(), cCockpit::SetCycle(), sr_fontCycleLabel, timeCameIntoView, tSysTimeFloat(), cCockpit::VIEWPORT_CYCLE, x, and eGameObject::z.

Referenced by Render().

04642                                             {
04643     if ( !this->Player() )
04644         return;
04645 
04646     float modelviewMatrix[16], projectionMatrix[16];
04647     float x, y, z, w;
04648     float xp, yp, wp;
04649     float alpha = 0.75;
04650 
04651     if (fadeOutNameAfter == 0) return; /* XXX put that in ::Render() */
04652     if ( !cam->RenderingMain() ) return; // no name in mirrored image
04653     if ( !showOwnName && cam->Player() == this->player ) return; // don't show own name
04654 
04655     glPushMatrix();
04656     /* position sign above center of cycle */
04657     glTranslatef(0.8, 0, 2.0);
04658     glGetFloatv(GL_MODELVIEW_MATRIX, modelviewMatrix);
04659     glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix);
04660     glPopMatrix();
04661 
04662     /* get coordinates of sign */
04663     x = modelviewMatrix[12];
04664     y = modelviewMatrix[13];
04665     z = modelviewMatrix[14];
04666     w = modelviewMatrix[15];
04667 
04668     /* multiply by projection matrix */
04669     xp = projectionMatrix[0] * x + projectionMatrix[4] * y +
04670          projectionMatrix[8] * z + projectionMatrix[12] * w;
04671     yp = projectionMatrix[1] * x + projectionMatrix[5] * y +
04672          projectionMatrix[9] * z + projectionMatrix[13] * w;
04673     wp = projectionMatrix[3] * x + projectionMatrix[7] * y +
04674          projectionMatrix[11] * z + projectionMatrix[15] * w;
04675 
04676     if (wp <= 0) {
04677         /* behind camera */
04678         timeCameIntoView = 0;
04679         return;
04680     }
04681 
04682     xp /= wp;
04683     yp /= wp;
04684     yp += rCHEIGHT_NORMAL;// * 2.0;
04685 
04686     if (xp <= -1 || xp >= 1 || yp <= -1 || yp >= 1) {
04687         /* out of screen */
04688         timeCameIntoView = 0;
04689         return;
04690     }
04691 
04692     /* it is visible */
04693 
04694     bool doname = true;
04695     if (fadeOutNameAfter > 0) {
04696         REAL now = tSysTimeFloat();
04697         if (timeCameIntoView == 0)
04698             timeCameIntoView = now;
04699 
04700         if (now - timeCameIntoView > fadeOutNameAfter) {
04701             doname = false;
04702         } else if (now - timeCameIntoView > fadeOutNameAfter - 1) {
04703             /* start to fade out */
04704             alpha = 0.75 - (now - timeCameIntoView -
04705                             (fadeOutNameAfter - 1)) * 0.75;
04706         }
04707     }
04708 
04709     ModelMatrix();
04710     glPushMatrix();
04711     glLoadIdentity();
04712 
04713     ProjMatrix();
04714     glPushMatrix();
04715     glLoadIdentity();
04716 
04717     glTranslatef(xp, yp, 0.);
04718     if(doname) {
04719         glColor4f(1, 1, 1, alpha);
04720         tColoredString name;
04721         if(sg_displayColoredNameOverCycles)
04722             name << *this->player;
04723         else
04724             name << this->player->GetName();
04725         DisplayText(0, 0, rCHEIGHT_NORMAL, name, sr_fontCycleLabel, 0, 0);
04726     }
04727     static cCockpit cycleCockpit(cCockpit::VIEWPORT_CYCLE);
04728     cycleCockpit.SetCycle(*this);
04729     cycleCockpit.Render();
04730 
04731     ProjMatrix();
04732     glPopMatrix();
04733 
04734     ModelMatrix();
04735     glPopMatrix();

Here is the call graph for this function:

Here is the caller graph for this function:

bool gCycle::RenderCockpitFixedBefore ( bool  primary = true  )  [virtual]

Reimplemented from eGameObject.

Definition at line 4738 of file gCycle.cpp.

04739                                          {
04740     /*
04741       if (alive)
04742       return true;
04743       else{
04744       REAL rd=se_GameTime()-deathTime;
04745       if (rd<1)
04746          return true;
04747       else{
04748          REAL d=1.25-rd;
04749          d*=8;
04750          if (d<0) d=0;
04751          glColor3f(d,d/2,d/4);
04752          glDisable(GL_TEXTURE_2D);
04753          glDisable(GL_TEXTURE);
04754          glDisable(GL_DEPTH_TEST);
04755          glRectf(-1,-1,1,1);
04756          glColor4f(1,1,1,rd*(2-rd/2));
04757          DisplayText(0,0,.05,.15,"You have been deleted.");
04758          return false;
04759       }
04760       }
04761     */
04762     return true;

eCoord gCycle::CamPos (  )  const [virtual]

Reimplemented from eGameObject.

Definition at line 4800 of file gCycle.cpp.

References eGameObject::dir, PredictPosition(), skew, and eGameObject::z.

Referenced by _wrap_GCycle_cam_pos().

04802 {
04803     return PredictPosition() + dir.Turn(0 ,-skew*z);
04804 
04805     //    gSensor s(this,pos, PredictPosition() - pos );
04806     //    s.detect(1);
04807 
04808     //    return s.before_hit + dir.Turn(0 ,-skew*z);
04809 
04810     // return pos + dir.Turn(0 ,-skew*z);

Here is the call graph for this function:

Here is the caller graph for this function:

eCoord gCycle::PredictPosition (  )  const [virtual]

Reimplemented from eGameObject.

Definition at line 4793 of file gCycle.cpp.

References predictPosition_.

Referenced by _wrap_GCycle_predict_position(), CamPos(), Render(), Render2D(), and Timestep().

04794                                      {
04795     return predictPosition_;
04796 
04797     //    eCoord p = pos + dir * (speed * se_PredictTime());
04798     //    return p + correctPosSmooth;

Here is the caller graph for this function:

eCoord gCycle::CamTop (  )  const [virtual]

Reimplemented from eGameObject.

Definition at line 4812 of file gCycle.cpp.

References eGameObject::dir, and skew.

Referenced by _wrap_GCycle_cam_top().

04814 {
04815     return dir.Turn(0,-skew);

Here is the caller graph for this function:

eCoord gCycle::CamDir (  )  const [virtual]

Reimplemented from eGameObject.

Definition at line 4817 of file gCycle.cpp.

References gJoystick::cameraDirection_, eGameObject::dir, joystick_, and tCoord::NormSquared().

Referenced by gCamera::CenterCycleDir().

04819 {
04820     if ( joystick_ && joystick_->cameraDirection_.NormSquared() > .25 )
04821     {
04822         return joystick_->cameraDirection_;
04823     }
04824     else
04825     {
04826         return dir;
04827     }

Here is the call graph for this function:

Here is the caller graph for this function:

eCoord gCycle::Direction ( void   )  const [virtual]

returns the current driving direction

Returns:
the currend driving direction

Reimplemented from gCycleMovement.

Definition at line 4829 of file gCycle.cpp.

References gJoystick::cameraDirection_, gCycleMovement::dirDrive, gCycleMovement::Direction(), joystick_, and tCoord::NormSquared().

Referenced by cCockpit::cb_TimeToImpactFront(), cWidget::Map::DrawMap(), gAIPlayer::EmergencySurvive(), ReadSync(), Render2D(), gAIPlayer::RightBeforeDeath(), gAIPlayer::Think(), gAIPlayer::ThinkCloseCombat(), gAIPlayer::ThinkPath(), and WriteSync().

04831 {
04832     return gCycleMovement::Direction();
04833 
04834     if ( joystick_ && joystick_->cameraDirection_.NormSquared() > .25 )
04835     {
04836         return joystick_->cameraDirection_;
04837     }
04838     else
04839     {
04840         return dirDrive;
04841     }

Here is the call graph for this function:

Here is the caller graph for this function:

void gCycle::RightBeforeDeath ( int  numTries  )  [virtual]

called when the cycle is very close to a wall and about to crash

Parameters:
numTries number of times this function will be called approximately before the cycle will be killed

Reimplemented from gCycleMovement.

Definition at line 5994 of file gCycle.cpp.

References correctPosSmooth, nextSync, nextSyncOwner, nNetObject::Owner(), sg_avoidBadOldClientSync, sg_GetSyncIntervalSelf(), sg_NoLocalTunnelOnSync, sg_syncIntervalEnemy, nVersionFeature::Supported(), and tSysTimeFloat().

05996 {
05997     if ( player )
05998     {
05999         player->RightBeforeDeath( numTries );
06000     }
06001 
06002     // delay syncs for old clients; they would tunnel locally
06003     if ( sg_avoidBadOldClientSync && !sg_NoLocalTunnelOnSync.Supported( Owner() ) )
06004     {
06005         nextSync=tSysTimeFloat()+sg_syncIntervalEnemy;
06006         nextSyncOwner=tSysTimeFloat()+sg_GetSyncIntervalSelf( this );
06007     }
06008 
06009     correctPosSmooth = correctPosSmooth * .5;

Here is the call graph for this function:

void gCycle::PrivateSettings (  )  [static]

Definition at line 122 of file gCycle.cpp.

References c_per, c_pwl, explosionRadius, wallsLength, and wallsStayUpDelay.

Referenced by _wrap_GCycle_private_settings(), and main().

00123 {
00124     static nSettingItem<REAL> c_wsud("CYCLE_WALLS_STAY_UP_DELAY",wallsStayUpDelay);
00125     static nSettingItem<REAL> c_wl("CYCLE_WALLS_LENGTH",wallsLength);
00126     static nSettingItem<REAL> c_er("CYCLE_EXPLOSION_RADIUS",explosionRadius);
00127 
00128     c_pwsud=&c_wsud;
00129     c_pwl  =&c_wl;
00130     c_per  =&c_er;
00131 }

Here is the caller graph for this function:

bool gCycle::DoIsDestinationUsed ( const gDestination dest  )  const [protected, virtual]

returns whether the given destination is in active use

Parameters:
dest the destination to test
Returns:
true if the destination is still in active use

Reimplemented from gCycleMovement.

Definition at line 6022 of file gCycle.cpp.

References gCycleMovement::DoIsDestinationUsed(), and extrapolator_.

06024 {
06025     return ( extrapolator_ && extrapolator_->IsDestinationUsed( dest ) ) || gCycleMovement::DoIsDestinationUsed( dest );

Here is the call graph for this function:


Friends And Related Function Documentation

friend class gPlayerWall [friend]

Definition at line 151 of file gCycle.h.

friend class gNetPlayerWall [friend]

Definition at line 152 of file gCycle.h.

Referenced by DropWall(), and SyncEnemy().

friend class gDestination [friend]

Definition at line 153 of file gCycle.h.

friend class gCycleWallRenderer [friend]

Definition at line 154 of file gCycle.h.

Referenced by MyInitAfterCreation().

friend class gCycleChatBot [friend]

Definition at line 161 of file gCycle.h.


Member Data Documentation

REAL gCycle::spawnTime_ [private]

time the cycle spawned at

Definition at line 156 of file gCycle.h.

Referenced by DropWall(), gCycle(), MyInitAfterCreation(), ReadSync(), Render(), SyncEnemy(), SyncFromExtrapolator(), TimestepCore(), and Vulnerable().

REAL gCycle::lastTimeAnim [private]

last time animation was simulated at

Definition at line 157 of file gCycle.h.

Referenced by gCycle(), MyInitAfterCreation(), SyncEnemy(), and TimestepCore().

REAL gCycle::timeCameIntoView [private]

Definition at line 159 of file gCycle.h.

Referenced by MyInitAfterCreation(), and RenderName().

std::auto_ptr< gCycleChatBot > gCycle::chatBot_ [private]

Definition at line 162 of file gCycle.h.

Referenced by gCycleChatBot::Get(), and Timestep().

bool gCycle::dropWallRequested_ [private]

flag indicating that someone requested a wall drop

Definition at line 164 of file gCycle.h.

Referenced by DropWall(), MyInitAfterCreation(), OnDropTempWall(), PassEdge(), and Timestep().

eCoord gCycle::lastGoodPosition_

Definition at line 166 of file gCycle.h.

Referenced by gCycleExtrapolator::CopyFrom(), MyInitAfterCreation(), and ReadSync().

REAL gCycle::skew

Definition at line 168 of file gCycle.h.

Referenced by CamPos(), CamTop(), MyInitAfterCreation(), ReadSync(), Render(), and TimestepCore().

REAL gCycle::skewDot

Definition at line 168 of file gCycle.h.

Referenced by DoTurn(), MyInitAfterCreation(), ReadSync(), SyncEnemy(), and TimestepCore().

bool gCycle::mp

Definition at line 170 of file gCycle.h.

Referenced by MyInitAfterCreation(), Render(), and ~gCycle().

rModel* gCycle::body

Definition at line 172 of file gCycle.h.

Referenced by MyInitAfterCreation(), Render(), and ~gCycle().

rModel * gCycle::front

Definition at line 172 of file gCycle.h.

Referenced by MyInitAfterCreation(), Render(), and ~gCycle().

rModel * gCycle::rear

Definition at line 172 of file gCycle.h.

Referenced by MyInitAfterCreation(), Render(), and ~gCycle().

rModel * gCycle::customModel

Definition at line 172 of file gCycle.h.

Referenced by gCycleVisuals::gCycleVisuals(), gCycleVisuals::LoadModel(), MyInitAfterCreation(), Render(), ~gCycle(), and gCycleVisuals::~gCycleVisuals().

gTextureCycle* gCycle::wheelTex

Definition at line 175 of file gCycle.h.

Referenced by MyInitAfterCreation(), Render(), and ~gCycle().

gTextureCycle * gCycle::bodyTex

Definition at line 175 of file gCycle.h.

Referenced by MyInitAfterCreation(), Render(), and ~gCycle().

gTextureCycle* gCycle::customTexture

Definition at line 176 of file gCycle.h.

Referenced by gCycleVisuals::gCycleVisuals(), gCycleVisuals::LoadTextures(), MyInitAfterCreation(), Render(), ~gCycle(), and gCycleVisuals::~gCycleVisuals().

eCoord gCycle::rotationFrontWheel

Definition at line 178 of file gCycle.h.

Referenced by MyInitAfterCreation(), Render(), and TimestepCore().

eCoord gCycle::rotationRearWheel

Definition at line 178 of file gCycle.h.

Referenced by MyInitAfterCreation(), Render(), and TimestepCore().

REAL gCycle::heightFrontWheel

Definition at line 179 of file gCycle.h.

REAL gCycle::heightRearWheel

Definition at line 179 of file gCycle.h.

uActionPlayer gCycle::s_brake [static]

Definition at line 183 of file gCycle.h.

Referenced by Act(), and gCycleChatBot::Activate().

gCycleMemory gCycle::memory

Definition at line 184 of file gCycle.h.

Referenced by CheckLoop(), and CycleBlocksWayHelper().

gRealColor gCycle::color_

Definition at line 186 of file gCycle.h.

Referenced by cWidget::Map::DrawWalls(), gCycle(), Kill(), MyInitAfterCreation(), ReadSync(), Render(), Render2D(), TimestepCore(), and WriteCreate().

gRealColor gCycle::trailColor_

Definition at line 187 of file gCycle.h.

Referenced by gCycle(), and MyInitAfterCreation().

eCoord gCycle::correctPosSmooth

Definition at line 192 of file gCycle.h.

Referenced by CalculatePredictPosition(), Die(), MyInitAfterCreation(), ReadSync(), RightBeforeDeath(), SyncFromExtrapolator(), TimestepCore(), and TransferPositionCorrectionToDistanceCorrection().

eCoord gCycle::predictPosition_

the best guess of where the cycle is at at display time

Definition at line 193 of file gCycle.h.

Referenced by CalculatePredictPosition(), Die(), MyInitAfterCreation(), PredictPosition(), and ReadSync().

REAL gCycle::correctDistanceSmooth

Definition at line 196 of file gCycle.h.

Referenced by gDestination::CopyFrom(), gCycle(), MyInitAfterCreation(), ReadSync(), SyncEnemy(), SyncFromExtrapolator(), TimestepCore(), and TransferPositionCorrectionToDistanceCorrection().

gCycleWallsDisplayListManager gCycle::displayList_ [private]

display list manager

Definition at line 202 of file gCycle.h.

Referenced by gNetPlayerWall::CanHaveDisplayList(), and gNetPlayerWall::HasDisplayList().

SyncData gCycle::lastSyncMessage_ [private]

Definition at line 210 of file gCycle.h.

Referenced by ReadSync(), ResetExtrapolator(), and SyncEnemy().

tJUST_CONTROLLED_PTR<gCycleExtrapolator> gCycle::extrapolator_ [private]

Definition at line 211 of file gCycle.h.

Referenced by DoIsDestinationUsed(), Extrapolate(), IsMe(), OnNotifyNewDestination(), PassEdge(), ReadSync(), ResetExtrapolator(), SyncFromExtrapolator(), and Timestep().

bool gCycle::resimulate_ [private]

Definition at line 212 of file gCycle.h.

Referenced by MyInitAfterCreation(), ReadSync(), ResetExtrapolator(), SyncEnemy(), SyncFromExtrapolator(), and Timestep().

nTimeRolling gCycle::nextSync [private]

Definition at line 223 of file gCycle.h.

Referenced by gCycle(), MyInitAfterCreation(), RequestSyncAll(), RightBeforeDeath(), and TimestepCore().

nTimeRolling gCycle::nextSyncOwner [private]

Definition at line 223 of file gCycle.h.

Referenced by gCycle(), MyInitAfterCreation(), RequestSyncOwner(), RightBeforeDeath(), and TimestepCore().

REAL gCycle::wallsStayUpDelay = 8.0f [static, private]

the time the cycle walls stay up ( negative values: they stay up forever )

Definition at line 338 of file gCycle.h.

Referenced by PrivateSettings(), and WallsStayUpDelay().

REAL gCycle::wallsLength = -1.0f [static, private]

the maximum total length of the walls

Definition at line 339 of file gCycle.h.

Referenced by MaxWallsLength(), PrivateSettings(), and WallsLength().

REAL gCycle::explosionRadius = 4.0f [static, private]

the radius of the holes blewn in by an explosion

Definition at line 340 of file gCycle.h.

Referenced by ExplosionRadius(), and PrivateSettings().

gJoystick* gCycle::joystick_ [private]

joystick control

Definition at line 341 of file gCycle.h.

Referenced by Act(), CamDir(), Direction(), MyInitAfterCreation(), OnRemoveFromGame(), and TimestepCore().


The documentation for this class was generated from the following files:
Generated on Sat Mar 15 23:36:15 2008 for Armagetron Advanced by  doxygen 1.5.4