Changeset 68:9d65d8683e8d

Show
Ignore:
Timestamp:
11/21/07 00:48:04 (3 years ago)
Author:
mdoison
Branch:
tjw-1.2
convert_revision:
svn:7c786126-522e-0410-a822-d6d8feae56ca/branches/tjw-1.2@89
Message:
  • Rename some functions with G_ prefix (tjw 1.2 patch)
  • Add team spectators (tjw 1.2 patch)
Location:
src/game
Files:
9 modified

Legend:

Unmodified
Added
Removed
  • src/game/g_active.c

    r66 r68  
    376376  pmove_t pm; 
    377377  gclient_t *client; 
     378  qboolean attack1, attack3; 
    378379  qboolean      doPmove = qtrue; 
    379380 
     
    382383  client->oldbuttons = client->buttons; 
    383384  client->buttons = ucmd->buttons; 
     385 
     386  attack1 = ( ( client->buttons & BUTTON_ATTACK ) && 
     387              !( client->oldbuttons & BUTTON_ATTACK ) ); 
     388  attack3 = ( ( client->buttons & BUTTON_USE_HOLDABLE ) && 
     389              !( client->oldbuttons & BUTTON_USE_HOLDABLE ) ); 
    384390 
    385391  if( client->sess.spectatorState == SPECTATOR_LOCKED || client->sess.spectatorState == SPECTATOR_FOLLOW ) 
     
    401407  if (doPmove) 
    402408  { 
     409    // in case the client entered the queue while following a teammate 
     410    if( ( client->pers.teamSelection == PTE_ALIENS && 
     411          G_SearchSpawnQueue( &level.alienSpawnQueue, ent-g_entities ) ) || 
     412        ( client->pers.teamSelection == PTE_HUMANS && 
     413          G_SearchSpawnQueue( &level.humanSpawnQueue, ent-g_entities ) ) ) 
     414    { 
     415      client->ps.pm_flags |= PMF_QUEUED; 
     416    } 
     417 
    403418    client->ps.speed = BG_FindSpeedForClass( client->ps.stats[ STAT_PCLASS ] ); 
    404419 
     
    426441    trap_UnlinkEntity( ent ); 
    427442 
    428     if( ( client->buttons & BUTTON_ATTACK ) && !( client->oldbuttons & BUTTON_ATTACK ) ) 
    429     { 
    430       //if waiting in a queue remove from the queue 
    431       if( client->ps.pm_flags & PMF_QUEUED ) 
    432       { 
    433         if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) 
    434           G_RemoveFromSpawnQueue( &level.alienSpawnQueue, client->ps.clientNum ); 
    435         else if( client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) 
    436           G_RemoveFromSpawnQueue( &level.humanSpawnQueue, client->ps.clientNum ); 
    437  
    438         client->pers.classSelection = PCL_NONE; 
    439         client->ps.stats[ STAT_PCLASS ] = PCL_NONE; 
    440       } 
    441       else if( client->pers.classSelection == PCL_NONE ) 
    442       { 
    443         if( client->pers.teamSelection == PTE_NONE ) 
    444           G_TriggerMenu( client->ps.clientNum, MN_TEAM ); 
    445         else if( client->pers.teamSelection == PTE_ALIENS ) 
    446           G_TriggerMenu( client->ps.clientNum, MN_A_CLASS ); 
    447         else if( client->pers.teamSelection == PTE_HUMANS ) 
    448           G_TriggerMenu( client->ps.clientNum, MN_H_SPAWN ); 
    449       } 
     443    if( ( attack1 || attack3 ) && ( client->ps.pm_flags & PMF_QUEUED ) ) 
     444    { 
     445      if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) 
     446        G_RemoveFromSpawnQueue( &level.alienSpawnQueue, client->ps.clientNum ); 
     447      else if( client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) 
     448        G_RemoveFromSpawnQueue( &level.humanSpawnQueue, client->ps.clientNum ); 
     449 
     450      client->pers.classSelection = PCL_NONE; 
     451      client->ps.stats[ STAT_PCLASS ] = PCL_NONE; 
     452    } 
     453     
     454    if( attack1 && client->pers.classSelection == PCL_NONE ) 
     455    { 
     456      if( client->pers.teamSelection == PTE_NONE ) 
     457        G_TriggerMenu( client->ps.clientNum, MN_TEAM ); 
     458      else if( client->pers.teamSelection == PTE_ALIENS ) 
     459        G_TriggerMenu( client->ps.clientNum, MN_A_CLASS ); 
     460      else if( client->pers.teamSelection == PTE_HUMANS ) 
     461        G_TriggerMenu( client->ps.clientNum, MN_H_SPAWN ); 
    450462    } 
    451463 
     
    466478  } 
    467479 
    468   if( ( client->buttons & BUTTON_USE_HOLDABLE ) && !( client->oldbuttons & BUTTON_USE_HOLDABLE ) ) 
     480  else if( attack1 && ent->client->sess.spectatorState == SPECTATOR_FOLLOW ) 
     481  { 
     482    G_StopFollowing( ent ); 
     483    client->pers.classSelection = PCL_NONE; 
     484    if( client->pers.teamSelection == PTE_NONE ) 
     485      G_TriggerMenu( ent-g_entities, MN_TEAM ); 
     486    else if( client->pers.teamSelection == PTE_ALIENS ) 
     487      G_TriggerMenu( ent-g_entities, MN_A_CLASS ); 
     488    else if( client->pers.teamSelection == PTE_HUMANS ) 
     489      G_TriggerMenu( ent-g_entities, MN_H_SPAWN ); 
     490  } 
     491   
     492  if( attack3 ) 
     493  { 
    469494    G_ToggleFollow( ent ); 
     495  } 
    470496} 
    471497 
     
    19051931  pers = &ent->client->pers; 
    19061932 
     1933  // save a copy of things from playerState in case of SPECTATOR_FOLLOW  
     1934  pers->score = ent->client->ps.persistant[ PERS_SCORE ]; 
     1935  pers->credit = ent->client->ps.persistant[ PERS_CREDIT ]; 
     1936 
    19071937  // 
    19081938  // If the end of unit layout is displayed, don't give 
  • src/game/g_buildable.c

    r65 r68  
    12401240    VectorCopy( origin, player->client->ps.origin ); 
    12411241    VectorCopy( vec3_origin, player->client->ps.velocity ); 
    1242     SetClientViewAngle( player, angles ); 
     1242    G_SetClientViewAngle( player, angles ); 
    12431243  } 
    12441244 
     
    13201320      G_SetOrigin( activator, hovelOrigin ); 
    13211321      VectorCopy( hovelOrigin, activator->client->ps.origin ); 
    1322       SetClientViewAngle( activator, hovelAngles ); 
     1322      G_SetClientViewAngle( activator, hovelAngles ); 
    13231323    } 
    13241324  } 
     
    13951395    G_SetOrigin( builder, newOrigin ); 
    13961396    VectorCopy( newOrigin, builder->client->ps.origin ); 
    1397     SetClientViewAngle( builder, newAngles ); 
     1397    G_SetClientViewAngle( builder, newAngles ); 
    13981398 
    13991399    //client leaves hovel 
     
    18371837                                G_SetOrigin(activator,spawn_origin); 
    18381838                                VectorCopy(spawn_origin,activator->client->ps.origin); 
    1839                                 SetClientViewAngle(activator,spawn_angles); 
     1839                                G_SetClientViewAngle(activator,spawn_angles); 
    18401840 
    18411841                                // Play the spawn sound effect 
  • src/game/g_client.c

    r65 r68  
    140140  if( client->ps.persistant[ PERS_CREDIT ] < 0 ) 
    141141    client->ps.persistant[ PERS_CREDIT ] = 0; 
     142  // keep PERS_CREDIT in sync if not following  
     143  if( client->sess.spectatorState != SPECTATOR_FOLLOW ) 
     144    client->ps.persistant[ PERS_CREDIT ] = client->pers.credit; 
    142145} 
    143146 
     
    146149======================================================================= 
    147150 
    148   SelectSpawnPoint 
     151  G_SelectSpawnPoint 
    149152 
    150153======================================================================= 
     
    181184/* 
    182185================ 
    183 SelectNearestDeathmatchSpawnPoint 
     186G_SelectNearestDeathmatchSpawnPoint 
    184187 
    185188Find the spot that we DON'T want to use 
     
    187190*/ 
    188191#define MAX_SPAWN_POINTS  128 
    189 gentity_t *SelectNearestDeathmatchSpawnPoint( vec3_t from ) 
     192gentity_t *G_SelectNearestDeathmatchSpawnPoint( vec3_t from ) 
    190193{ 
    191194  gentity_t *spot; 
     
    216219/* 
    217220================ 
    218 SelectRandomDeathmatchSpawnPoint 
     221G_SelectRandomDeathmatchSpawnPoint 
    219222 
    220223go to a random point that doesn't telefrag 
     
    222225*/ 
    223226#define MAX_SPAWN_POINTS  128 
    224 gentity_t *SelectRandomDeathmatchSpawnPoint( void ) 
     227gentity_t *G_SelectRandomDeathmatchSpawnPoint( void ) 
    225228{ 
    226229  gentity_t *spot; 
     
    251254/* 
    252255=========== 
    253 SelectRandomFurthestSpawnPoint 
     256G_SelectRandomFurthestSpawnPoint 
    254257 
    255258Chooses a player start, deathmatch start, etc 
    256259============ 
    257260*/ 
    258 gentity_t *SelectRandomFurthestSpawnPoint ( vec3_t avoidPoint, vec3_t origin, vec3_t angles ) 
     261gentity_t *G_SelectRandomFurthestSpawnPoint ( vec3_t avoidPoint, vec3_t origin, vec3_t angles ) 
    259262{ 
    260263  gentity_t *spot; 
     
    334337/* 
    335338================ 
    336 SelectAlienSpawnPoint 
     339G_SelectAlienSpawnPoint 
    337340 
    338341go to a random point that doesn't telefrag 
    339342================ 
    340343*/ 
    341 gentity_t *SelectAlienSpawnPoint( vec3_t preference ) 
     344gentity_t *G_SelectAlienSpawnPoint( vec3_t preference ) 
    342345{ 
    343346  gentity_t *spot; 
     
    383386/* 
    384387================ 
    385 SelectHumanSpawnPoint 
     388G_SelectHumanSpawnPoint 
    386389 
    387390go to a random point that doesn't telefrag 
    388391================ 
    389392*/ 
    390 gentity_t *SelectHumanSpawnPoint( vec3_t preference ) 
     393gentity_t *G_SelectHumanSpawnPoint( vec3_t preference ) 
    391394{ 
    392395  gentity_t *spot; 
     
    432435/* 
    433436=========== 
    434 SelectSpawnPoint 
     437G_SelectSpawnPoint 
    435438 
    436439Chooses a player start, deathmatch start, etc 
    437440============ 
    438441*/ 
    439 gentity_t *SelectSpawnPoint( vec3_t avoidPoint, vec3_t origin, vec3_t angles ) 
    440 { 
    441   return SelectRandomFurthestSpawnPoint( avoidPoint, origin, angles ); 
     442gentity_t *G_SelectSpawnPoint( vec3_t avoidPoint, vec3_t origin, vec3_t angles ) 
     443{ 
     444  return G_SelectRandomFurthestSpawnPoint( avoidPoint, origin, angles ); 
    442445} 
    443446 
     
    445448/* 
    446449=========== 
    447 SelectTremulousSpawnPoint 
     450G_SelectTremulousSpawnPoint 
    448451 
    449452Chooses a player start, deathmatch start, etc 
    450453============ 
    451454*/ 
    452 gentity_t *SelectTremulousSpawnPoint( pTeam_t team, vec3_t preference, vec3_t origin, vec3_t angles ) 
     455gentity_t *G_SelectTremulousSpawnPoint( pTeam_t team, vec3_t preference, vec3_t origin, vec3_t angles ) 
    453456{ 
    454457  gentity_t *spot = NULL; 
    455458 
    456459  if( team == PTE_ALIENS ) 
    457     spot = SelectAlienSpawnPoint( preference ); 
     460    spot = G_SelectAlienSpawnPoint( preference ); 
    458461  else if( team == PTE_HUMANS ) 
    459     spot = SelectHumanSpawnPoint( preference ); 
     462    spot = G_SelectHumanSpawnPoint( preference ); 
    460463 
    461464  //no available spots 
     
    478481/* 
    479482=========== 
    480 SelectInitialSpawnPoint 
     483G_SelectInitialSpawnPoint 
    481484 
    482485Try to find a spawn point marked 'initial', otherwise 
     
    484487============ 
    485488*/ 
    486 gentity_t *SelectInitialSpawnPoint( vec3_t origin, vec3_t angles ) 
     489gentity_t *G_SelectInitialSpawnPoint( vec3_t origin, vec3_t angles ) 
    487490{ 
    488491  gentity_t *spot; 
     
    497500  if( !spot || SpotWouldTelefrag( spot ) ) 
    498501  { 
    499     return SelectSpawnPoint( vec3_origin, origin, angles ); 
     502    return G_SelectSpawnPoint( vec3_origin, origin, angles ); 
    500503  } 
    501504 
     
    509512/* 
    510513=========== 
    511 SelectSpectatorSpawnPoint 
     514G_SelectSpectatorSpawnPoint 
    512515 
    513516============ 
    514517*/ 
    515 gentity_t *SelectSpectatorSpawnPoint( vec3_t origin, vec3_t angles ) 
     518gentity_t *G_SelectSpectatorSpawnPoint( vec3_t origin, vec3_t angles ) 
    516519{ 
    517520  FindIntermissionPoint( ); 
     
    526529/* 
    527530=========== 
    528 SelectAlienLockSpawnPoint 
     531G_SelectAlienLockSpawnPoint 
    529532 
    530533Try to find a spawn point for alien intermission otherwise 
     
    532535============ 
    533536*/ 
    534 gentity_t *SelectAlienLockSpawnPoint( vec3_t origin, vec3_t angles ) 
     537gentity_t *G_SelectAlienLockSpawnPoint( vec3_t origin, vec3_t angles ) 
    535538{ 
    536539  gentity_t *spot; 
     
    540543 
    541544  if( !spot ) 
    542     return SelectSpectatorSpawnPoint( origin, angles ); 
     545    return G_SelectSpectatorSpawnPoint( origin, angles ); 
    543546 
    544547  VectorCopy( spot->s.origin, origin ); 
     
    551554/* 
    552555=========== 
    553 SelectHumanLockSpawnPoint 
     556G_SelectHumanLockSpawnPoint 
    554557 
    555558Try to find a spawn point for human intermission otherwise 
     
    557560============ 
    558561*/ 
    559 gentity_t *SelectHumanLockSpawnPoint( vec3_t origin, vec3_t angles ) 
     562gentity_t *G_SelectHumanLockSpawnPoint( vec3_t origin, vec3_t angles ) 
    560563{ 
    561564  gentity_t *spot; 
     
    565568 
    566569  if( !spot ) 
    567     return SelectSpectatorSpawnPoint( origin, angles ); 
     570    return G_SelectSpectatorSpawnPoint( origin, angles ); 
    568571 
    569572  VectorCopy( spot->s.origin, origin ); 
     
    747750/* 
    748751================== 
    749 SetClientViewAngle 
     752G_SetClientViewAngle 
    750753 
    751754================== 
    752755*/ 
    753 void SetClientViewAngle( gentity_t *ent, vec3_t angle ) 
     756void G_SetClientViewAngle( gentity_t *ent, vec3_t angle ) 
    754757{ 
    755758  int     i; 
     
    11561159  strcpy( c2, Info_ValueForKey( userinfo, "color2" ) ); 
    11571160 
    1158   if( client->ps.pm_flags & PMF_FOLLOW ) 
    1159     team = PTE_NONE; 
    1160   else 
    1161     team = client->ps.stats[ STAT_PTEAM ]; 
     1161  team = client->pers.teamSelection; 
    11621162 
    11631163  // send over a subset of the userinfo keys so other clients can 
     
    13411341  client->pers.enterTime = level.time; 
    13421342  client->pers.teamState.state = TEAM_BEGIN; 
     1343  client->pers.classSelection = PCL_NONE; 
    13431344 
    13441345  // save eflags around this, because changing teams will 
     
    14631464  { 
    14641465    if( teamLocal == PTE_NONE ) 
    1465       spawnPoint = SelectSpectatorSpawnPoint( spawn_origin, spawn_angles ); 
     1466      spawnPoint = G_SelectSpectatorSpawnPoint( spawn_origin, spawn_angles ); 
    14661467    else if( teamLocal == PTE_ALIENS ) 
    1467       spawnPoint = SelectAlienLockSpawnPoint( spawn_origin, spawn_angles ); 
     1468      spawnPoint = G_SelectAlienLockSpawnPoint( spawn_origin, spawn_angles ); 
    14681469    else if( teamLocal == PTE_HUMANS ) 
    1469       spawnPoint = SelectHumanLockSpawnPoint( spawn_origin, spawn_angles ); 
     1470      spawnPoint = G_SelectHumanLockSpawnPoint( spawn_origin, spawn_angles ); 
    14701471  } 
    14711472  else 
     
    15221523  client->ps.persistant[ PERS_SPAWN_COUNT ]++; 
    15231524  client->ps.persistant[ PERS_TEAM ] = client->sess.sessionTeam; 
     1525 
     1526  // restore really persistant things 
     1527  client->ps.persistant[ PERS_SCORE ] = client->pers.score; 
     1528  client->ps.persistant[ PERS_CREDIT ] = client->pers.credit; 
    15241529 
    15251530  client->airOutTime = level.time + 12000; 
     
    16481653 
    16491654  trap_GetUsercmd( client - level.clients, &ent->client->pers.cmd ); 
    1650   SetClientViewAngle( ent, spawn_angles ); 
     1655  G_SetClientViewAngle( ent, spawn_angles ); 
    16511656 
    16521657  if( !( client->sess.sessionTeam == TEAM_SPECTATOR ) ) 
  • src/game/g_cmds.c

    r67 r68  
    264264    if( cl->pers.connected == CON_CONNECTING ) 
    265265      ping = -1; 
     266    else if( cl->sess.spectatorState == SPECTATOR_FOLLOW ) 
     267      ping = cl->pers.ping < 999 ? cl->pers.ping : 999; 
    266268    else 
    267269      ping = cl->ps.ping < 999 ? cl->ps.ping : 999; 
    268270 
    269     if( cl->ps.stats[ STAT_HEALTH ] > 0 ) 
     271    if( cl->sess.sessionTeam != TEAM_SPECTATOR ) 
    270272    { 
    271273      weapon = cl->ps.weapon; 
     
    556558    if( ent->client && ent->client->pers.connected == CON_CONNECTED ) 
    557559    { 
    558       // stop following clients 
    559       if( ent->client->sess.sessionTeam == TEAM_SPECTATOR && 
    560           ent->client->sess.spectatorState == SPECTATOR_FOLLOW && 
    561           ent->client->sess.spectatorClient == self->client->ps.clientNum ) 
    562       { 
    563         if( !G_FollowNewClient( ent, 1 ) ) 
    564           G_StopFollowing( ent ); 
    565       } 
    566560      // cure poison 
    567561      if( ent->client->ps.stats[ STAT_STATE ] & SS_POISONCLOUDED && 
     
    596590    && ( level.time - ent->client->pers.teamChangeTime ) > 60000 ) ) 
    597591  { 
    598     if( oldTeam == PTE_NONE ) 
    599     { 
    600       // ps.persistant[] from a spectator cannot be trusted 
    601       ent->client->ps.persistant[ PERS_SCORE ] = ent->client->pers.savedScore; 
    602       ent->client->ps.persistant[ PERS_CREDIT ] = ent->client->pers.savedCredit; 
    603     } 
    604     else if( oldTeam == PTE_ALIENS ) 
    605     { 
    606       // always save in human credtis 
    607       ent->client->ps.persistant[ PERS_CREDIT ] *= 
    608         (float)FREEKILL_HUMAN / FREEKILL_ALIEN; 
    609     } 
    610  
    611     if( newTeam == PTE_NONE ) 
    612     { 
    613       // save values before the client enters the spectator team and their 
    614       // ps.persistant[] values become trashed 
    615       ent->client->pers.savedScore = ent->client->ps.persistant[ PERS_SCORE ]; 
    616       ent->client->pers.savedCredit = ent->client->ps.persistant[ PERS_CREDIT ]; 
    617     } 
     592    if( oldTeam == PTE_ALIENS ) 
     593      ent->client->pers.credit *= (float)FREEKILL_HUMAN / FREEKILL_ALIEN; 
    618594    else if( newTeam == PTE_ALIENS ) 
    619     { 
    620       // convert to alien currency 
    621       ent->client->ps.persistant[ PERS_CREDIT ] *= 
    622         (float)FREEKILL_ALIEN / FREEKILL_HUMAN; 
    623     } 
     595      ent->client->pers.credit *= (float)FREEKILL_ALIEN / FREEKILL_HUMAN; 
    624596  } 
    625597  else 
    626598  { 
    627     ent->client->ps.persistant[ PERS_CREDIT ] = 0; 
    628     ent->client->ps.persistant[ PERS_SCORE ] = 0; 
    629     ent->client->pers.savedScore = 0; 
    630     ent->client->pers.savedCredit = 0; 
     599    ent->client->pers.credit = 0; 
     600    ent->client->pers.score = 0; 
    631601  } 
    632602 
     
    698668  //guard against build timer exploit 
    699669  if( ent->client->pers.teamSelection != PTE_NONE && 
     670      ent->client->sess.sessionTeam != TEAM_SPECTATOR && 
    700671      ( ent->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_BUILDER0 || 
    701672      ent->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_BUILDER0_UPG || 
     
    16221593  trace_t   tr, tr2; 
    16231594  vec3_t    infestOrigin; 
    1624   int       allowedClasses[ PCL_NUM_CLASSES ]; 
    1625   int       numClasses = 0; 
    16261595  pClass_t  currentClass = ent->client->ps.stats[ STAT_PCLASS ]; 
    16271596  pClass_t  newClass; 
     
    16381607  qboolean  humanNear = qfalse; 
    16391608 
    1640   if( ent->client->ps.stats[ STAT_HEALTH ] <= 0 ) 
    1641     return; 
    1642  
    16431609  clientNum = ent->client - level.clients; 
    16441610  trap_Argv( 1, s, sizeof( s ) ); 
    1645  
    1646   if( BG_ClassIsAllowed( PCL_ALIEN_BUILDER0 ) ) 
    1647     allowedClasses[ numClasses++ ] = PCL_ALIEN_BUILDER0; 
    1648  
    1649   if( BG_ClassIsAllowed( PCL_ALIEN_BUILDER0_UPG ) && 
    1650       BG_FindStagesForClass( PCL_ALIEN_BUILDER0_UPG, g_alienStage.integer ) ) 
    1651     allowedClasses[ numClasses++ ] = PCL_ALIEN_BUILDER0_UPG; 
    1652  
    1653   if( BG_ClassIsAllowed( PCL_ALIEN_LEVEL0 ) ) 
    1654     allowedClasses[ numClasses++ ] = PCL_ALIEN_LEVEL0; 
     1611  newClass = BG_FindClassNumForName( s ); 
     1612 
     1613  if( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) 
     1614  { 
     1615    if( ent->client->sess.spectatorState == SPECTATOR_FOLLOW ) 
     1616      G_StopFollowing( ent ); 
     1617    if( ent->client->pers.teamSelection == PTE_ALIENS ) 
     1618    { 
     1619      if( newClass != PCL_ALIEN_BUILDER0 && 
     1620          newClass != PCL_ALIEN_BUILDER0_UPG && 
     1621          newClass != PCL_ALIEN_LEVEL0 ) 
     1622      { 
     1623        trap_SendServerCommand( ent-g_entities, 
     1624          va( "print \"You cannot spawn with class %s\n\"", s ) ); 
     1625        return; 
     1626      } 
     1627  
     1628      if( !BG_ClassIsAllowed( newClass ) ) 
     1629      { 
     1630        trap_SendServerCommand( ent-g_entities, 
     1631          va( "print \"Class %s is not allowed\n\"", s ) ); 
     1632        return; 
     1633      } 
     1634      if( !BG_FindStagesForClass( newClass, g_alienStage.integer ) ) 
     1635      { 
     1636        trap_SendServerCommand( ent-g_entities, 
     1637          va( "print \"Class %s not allowed at stage %d\n\"", 
     1638              s, g_alienStage.integer ) ); 
     1639        return; 
     1640      } 
     1641  
     1642      // spawn from an egg 
     1643      if( G_PushSpawnQueue( &level.alienSpawnQueue, clientNum ) ) 
     1644      { 
     1645        ent->client->pers.classSelection = newClass; 
     1646        ent->client->ps.stats[ STAT_PCLASS ] = newClass; 
     1647      } 
     1648    } 
     1649    else if( ent->client->pers.teamSelection == PTE_HUMANS ) 
     1650    { 
     1651      //set the item to spawn with 
     1652      if( !Q_stricmp( s, BG_FindNameForWeapon( WP_MACHINEGUN ) ) && 
     1653          BG_WeaponIsAllowed( WP_MACHINEGUN ) ) 
     1654      { 
     1655        ent->client->pers.humanItemSelection = WP_MACHINEGUN; 
     1656      } 
     1657      else if( !Q_stricmp( s, BG_FindNameForWeapon( WP_HBUILD ) ) && 
     1658               BG_WeaponIsAllowed( WP_HBUILD ) ) 
     1659      { 
     1660        ent->client->pers.humanItemSelection = WP_HBUILD; 
     1661      } 
     1662      else if( !Q_stricmp( s, BG_FindNameForWeapon( WP_HBUILD2 ) ) && 
     1663               BG_WeaponIsAllowed( WP_HBUILD2 ) && 
     1664               BG_FindStagesForWeapon( WP_HBUILD2, g_humanStage.integer ) ) 
     1665      { 
     1666        ent->client->pers.humanItemSelection = WP_HBUILD2; 
     1667      } 
     1668      else 
     1669      { 
     1670        trap_SendServerCommand( ent-g_entities, 
     1671          "print \"Unknown starting item\n\"" ); 
     1672        return; 
     1673      } 
     1674      // spawn from a telenode 
     1675      if( G_PushSpawnQueue( &level.humanSpawnQueue, clientNum ) ) 
     1676      { 
     1677        ent->client->pers.classSelection = PCL_HUMAN; 
     1678        ent->client->ps.stats[ STAT_PCLASS ] = PCL_HUMAN; 
     1679      } 
     1680    } 
     1681    return; 
     1682  } 
     1683 
     1684  if( ent->health <= 0 ) 
     1685    return; 
    16551686 
    16561687  if( ent->client->pers.teamSelection == PTE_ALIENS && 
     
    16581689      !( ent->client->ps.stats[ STAT_STATE ] & SS_HOVELING ) ) 
    16591690  { 
    1660     newClass = BG_FindClassNumForName( s ); 
    16611691    if( newClass == PCL_NONE ) 
    16621692    { 
    1663       trap_SendServerCommand( ent-g_entities, va( "print \"Unknown class\n\"" ) ); 
     1693      trap_SendServerCommand( ent-g_entities, "print \"Unknown class\n\"" ); 
    16641694      return; 
    16651695    } 
     
    17161746 
    17171747      //guard against selling the HBUILD weapons exploit 
    1718       if( ( currentClass == PCL_ALIEN_BUILDER0 || 
     1748      if( ent->client->sess.sessionTeam != TEAM_SPECTATOR && 
     1749          ( currentClass == PCL_ALIEN_BUILDER0 || 
    17191750            currentClass == PCL_ALIEN_BUILDER0_UPG ) && 
    17201751          ent->client->ps.stats[ STAT_MISC ] > 0 ) 
     
    17921823      } 
    17931824    } 
    1794     else 
    1795     { 
    1796       //spawning from an egg 
    1797       for( i = 0; i < numClasses; i++ ) 
    1798       { 
    1799         if( allowedClasses[ i ] == newClass && 
    1800             BG_FindStagesForClass( newClass, g_alienStage.integer ) && 
    1801             BG_ClassIsAllowed( newClass ) ) 
    1802         { 
    1803           G_LogOnlyPrintf("ClientTeamClass: %i alien %s\n", clientNum, s); 
    1804  
    1805           ent->client->pers.classSelection = 
    1806             ent->client->ps.stats[ STAT_PCLASS ] = newClass; 
    1807           G_PushSpawnQueue( &level.alienSpawnQueue, clientNum ); 
    1808           return; 
    1809         } 
    1810       } 
    1811       trap_SendServerCommand( ent-g_entities, va( "print \"You cannot spawn as this class\n\"" ) ); 
    1812       return; 
    1813     } 
    18141825  } 
    18151826  else if( ent->client->pers.teamSelection == PTE_HUMANS ) 
    18161827  { 
    18171828    //humans cannot use this command whilst alive 
    1818     if( ent->client->pers.classSelection != PCL_NONE ) 
    1819     { 
    1820       trap_SendServerCommand( ent-g_entities, va( "print \"You must be dead to use the class command\n\"" ) ); 
    1821       return; 
    1822     } 
    1823  
    1824     ent->client->pers.classSelection = 
    1825       ent->client->ps.stats[ STAT_PCLASS ] = PCL_HUMAN; 
    1826  
    1827     //set the item to spawn with 
    1828     if( !Q_stricmp( s, BG_FindNameForWeapon( WP_MACHINEGUN ) ) && BG_WeaponIsAllowed( WP_MACHINEGUN ) ) 
    1829       ent->client->pers.humanItemSelection = WP_MACHINEGUN; 
    1830     else if( !Q_stricmp( s, BG_FindNameForWeapon( WP_HBUILD ) ) && BG_WeaponIsAllowed( WP_HBUILD ) ) 
    1831       ent->client->pers.humanItemSelection = WP_HBUILD; 
    1832     else if( !Q_stricmp( s, BG_FindNameForWeapon( WP_HBUILD2 ) ) && BG_WeaponIsAllowed( WP_HBUILD2 ) && 
    1833         BG_FindStagesForWeapon( WP_HBUILD2, g_humanStage.integer ) ) 
    1834       ent->client->pers.humanItemSelection = WP_HBUILD2; 
    1835     else 
    1836     { 
    1837       ent->client->pers.classSelection = PCL_NONE; 
    1838       trap_SendServerCommand( ent-g_entities, va( "print \"Unknown starting item\n\"" ) ); 
    1839       return; 
    1840     } 
    1841  
    1842     G_LogOnlyPrintf("ClientTeamClass: %i human %s\n", clientNum, s); 
    1843  
    1844     G_PushSpawnQueue( &level.humanSpawnQueue, clientNum ); 
     1829    trap_SendServerCommand( ent-g_entities, 
     1830      "print \"You must be dead to use the class command\n\"" ); 
     1831    return; 
    18451832  } 
    18461833} 
     
    27862773/* 
    27872774================= 
     2775G_StopFromFollowing 
     2776 
     2777stops any other clients from following this one 
     2778called when a player leaves a team or dies 
     2779================= 
     2780*/ 
     2781void G_StopFromFollowing( gentity_t *ent ) 
     2782{ 
     2783  int i; 
     2784 
     2785  for( i = 0; i < level.maxclients; i++ ) 
     2786  { 
     2787    if( level.clients[ i ].sess.sessionTeam == TEAM_SPECTATOR && 
     2788        level.clients[ i ].sess.spectatorState == SPECTATOR_FOLLOW && 
     2789        level.clients[ i ].sess.spectatorClient == ent->client->ps.clientNum ) 
     2790    { 
     2791      if( !G_FollowNewClient( &g_entities[ i ], 1 ) ) 
     2792        G_StopFollowing( &g_entities[ i ] ); 
     2793    } 
     2794  } 
     2795} 
     2796 
     2797/* 
     2798================= 
    27882799G_StopFollowing 
    27892800 
     
    27962807  ent->client->ps.persistant[ PERS_TEAM ] = TEAM_SPECTATOR; 
    27972808  ent->client->sess.sessionTeam = TEAM_SPECTATOR; 
    2798   ent->client->sess.spectatorState = SPECTATOR_FREE; 
     2809  ent->client->ps.stats[ STAT_PTEAM ] = ent->client->pers.teamSelection; 
     2810 
     2811  if( ent->client->pers.teamSelection == PTE_NONE ) 
     2812  { 
     2813    ent->client->sess.spectatorState = SPECTATOR_FREE; 
     2814  } 
     2815  else 
     2816  { 
     2817    vec3_t   spawn_origin, spawn_angles; 
     2818 
     2819    ent->client->sess.spectatorState = SPECTATOR_LOCKED; 
     2820    if( ent->client->pers.teamSelection == PTE_ALIENS ) 
     2821      G_SelectAlienLockSpawnPoint( spawn_origin, spawn_angles ); 
     2822    else if( ent->client->pers.teamSelection == PTE_HUMANS ) 
     2823      G_SelectHumanLockSpawnPoint( spawn_origin, spawn_angles ); 
     2824    G_SetOrigin( ent, spawn_origin ); 
     2825    VectorCopy( spawn_origin, ent->client->ps.origin ); 
     2826    G_SetClientViewAngle( ent, spawn_angles ); 
     2827  } 
    27992828  ent->client->sess.spectatorClient = -1; 
    28002829  ent->client->ps.pm_flags &= ~PMF_FOLLOW; 
    2801   ent->client->ps.stats[ STAT_PTEAM ] = PTE_NONE; 
    28022830 
    28032831  ent->client->ps.stats[ STAT_STATE ] &= ~SS_WALLCLIMBING; 
     
    28642892 
    28652893    // can't follow another spectator 
    2866     if( level.clients[ clientnum ].pers.teamSelection == PTE_NONE ) 
     2894    if( level.clients[ clientnum ].sess.sessionTeam == TEAM_SPECTATOR ) 
     2895      continue; 
     2896 
     2897    // can only follow teammates when dead and on a team 
     2898    if( ent->client->pers.teamSelection != PTE_NONE &&  
     2899        ( level.clients[ clientnum ].pers.teamSelection !=  
     2900          ent->client->pers.teamSelection ) ) 
    28672901      continue; 
    28682902 
     
    30073041 
    30083042  // won't work unless spectating 
     3043  if( ent->client->sess.sessionTeam != TEAM_SPECTATOR ) 
     3044    return; 
    30093045  if( ent->client->sess.spectatorState == SPECTATOR_NOT ) 
    30103046    return; 
     
    32113247  { "donate", CMD_TEAM, Cmd_Donate_f }, 
    32123248 
    3213   { "follow", CMD_NOTEAM, Cmd_Follow_f }, 
    3214   { "follownext", CMD_NOTEAM, Cmd_FollowCycle_f }, 
    3215   { "followprev", CMD_NOTEAM, Cmd_FollowCycle_f }, 
     3249  { "follow", CMD_SPEC, Cmd_Follow_f }, 
     3250  { "follownext", CMD_SPEC, Cmd_FollowCycle_f }, 
     3251  { "followprev", CMD_SPEC, Cmd_FollowCycle_f }, 
    32163252 
    32173253  { "where", CMD_TEAM, Cmd_Where_f }, 
     
    32853321  } 
    32863322 
    3287   if( cmds[ i ].cmdFlags & CMD_NOTEAM && 
    3288       ent->client->pers.teamSelection != PTE_NONE ) 
     3323  if( cmds[ i ].cmdFlags & CMD_SPEC && 
     3324      ent->client->sess.sessionTeam != TEAM_SPECTATOR ) 
    32893325  { 
    32903326    trap_SendServerCommand( clientNum, 
    3291       "print \"Cannot use this command when on a team\n\"" ); 
     3327      "print \"You can only use this command when spectating\n\"" ); 
    32923328    return; 
    32933329  } 
  • src/game/g_combat.c

    r1 r68  
    148148  // stop any following clients 
    149149  // r1: removed, annoying. 
     150  // G_StopFromFollowing( self ); 
    150151 
    151152  self->client->ps.pm_type = PM_DEAD; 
  • src/game/g_local.h

    r66 r68  
    346346  int                 nameChanges; 
    347347 
    348   // used to save persistant[] values while in SPECTATOR_FOLLOW mode 
    349   int                 savedScore; 
    350   int                 savedCredit; 
     348  // used to save playerState_t values while in SPECTATOR_FOLLOW mode 
     349  int                 score; 
     350  int                 credit; 
    351351  int                 ping; 
    352352 
     
    484484int       G_PopSpawnQueue( spawnQueue_t *sq ); 
    485485int       G_PeekSpawnQueue( spawnQueue_t *sq ); 
    486 void      G_PushSpawnQueue( spawnQueue_t *sq, int clientNum ); 
     486qboolean  G_SearchSpawnQueue( spawnQueue_t *sq, int clientNum ); 
     487qboolean  G_PushSpawnQueue( spawnQueue_t *sq, int clientNum ); 
    487488qboolean  G_RemoveFromSpawnQueue( spawnQueue_t *sq, int clientNum ); 
    488489int       G_GetPosInSpawnQueue( spawnQueue_t *sq, int clientNum ); 
     
    670671#define CMD_MESSAGE       0x02 // sends message to others (skip when muted) 
    671672#define CMD_TEAM          0x04 // must be on a team 
    672 #define CMD_NOTEAM        0x08 // must not be on a team 
     673#define CMD_SPEC          0x08 // must be in spectator mode 
    673674#define CMD_ALIEN         0x10 
    674675#define CMD_HUMAN         0x20 
     
    698699// 
    699700void      Cmd_Score_f( gentity_t *ent ); 
     701void      G_StopFromFollowing( gentity_t *ent ); 
    700702void      G_StopFollowing( gentity_t *ent ); 
    701703qboolean  G_FollowNewClient( gentity_t *ent, int dir ); 
     
    917919void      G_AddCreditToClient( gclient_t *client, short credit, qboolean cap ); 
    918920team_t    TeamCount( int ignoreClientNum, int team ); 
    919 void      SetClientViewAngle( gentity_t *ent, vec3_t angle ); 
    920 gentity_t *SelectTremulousSpawnPoint( pTeam_t team, vec3_t preference, vec3_t origin, vec3_t angles ); 
    921 gentity_t *SelectSpawnPoint( vec3_t avoidPoint, vec3_t origin, vec3_t angles ); 
     921void      G_SetClientViewAngle( gentity_t *ent, vec3_t angle ); 
     922gentity_t *G_SelectTremulousSpawnPoint( pTeam_t team, vec3_t preference, vec3_t origin, vec3_t angles ); 
     923gentity_t *G_SelectSpawnPoint( vec3_t avoidPoint, vec3_t origin, vec3_t angles ); 
     924gentity_t *G_SelectAlienLockSpawnPoint( vec3_t origin, vec3_t angles ); 
     925gentity_t *G_SelectHumanLockSpawnPoint( vec3_t origin, vec3_t angles ); 
    922926void      SpawnCorpse( gentity_t *ent ); 
    923927void      respawn( gentity_t *ent ); 
  • src/game/g_main.c

    r66 r68  
    821821 
    822822  // then sort by score 
    823   if( ca->ps.persistant[ PERS_SCORE ] > cb->ps.persistant[ PERS_SCORE ] ) 
     823  if( ca->pers.score > cb->pers.score ) 
    824824    return -1; 
    825   else if( ca->ps.persistant[ PERS_SCORE ] < cb->ps.persistant[ PERS_SCORE ] ) 
     825  else if( ca->pers.score < cb->pers.score ) 
    826826    return 1; 
    827827  else 
     
    905905/* 
    906906============ 
     907G_SearchSpawnQueue 
     908 
     909Look to see if clientNum is already in the spawnQueue 
     910============ 
     911*/ 
     912qboolean G_SearchSpawnQueue( spawnQueue_t *sq, int clientNum ) 
     913{ 
     914  int i; 
     915 
     916  for( i = 0; i < MAX_CLIENTS; i++ ) 
     917    if( sq->clients[ i ] == clientNum ) 
     918      return qtrue; 
     919  return qfalse; 
     920} 
     921 
     922/* 
     923============ 
    907924G_PushSpawnQueue 
    908925 
     
    910927============ 
    911928*/ 
    912 void G_PushSpawnQueue( spawnQueue_t *sq, int clientNum ) 
    913 { 
     929qboolean G_PushSpawnQueue( spawnQueue_t *sq, int clientNum ) 
     930{ 
     931  // don't add the same client more than once 
     932  if( G_SearchSpawnQueue( sq, clientNum ) ) 
     933    return qfalse; 
     934 
    914935  sq->back = QUEUE_PLUS1( sq->back ); 
    915936  sq->clients[ sq->back ] = clientNum; 
    916937 
    917938  g_entities[ clientNum ].client->ps.pm_flags |= PMF_QUEUED; 
     939  return qtrue; 
    918940} 
    919941 
     
    10491071    ent = &g_entities[ clientNum ]; 
    10501072 
    1051     if( ( spawn = SelectTremulousSpawnPoint( team, 
     1073    if( ( spawn = G_SelectTremulousSpawnPoint( team, 
    10521074            ent->client->pers.lastDeathLocation, 
    10531075            spawn_origin, spawn_angles ) ) ) 
     
    15851607  if( !ent ) 
    15861608  { // the map creator forgot to put in an intermission point... 
    1587     SelectSpawnPoint( vec3_origin, level.intermission_origin, level.intermission_angle ); 
     1609    G_SelectSpawnPoint( vec3_origin, level.intermission_origin, level.intermission_angle ); 
    15881610  } 
    15891611  else 
  • src/game/g_misc.c

    r0 r68  
    9090 
    9191  // set angles 
    92   SetClientViewAngle( player, angles ); 
     92  G_SetClientViewAngle( player, angles ); 
    9393 
    9494  // kill anything at the destination 
  • src/game/g_ptr.c

    r0 r68  
    6464    client->pers.connection->clientTeam = client->pers.teamSelection; 
    6565    if( client->pers.teamSelection == PTE_NONE ) 
    66       client->pers.connection->clientCredit = client->pers.savedCredit; 
     66      client->pers.connection->clientCredit = client->pers.credit; 
    6767    else 
    6868      client->pers.connection->clientCredit = client->ps.persistant[ PERS_CREDIT ];