diff options
Diffstat (limited to 'src/game')
| -rw-r--r-- | src/game/bg_misc.c | 13 | ||||
| -rw-r--r-- | src/game/bg_pmove.c | 42 | ||||
| -rw-r--r-- | src/game/bg_public.h | 8 | ||||
| -rw-r--r-- | src/game/g_active.c | 32 | ||||
| -rw-r--r-- | src/game/g_admin.c | 6 | ||||
| -rw-r--r-- | src/game/g_buildable.c | 78 | ||||
| -rw-r--r-- | src/game/g_client.c | 9 | ||||
| -rw-r--r-- | src/game/g_cmds.c | 138 | ||||
| -rw-r--r-- | src/game/g_combat.c | 27 | ||||
| -rw-r--r-- | src/game/g_local.h | 2 | ||||
| -rw-r--r-- | src/game/g_main.c | 8 | ||||
| -rw-r--r-- | src/game/g_weapon.c | 58 | ||||
| -rw-r--r-- | src/game/tremulous.h | 10 | 
13 files changed, 272 insertions, 159 deletions
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c index b96c8a9..a416ecb 100644 --- a/src/game/bg_misc.c +++ b/src/game/bg_misc.c @@ -2804,6 +2804,19 @@ static const upgradeAttributes_t bg_upgrades[ ] =      qtrue,                  //qboolean purchasable      qfalse,                 //qboolean usable      TEAM_HUMANS             //team_t  team; +  }, +  { +    UP_NIGHTVISION,         //int   upgradeNum; +    0,                      //int   price; +    0,                      //int  stages +    SLOT_NONE,              //int   slots; +    "nightvision",          //char  *upgradeName; +    "",                     //char  *humanName; +    "", +    0, +    qfalse,                 //qboolean purchasable +    qtrue,                  //qboolean usable +    TEAM_ALIENS             //team_t  team;    }  }; diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c index 3b53dc9..d5719a5 100644 --- a/src/game/bg_pmove.c +++ b/src/game/bg_pmove.c @@ -672,6 +672,9 @@ static qboolean PM_CheckWallJump( void )    float   upFraction = 1.5f;    trace_t trace; +  if( pm->waterlevel ) +    return qfalse; +      if( !( BG_Class( pm->ps->stats[ STAT_CLASS ] )->abilities & SCA_WALLJUMPER ) )      return qfalse; @@ -935,27 +938,45 @@ static qboolean PM_CheckWaterJump( void )    vec3_t  spot;    int     cont;    vec3_t  flatforward; +  vec3_t  mins, maxs; +  float   a, r;    if( pm->ps->pm_time )      return qfalse; -  // check for water jump -  if( pm->waterlevel != 2 ) +  if( pm->cmd.upmove < 10 ) +    // not holding jump      return qfalse; +  // check for water jump +  //if( pm->waterlevel != 2 ) +  //  return qfalse; +    flatforward[ 0 ] = pml.forward[ 0 ];    flatforward[ 1 ] = pml.forward[ 1 ];    flatforward[ 2 ] = 0;    VectorNormalize( flatforward ); -  VectorMA( pm->ps->origin, 30, flatforward, spot ); -  spot[ 2 ] += 4; +  BG_ClassBoundingBox( pm->ps->stats[ STAT_CLASS ], mins, maxs, NULL, NULL, NULL ); +   +  // bbox bottom +  spot[ 0 ] = pm->ps->origin[ 0 ]; +  spot[ 1 ] = pm->ps->origin[ 1 ]; +  spot[ 2 ] = pm->ps->origin[ 2 ] + mins[ 2 ]; + +  // project the flatforward vector onto the bbox (just a bit longer, so we'll actually hit a wall) +  // then add it to spot +  #define fmod(a,n) ((a)-(n)*floor((a)/(n))) +  a = pm->ps->viewangles[ YAW ] / ( 180.0f / M_PI ); +  r = ( maxs[ 0 ] + 1 ) * 1.0f / cos( fmod( a+0.25f*M_PI, 0.5f*M_PI ) - 0.25f*M_PI ); +  VectorMA( spot, r, flatforward, spot ); +    cont = pm->pointcontents( spot, pm->ps->clientNum );    if( !( cont & CONTENTS_SOLID ) )      return qfalse; -  spot[ 2 ] += 16; +  spot[ 2 ] = pm->ps->origin[ 2 ] + maxs[ 2 ];    cont = pm->pointcontents( spot, pm->ps->clientNum );    if( cont ) @@ -2409,32 +2430,35 @@ static void PM_SetWaterLevel( void )    int     cont;    int     sample1;    int     sample2; +  vec3_t  mins;    //    // get waterlevel, accounting for ducking    //    pm->waterlevel = 0;    pm->watertype = 0; +   +  BG_ClassBoundingBox( pm->ps->stats[ STAT_CLASS ], mins, NULL, NULL, NULL, NULL );    point[ 0 ] = pm->ps->origin[ 0 ];    point[ 1 ] = pm->ps->origin[ 1 ]; -  point[ 2 ] = pm->ps->origin[ 2 ] + MINS_Z + 1; +  point[ 2 ] = pm->ps->origin[ 2 ] + mins[2] + 1;    cont = pm->pointcontents( point, pm->ps->clientNum );    if( cont & MASK_WATER )    { -    sample2 = pm->ps->viewheight - MINS_Z; +    sample2 = pm->ps->viewheight - mins[2];      sample1 = sample2 / 2;      pm->watertype = cont;      pm->waterlevel = 1; -    point[ 2 ] = pm->ps->origin[ 2 ] + MINS_Z + sample1; +    point[ 2 ] = pm->ps->origin[ 2 ] + mins[2] + sample1;      cont = pm->pointcontents( point, pm->ps->clientNum );      if( cont & MASK_WATER )      {        pm->waterlevel = 2; -      point[ 2 ] = pm->ps->origin[ 2 ] + MINS_Z + sample2; +      point[ 2 ] = pm->ps->origin[ 2 ] + mins[2] + sample2;        cont = pm->pointcontents( point, pm->ps->clientNum );        if( cont & MASK_WATER ) diff --git a/src/game/bg_public.h b/src/game/bg_public.h index 64ce615..e06015d 100644 --- a/src/game/bg_public.h +++ b/src/game/bg_public.h @@ -233,8 +233,9 @@ typedef enum    STAT_BUILDABLE, // which ghost model to display for building    STAT_FALLDIST,  // the distance the player fell    STAT_VIEWLOCK,  // direction to lock the view in -  STAT_FUEL       // jetpacks -  // netcode has space for 2 more +  STAT_FUEL,      // jetpacks +  STAT_SHAKE      // camera shake +  // netcode has space for 1 more  } statIndex_t;  #define SCA_WALLCLIMBER         0x00000001 @@ -397,6 +398,8 @@ typedef enum    UP_BIORES,    UP_AMMO, +   +  UP_NIGHTVISION, // aliens    UP_NUM_UPGRADES  } upgrade_t; @@ -630,6 +633,7 @@ typedef enum    MN_B_CUBOID_MODE1,    MN_B_CUBOID_MODE2,    MN_B_TOODENSE, +  MN_B_INVALIDSIZE,    //alien build    MN_A_ONEOVERMIND, diff --git a/src/game/g_active.c b/src/game/g_active.c index 05bda16..1fa0caa 100644 --- a/src/game/g_active.c +++ b/src/game/g_active.c @@ -168,6 +168,19 @@ void P_WorldEffects( gentity_t *ent )      ent->client->airOutTime = level.time + 12000;      ent->damage = 2;    } +} + +void P_WorldEffects_Fast( gentity_t *ent ) +{ +  int       waterlevel; + +  if( ent->client->noclip ) +  { +    ent->client->airOutTime = level.time + 12000; // don't need air +    return; +  } + +  waterlevel = ent->waterlevel;    //    // check for sizzle damage (move to pmove?) @@ -175,26 +188,24 @@ void P_WorldEffects( gentity_t *ent )    if( waterlevel &&        ( ent->watertype & ( CONTENTS_LAVA | CONTENTS_SLIME ) ) )    { -    if( ent->health > 0 && -        ent->pain_debounce_time <= level.time  ) +    if( ent->health > 0 )      {        if( ent->watertype & CONTENTS_LAVA )        {          G_Damage( ent, NULL, NULL, NULL, NULL, -          30 * waterlevel, 0, MOD_LAVA ); +          3 * waterlevel, 0, MOD_LAVA );        }        if( ent->watertype & CONTENTS_SLIME )        {          G_Damage( ent, NULL, NULL, NULL, NULL, -          10 * waterlevel, 0, MOD_SLIME ); +          1 * waterlevel, 0, MOD_SLIME );        }      }    }  } -  /*  ===============  G_SetClientSound @@ -629,6 +640,8 @@ void ClientTimerActions( gentity_t *ent, int msec )      weapon_t weapon = BG_GetPlayerWeapon( &client->ps );      client->time100 -= 100; +     +    P_WorldEffects_Fast( ent );      // Restore or subtract stamina      if( stopped || client->ps.pm_type == PM_JETPACK ) @@ -757,13 +770,16 @@ void ClientTimerActions( gentity_t *ent, int msec )      if( ent->client->bioresHealTimer >= 100 )      {        int delta; -       +        delta = ent->client->bioresHealTimer / 100;        ent->health = MAX( MIN( ent->health+delta, ent->client->ps.stats[ STAT_MAX_HEALTH ] ), 1 ); -       +        ent->client->bioresHealTimer %= 100;      } -       + +    ent->client->ps.stats[ STAT_SHAKE ] *= 0.77f; +    if( ent->client->ps.stats[ STAT_SHAKE ] < 0 ) +      ent->client->ps.stats[ STAT_SHAKE ] = 0;    }    while( client->time1000 >= 1000 ) diff --git a/src/game/g_admin.c b/src/game/g_admin.c index 25e3e9b..90f42c8 100644 --- a/src/game/g_admin.c +++ b/src/game/g_admin.c @@ -641,7 +641,7 @@ static void admin_default_levels( void )    l->level = level++;    Q_strncpyz( l->name, "^4Unknown Player", sizeof( l->name ) );    Q_strncpyz( l->flags, -    "listplayers admintest adminhelp time", +    "listplayers admintest adminhelp time register",      sizeof( l->flags ) );    l = l->next = BG_Alloc( sizeof( g_admin_level_t ) ); @@ -3498,6 +3498,8 @@ qboolean G_admin_register( gentity_t *ent )    Q_strncpyz( ent->client->pers.admin->name,                 ent->client->pers.netname,                 sizeof( ent->client->pers.admin->name ) ); -   + +  admin_writeconfig( ); +    return qtrue;  } diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c index b13c54a..0039ccd 100644 --- a/src/game/g_buildable.c +++ b/src/game/g_buildable.c @@ -2524,39 +2524,46 @@ void Cuboid_Think(gentity_t *self)  }  //Cuboids need a new die function because of the cuboid explosion effects. -void Cuboid_Die(gentity_t *self,gentity_t *inflictor,gentity_t *attacker,int damage,int mod) +void Cuboid_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod )  {    vec3_t dir; -  qboolean event=qfalse; +  qboolean event = qfalse;    const cuboidAttributes_t *cuboid; -  cuboid=BG_CuboidAttributes(self->s.modelindex); -  G_SetBuildableAnim(self,BANIM_DESTROY1,qtrue); // just for sound -  self->die=nullDieFunction; -  self->killedBy=attacker-g_entities; -  self->powered=qfalse; -  self->s.eFlags&=~EF_FIRING; -  G_LogDestruction(self,attacker,mod); -  dir[0]=dir[1]=0; -  dir[2]=1; +  cuboid = BG_CuboidAttributes( self->s.modelindex ); +  G_SetBuildableAnim( self, BANIM_DESTROY1, qtrue ); // just for sound +  self->die = nullDieFunction; +  self->killedBy = attacker - g_entities; +  self->powered = qfalse; +  self->s.eFlags &= ~EF_FIRING; +  G_LogDestruction( self, attacker, mod ); +  dir[ 0 ] = +  dir[ 1 ] = 0; +  dir[ 2 ] = 1;    self->timestamp = level.time; -  G_QueueBuildPoints(self); -  if(mod!=MOD_DECONSTRUCT&&self->spawned) +  G_QueueBuildPoints( self ); +   +  if( mod != MOD_DECONSTRUCT && self->spawned )    { -    G_RewardAttackers(self); -    G_RadiusDamage(self->s.pos.trBase,g_entities+self->killedBy,self->splashDamage,self->splashRadius,self,self->splashMethodOfDeath); +    G_RewardAttackers( self ); +    G_RadiusDamage( self->s.pos.trBase, +                    g_entities + self->killedBy, +                    self->splashDamage, +                    self->splashRadius, +                    self, +                    self->splashMethodOfDeath );      //NOTE: all cuboid info is already packed -    self->s.eType=ET_EVENTS+EV_CUBOID_EXPLOSION; +    self->s.eType = ET_EVENTS + EV_CUBOID_EXPLOSION;      self->freeAfterEvent = qtrue; -    G_AddEvent(self,EV_HUMAN_BUILDABLE_EXPLOSION,DirToByte(dir)); -    event=qtrue; -    self->r.contents=0; -    trap_LinkEntity(self); +    G_AddEvent( self, EV_HUMAN_BUILDABLE_EXPLOSION, DirToByte( dir ) ); +    event = qtrue; +    self->r.contents = 0; +    trap_LinkEntity( self );    }    else    { -    self->s.eType=0; -    G_FreeEntity(self); +    self->s.eType = 0; +    G_FreeEntity( self );    }  } @@ -3440,12 +3447,18 @@ itemBuildError_t G_CanBuild( gentity_t *ent, buildable_t buildable, int distance    int               contents;    playerState_t     *ps = &ent->client->ps; -  if( BG_Buildable(buildable,NULL)->cuboid ) -    BG_CuboidBBox(cuboidSize,mins,maxs); +  if( BG_Buildable( buildable, NULL )->cuboid ) +  { +    if( !G_CheckCuboidSize( cuboidSize, buildable ) ) +      return IBE_INVALIDSIZE; +    BG_CuboidBBox( cuboidSize, mins, maxs ); +  }    else      BG_BuildableBoundingBox( buildable, mins, maxs ); - -  if(!BG_PositionBuildableRelativeToPlayer( ps, BG_Buildable(buildable,NULL)->cuboid, mins, maxs, trap_Trace, entity_origin, angles, &tr1 )) +   +  if( !BG_PositionBuildableRelativeToPlayer( +        ps, BG_Buildable( buildable, NULL )->cuboid, +        mins, maxs, trap_Trace, entity_origin, angles, &tr1 ) )      return IBE_NOSURF;    trap_Trace( &tr2, entity_origin, mins, maxs, entity_origin, -1, MASK_PLAYERSOLID );    trap_Trace( &tr3, ps->origin, NULL, NULL, entity_origin, ent->s.number, MASK_PLAYERSOLID ); @@ -3964,15 +3977,19 @@ qboolean G_BuildIfValid( gentity_t *ent, buildable_t buildable, vec3_t cuboidSiz      case IBE_LASTSPAWN:        G_TriggerMenu( ent->client->ps.clientNum, MN_B_LASTSPAWN );        return qfalse; -       +      case IBE_NOSURF:        G_TriggerMenu( ent->client->ps.clientNum, MN_B_NOSURF );        return qfalse; -       +      case IBE_TOODENSE:        G_TriggerMenu( ent->client->ps.clientNum, MN_B_TOODENSE );        return qfalse; +    case IBE_INVALIDSIZE: +      G_TriggerMenu( ent->client->ps.clientNum, MN_B_INVALIDSIZE ); +      return qfalse; +      default:        break;    } @@ -4577,7 +4594,10 @@ void G_RemoveUnbuiltBuildables( gentity_t *self )      if( ent->builtBy != self->client->ps.clientNum )        continue; -     + +    if( ent->s.modelindex < CUBOID_FIRST ) +      continue; +      G_Damage( ent, self, NULL, dir, dir, ent->health, 0, MOD_DECONSTRUCT );    }  } diff --git a/src/game/g_client.c b/src/game/g_client.c index c8421f0..7596ea1 100644 --- a/src/game/g_client.c +++ b/src/game/g_client.c @@ -1397,7 +1397,7 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles          // try to unblock the player          if( tr.startsolid )          { -          Com_Printf("DEBUG: player is stuck!\n"); +          //Com_Printf("DEBUG: player is stuck!\n");            for( i = 0; i < 16*2; i++ )            {              float a, r; @@ -1414,7 +1414,7 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles              if( !tr.startsolid )              { -             Com_Printf("DEBUG: player position fixed at iteration %i\n",i); +             //Com_Printf("DEBUG: player position fixed at iteration %i\n",i);               VectorCopy( neworigin, spawn_origin );               break;              } @@ -1547,6 +1547,11 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles    else      weapon = WP_NONE; +  // give nightvision to basilisks +  if( ent->client->pers.classSelection == PCL_ALIEN_LEVEL1 || +      ent->client->pers.classSelection == PCL_ALIEN_LEVEL1_UPG ) +    BG_AddUpgradeToInventory( UP_NIGHTVISION, client->ps.stats ); +    maxAmmo = BG_Weapon( weapon )->maxAmmo;    maxClips = BG_Weapon( weapon )->maxClips;    client->ps.stats[ STAT_WEAPON ] = weapon; diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index 468dde0..2c15638 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -2527,21 +2527,30 @@ void Cmd_Sell_f( gentity_t *ent )  /*  ================= -Cmd_CheckCuboidSize +G_CheckCuboidSize  Check if the specified dimensions are valid.  =================  */ -qboolean Cmd_CheckCuboidSize(vec3_t dims) +qboolean G_CheckCuboidSize( vec3_t dims, buildable_t type )  { - if(g_cuboidSizeLimit.integer) -  if(dims[0]>g_cuboidSizeLimit.integer||dims[1]>g_cuboidSizeLimit.integer||dims[2]>g_cuboidSizeLimit.integer) -   return qfalse; - if(dims[0]*dims[1]*dims[2]<CUBOID_MINVOLUME) -   return qfalse; - if(dims[0]<1||dims[1]<1||dims[2]<1) -  return qfalse; - return qtrue; +  if( g_cuboidSizeLimit.integer ) +    if( dims[ 0 ] > g_cuboidSizeLimit.integer || +       dims[ 1 ] > g_cuboidSizeLimit.integer || +       dims[ 2 ] > g_cuboidSizeLimit.integer ) +      return qfalse; + +    if( dims[ 0 ] * dims[ 1 ] * dims[ 2 ] < CUBOID_MINVOLUME) +    return qfalse; + +  if( dims[ 0 ] < 1 || dims[ 1 ] < 1 || dims[ 2 ] < 1 ) +    return qfalse; + +  if( g_cuboidHealthLimit.integer ) +    if( BG_Buildable( type, dims )->health > g_cuboidHealthLimit.integer ) +      return qfalse; + +  return qtrue;  }  /* @@ -2554,33 +2563,32 @@ Update player's cuboid selection (after validation) with data sent over network.  */  void Cmd_Cb_f(gentity_t *ent)  { - char s[MAX_TOKEN_CHARS]; - int echo; - vec3_t dims; +  char s[MAX_TOKEN_CHARS]; +  int echo; +  vec3_t dims; - if(trap_Argc()!=5) -  return; - trap_Argv(1,s,sizeof(s)); - echo=atoi(s); - trap_Argv(2,s,sizeof(s)); - dims[0]=atof(s); - trap_Argv(3,s,sizeof(s)); - dims[1]=atof(s); - trap_Argv(4,s,sizeof(s)); - dims[2]=atof(s); - if(Cmd_CheckCuboidSize(dims)) - {  -  VectorCopy(dims,ent->client->cuboidSelection); -  trap_SendServerCommand(ent->client-level.clients,va("cb3 %i\n",echo)); -  G_RelayCuboidToSpectators(ent->client); - } - else - { -  if(Cmd_CheckCuboidSize(ent->client->cuboidSelection)) -   trap_SendServerCommand(ent->client-level.clients,va("cb3 %i %f %f %f\n",echo,ent->client->cuboidSelection[0],ent->client->cuboidSelection[1],ent->client->cuboidSelection[2])); +  if( trap_Argc( ) != 5 ) +    return; + +  trap_Argv( 1, s, sizeof( s ) ); +  echo = atoi( s ); +  trap_Argv( 2, s, sizeof( s ) ); +  dims[ 0 ] = atof( s ); +  trap_Argv( 3, s, sizeof( s ) ); +  dims[ 1 ] = atof( s ); +  trap_Argv( 4, s, sizeof( s ) ); +  dims[ 2 ] = atof( s ); + +  VectorCopy( dims, ent->client->cuboidSelection ); +  G_RelayCuboidToSpectators( ent->client ); + +  if( G_CheckCuboidSize( dims, ent->client->ps.stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT ) ) +    trap_SendServerCommand( ent->client - level.clients, va( "cb3 %i\n", echo ) );    else -   trap_SendServerCommand(ent->client-level.clients,va("cb3 %i %f %f %f\n",echo,g_cuboidSizeLimit.integer,g_cuboidSizeLimit.integer,g_cuboidSizeLimit.integer)); - } +  { +    trap_SendServerCommand( ent->client - level.clients, va( "cb4 %i\n", echo ) ); +    ent->client->ps.stats[ STAT_BUILDABLE ] &= ~SB_VALID_TOGGLEBIT; +  }  } @@ -2627,37 +2635,35 @@ void Cmd_Build_f( gentity_t *ent )    {      if( trap_Argc() >= 5 )      { -      trap_Argv(2,s,sizeof(s)); -      dims[0]=MAX(1,atof(s)); -      trap_Argv(3,s,sizeof(s)); -      dims[1]=MAX(1,atof(s)); -      trap_Argv(4,s,sizeof(s)); -      dims[2]=MAX(1,atof(s)); -      if(!Cmd_CheckCuboidSize(dims)) +      trap_Argv( 2, s, sizeof( s ) ); +      dims[ 0 ] = MAX( 1, atof( s ) ); +      trap_Argv( 3, s, sizeof( s ) ); +      dims[ 1 ] = MAX( 1, atof( s ) ); +      trap_Argv( 4, s, sizeof( s ) ); +      dims[ 2 ] = MAX( 1, atof( s ) ); +      if( !G_CheckCuboidSize( dims, buildable ) )        { -        Com_sprintf(buf,sizeof(buf),"print \"^1error: invalid cuboid size (min volume: %i, max size: %s)\n\"", -                    CUBOID_MINVOLUME,(g_cuboidSizeLimit.integer?va("%ix%ix%i",g_cuboidSizeLimit.integer,g_cuboidSizeLimit.integer, g_cuboidSizeLimit.integer):"no limit")); -        trap_SendServerCommand(ent->client-level.clients,buf); +        G_TriggerMenu( ent->client->ps.clientNum, MN_B_INVALIDSIZE );          return;        } -      VectorCopy(dims,ent->client->cuboidSelection); +      VectorCopy( dims, ent->client->cuboidSelection );      }      // client is building a cuboid for the first time so reset the selection to default -    if(!Cmd_CheckCuboidSize(ent->client->cuboidSelection)) +    if( !G_CheckCuboidSize(ent->client->cuboidSelection, buildable) )      { -      ent->client->cuboidSelection[0]=32; -      ent->client->cuboidSelection[1]=32; -      ent->client->cuboidSelection[2]=32; -      trap_SendServerCommand(ent->client-level.clients,"cb2 32 32 32"); -      G_RelayCuboidToSpectators(ent->client); +      ent->client->cuboidSelection[ 0 ] = 30; +      ent->client->cuboidSelection[ 1 ] = 30; +      ent->client->cuboidSelection[ 2 ] = 30; +      trap_SendServerCommand( ent->client-level.clients, "cb2 30 30 30" ); +      G_RelayCuboidToSpectators( ent->client );      } -    if(!BG_CuboidAllowed((team==TEAM_ALIENS?g_alienStage.integer:g_humanStage.integer))) +    if( !BG_CuboidAllowed( ( team == TEAM_ALIENS ? g_alienStage.integer : g_humanStage.integer ) ) )      { -      if(BG_CuboidMode()==1) -        G_TriggerMenu(ent->client->ps.clientNum,MN_B_CUBOID_MODE1); +      if( BG_CuboidMode() == 1 ) +        G_TriggerMenu(ent->client->ps.clientNum, MN_B_CUBOID_MODE1 );        else -        G_TriggerMenu(ent->client->ps.clientNum,MN_B_CUBOID_MODE2); +        G_TriggerMenu(ent->client->ps.clientNum, MN_B_CUBOID_MODE2 );        return;      }    } @@ -2751,12 +2757,13 @@ void Cmd_Build_f( gentity_t *ent )      if( err == MN_NONE || ent->client->pers.disableBlueprintErrors )      { -     trap_SendServerCommand(ent->client-level.clients,va("cb2 %f %f %f\n", -                                                         ent->client->cuboidSelection[0], -                                                         ent->client->cuboidSelection[1], -                                                         ent->client->cuboidSelection[2])); -     G_RelayCuboidToSpectators(ent->client); -     ent->client->ps.stats[ STAT_BUILDABLE ] |= buildable; +      trap_SendServerCommand( ent->client - level.clients, +                              va( "cb2 %f %f %f\n", +                                  ent->client->cuboidSelection[ 0 ], +                                  ent->client->cuboidSelection[ 1 ], +                                  ent->client->cuboidSelection[ 2 ] ) ); +      G_RelayCuboidToSpectators( ent->client ); +      ent->client->ps.stats[ STAT_BUILDABLE ] |= buildable;      }      else        G_TriggerMenu( ent->client->ps.clientNum, err ); @@ -3298,12 +3305,7 @@ Cmd_Debug1_f  */  void Cmd_Debug1_f( gentity_t *other )  { -            other->client->isImpregnated = qtrue; -            other->client->isImplantMature = qfalse; -            other->client->impregnationTime = level.time; -            other->client->impregnatedBy = -1; -                  other->client->isImplantMature = qtrue; -      other->client->ps.stats[ STAT_STATE ] |= SS_IMPLANTED; +  other->client->ps.stats[ STAT_SHAKE ] += 70;  }  /* diff --git a/src/game/g_combat.c b/src/game/g_combat.c index 1b6708f..fe5d607 100644 --- a/src/game/g_combat.c +++ b/src/game/g_combat.c @@ -1329,7 +1329,7 @@ G_RadiusDamage  qboolean G_RadiusDamage( vec3_t origin, gentity_t *attacker, float damage,                           float radius, gentity_t *ignore, int mod )  { -  float     points, dist; +  float     points, dist, shake;    gentity_t *ent;    int       entityList[ MAX_GENTITIES ];    int       numListedEntities; @@ -1389,6 +1389,31 @@ qboolean G_RadiusDamage( vec3_t origin, gentity_t *attacker, float damage,      }    } +  for( i = 0; i < 3; i++ ) +  { +    mins[ i ] = origin[ i ] - radius * 2; +    maxs[ i ] = origin[ i ] + radius * 2; +  } + +  numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES ); + +  for( e = 0; e < numListedEntities; e++ ) +  { +    ent = g_entities + entityList[ e ]; + +    if( ent == ignore ) +      continue; + +    if( !ent->client ) +      continue; + +    if( !ent->takedamage ) +      continue; + +    shake = damage * 10 / Distance( origin, ent->r.currentOrigin ); +    ent->client->ps.stats[ STAT_SHAKE ] += (int) shake; +  } +      return hitClient;  } diff --git a/src/game/g_local.h b/src/game/g_local.h index 3bd8642..001c7d9 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -790,6 +790,7 @@ typedef enum    IBE_LASTSPAWN,    IBE_NOSURF,    IBE_TOODENSE, +  IBE_INVALIDSIZE,    IBE_MAXERRORS  } itemBuildError_t; @@ -1221,6 +1222,7 @@ extern  vmCvar_t  g_censorship;  extern  vmCvar_t  g_unlimited;  extern  vmCvar_t  g_instantBuild;  extern  vmCvar_t  g_cuboidSizeLimit; +extern  vmCvar_t  g_cuboidHealthLimit;  extern  vmCvar_t  g_buildableDensityLimit;  extern  vmCvar_t  g_buildableDensityLimitRange; diff --git a/src/game/g_main.c b/src/game/g_main.c index 8f43d81..0f9c31c 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -152,6 +152,7 @@ vmCvar_t  g_tag;  vmCvar_t  g_unlimited;  vmCvar_t  g_instantBuild;  vmCvar_t  g_cuboidSizeLimit; +vmCvar_t  g_cuboidHealthLimit;  vmCvar_t  g_cuboidMode;  vmCvar_t  g_buildableDensityLimit; @@ -295,11 +296,12 @@ static cvarTable_t   gameCvarTable[ ] =    { &g_unlimited, "g_unlimited", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qfalse },    { &g_instantBuild, "g_instantBuild", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qfalse }, -  { &g_cuboidSizeLimit, "g_cuboidSizeLimit", "0", CVAR_ARCHIVE, 0, qfalse }, +  { &g_cuboidSizeLimit, "g_cuboidSizeLimit", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qfalse }, +  { &g_cuboidHealthLimit, "g_cuboidHealthLimit", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qfalse },    { &g_cuboidMode, "g_cuboidMode", "0", CVAR_ARCHIVE, 0, qfalse }, -  { &g_buildableDensityLimit, "g_buildableDensityLimit", "0", CVAR_ARCHIVE, 0, qfalse }, -  { &g_buildableDensityLimitRange, "g_buildableDensityLimitRange", "0", CVAR_ARCHIVE, 0, qfalse } +  { &g_buildableDensityLimit, "g_buildableDensityLimit", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qfalse }, +  { &g_buildableDensityLimitRange, "g_buildableDensityLimitRange", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qfalse }  };  static int gameCvarTableSize = sizeof( gameCvarTable ) / sizeof( gameCvarTable[ 0 ] ); diff --git a/src/game/g_weapon.c b/src/game/g_weapon.c index 42c85b5..4a28083 100644 --- a/src/game/g_weapon.c +++ b/src/game/g_weapon.c @@ -45,7 +45,7 @@ void G_ForceWeaponChange( gentity_t *ent, weapon_t weapon )      ps->weaponTime = 250;      ps->weaponstate = WEAPON_READY;    } - +      if( weapon == WP_NONE ||        !BG_InventoryContainsWeapon( weapon, ps->stats ) )    { @@ -76,7 +76,7 @@ void G_GiveClientMaxAmmo( gentity_t *ent, qboolean buyingEnergyAmmo )    for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ )    {      qboolean energyWeapon; - +        energyWeapon = BG_Weapon( i )->usesEnergy;      if( !BG_InventoryContainsWeapon( i, ent->client->ps.stats ) ||          BG_Weapon( i )->infiniteAmmo || @@ -84,10 +84,10 @@ void G_GiveClientMaxAmmo( gentity_t *ent, qboolean buyingEnergyAmmo )                           ent->client->ps.ammo, ent->client->ps.clips ) ||          ( buyingEnergyAmmo && !energyWeapon ) )        continue; - +            maxAmmo = BG_Weapon( i )->maxAmmo;      maxClips = BG_Weapon( i )->maxClips; - +          // Apply battery pack modifier      if( energyWeapon &&          BG_InventoryContainsUpgrade( UP_BATTPACK, ent->client->ps.stats ) ) @@ -142,7 +142,7 @@ static void G_WideTrace( trace_t *tr, gentity_t *ent, float range,    vec3_t    end;    VectorSet( mins, -width, -width, -height ); -  VectorSet( maxs, width, width, height ); +  VectorSet( maxs, width, width, width );    *target = NULL; @@ -459,8 +459,8 @@ void massDriverFire( gentity_t *ent )    SnapVectorTowards( tr.endpos, muzzle );    // send impact -  if( traceEnt->takedamage && -      (traceEnt->s.eType == ET_BUILDABLE || +  if( traceEnt->takedamage &&  +      (traceEnt->s.eType == ET_BUILDABLE ||          traceEnt->s.eType == ET_PLAYER ) )    {      BloodSpurt( ent, traceEnt, &tr ); @@ -507,7 +507,7 @@ void hiveFire( gentity_t *ent )    // Fire from the hive tip, not the center    VectorMA( muzzle, ent->r.maxs[ 2 ], ent->s.origin2, origin ); - +      fire_hive( ent, origin, forward );  } @@ -549,7 +549,7 @@ void flamerFire( gentity_t *ent )  {    vec3_t origin; -  // Correct muzzle so that the missile does not start in the ceiling +  // Correct muzzle so that the missile does not start in the ceiling     VectorMA( muzzle, -7.0f, up, origin );    // Correct muzzle so that the missile fires from the player's hand @@ -606,8 +606,8 @@ void lasGunFire( gentity_t *ent )    SnapVectorTowards( tr.endpos, muzzle );    // send impact -  if( traceEnt->takedamage && -      (traceEnt->s.eType == ET_BUILDABLE || +  if( traceEnt->takedamage &&  +      (traceEnt->s.eType == ET_BUILDABLE ||          traceEnt->s.eType == ET_PLAYER ) )    {      BloodSpurt( ent, traceEnt, &tr ); @@ -771,9 +771,9 @@ void CheckCkitRepair( gentity_t *ent )      if(BG_Buildable(traceEnt->s.modelindex,NULL)->cuboid)        if(!BG_CuboidAttributes(traceEnt->s.modelindex)->repairable)          return; - +            bHealth = BG_Buildable( traceEnt->s.modelindex, traceEnt->cuboidSize )->health; - +          if( traceEnt->health < bHealth )      {        traceEnt->health += HBUILD_HEALRATE; @@ -960,7 +960,7 @@ void CheckGrabAttack( gentity_t *ent )      if( traceEnt->client->ps.stats[ STAT_HEALTH ] <= 0 )        return; - +          if( !( traceEnt->client->ps.stats[ STAT_STATE ] & SS_GRABBED ) )      {        AngleVectors( traceEnt->client->ps.viewangles, dir, NULL, NULL ); @@ -1001,7 +1001,7 @@ void poisonCloud( gentity_t *ent )    for( i = 0; i < num; i++ )    {      humanPlayer = &g_entities[ entityList[ i ] ]; - +          if( humanPlayer->client &&          humanPlayer->client->pers.teamSelection == TEAM_HUMANS )      { @@ -1066,13 +1066,12 @@ static void G_FindZapChainTargets( zap_t *zap )      distance = Distance( ent->s.origin, enemy->s.origin ); -    if ( ( enemy->client -		&& -		enemy->client->ps.stats[ STAT_TEAM ] == TEAM_HUMANS) || -       ( enemy->s.eType == ET_BUILDABLE && BG_Buildable( enemy->s.modelindex, NULL )->team == TEAM_HUMANS && -       ( !BG_Buildable(enemy->s.modelindex,NULL)->cuboid||BG_CuboidAttributes( enemy->s.modelindex )->zappable ) ) && -       enemy->health > 0 && distance <= LEVEL2_AREAZAP_CHAIN_RANGE ) +    if((enemy->client&&enemy->client->ps.stats[STAT_TEAM]==TEAM_HUMANS) ||  +       (enemy->s.eType==ET_BUILDABLE&&BG_Buildable(enemy->s.modelindex,NULL)->team==TEAM_HUMANS &&  +       (!BG_Buildable(enemy->s.modelindex,NULL)->cuboid||BG_CuboidAttributes(enemy->s.modelindex)->zappable)) && +       enemy->health>0 && distance <= LEVEL2_AREAZAP_CHAIN_RANGE)      { +             // world-LOS check: trace against the world, ignoring other BODY entities        trap_Trace( &tr, ent->s.origin, NULL, NULL,           enemy->s.origin, ent->s.number, CONTENTS_SOLID ); @@ -1147,7 +1146,7 @@ static void G_CreateNewZap( gentity_t *creator, gentity_t *target )        {          G_Damage( zap->targets[ i ], target, zap->creator, forward, target->s.origin,                    LEVEL2_AREAZAP_DMG * ( 1 - pow( (zap->distances[ i ] / -                    LEVEL2_AREAZAP_CHAIN_RANGE ), LEVEL2_AREAZAP_CHAIN_FALLOFF ) ) + 1, +                  LEVEL2_AREAZAP_CHAIN_RANGE ) , LEVEL2_AREAZAP_CHAIN_FALLOFF ) ) + 1,                    DAMAGE_NO_KNOCKBACK | DAMAGE_NO_LOCDAMAGE,                    MOD_LEVEL2_ZAP );        } @@ -1163,7 +1162,6 @@ static void G_CreateNewZap( gentity_t *creator, gentity_t *target )  } -  /*  ===============  G_UpdateZaps @@ -1253,9 +1251,9 @@ void areaZapFire( gentity_t *ent )    if( traceEnt == NULL )      return; -  if( ( ( traceEnt->client && traceEnt->client->ps.stats[ STAT_TEAM ] == TEAM_HUMANS ) || +  if( ( traceEnt->client && traceEnt->client->ps.stats[ STAT_TEAM ] == TEAM_HUMANS ) ||        ( traceEnt->s.eType == ET_BUILDABLE && -        BG_Buildable( traceEnt->s.modelindex, NULL )->team == TEAM_HUMANS ) ) && +        BG_Buildable( traceEnt->s.modelindex, NULL )->team == TEAM_HUMANS ) &&           ( !BG_Buildable( traceEnt->s.modelindex, NULL )->cuboid ||            BG_CuboidAttributes( traceEnt->s.modelindex )->zappable ) )    { @@ -1309,7 +1307,7 @@ qboolean CheckPounceAttack( gentity_t *ent )    if( !traceEnt->takedamage )      return qfalse; - +        // Deal damage    timeMax = ent->client->ps.weapon == WP_ALEVEL3 ? LEVEL3_POUNCE_TIME :                                                     LEVEL3_POUNCE_TIME_UPG; @@ -1411,7 +1409,7 @@ void G_CrushAttack( gentity_t *ent, gentity_t *victim )    if( damage < 0 )      damage = 0; - +        // Players also get damaged periodically    if( victim->client &&        ent->client->lastCrushTime + LEVEL4_CRUSH_REPEAT < level.time ) @@ -1419,7 +1417,7 @@ void G_CrushAttack( gentity_t *ent, gentity_t *victim )      ent->client->lastCrushTime = level.time;      damage += LEVEL4_CRUSH_DAMAGE;    } - +      if( damage < 1 )      return; @@ -1527,7 +1525,7 @@ void FireWeapon2( gentity_t *ent )      case WP_ALEVEL2_UPG:        areaZapFire( ent );        break; - +            case WP_ABUILD:      case WP_ABUILD2:      case WP_HBUILD: @@ -1549,7 +1547,7 @@ void FireWeapon( gentity_t *ent )    {      // set aiming directions      AngleVectors( ent->client->ps.viewangles, forward, right, up ); -    CalcMuzzlePoint( ent, forward, right, up, muzzle ); +    CalcMuzzlePoint( ent, forward, right, up, muzzle );        }    else    { diff --git a/src/game/tremulous.h b/src/game/tremulous.h index 7f8836f..bf60cd0 100644 --- a/src/game/tremulous.h +++ b/src/game/tremulous.h @@ -95,7 +95,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  #define LEVEL3_CLAW_DMG             ADM(80)  #define LEVEL3_CLAW_RANGE           80.0f -#define LEVEL3_CLAW_UPG_RANGE       LEVEL3_CLAW_RANGE + 3.0f +#define LEVEL3_CLAW_UPG_RANGE       LEVEL3_CLAW_RANGE + 3.0f            #define LEVEL3_CLAW_WIDTH           12.0f  #define LEVEL3_CLAW_REPEAT          900  #define LEVEL3_CLAW_K_SCALE         1.0f @@ -107,7 +107,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  #define LEVEL3_POUNCE_WIDTH         14.0f  #define LEVEL3_POUNCE_TIME          800      // msec for full Dragoon pounce  #define LEVEL3_POUNCE_TIME_UPG      800      // msec for full Adv. Dragoon pounce -#define LEVEL3_POUNCE_TIME_MIN      200      // msec before which pounce cancels +#define LEVEL3_POUNCE_TIME_MIN      200      // msec before which pounce cancels    #define LEVEL3_POUNCE_REPEAT        400      // msec before a new pounce starts  #define LEVEL3_POUNCE_SPEED_MOD     0.75f    // walking speed modifier for pounce charging  #define LEVEL3_POUNCE_JUMP_MAG      700      // Dragoon pounce jump power @@ -139,7 +139,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  #define LEVEL4_CRUSH_REPEAT            500   // player damage repeat  #define LEVEL4_BOMB_DMG                150 -#define LEVEL4_BOMB_RADIUS             400 +#define LEVEL4_BOMB_RADIUS             400   #define LEVEL4_BOMB_SPEED              500.0f  #define LEVEL4_BOMB_REGEN              120000 // minimum time between getting a bomb @@ -692,7 +692,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  #define DAMAGE_FRACTION_FOR_KILL    0.5f //how much damage players (versus structures) need to                                           //do to increment the stage kill counters - +                                           #define MAXIMUM_BUILD_TIME          20000 // used for pie timer  /* @@ -715,5 +715,5 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  #define ALIEN_IMPLANT_MATURING_CHANCE         0.05f  //chance of maturing (every second)  #define ALIEN_HATCHING_VELOCITY               250.0f -#define ALIEN_HATCHING_MAX_BATTLESUIT_HEALTH  80 // alien dies if tried to spawn from a battlesuit at least this healthy +#define ALIEN_HATCHING_MAX_BATTLESUIT_HEALTH  80 // alien dies if tried to spawn from a battlesuit at least this healthy   #define ALIEN_FAILED_HATCH_DAMAGE             65 // shouldn't be higher than the value above  | 
