diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cgame/cg_buildable.c | 164 | ||||
-rw-r--r-- | src/cgame/cg_consolecmds.c | 1 | ||||
-rw-r--r-- | src/cgame/cg_draw.c | 13 | ||||
-rw-r--r-- | src/cgame/cg_local.h | 35 | ||||
-rw-r--r-- | src/cgame/cg_main.c | 45 | ||||
-rw-r--r-- | src/cgame/cg_players.c | 28 | ||||
-rw-r--r-- | src/cgame/cg_scanner.c | 72 | ||||
-rw-r--r-- | src/cgame/cg_servercmds.c | 35 | ||||
-rw-r--r-- | src/cgame/cg_tutorial.c | 91 | ||||
-rw-r--r-- | src/cgame/cg_view.c | 12 | ||||
-rw-r--r-- | src/cgame/cg_weapons.c | 12 | ||||
-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 | 9 | ||||
-rw-r--r-- | src/game/tremulous.h | 2 |
24 files changed, 561 insertions, 321 deletions
diff --git a/src/cgame/cg_buildable.c b/src/cgame/cg_buildable.c index b1d40b0..0c851b0 100644 --- a/src/cgame/cg_buildable.c +++ b/src/cgame/cg_buildable.c @@ -683,7 +683,7 @@ void CG_InitBuildables( void ) } } - cg.buildablesFraction = (float)i / (float)( BA_NUM_BUILDABLES - 1 ); + cg.buildablesFraction = (float)i / (float)( CUBOID_FIRST - 1 ); trap_UpdateScreen( ); } @@ -1024,19 +1024,20 @@ void CG_GhostBuildable( buildable_t buildable, vec3_t dims ) if(BG_Buildable(buildable, NULL)->cuboid) { - qhandle_t shader, ashader; - - CG_Cuboid_Send(); //NOTE: CG_Cuboid_Send has its own timer so we don't spam server with commands every frame - - if(cg.forbidCuboids) - shader=cgs.media.cuboidYellowBuildShader; - else if(ps->stats[STAT_BUILDABLE]&SB_VALID_TOGGLEBIT) - shader=cgs.media.cuboidGreenBuildShader; - else - shader=cgs.media.cuboidRedBuildShader; - CG_DrawCuboid(entity_origin,dims,shader,0); - CG_DrawCuboidAxis(entity_origin,dims,cg_cuboidResizeAxis.integer,cgs.media.cuboidAxis); - return; + qhandle_t shader, ashader; + + CG_Cuboid_Send( ); //NOTE: CG_Cuboid_Send has its own timer so we don't spam server with commands every frame + + if( cg.waitForCB ) + shader = cgs.media.cuboidYellowBuildShader; + else if( cg.cuboidValid && ps->stats[ STAT_BUILDABLE ] & SB_VALID_TOGGLEBIT ) + shader = cgs.media.cuboidGreenBuildShader; + else + shader = cgs.media.cuboidRedBuildShader; + + CG_DrawCuboid( entity_origin, dims, shader, 0 ); + CG_DrawCuboidAxis( entity_origin, dims, cg_cuboidResizeAxis.integer, cgs.media.cuboidAxis ); + return; } VectorCopy(ps->viewangles,viewangles); @@ -1896,7 +1897,16 @@ void CG_Buildable( centity_t *cent ) CG_PositionEntityOnTag( &turretBarrel, &ent, ent.hModel, "tag_turret" ); VectorCopy( cent->lerpOrigin, turretBarrel.lightingOrigin ); - AnglesToAxis( es->angles2, flatAxis ); + + { + vec3_t interpolated; + int i; + + for( i = 0; i < 3 ; i++ ) + interpolated[ i ] = LerpAngle( es->angles2[ i ], cent->nextState.angles2[ i ], cg.frameInterpolation ); + + AnglesToAxis( interpolated, flatAxis ); + } RotatePointAroundVector( turretBarrel.axis[ 0 ], xNormal, flatAxis[ 0 ], -rotAngle ); RotatePointAroundVector( turretBarrel.axis[ 1 ], xNormal, flatAxis[ 1 ], -rotAngle ); @@ -2090,32 +2100,36 @@ Send the cuboid selection via commands. */ void CG_Cuboid_Send(void) { - static qboolean init=qfalse; + static qboolean init = qfalse; static int lastupdate; static vec3_t lastcuboid; - if(!BG_Buildable(cg.predictedPlayerState.stats[STAT_BUILDABLE]&~SB_VALID_TOGGLEBIT,NULL)->cuboid) - return; + if( !BG_Buildable( cg.predictedPlayerState.stats[ STAT_BUILDABLE ] &~ SB_VALID_TOGGLEBIT, NULL)->cuboid) + return; - if(!init) + if( !init ) { - lastupdate=cg.time; - VectorCopy(cg.cuboidSelection,lastcuboid); - init=qtrue; + lastupdate = cg.time; + VectorCopy( cg.cuboidSelection, lastcuboid ); + init = qtrue; } - if(lastupdate+100>cg.time) - return; + if( lastupdate + 100 > cg.time ) + return; - if(!VectorCompareEpsilon(lastcuboid,cg.cuboidSelection,1e-3)) + if( !VectorCompareEpsilon( lastcuboid, cg.cuboidSelection, 1e-3 ) ) { - cg.latestCBNumber++; - cg.latestCBNumber%=100; - trap_SendClientCommand(va("cb %i %f %f %f\n",cg.latestCBNumber,cg.cuboidSelection[0],cg.cuboidSelection[1],cg.cuboidSelection[2])); - cg.forbidCuboids=qtrue; //wait for response + cg.latestCBNumber++; + cg.latestCBNumber %= 100; + trap_SendClientCommand( va("cb %i %f %f %f\n", + cg.latestCBNumber, + cg.cuboidSelection[ 0 ], + cg.cuboidSelection[ 1 ], + cg.cuboidSelection[ 2 ] ) ); + cg.waitForCB = qtrue; //wait for response } - lastupdate=cg.time; - VectorCopy(cg.cuboidSelection,lastcuboid); + lastupdate = cg.time; + VectorCopy( cg.cuboidSelection, lastcuboid ); } /* @@ -2127,47 +2141,55 @@ Server responded to our cb with either cb2 or cb3. */ void CG_Cuboid_Response(void) { - // cb2 <a> <b> <c> : server sets client-side cuboid - // cb3 <echo> : server agrees on player's cuboid - // cb3 <echo> <a> <b> <c> : server doesnt agree on player's cuboid and corrects it - static qboolean init = qfalse; + // cb2 <a> <b> <c> : server sets client-side cuboid + // cb3 <echo> : server agrees on player's cuboid + // cb4 <echo> : server disagrees on player's cuboid + int offs; if( !BG_Buildable( cg.predictedPlayerState.stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT, NULL )->cuboid ) return; if( !Q_stricmp( CG_Argv( 0 ), "cb2" ) && trap_Argc( ) == 4 ) { - cg.cuboidSelection[ 0 ] = atof( CG_Argv( 1 ) ); - cg.cuboidSelection[ 1 ] = atof( CG_Argv( 2 ) ); - cg.cuboidSelection[ 2 ] = atof( CG_Argv( 3 ) ); - return; + if( trap_Argc( ) == 4 || + ( offs = 1, trap_Argc() == 5 && atoi( CG_Argv( 1 ) ) == cg.latestCBNumber ) ) + { + cg.cuboidValid = qtrue; + cg.cuboidSelection[ 0 ] = atof( CG_Argv( 1 + offs ) ); + cg.cuboidSelection[ 1 ] = atof( CG_Argv( 2 + offs ) ); + cg.cuboidSelection[ 2 ] = atof( CG_Argv( 3 + offs ) ); + return; + } } else if( !Q_stricmp( CG_Argv( 0 ), "cb3" ) ) { if( trap_Argc( ) == 2 ) { if( atoi( CG_Argv( 1 ) ) == cg.latestCBNumber ) - cg.forbidCuboids = qfalse; + cg.waitForCB = qfalse; + cg.cuboidValid = qtrue; return; } - else if( trap_Argc() == 5) + } + else if( !Q_stricmp( CG_Argv( 0 ), "cb4" ) ) + { + if( trap_Argc() == 2 ) { - cg.cuboidSelection[ 0 ] = atof( CG_Argv( 2 ) ); - cg.cuboidSelection[ 1 ] = atof( CG_Argv( 3 ) ); - cg.cuboidSelection[ 2 ] = atof( CG_Argv( 4 ) ); if( atoi( CG_Argv( 1 ) ) == cg.latestCBNumber ) - { - cg.forbidCuboids = qfalse; + { + cg.waitForCB = qfalse; + cg.cuboidValid = qfalse; + if( cg.lastCuboidError + 250 < cg.time ) { trap_S_StartLocalSound( cgs.media.cuboidErrorSound, CHAN_LOCAL_SOUND ); cg.lastCuboidError = cg.time; - } + } } - return; + return; } } - Com_Printf( "^3warning: wrong cb2/cb3 from server\n" ); + Com_Printf( "^3warning: wrong cb from server\n" ); } /* @@ -2237,7 +2259,6 @@ void CG_CuboidRotate_f(void) break; } trap_S_StartLocalSound( cgs.media.cuboidRotateSound, CHAN_LOCAL_SOUND ); - CG_Cuboid_Send( ); } /* @@ -2257,7 +2278,7 @@ void CG_CuboidAxis_f(void) axis = cg_cuboidResizeAxis.integer; if( !BG_Buildable( cg.predictedPlayerState.stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT, NULL )->cuboid) return; - if( !CG_Argv( 1 ) ) + if( trap_Argc( ) < 2 ) { Com_Printf( "cuboidAxis next|0|1|2 : set axis on which you want to resize your cuboid selection (0 - X, 1 - Y, 2 - Z)\n" ); return; @@ -2272,20 +2293,51 @@ void CG_CuboidAxis_f(void) /* ====================== +CG_CuboidSize_f + +Set the cuboid selection +Syntax: + cuboidAxis x y z +====================== +*/ +void CG_CuboidSize_f(void) +{ + int axis; + + if( trap_Argc( ) < 4 ) + { + Com_Printf( "cuboidAxis x y z : set the cuboid selection\n" ); + return; + } + + VectorSet( cg.cuboidSelection, + atof( CG_Argv( 1 ) ), + atof( CG_Argv( 2 ) ), + atof( CG_Argv( 3 ) ) ); + + trap_S_StartLocalSound( cgs.media.cuboidResizeSoundA, CHAN_LOCAL_SOUND ); +} + +/* +====================== CG_CuboidAttack_f Replaces +attack/-attack. If building a cuboid and the selection is somehow invalid, play an error sound. -Otherwise send the normal +attack / -attack; +Otherwise send the normal +attack / -attack. ====================== */ void CG_CuboidAttack_f(void) { - if( BG_Buildable( cg.predictedPlayerState.stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT, NULL )->cuboid && - cg.forbidCuboids ) + if( BG_Buildable( cg.predictedPlayerState.stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT, NULL )->cuboid ) { - trap_S_StartLocalSound( cgs.media.cuboidErrorSound, CHAN_LOCAL_SOUND ); - return; + if( cg.waitForCB ) + return; + else if( !cg.cuboidValid ) + { + trap_S_StartLocalSound( cgs.media.cuboidErrorSound, CHAN_LOCAL_SOUND ); + return; + } } trap_SendClientCommand( va( "%s", CG_Argv(0) ) ); } diff --git a/src/cgame/cg_consolecmds.c b/src/cgame/cg_consolecmds.c index 0f1a3cf..cf3996d 100644 --- a/src/cgame/cg_consolecmds.c +++ b/src/cgame/cg_consolecmds.c @@ -195,6 +195,7 @@ static consoleCommand_t commands[ ] = { "clientlist", CG_ClientList_f }, { "cuboidAxis", CG_CuboidAxis_f }, { "cuboidRotate", CG_CuboidRotate_f }, + { "cuboidSize", CG_CuboidSize_f }, { "destroyTestPS", CG_DestroyTestPS_f }, { "destroyTestTS", CG_DestroyTestTS_f }, { "nextframe", CG_TestModelNextFrame_f }, diff --git a/src/cgame/cg_draw.c b/src/cgame/cg_draw.c index 84c49a5..aa6df3d 100644 --- a/src/cgame/cg_draw.c +++ b/src/cgame/cg_draw.c @@ -2468,7 +2468,7 @@ CG_DrawTutorial static void CG_DrawTutorial( rectDef_t *rect, float text_x, float text_y, vec4_t color, float scale, int textalign, int textvalign, int textStyle ) { - if( !cg_tutorial.integer && !cg_modTutorial.integer ) + if( !cg_tutorial.integer ) return; UI_DrawTextBlock( rect, text_x, text_y, color, scale, textalign, textvalign, textStyle, CG_TutorialText( ) ); @@ -2630,6 +2630,8 @@ static void CG_ScanForCrosshairEntity( void ) CG_Trace( &trace, start, vec3_origin, vec3_origin, end, cg.snap->ps.clientNum, CONTENTS_SOLID|CONTENTS_BODY ); + cg.crosshairDistance = Distance( start, trace.endpos ); + // if the player is in fog, don't show it content = trap_CM_PointContents( trace.endpos, 0 ); if( content & CONTENTS_FOG ) @@ -3108,6 +3110,9 @@ static void CG_DrawLighting( void ) CG_DrawPic( 0, 0, 640, 480, cgs.media.whiteShader ); trap_R_SetColor( NULL ); } + + if( BG_UpgradeIsActive( UP_NIGHTVISION, cg.predictedPlayerState.stats ) ) + CG_DrawPic( 0, 0, 640, 480, cgs.media.basivisionShader ); } /* @@ -3525,9 +3530,9 @@ void CG_DrawSplash( void ) trap_R_SetColor( color ); ts = 0.33f; - tw = UI_Text_Width( MODVER_TITLE, ts ); - th = UI_Text_Height( MODVER_TITLE, ts ); - UI_Text_Paint( x + w/2 - tw/2, y + h + th, ts, color, MODVER_TITLE, 0, 0, ITEM_TEXTSTYLE_SHADOWEDMORE ); + tw = UI_Text_Width( SPLASH_VERSION, ts ); + th = UI_Text_Height( SPLASH_VERSION, ts ); + UI_Text_Paint( x + w/2 - tw/2, y + h + th, ts, color, SPLASH_VERSION, 0, 0, ITEM_TEXTSTYLE_SHADOWEDMORE ); } color[ 3 ] = ( t > 3.0f ) ? 4.0f - t : 1.0f; diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h index a8316c5..4893060 100644 --- a/src/cgame/cg_local.h +++ b/src/cgame/cg_local.h @@ -809,6 +809,7 @@ typedef struct weaponInfoMode_s qhandle_t impactParticleSystem; qhandle_t impactMark; qhandle_t impactMarkSize; + qboolean impactMarkAlphaFade; sfxHandle_t impactSound[ 4 ]; //random impact sound sfxHandle_t impactFleshSound[ 4 ]; //random impact sound } weaponInfoMode_t; @@ -1056,6 +1057,7 @@ typedef struct int lastKillTime; // crosshair client ID + float crosshairDistance; int crosshairBuildable; int crosshairClientNum; int crosshairClientTime; @@ -1184,9 +1186,10 @@ typedef struct int nextWeaponClickTime; vec3_t cuboidSelection; - qboolean forbidCuboids; //if true then dont let player build a cuboid - int latestCBNumber; //wait for this number from server before building a cuboid - int lastCuboidError; //last time error sound was played + qboolean waitForCB; + qboolean cuboidValid; + int latestCBNumber; // for syncing with the server + int lastCuboidError; // last time an error sound was played qhandle_t announcerStack[ MAX_ANNOUNCER_STACK ]; int announcerStackPos; @@ -1371,6 +1374,10 @@ typedef struct qhandle_t alienHatchPS; sfxHandle_t alienHatchSound; sfxHandle_t alienFailedHatchSound; + + qhandle_t basivisionShader; + qhandle_t basivisionBlipShader; + qhandle_t basivisionFlareShader; } cgMedia_t; typedef struct @@ -1582,10 +1589,6 @@ extern vmCvar_t cg_disableCommandDialogs; extern vmCvar_t cg_disableScannerPlane; extern vmCvar_t cg_tutorial; -extern vmCvar_t cg_modTutorial; -extern vmCvar_t cg_modTutorialReference; -extern vmCvar_t cg_lastModVersion; - extern vmCvar_t cg_painBlendUpRate; extern vmCvar_t cg_painBlendDownRate; extern vmCvar_t cg_painBlendMax; @@ -1627,6 +1630,10 @@ extern vmCvar_t cg_fuelInfoX; extern vmCvar_t cg_fuelInfoY; extern vmCvar_t cg_fuelInfoScale; +extern vmCvar_t cg_announcer; + +extern vmCvar_t cg_cameraShakeMagnitude; + // // cg_main.c // @@ -1748,6 +1755,7 @@ void CG_HumanBuildableExplosion( vec3_t origin, vec3_t dir ); void CG_AlienBuildableExplosion( vec3_t origin, vec3_t dir ); void CG_CuboidAxis_f(void); void CG_CuboidRotate_f(void); +void CG_CuboidSize_f(void); void CG_Cuboid_Send(void); void CG_Cuboid_Response(void); void CG_CuboidResize( qboolean enlarge ); @@ -2185,15 +2193,4 @@ typedef enum // mod version data -#define MODVER_CURRENT 6 -#define MODVER_C2_0_1_5 6 -#define MODVER_C2_0_1_4 5 -#define MODVER_C2_0_1_3 4 -#define MODVER_C2_0_1_2 3 -#define MODVER_C2_0_1_1 2 -#define MODVER_C2_0_1_0 1 -#define MODVER_TITLE "0.1.5 (Sep 12)" - - - - +#define SPLASH_VERSION "0.1.6 (Jan 14)" diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c index c1c7a0d..ff3d567 100644 --- a/src/cgame/cg_main.c +++ b/src/cgame/cg_main.c @@ -192,10 +192,6 @@ vmCvar_t cg_disableCommandDialogs; vmCvar_t cg_disableScannerPlane; vmCvar_t cg_tutorial; -vmCvar_t cg_modTutorial; -vmCvar_t cg_modTutorialReference; -vmCvar_t cg_lastModVersion; - vmCvar_t cg_painBlendUpRate; vmCvar_t cg_painBlendDownRate; vmCvar_t cg_painBlendMax; @@ -237,6 +233,10 @@ vmCvar_t cg_fuelInfoX; vmCvar_t cg_fuelInfoY; vmCvar_t cg_fuelInfoScale; +vmCvar_t cg_announcer; + +vmCvar_t cg_cameraShakeMagnitude; + typedef struct { vmCvar_t *vmCvar; @@ -366,27 +366,26 @@ static cvarTable_t cvarTable[ ] = { &pmove_fixed, "pmove_fixed", "0", 0}, { &pmove_msec, "pmove_msec", "8", 0}, { &cg_noTaunt, "cg_noTaunt", "0", CVAR_ARCHIVE}, - + { &cg_voice, "voice", "default", CVAR_USERINFO|CVAR_ARCHIVE}, { &cg_emoticons, "cg_emoticons", "1", CVAR_LATCH|CVAR_ARCHIVE}, { &cg_chatTeamPrefix, "cg_chatTeamPrefix", "1", CVAR_ARCHIVE }, - + { &cg_cuboidResizeAxis, "cg_cuboidResizeAxis", "2", 0 }, { &cg_cuboidResizeRate, "cg_cuboidResizeRate", "5", CVAR_ARCHIVE }, { &cg_cuboidPSQuality, "cg_cuboidPSQuality", "3", CVAR_ARCHIVE }, - + { &cg_cuboidInfoX, "cg_cuboidInfoX" ,"0", CVAR_ARCHIVE }, { &cg_cuboidInfoY, "cg_cuboidInfoY" ,"150", CVAR_ARCHIVE }, - - { &cg_modTutorial, "cg_modTutorial", "1", CVAR_ARCHIVE }, - { &cg_modTutorialReference, "cg_modTutorialReference", "0", CVAR_ARCHIVE }, - { &cg_lastModVersion, "cg_lastModVersion", "0", CVAR_ARCHIVE }, - + { &cg_fuelInfoX, "cg_fuelInfoX" ,"0", CVAR_ARCHIVE }, { &cg_fuelInfoY, "cg_fuelInfoY" ,"150", CVAR_ARCHIVE }, - { &cg_fuelInfoScale, "cg_fuelInfoScale" ,"0.5", CVAR_ARCHIVE } + { &cg_fuelInfoScale, "cg_fuelInfoScale" ,"0.5", CVAR_ARCHIVE }, + { &cg_announcer, "cg_announcer", "1", CVAR_ARCHIVE }, + + { &cg_cameraShakeMagnitude, "cg_cameraShakeMagnitude", "1", CVAR_ARCHIVE } }; static int cvarTableSize = sizeof( cvarTable ) / sizeof( cvarTable[0] ); @@ -819,26 +818,30 @@ static void CG_RegisterGraphics( void ) cgs.media.greenBuildShader = trap_R_RegisterShader("gfx/misc/greenbuild" ); cgs.media.redBuildShader = trap_R_RegisterShader("gfx/misc/redbuild" ); cgs.media.humanSpawningShader = trap_R_RegisterShader("models/buildables/telenode/rep_cyl" ); - + for( i = 0; i < CUBOID_CRACK_TEXTURES - 1; i++ ) cgs.media.cuboidCracks[ i ] = trap_R_RegisterShader( va( "models/cuboid/cracks_%i", i ) ); - + cgs.media.cuboidModel = trap_R_RegisterModel( "models/cuboid/cuboid.md3" ); cgs.media.cuboidRedBuildShader = trap_R_RegisterShader( "gfx/cuboid/build_red" ); cgs.media.cuboidYellowBuildShader = trap_R_RegisterShader( "gfx/cuboid/build_yellow" ); cgs.media.cuboidGreenBuildShader = trap_R_RegisterShader( "gfx/cuboid/build_green" ); cgs.media.cuboidAxis = trap_R_RegisterShader( "gfx/cuboid/build_axis" ); cgs.media.cuboidAlienPrebuild = trap_R_RegisterShader( "gfx/cuboid/prebuild_alien" ); - - cg.forbidCuboids=qfalse; - cg.latestCBNumber=0; - + + cg.waitForCB = qfalse; + cg.cuboidValid = qfalse; + cg.latestCBNumber = 0; + for( i = 0; i < 15; i++ ) cgs.media.splashLogo[ i ] = trap_R_RegisterShader( va( "cuboid/logo_%i.tga", i ) ); cgs.media.splashLeft = trap_R_RegisterShader( "cuboid/logo_left.tga" ); cgs.media.splashRight = trap_R_RegisterShader( "cuboid/logo_right.tga" ); - - + + cgs.media.basivisionShader = trap_R_RegisterShader( "gfx/2d/basivision" ); + cgs.media.basivisionBlipShader = trap_R_RegisterShader( "gfx/2d/basivisionBlip" ); + cgs.media.basivisionFlareShader = trap_R_RegisterShader( "gfx/2d/basivisionFlare" ); + for( i = 0; i < 8; i++ ) cgs.media.buildWeaponTimerPie[ i ] = trap_R_RegisterShader( buildWeaponTimerPieShaders[ i ] ); diff --git a/src/cgame/cg_players.c b/src/cgame/cg_players.c index 99f9f9e..63464e1 100644 --- a/src/cgame/cg_players.c +++ b/src/cgame/cg_players.c @@ -1428,9 +1428,35 @@ static void CG_PlayerUpgrades( centity_t *cent, refEntity_t *torso ) held = es->modelindex; active = es->modelindex2; - + jetjump = ( cent->jetPackJumpTime + 100 > cg.time && !( active & ( 1 << UP_JETPACK ) ) ); + if( es->number == cg.snap->ps.clientNum ) + { + static int lastTime=0; + static float last=0.0f; + + if( active & ( 1 << UP_NIGHTVISION ) ) + { + float dt, cur, target; + dt = 0.001f * ( cg.time - lastTime ); + target = sqrt( cg.crosshairDistance * 3.0f ); + cur = last + ( target - last ) * dt * 15.0f; + + last = cur; + lastTime = cg.time; + + cur = pow( cur, 2 ); + trap_R_AddAdditiveLightToScene( cent->lerpOrigin, cur, 1, 1, 1 ); + } + else + { + lastTime = cg.time; + last = 0.0f; + } + } + + if( held & ( 1 << UP_JETPACK ) ) { memset( &jetpack, 0, sizeof( jetpack ) ); diff --git a/src/cgame/cg_scanner.c b/src/cgame/cg_scanner.c index 3941956..821c8bf 100644 --- a/src/cgame/cg_scanner.c +++ b/src/cgame/cg_scanner.c @@ -62,9 +62,9 @@ void CG_UpdateEntityPositions( void ) !( cent->currentState.eFlags & EF_DEAD ) ) { if( BG_Buildable(cent->currentState.modelindex,NULL)->cuboid ) - if( !BG_CuboidAttributes(cent->currentState.modelindex)->detectable ) - continue; //forget about undetectable cuboids - + if( !BG_CuboidAttributes(cent->currentState.modelindex)->detectable ) + continue; //forget about undetectable cuboids + // add to list of item positions (for creep) if( cent->currentState.modelindex2 == TEAM_ALIENS ) { @@ -218,6 +218,29 @@ static void CG_DrawDir( rectDef_t *rect, vec3_t origin, vec4_t colour ) /* ============= +CG_BasivisionBlip +============= +*/ +void CG_BasivisionBlip( vec3_t origin, float size, qhandle_t shader, float flareSize, qhandle_t flare ) +{ + float x, y, s; + + if( !CG_WorldToScreen( origin, &x, &y ) ) + return; + + size = size * 1000 / Distance( origin, entityPositions.origin ); + + if( shader ) + CG_DrawPic( x - ( size * cgDC.aspectScale ) / 2, y - size / 2, size * cgDC.aspectScale, size, + cgs.media.basivisionBlipShader ); + + if( flare ) + CG_DrawPic( x - ( flareSize * cgDC.aspectScale ) / 2, y - flareSize / 2, flareSize * cgDC.aspectScale, flareSize, + cgs.media.basivisionFlareShader ); +} + +/* +============= CG_AlienSense ============= */ @@ -231,24 +254,39 @@ void CG_AlienSense( rectDef_t *rect ) VectorCopy( entityPositions.origin, origin ); - //draw human buildables - for( i = 0; i < entityPositions.numHumanBuildables; i++ ) + if( BG_UpgradeIsActive( UP_NIGHTVISION, cg.predictedPlayerState.stats ) ) { - VectorClear( relOrigin ); - VectorSubtract( entityPositions.humanBuildablePos[ i ], origin, relOrigin ); - - if( VectorLength( relOrigin ) < ALIENSENSE_RANGE ) - CG_DrawDir( rect, relOrigin, buildable ); + for( i = 0; i < entityPositions.numHumanBuildables; i++ ) + CG_BasivisionBlip( entityPositions.humanBuildablePos[ i ], + 0, 0, + 150, cgs.media.basivisionBlipShader ); + + for( i = 0; i < entityPositions.numHumanClients; i++ ) + CG_BasivisionBlip( entityPositions.humanClientPos[ i ], + 60, cgs.media.basivisionBlipShader, + 80, cgs.media.basivisionFlareShader ); } - - //draw human clients - for( i = 0; i < entityPositions.numHumanClients; i++ ) + else { - VectorClear( relOrigin ); - VectorSubtract( entityPositions.humanClientPos[ i ], origin, relOrigin ); + //draw human buildables + for( i = 0; i < entityPositions.numHumanBuildables; i++ ) + { + VectorClear( relOrigin ); + VectorSubtract( entityPositions.humanBuildablePos[ i ], origin, relOrigin ); + + if( VectorLength( relOrigin ) < ALIENSENSE_RANGE ) + CG_DrawDir( rect, relOrigin, buildable ); + } - if( VectorLength( relOrigin ) < ALIENSENSE_RANGE ) - CG_DrawDir( rect, relOrigin, client ); + //draw human clients + for( i = 0; i < entityPositions.numHumanClients; i++ ) + { + VectorClear( relOrigin ); + VectorSubtract( entityPositions.humanClientPos[ i ], origin, relOrigin ); + + if( VectorLength( relOrigin ) < ALIENSENSE_RANGE ) + CG_DrawDir( rect, relOrigin, client ); + } } } diff --git a/src/cgame/cg_servercmds.c b/src/cgame/cg_servercmds.c index 2a71b62..cf820c0 100644 --- a/src/cgame/cg_servercmds.c +++ b/src/cgame/cg_servercmds.c @@ -634,8 +634,8 @@ void CG_Menu( int menu, int arg ) case MN_B_CUBOID_MODE1: longMsg = "On this map noone is allowed to build a cuboid before reaching " - "stage 2 to prevent players from cheating."; - shortMsg = "Cuboids are disabled on stage 1"; + "Stage 2 to prevent players from cheating."; + shortMsg = "Cuboids are disabled on Stage 1"; break; case MN_B_CUBOID_MODE2: @@ -650,6 +650,14 @@ void CG_Menu( int menu, int arg ) shortMsg = "Buildable density is too high here"; break; + case MN_B_INVALIDSIZE: + longMsg = "You cannot build a cuboid of the selected size." + "Most likely the size is too big, too small or " + "invalid. Keep changing it until the preview " + "turns green."; + shortMsg = "Invalid cuboid size"; + break; + //=============================== case MN_H_NOBP: @@ -1274,12 +1282,13 @@ void CG_ProcessAnnouncer( void ) if( last + ANNOUNCER_DELAY > cg.time ) return; - + cg.announcerStackPos++; cg.announcerStackPos %= MAX_ANNOUNCER_STACK; - - trap_S_StartLocalSound( cg.announcerStack[ cg.announcerStackPos ], CHAN_VOICE ); - + + if( cg_announcer.integer ) + trap_S_StartLocalSound( cg.announcerStack[ cg.announcerStackPos ], CHAN_VOICE ); + last = cg.time; } @@ -1293,12 +1302,15 @@ Play an announcer sound static void CG_Announce( void ) { const char *event, *soundName; - + + if( !cg_announcer.integer ) + return; + if( trap_Argc( ) != 2 ) return; - + event = CG_Argv( 1 ); - + if( !Q_stricmp( event, "votenow" ) || !Q_stricmp( event, "votecancelled" ) || !Q_stricmp( event, "votefailed" ) || @@ -1347,8 +1359,9 @@ static void CG_GameCmds_f( void ) static consoleCommand_t svcommands[ ] = { { "announce", CG_Announce }, - { "cb2", CG_Cuboid_Response }, // set local cuboid - { "cb3", CG_Cuboid_Response }, // set local cuboid and print a "limit exceeded" warning + { "cb2", CG_Cuboid_Response }, + { "cb3", CG_Cuboid_Response }, + { "cb4", CG_Cuboid_Response }, { "chat", CG_Chat_f }, { "clientLevelShot", CG_ClientLevelShot_f }, { "cmds", CG_GameCmds_f }, diff --git a/src/cgame/cg_tutorial.c b/src/cgame/cg_tutorial.c index f68d070..212db33 100644 --- a/src/cgame/cg_tutorial.c +++ b/src/cgame/cg_tutorial.c @@ -639,21 +639,6 @@ const char *CG_TutorialText( void ) playerState_t *ps; static char text[ MAX_TUTORIAL_TEXT ]; static int refreshBindings = 0; - static qboolean checkedUpdate = qfalse; - - // force mod tutorial if new version - if( !checkedUpdate ) - { - trap_Cvar_Update( &cg_lastModVersion ); - - if( cg_lastModVersion.integer < MODVER_CURRENT ) - { - trap_Cvar_Set( "cg_modTutorial", "1" ); - trap_Cvar_Set( "cg_modTutorialReference", va( "%i", cg_lastModVersion.integer ) ); - trap_Cvar_Set( "cg_lastModVersion", va( "%i", MODVER_CURRENT ) ); - } - checkedUpdate = qtrue; - } if( refreshBindings == 0 ) CG_GetBindings( ); @@ -663,14 +648,11 @@ const char *CG_TutorialText( void ) text[ 0 ] = '\0'; ps = &cg.snap->ps; - if( cg_modTutorial.integer ) - { - CG_NewText( text, ps ); - - if( !cg_tutorial.integer ) - return text; - } - + CG_NewText( text, ps ); + + if( !cg_tutorial.integer ) + return text; + if( !cg.intermissionStarted && !cg.demoPlayback ) { if( ps->persistant[ PERS_SPECSTATE ] != SPECTATOR_NOT || @@ -800,38 +782,31 @@ static void CG_CuboidText( char *text, playerState_t *ps ) static void CG_NewText( char *text, playerState_t *ps ) { - int reference; - - reference = cg_modTutorialReference.integer; - if( !cg.intermissionStarted && !cg.demoPlayback ) { if( ps->persistant[ PERS_SPECSTATE ] == SPECTATOR_NOT && !( ps->pm_flags & PMF_FOLLOW ) && ps->stats[ STAT_HEALTH ] > 0 ) { - if( reference >= MODVER_C2_0_1_0 ) + if( BG_InventoryContainsUpgrade( UP_JETPACK, ps->stats ) ) { - if( BG_InventoryContainsUpgrade( UP_JETPACK, ps->stats ) ) + if( ps->stats[ STAT_FUEL ] > JETPACK_FUEL_JUMP ) { - if( ps->stats[ STAT_FUEL ] > JETPACK_FUEL_JUMP ) - { - Q_strcat( text, MAX_TUTORIAL_TEXT, - va( "Press %s to perform a jetpack-aided jump. It uses fuel instead of stamina\n", - CG_KeyNameForCommand( "+moveup" ) ) ); - } - if( ps->stats[ STAT_FUEL ] <= JETPACK_FUEL_LOW ) - { - Q_strcat( text, MAX_TUTORIAL_TEXT, - va( "You are running low on jet fuel. Find an Armoury and press %s to refuel\n", - CG_KeyNameForCommand( "buy ammo" ) ) ); - } - else if( ps->stats[ STAT_FUEL ] <= 0 ) - { - Q_strcat( text, MAX_TUTORIAL_TEXT, - va( "You are out of jet fuel. You can no longer fly. Find an Armoury and press %s to refuel\n", - CG_KeyNameForCommand( "buy ammo" ) ) ); - } + Q_strcat( text, MAX_TUTORIAL_TEXT, + va( "Press %s to perform a jetpack-aided jump. It uses fuel instead of stamina\n", + CG_KeyNameForCommand( "+moveup" ) ) ); + } + if( ps->stats[ STAT_FUEL ] <= JETPACK_FUEL_LOW ) + { + Q_strcat( text, MAX_TUTORIAL_TEXT, + va( "You are running low on jet fuel. Find an Armoury and press %s to refuel\n", + CG_KeyNameForCommand( "buy ammo" ) ) ); + } + else if( ps->stats[ STAT_FUEL ] <= 0 ) + { + Q_strcat( text, MAX_TUTORIAL_TEXT, + va( "You are out of jet fuel. You can no longer fly. Find an Armoury and press %s to refuel\n", + CG_KeyNameForCommand( "buy ammo" ) ) ); } } @@ -840,22 +815,18 @@ static void CG_NewText( char *text, playerState_t *ps ) case WP_ABUILD: case WP_ABUILD2: case WP_HBUILD: - if( reference >= MODVER_C2_0_1_0 ) - { - CG_CuboidText( text, ps ); - if( ps->weapon == WP_ABUILD2 ) - Q_strcat( text, MAX_TUTORIAL_TEXT, - "Spitting at a human has a chance of impregnating him\n" - "with an alien egg. After a certain amount of time,\n" - "the egg can be spawned from by aliens, killing the human.\n" ); - } + CG_CuboidText( text, ps ); + if( ps->weapon == WP_ABUILD2 ) + Q_strcat( text, MAX_TUTORIAL_TEXT, + "Spitting at a human has a chance of impregnating him\n" + "with an alien egg. After a certain amount of time,\n" + "the egg can be spawned from by aliens, killing the human.\n" ); break; case WP_ALEVEL4: - if( reference >= MODVER_C2_0_1_0 ) - Q_strcat( text, MAX_TUTORIAL_TEXT, - va( "Press %s to drop a Tyrant Bomb. It can be regerated by touching a Booster.\n", - CG_KeyNameForCommand( "+button2" ) ) ); + Q_strcat( text, MAX_TUTORIAL_TEXT, + va( "Press %s to drop a Tyrant Bomb. It can be regerated by touching a Booster.\n", + CG_KeyNameForCommand( "+button2" ) ) ); break; } } diff --git a/src/cgame/cg_view.c b/src/cgame/cg_view.c index 4b2b254..97b7582 100644 --- a/src/cgame/cg_view.c +++ b/src/cgame/cg_view.c @@ -578,6 +578,18 @@ void CG_OffsetFirstPersonView( void ) origin[ 2 ] += cg.predictedPlayerState.viewheight; return; } + // camera shake effect + else if( cg.snap->ps.stats[ STAT_SHAKE ] > 0 ) + { + float fac, mag; + + fac = (float) cg.snap->ps.stats[ STAT_SHAKE ] * + cg_cameraShakeMagnitude.value * 0.15f; + + angles[ 0 ] += crandom() * fac; + angles[ 1 ] += crandom() * fac; + angles[ 2 ] += crandom() * fac; + } // add angles based on damage kick if( cg.damageTime ) diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c index f844f81..7e22baf 100644 --- a/src/cgame/cg_weapons.c +++ b/src/cgame/cg_weapons.c @@ -414,6 +414,11 @@ static qboolean CG_ParseWeaponModeSection( weaponInfoMode_t *wim, char **text_p continue; } + else if( !Q_stricmp( token, "impactMarkAlphaFade" ) ) + { + wim->impactMarkAlphaFade = qtrue; + continue; + } else if( !Q_stricmp( token, "}" ) ) return qtrue; //reached the end of this weapon section else @@ -1253,6 +1258,10 @@ static qboolean CG_WeaponSelectable( weapon_t weapon ) if( !BG_InventoryContainsWeapon( weapon, cg.snap->ps.stats ) ) return qfalse; + // needed for basilisk nightvision + if( BG_Weapon( weapon )->team != TEAM_HUMANS ) + return qfalse; + return qtrue; } @@ -1742,7 +1751,8 @@ void CG_MissileHitWall( weapon_t weaponNum, weaponMode_t weaponMode, int clientN // impact mark // if( radius > 0.0f ) - CG_ImpactMark( mark, origin, dir, random( ) * 360, 1, 1, 1, 1, qfalse, radius, qfalse ); + CG_ImpactMark( mark, origin, dir, random( ) * 360, 1, 1, 1, 1, + weapon->wim[ weaponMode ].impactMarkAlphaFade, radius, qfalse ); } 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 11d4892..4a28083 100644 --- a/src/game/g_weapon.c +++ b/src/game/g_weapon.c @@ -1136,9 +1136,7 @@ static void G_CreateNewZap( gentity_t *creator, gentity_t *target ) if( target->health > 0 ) { G_Damage( target, creator, creator, forward, - target->s.origin, LEVEL2_AREAZAP_DMG * - ( ( target->s.eType == ET_BUILDABLE ) - ? LEVEL2_AREAZAP_DMG_MOD : 1.0f ), + target->s.origin, LEVEL2_AREAZAP_DMG, DAMAGE_NO_KNOCKBACK | DAMAGE_NO_LOCDAMAGE, MOD_LEVEL2_ZAP ); @@ -1147,9 +1145,8 @@ static void G_CreateNewZap( gentity_t *creator, gentity_t *target ) for( i = 1; i < zap->numTargets; i++ ) { 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 ) - * ( ( zap->targets[ i ]->s.eType == ET_BUILDABLE ) ? LEVEL2_AREAZAP_DMG_MOD : 1.0f ), + LEVEL2_AREAZAP_DMG * ( 1 - pow( (zap->distances[ i ] / + LEVEL2_AREAZAP_CHAIN_RANGE ) , LEVEL2_AREAZAP_CHAIN_FALLOFF ) ) + 1, DAMAGE_NO_KNOCKBACK | DAMAGE_NO_LOCDAMAGE, MOD_LEVEL2_ZAP ); } diff --git a/src/game/tremulous.h b/src/game/tremulous.h index a44a306..bf60cd0 100644 --- a/src/game/tremulous.h +++ b/src/game/tremulous.h @@ -82,7 +82,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define LEVEL2_CLAW_K_SCALE 1.0f #define LEVEL2_CLAW_U_REPEAT 400 #define LEVEL2_CLAW_U_K_SCALE 1.0f -#define LEVEL2_AREAZAP_DMG 6 //ADM(60) +#define LEVEL2_AREAZAP_DMG ADM(60) #define LEVEL2_AREAZAP_RANGE 200.0f #define LEVEL2_AREAZAP_CHAIN_RANGE 150.0f #define LEVEL2_AREAZAP_CHAIN_FALLOFF 8.0f |