From cb9fa0b183874b0483dc53b5e52066f73bbc8ddb Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Sun, 18 Dec 2016 10:09:01 +0100 Subject: [PATCH] Added a basic spectator HUD Added nightvision Added zoom modes for weapons that are supposed to have them Fixed a bug in which spectators could interact with the game-world Overhauled the way the rule system works Switched to autocvars for most cvar-related variables --- Source/Client/Defs.h | 10 +++-- Source/Client/Draw.c | 37 +++++++++------- Source/Client/Event.c | 5 +++ Source/Client/HUD.c | 12 +++--- Source/Client/HUDCrosshair.c | 6 ++- Source/Client/HUDOrbituaries.c | 2 +- Source/Client/Nightvision.c | 77 ++++++++++++++++++++++++++++++++++ Source/Client/VGUI.c | 16 +++---- Source/Client/VGUIObjects.c | 5 +++ Source/Client/VGUIScoreboard.c | 27 ++++++------ Source/Client/VGUISpectator.c | 60 ++++++++++++++++++++++++++ Source/Client/View.c | 12 +++--- Source/Client/progs.src | 2 + Source/Globals.h | 1 + Source/Server/Client.c | 4 +- Source/Server/Damage.c | 11 ++--- Source/Server/Defs.h | 8 ++++ Source/Server/FuncDoor.c | 1 - Source/Server/Main.c | 1 + Source/Server/Player.c | 6 ++- Source/Server/Rules.c | 6 +-- Source/Server/Timer.c | 2 +- Source/Server/Triggers.c | 66 +++++++++++++++++++++++++++++ Source/Shared/WeaponAUG.c | 30 +++++++++---- Source/Shared/WeaponAWP.c | 14 +++++++ Source/Shared/WeaponC4Bomb.c | 2 +- Source/Shared/WeaponG3SG1.c | 14 +++++++ Source/Shared/WeaponSG550.c | 14 +++++++ Source/Shared/WeaponSG552.c | 12 ++++++ Source/Shared/WeaponScout.c | 14 +++++++ Source/Shared/Weapons.c | 16 +++---- 31 files changed, 410 insertions(+), 83 deletions(-) create mode 100644 Source/Client/Nightvision.c create mode 100644 Source/Client/VGUISpectator.c diff --git a/Source/Client/Defs.h b/Source/Client/Defs.h index 0da03cf1..560b0b69 100644 --- a/Source/Client/Defs.h +++ b/Source/Client/Defs.h @@ -24,9 +24,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define DRAWFLAG_MODULATE 2 #define DRAWFLAG_2XMODULATE 3 -var vector autocvar_con_color; // autocvar of "con_color" -var vector autocvar_vgui_color; // autocvar of "vgui_color" -var vector autocvar_cross_color; // autocvar of "cross_color" +// Clientside cvars +var vector autocvar_con_color = '255 128 0'; // autocvar of "con_color" +var vector autocvar_vgui_color = '255 128 0'; // autocvar of "vgui_color" +var vector autocvar_cross_color = '0 255 0'; // autocvar of "cross_color" +var float autocvar_cl_bob = 0.01; +var float autocvar_cl_bobcycle = 0.8; +var float autocvar_cl_bobup = 0.5; vector vHUDColor; // Defined in HUD_Draw (HUD.c) vector vVGUIColor; // Defined in HUD_Draw (VGUI.c) diff --git a/Source/Client/Draw.c b/Source/Client/Draw.c index 23fb5ee9..d669fb99 100644 --- a/Source/Client/Draw.c +++ b/Source/Client/Draw.c @@ -37,21 +37,17 @@ Receives a message and sorts it into the chat messagebuffer ================= */ void CSQC_Parse_Print(string sMessage, float fLevel ) { - if ( fLevel == PRINT_CHAT ) { - if ( iLineScroll < ( CHAT_LINES - 1 ) ) { - sMSGBuffer[ iLineScroll + 1 ] = sMessage; - iLineScroll++; - } else { - for ( int i = 0; i < ( CHAT_LINES - 1 ); i++ ) { - sMSGBuffer[ i ] = sMSGBuffer[ i + 1 ]; - } - sMSGBuffer[ CHAT_LINES - 1 ] = sMessage; - } - - fChatTime = time + CHAT_TIME; + if ( iLineScroll < ( CHAT_LINES - 1 ) ) { + sMSGBuffer[ iLineScroll + 1 ] = sMessage; + iLineScroll++; } else { - print( sMessage ); + for ( int i = 0; i < ( CHAT_LINES - 1 ); i++ ) { + sMSGBuffer[ i ] = sMSGBuffer[ i + 1 ]; + } + sMSGBuffer[ CHAT_LINES - 1 ] = sMessage; } + + fChatTime = time + CHAT_TIME; } /* @@ -73,7 +69,7 @@ void CSQC_DrawChat( void ) { for ( int i = 0; i < CHAT_LINES; i++ ) { drawstring( vChatPos + '1 1', sMSGBuffer[ i ], '8 8 0', '0 0 0', VGUI_WINDOW_FGALPHA, 0 ); - drawstring( vChatPos, sMSGBuffer[ i ], '8 8 0', VGUI_WINDOW_FGCOLOR, VGUI_WINDOW_FGALPHA, 0 ); + drawstring( vChatPos, sMSGBuffer[ i ], '8 8 0', vHUDColor, 1, DRAWFLAG_ADDITIVE ); vChatPos_y += 12; } } @@ -156,6 +152,8 @@ void CSQC_UpdateView( float fWinWidth, float fWinHeight, float fGameFocus ) { addentities( MASK_ENGINE ); + Nightvision_PreDraw(); + // When Cameratime is active, draw on the forced coords instead if ( fCameraTime > time ) { setproperty( VF_ORIGIN, vCameraPos) ; @@ -168,10 +166,19 @@ void CSQC_UpdateView( float fWinWidth, float fWinHeight, float fGameFocus ) { renderscene(); + Nightvision_PostDraw(); + if( fGameFocus == TRUE ) { - HUD_Draw(); + // The spectator sees things... differently + if ( getplayerkeyvalue( player_localnum, "*spectator" ) == "1" ) { + VGUI_DrawSpectatorHUD(); + } else { + HUD_Draw(); + } + CSQC_DrawChat(); + // Don't even try to draw centerprints and VGUI menus when scores are shown if ( iShowScores == TRUE ) { VGUI_Scores_Show(); } else { diff --git a/Source/Client/Event.c b/Source/Client/Event.c index c4c9895b..3f6c2ef8 100644 --- a/Source/Client/Event.c +++ b/Source/Client/Event.c @@ -32,6 +32,7 @@ void CSQC_ConsoleCommand_Init( void ) { registercommand( "invprev" ); registercommand( "+showscores" ); registercommand( "-showscores" ); + registercommand( "nightvision" ); } /* @@ -70,6 +71,10 @@ float CSQC_ConsoleCommand( string sCMD ) { iShowScores = FALSE; return TRUE; break; + case "nightvision": + Nightvision_Toggle(); + return TRUE; + break; } return FALSE; } diff --git a/Source/Client/HUD.c b/Source/Client/HUD.c index e9d03613..cba74960 100644 --- a/Source/Client/HUD.c +++ b/Source/Client/HUD.c @@ -133,7 +133,7 @@ void HUD_DrawArmor( void ) { fArmorAlpha = HUD_ALPHA; } - vector vArmorPos = [ 112, vVideoResolution_y - 42 ]; + vector vArmorPos = [ 128, vVideoResolution_y - 42 ]; drawsubpic( vArmorPos, '24 24 0', HUD_NUMFILE_LAYER, [ 0, NUMSIZE_Y], [ NUMSIZE_X, NUMSIZE_X ], vHUDColor, fArmorAlpha, DRAWFLAG_ADDITIVE ); HUD_DrawNums( getstatf( STAT_ARMOR ), vArmorPos + '72 0', fArmorAlpha, vHUDColor); fOldArmor = getstatf( STAT_ARMOR ); @@ -187,20 +187,20 @@ void HUD_DrawTimer( void ) { vector vTimePos = [ ( vVideoResolution_x / 2 ) - 62, vVideoResolution_y - 42 ]; if( serverkey( "timelimit" ) ) { - float fTimeLeft = ( stof(serverkey( "timelimit" )) * 60 ) - getstatf( STAT_GAMETIME ); - if( fTimeLeft < 0 ) { + float fTimeLeft = ( stof( serverkey( "timelimit" ) ) * 60 ) - getstatf( STAT_GAMETIME ); + if ( fTimeLeft < 0 ) { iMinutes = iSeconds = iTens = iUnits = 0; } else { iMinutes = fTimeLeft / 60; iSeconds = fTimeLeft - 60 * iMinutes; iTens = iSeconds / 10; - iUnits = iSeconds - 10*iTens; + iUnits = iSeconds - 10 * iTens; } } else { iMinutes = getstatf( STAT_GAMETIME ) / 60; - iSeconds = getstatf( STAT_GAMETIME ) - 60*iMinutes; + iSeconds = getstatf( STAT_GAMETIME ) - 60 * iMinutes; iTens = iSeconds / 10; - iUnits = iSeconds - 10*iTens; + iUnits = iSeconds - 10 * iTens; } // Flashing red numbers diff --git a/Source/Client/HUDCrosshair.c b/Source/Client/HUDCrosshair.c index 11f998cb..9dcea96c 100644 --- a/Source/Client/HUDCrosshair.c +++ b/Source/Client/HUDCrosshair.c @@ -37,7 +37,11 @@ void HUD_DrawCrosshair( void ) { float fDistance = wptTable[ getstatf( STAT_ACTIVEWEAPON ) ].iCrosshairMinDistance; float fDeltaDistance = wptTable[ getstatf( STAT_ACTIVEWEAPON ) ].iCrosshairDeltaDistance; - vCrossColor = autocvar_cross_color * ( 1 / 255 ); + if ( iNightVision == FALSE ) { + vCrossColor = autocvar_cross_color * ( 1 / 255 ); + } else { + vCrossColor = '1 0 0'; + } if ( !( getstatf( STAT_FLAGS ) & FL_ONGROUND) ) { // If we are in the air... fDistance = fDistance * 2; diff --git a/Source/Client/HUDOrbituaries.c b/Source/Client/HUDOrbituaries.c index 77577f74..c7e0ffcf 100644 --- a/Source/Client/HUDOrbituaries.c +++ b/Source/Client/HUDOrbituaries.c @@ -81,7 +81,7 @@ This actually displays the contents of orbBuffer ================= */ void HUD_DrawOrbituaries( void ) { - vector vOrbPos = [ vVideoResolution_x - 200, 16 ]; + vector vOrbPos = [ vVideoResolution_x - 200, 56 ]; if ( fOrbituaryTime < time && iOrbituaryScroll >= 0 ) { // We are cheap, just clear the attacker and we're good. diff --git a/Source/Client/Nightvision.c b/Source/Client/Nightvision.c new file mode 100644 index 00000000..07829ec1 --- /dev/null +++ b/Source/Client/Nightvision.c @@ -0,0 +1,77 @@ +/* +OpenCS Project +Copyright (C) 2015 Marco "eukara" Hladik + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +int iNightVision; + +/* +================= +Nightvision_Toggle + +Called by the cmd 'nightvision' +================= +*/ +void Nightvision_Toggle( void ) { + if( getplayerkeyvalue( player_localnum, "*spectator" ) == "1" ) { + return; + } + + if ( !( getstatf( STAT_EQUIPMENT ) & EQUIPMENT_NIGHTVISION ) ) { + return; + } + + iNightVision = 1 - iNightVision; + + if ( iNightVision == TRUE ) { + localsound( "items/nvg_on.wav", CHAN_ITEM, 1 ); + } else { + localsound( "items/nvg_off.wav", CHAN_ITEM, 1 ); + } +} + +/* +================= +Nightvision_PreDraw + +Called before rendering the frame in Draw.c +================= +*/ +void Nightvision_PreDraw( void ) { + if( getplayerkeyvalue( player_localnum, "*spectator" ) == "1" ) { + iNightVision = FALSE; + return; + } + + if ( iNightVision == TRUE ) { + dynamiclight_add( getproperty( VF_ORIGIN ), 500, '0 0.75 0'); + } +} + +/* +================= +Nightvision_PostDraw + +Called after rendering the frame in Draw.c +================= +*/ +void Nightvision_PostDraw( void ) { + if ( iNightVision == TRUE ) { + drawfill( '0 0', vVideoResolution, '0 0.5 0', 1, DRAWFLAG_ADDITIVE ); + } +} diff --git a/Source/Client/VGUI.c b/Source/Client/VGUI.c index d35eae1f..f7b8a597 100644 --- a/Source/Client/VGUI.c +++ b/Source/Client/VGUI.c @@ -86,14 +86,16 @@ void CSQC_VGUI_Init( void ) { // Now load the MAP DESCRIPTION fmMOTD = fopen( sprintf( "maps/%s.txt", mapname ), FILE_READ); - for ( int i = 0; i < 35; i++ ) { - sTemp = fgets( fmMOTD ); - if not ( sTemp ) { - break; - } - sMapString[ i ] = sTemp; + if ( fmMOTD != -1 ) { + for ( int i = 0; i < 35; i++ ) { + sTemp = fgets( fmMOTD ); + if not ( sTemp ) { + break; + } + sMapString[ i ] = sTemp; + } + fclose( fmMOTD ); } - fclose( fmMOTD ); // We start on the MOTD, always fVGUI_Display = VGUI_MOTD; diff --git a/Source/Client/VGUIObjects.c b/Source/Client/VGUIObjects.c index c0be19bc..27ba52ef 100644 --- a/Source/Client/VGUIObjects.c +++ b/Source/Client/VGUIObjects.c @@ -144,3 +144,8 @@ void VGUI_FakeButton( string sLabel, vector vPos, vector vSize ) { void VGUI_Text( string sText, vector vPos, vector vSize ) { drawstring( vPos, sText, vSize, vVGUIColor, VGUI_WINDOW_FGALPHA, DRAWFLAG_ADDITIVE ); } + +void VGUI_RightText( vector vPos, string sText, vector vSize, vector vColor ) { + vPos_x -= stringwidth( sText, FALSE, vSize ); + drawstring( vPos, sText, vSize, vColor, 1, 0 ); +} diff --git a/Source/Client/VGUIScoreboard.c b/Source/Client/VGUIScoreboard.c index f692a011..a6c910cf 100644 --- a/Source/Client/VGUIScoreboard.c +++ b/Source/Client/VGUIScoreboard.c @@ -30,11 +30,6 @@ string sScoreTeams[4] = { // This is seperated from the other VGUI stuff so we can check scores while buying and whatnot int iShowScores; -void VGUI_Scores_AlignedText( vector vPos, string sText, vector vSize, vector vColor ) { - vPos_x -= stringwidth( sText, FALSE, vSize ); - drawstring( vPos, sText, vSize, vColor, 1, 0 ); -} - vector VGUI_Scores_DrawTeam( vector vPos, float fTeam ) { vector vColor; @@ -67,15 +62,15 @@ vector VGUI_Scores_DrawTeam( vector vPos, float fTeam ) { // Spectators don't have stats worth caring about if ( fTeam != TEAM_SPECTATOR ) { - VGUI_Scores_AlignedText( vNewPos + '320 0', getplayerkeyvalue( i, INFOKEY_P_FRAGS ), '8 8 0', vColor ); - VGUI_Scores_AlignedText( vNewPos + '384 0', getplayerkeyvalue( i, "*deaths" ), '8 8 0', vColor ); + VGUI_RightText( vNewPos + '320 0', getplayerkeyvalue( i, INFOKEY_P_FRAGS ), '8 8 0', vColor ); + VGUI_RightText( vNewPos + '384 0', getplayerkeyvalue( i, "*deaths" ), '8 8 0', vColor ); } - VGUI_Scores_AlignedText( vNewPos + '456 0', getplayerkeyvalue( i, INFOKEY_P_PING ), '8 8 0', vColor ); + VGUI_RightText( vNewPos + '456 0', getplayerkeyvalue( i, INFOKEY_P_PING ), '8 8 0', vColor ); if ( getplayerkeyvalue( i, INFOKEY_P_VOIPSPEAKING ) == "0" ) { - VGUI_Scores_AlignedText( vNewPos + '508 0', "N", '8 8 0', '1 1 1' ); + VGUI_RightText( vNewPos + '508 0', "N", '8 8 0', '1 1 1' ); } else { - VGUI_Scores_AlignedText( vNewPos + '508 0', "Y", '8 8 0', '1 1 1' ); + VGUI_RightText( vNewPos + '508 0', "Y", '8 8 0', '1 1 1' ); } vNewPos += '0 14'; @@ -95,9 +90,9 @@ vector VGUI_Scores_DrawTeam( vector vPos, float fTeam ) { // Draw the amount of rounds we've von if ( fTeam == TEAM_CT ) { - VGUI_Scores_AlignedText( vPos + '320 0', sprintf( "%i", getstati( STAT_WON_CT ) ), '16 16 0', vColor ); + VGUI_RightText( vPos + '320 0', sprintf( "%i", getstati( STAT_WON_CT ) ), '16 16 0', vColor ); } else if ( fTeam == TEAM_T ) { - VGUI_Scores_AlignedText( vPos + '320 0', sprintf( "%i", getstati( STAT_WON_T ) ), '16 16 0', vColor ); + VGUI_RightText( vPos + '320 0', sprintf( "%i", getstati( STAT_WON_T ) ), '16 16 0', vColor ); } // Now we know the playercount, so let's calculate the position next to the Teamname String and print it @@ -111,9 +106,13 @@ vector VGUI_Scores_DrawTeam( vector vPos, float fTeam ) { void VGUI_Scores_Show( void ) { vector vMainPos; vector v1, v2, v3; - vector vSize = '540 500'; + vector vSize; + + vSize_x = 540; + vSize_y = vVideoResolution_y - 112; + vMainPos_x = ( vVideoResolution_x / 2 ) - (vSize_x / 2); - vMainPos_y = ( vVideoResolution_y / 2 ) - (vSize_y / 2); + vMainPos_y = 56; // Draw the background drawfill( vMainPos, vSize - '1 1 0', VGUI_WINDOW_BGCOLOR, VGUI_WINDOW_BGALPHA ); diff --git a/Source/Client/VGUISpectator.c b/Source/Client/VGUISpectator.c new file mode 100644 index 00000000..e488e9fc --- /dev/null +++ b/Source/Client/VGUISpectator.c @@ -0,0 +1,60 @@ +/* +OpenCS Project +Copyright (C) 2015 Marco "eukara" Hladik + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "VGUI.h" + +void VGUI_DrawSpectatorHUD( void ) { + // Draw the borders + drawfill( [ 0, 0 ], [ vVideoResolution_x, 40 ], '0 0 0', 1 ); + drawfill( [ 0, vVideoResolution_y - 40], [ vVideoResolution_x, 40 ], '0 0 0', 1 ); + + // Draw the timer + int iMinutes, iSeconds, iTens, iUnits; + if( serverkey( "timelimit" ) ) { + float fTimeLeft = ( stof( serverkey( "timelimit" ) ) * 60 ) - getstatf( STAT_GAMETIME ); + if ( fTimeLeft < 0 ) { + iMinutes = iSeconds = iTens = iUnits = 0; + } else { + iMinutes = fTimeLeft / 60; + iSeconds = fTimeLeft - 60 * iMinutes; + iTens = iSeconds / 10; + iUnits = iSeconds - 10 * iTens; + } + } else { + iMinutes = getstatf( STAT_GAMETIME ) / 60; + iSeconds = getstatf( STAT_GAMETIME ) - 60 * iMinutes; + iTens = iSeconds / 10; + iUnits = iSeconds - 10 * iTens; + } + + drawpic( [ vVideoResolution_x - 70, 20 ], "gfx/vgui/640_timer", '14 14', '1 1 1', 1 ); + VGUI_RightText( [ vVideoResolution_x - 16, 23 ], sprintf( "%i:%i%i", iMinutes, iTens, iUnits ), '8 8 0', '0.56 0.56 0.21' ); + + // Draw the money + drawstring( [ vVideoResolution_x - 67, 6 ], "$", '8 8 0', '0.56 0.56 0.21', 1, 0 ); + VGUI_RightText( [ vVideoResolution_x - 16, 6 ], sprintf( "%d", getstatf( STAT_MONEY ) ), '8 8 0', '0.56 0.56 0.21' ); + + // Seperator + drawfill( [ vVideoResolution_x - 85, 6 ], [ 2, 28 ], '0.56 0.56 0.21', 1 ); + + // Team Stats + VGUI_RightText( [ vVideoResolution_x - 96, 6 ], sprintf( "Terrorists: %d", getstatf( STAT_WON_T ) ), '8 8 0', '0.56 0.56 0.21' ); + VGUI_RightText( [ vVideoResolution_x - 96, 23 ], sprintf( "CT Forces: %d", getstatf( STAT_WON_CT ) ), '8 8 0', '0.56 0.56 0.21' ); +} diff --git a/Source/Client/View.c b/Source/Client/View.c index d1943658..8a3f37c3 100644 --- a/Source/Client/View.c +++ b/Source/Client/View.c @@ -63,19 +63,19 @@ float View_CalcBob( void ) { } fBobTime += frametime; - fCycle = fBobTime - (int)( fBobTime / cvar( "cl_bobcycle" ) ) * cvar( "cl_bobcycle" ); - fCycle /= cvar( "cl_bobcycle" ); + fCycle = fBobTime - (int)( fBobTime / autocvar_cl_bobcycle ) * autocvar_cl_bobcycle; + fCycle /= autocvar_cl_bobcycle; - if ( fCycle < cvar( "cl_bobup" ) ) { - fCycle = MATH_PI * fCycle / cvar( "cl_bobup" ); + if ( fCycle < autocvar_cl_bobup ) { + fCycle = MATH_PI * fCycle / autocvar_cl_bobup; } else { - fCycle = MATH_PI + MATH_PI * ( fCycle - cvar( "cl_bobup" ) )/( 1.0 - cvar( "cl_bobup" ) ); + fCycle = MATH_PI + MATH_PI * ( fCycle - autocvar_cl_bobup )/( 1.0 - autocvar_cl_bobup ); } vVelocity = pmove_vel; //ePlayerEnt.velocity; vVelocity_z = 0; - fBob = sqrt( vVelocity_x * vVelocity_x + vVelocity_y * vVelocity_y ) * cvar( "cl_bob" ); + fBob = sqrt( vVelocity_x * vVelocity_x + vVelocity_y * vVelocity_y ) * autocvar_cl_bob; fBob = fBob * 0.3 + fBob * 0.7 * sin(fCycle); fBob = min( fBob, 4 ); fBob = max( fBob, -7 ); diff --git a/Source/Client/progs.src b/Source/Client/progs.src index c52fc03f..87b07e06 100644 --- a/Source/Client/progs.src +++ b/Source/Client/progs.src @@ -44,11 +44,13 @@ Defs.h View.c VGUIObjects.c +VGUISpectator.c VGUIScoreboard.c VGUIMOTD.c VGUIBuyMenu.c VGUITeamSelect.c VGUI.c +Nightvision.c HUDCrosshair.c HUDWeaponSelect.c HUDOrbituaries.c diff --git a/Source/Globals.h b/Source/Globals.h index 646d2713..526d5c7d 100644 --- a/Source/Globals.h +++ b/Source/Globals.h @@ -40,6 +40,7 @@ enum { STAT_SLOT_PRIMARY, STAT_SLOT_SECONDARY, STAT_SLOT_GRENADE, + STAT_EQUIPMENT, STAT_CURRENT_MAG, STAT_CURRENT_CALIBER, STAT_PROGRESS, diff --git a/Source/Server/Client.c b/Source/Server/Client.c index b6713292..c76a1693 100644 --- a/Source/Server/Client.c +++ b/Source/Server/Client.c @@ -69,7 +69,9 @@ void PutClientInServer( void ) { //self.SendEntity = Player_SendEntity; // Because we don't want to reset these when we die - Money_AddMoney( self, cvar( "mp_startmoney" ) ); + Money_AddMoney( self, autocvar_mp_startmoney ); + + self.team = 0; forceinfokey( self, "*team", "0" ); } diff --git a/Source/Server/Damage.c b/Source/Server/Damage.c index 0c76ea76..9c63ddd1 100644 --- a/Source/Server/Damage.c +++ b/Source/Server/Damage.c @@ -52,14 +52,15 @@ void Damage_Apply( entity eTarget, entity eAttacker, int iDamage, vector vHitPos // Target is dead and a client.... if ( eTarget.health <= 0 ) { - if ( ( eTarget.flags & FL_CLIENT ) && ( eAttacker.flags & FL_CLIENT ) ) { - Damage_CastOrbituary( eAttacker, eTarget, eAttacker.weapon, FALSE ); - eAttacker.frags++; + if ( eTarget.flags & FL_CLIENT ) { eTarget.fDeaths++; - forceinfokey( eTarget, "*deaths", ftos( eTarget.fDeaths ) ); - + } + + if ( ( eTarget.flags & FL_CLIENT ) && ( eAttacker.flags & FL_CLIENT ) ) { + eAttacker.frags++; Money_AddMoney( eAttacker, 300 ); + Damage_CastOrbituary( eAttacker, eTarget, eAttacker.weapon, FALSE ); } } diff --git a/Source/Server/Defs.h b/Source/Server/Defs.h index 3b24bd93..8fbb03c7 100644 --- a/Source/Server/Defs.h +++ b/Source/Server/Defs.h @@ -26,6 +26,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define VEC_CHULL_MAX '16 16 18' #define VEC_PLAYER_CVIEWPOS '0 0 12' +// Server cvars +var float autocvar_mp_startmoney = 800; +var float autocvar_mp_buytime = 90; +var float autocvar_mp_freezetime = 6; +var float autocvar_mp_c4timer = 45; +var float autocvar_mp_roundtime = 5; +var float autocvar_mp_fillweapons = 0; + // Particle Fields float EFFECT_GUNSHOT; float EFFECT_BLOOD; diff --git a/Source/Server/FuncDoor.c b/Source/Server/FuncDoor.c index f8ac39d7..faebe5e9 100644 --- a/Source/Server/FuncDoor.c +++ b/Source/Server/FuncDoor.c @@ -44,7 +44,6 @@ enum { .float speed; .float lip; -.float dmg; .float state; .vector pos1, pos2; diff --git a/Source/Server/Main.c b/Source/Server/Main.c index aab9d6e0..298a0d22 100644 --- a/Source/Server/Main.c +++ b/Source/Server/Main.c @@ -272,6 +272,7 @@ void worldspawn( void ) { clientstat( STAT_SLOT_PRIMARY, EV_FLOAT, fSlotPrimary ); clientstat( STAT_SLOT_SECONDARY, EV_FLOAT, fSlotSecondary ); clientstat( STAT_SLOT_GRENADE, EV_FLOAT, fSlotGrenade ); + clientstat( STAT_EQUIPMENT, EV_INTEGER, iEquipment ); clientstat( STAT_CURRENT_MAG, EV_INTEGER, iCurrentMag ); clientstat( STAT_CURRENT_CALIBER, EV_INTEGER, iCurrentCaliber ); clientstat( STAT_TEAM, EV_INTEGER, team ); diff --git a/Source/Server/Player.c b/Source/Server/Player.c index cc8f8831..c072602f 100644 --- a/Source/Server/Player.c +++ b/Source/Server/Player.c @@ -62,7 +62,7 @@ void Player_Death( void ) { iAlivePlayers_T--; // If the bomb has been planted, T deaths don't matter anymore - if ( iAlivePlayers_T == 0 && iBombPlanted == FALSE ) { + if ( ( iAlivePlayers_T == 0 ) && ( iBombPlanted == FALSE ) ) { Rules_RoundOver( TEAM_CT, 3600, FALSE ); } } else if ( self.team == TEAM_CT ) { @@ -157,7 +157,9 @@ Player_UseDown ==================== */ void Player_UseDown( void ) { - if ( !( self.flags & FL_USERELEASED ) ) { + if ( self.health <= 0 ) { + return; + } else if ( !( self.flags & FL_USERELEASED ) ) { return; } diff --git a/Source/Server/Rules.c b/Source/Server/Rules.c index a6e7c310..e1c34608 100644 --- a/Source/Server/Rules.c +++ b/Source/Server/Rules.c @@ -28,8 +28,8 @@ enum { // Checks if it is possible for players to buy anything float Rules_BuyingPossible( void ) { if ( fGameState == GAME_ACTIVE ) { - if ( ( ( cvar( "mp_roundtime" ) * 60 ) - fGameTime ) > cvar( "mp_buytime" ) ) { - centerprint( self, sprintf( "%d seconds have passed...\nYou can't buy anything now!", cvar( "mp_buytime" ) ) ); + if ( ( ( autocvar_mp_roundtime * 60 ) - fGameTime ) > autocvar_mp_buytime ) { + centerprint( self, sprintf( "%d seconds have passed...\nYou can't buy anything now!", autocvar_mp_buytime ) ); self.fAttackFinished = time + 1.0; return FALSE; } @@ -127,7 +127,7 @@ void Rules_Restart( void ) { self = eOld; - Timer_Begin( cvar( "mp_freezetime" ), GAME_FREEZE ); + Timer_Begin( autocvar_mp_freezetime, GAME_FREEZE ); Money_ResetTeamReward(); } diff --git a/Source/Server/Timer.c b/Source/Server/Timer.c index 6b717727..961e6681 100644 --- a/Source/Server/Timer.c +++ b/Source/Server/Timer.c @@ -57,7 +57,7 @@ void Timer_Update( void ) { Rules_TimeOver(); Timer_Begin( 5, GAME_END); // Round is over, 5 seconds til a new round starts } else { - Timer_Begin( cvar( "mp_roundtime" ) * 60, GAME_ACTIVE ); // Unfreeze + Timer_Begin( autocvar_mp_roundtime * 60, GAME_ACTIVE ); // Unfreeze float fRand = floor( random( 1, 4 ) ); if ( fRand == 1 ) { diff --git a/Source/Server/Triggers.c b/Source/Server/Triggers.c index 61ec242f..f3ee934f 100644 --- a/Source/Server/Triggers.c +++ b/Source/Server/Triggers.c @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. .string killtarget; .float wait; .float delay; +.float dmg; /* ================= @@ -114,6 +115,71 @@ void trigger_camera( void ) { self.vUse = trigger_camera_use; } +/* +================= +trigger_hurt + +Brush that damages things, especially players +================= +*/ +#define SF_HURT_ONCE 1 // Turn off once it fired the first time +#define SF_HURT_OFF 2 // Needs to be triggered in order to work again +#define SF_HURT_NOPLAYERS 8 // Don't hurt players +#define SF_HURT_FIREONPLAYER 16 // Only call UseTarget functions when it's a player +#define SF_HURT_TOUCHPLAYER 32 // Only hurt players + +void trigger_hurt( void ) { + static void trigger_hurt_use( void ) { + if ( self.solid == SOLID_NOT ) { + self.solid = SOLID_TRIGGER; + } else { + self.solid = SOLID_NOT; + } + } + + static void trigger_hurt_touch( void ) { + if ( self.fAttackFinished > self.ltime ) { + return; + } else if ( other.takedamage == DAMAGE_NO ) { + return; + } else if ( ( self.spawnflags & SF_HURT_TOUCHPLAYER ) && !( other.flags & FL_CLIENT ) ) { + return; + } else if ( ( self.spawnflags & SF_HURT_NOPLAYERS ) && ( other.flags & FL_CLIENT ) ) { + return; + } + + if ( self.spawnflags & SF_HURT_FIREONPLAYER ) { + if ( other.flags & FL_CLIENT ) { + Entities_UseTargets(); + } + } else { + Entities_UseTargets(); + } + + Damage_Apply( other, self, self.dmg, other.origin ); + + // Shut it down if used once + if ( self.spawnflags & SF_HURT_ONCE ) { + self.solid = SOLID_NOT; + } + + self.fAttackFinished = self.ltime + 0.5; + } + + self.angles = '0 0 0'; + self.solid = SOLID_TRIGGER; + + setmodel( self, self.model ); + self.model = 0; + + if ( self.spawnflags & SF_HURT_OFF ) { + self.solid = SOLID_NOT; + } + + self.vUse = trigger_hurt_use; + self.touch = trigger_hurt_touch; +} + /* ================= multi_manager diff --git a/Source/Shared/WeaponAUG.c b/Source/Shared/WeaponAUG.c index 5493e6be..35275b74 100644 --- a/Source/Shared/WeaponAUG.c +++ b/Source/Shared/WeaponAUG.c @@ -57,20 +57,20 @@ enum { }; void WeaponAUG_Draw( void ) { - #ifdef SSQC +#ifdef SSQC OpenCSGunBase_Draw(); - #else +#else View_PlayAnimation( ANIM_AUG_DRAW ); Sound_Delayed( "weapons/aug_boltpull.wav", 1.0, 0.5 ); - #endif +#endif } void WeaponAUG_PrimaryFire( void ) { - #ifdef SSQC +#ifdef SSQC if ( OpenCSGunBase_PrimaryFire() == TRUE ) { sound( self, CHAN_WEAPON, "weapons/aug-1.wav", 1, ATTN_NORM ); } - #else +#else int iRand = (int)floor( random( 1, 4 ) ); if ( iRand == 1 ) { View_PlayAnimation( ANIM_AUG_SHOOT1 ); @@ -81,20 +81,32 @@ void WeaponAUG_PrimaryFire( void ) { } OpenCSGunBase_ShotMultiplierHandle( 1 ); - #endif +#endif +} + +void WeaponAUG_SecondaryFire( void ) { +#ifdef SSQC + if ( self.viewzoom != 1.0 ) { + self.viewzoom = 1.0; + } else { + self.viewzoom = 0.6; + } + + self.fAttackFinished = time + 0.5; +#endif } void WeaponAUG_Reload( void ) { - #ifdef SSQC +#ifdef SSQC if ( OpenCSGunBase_Reload() == TRUE ) { // Play Sound } - #else +#else View_PlayAnimation( ANIM_AUG_RELOAD ); Sound_Delayed( "weapons/aug_boltpull.wav", 1.0, 0.5 ); Sound_Delayed( "weapons/aug_clipout.wav", 1.0, 1.3 ); Sound_Delayed( "weapons/aug_clipin.wav", 1.0, 2.2 ); Sound_Delayed( "weapons/aug_boltslap.wav", 1.0, 2.8 ); - #endif +#endif } diff --git a/Source/Shared/WeaponAWP.c b/Source/Shared/WeaponAWP.c index 4c114dd4..f4aeb45c 100644 --- a/Source/Shared/WeaponAWP.c +++ b/Source/Shared/WeaponAWP.c @@ -86,6 +86,20 @@ void WeaponAWP_PrimaryFire( void ) { #endif } +void WeaponAWP_SecondaryFire( void ) { +#ifdef SSQC + if ( self.viewzoom == 1.0 ) { + self.viewzoom = 0.45; + } else if ( self.viewzoom == 0.45 ) { + self.viewzoom = 0.1; + } else { + self.viewzoom = 1.0; + } + + self.fAttackFinished = time + 0.5; +#endif +} + void WeaponAWP_Reload( void ) { #ifdef SSQC if ( OpenCSGunBase_Reload() == TRUE ) { diff --git a/Source/Shared/WeaponC4Bomb.c b/Source/Shared/WeaponC4Bomb.c index 1257e81f..8a214ba7 100644 --- a/Source/Shared/WeaponC4Bomb.c +++ b/Source/Shared/WeaponC4Bomb.c @@ -141,7 +141,7 @@ void WeaponC4BOMB_Drop( vector vBombPos ) { setmodel( eBomb, "models/w_c4.mdl" ); eBomb.solid = SOLID_BBOX; eBomb.customphysics = C4BombThink; - eBomb.fAttackFinished = time + cvar( "mp_c4timer" ); + eBomb.fAttackFinished = time + autocvar_mp_c4timer; eBomb.vUse = C4BombUse; eBomb.iUsable = TRUE; diff --git a/Source/Shared/WeaponG3SG1.c b/Source/Shared/WeaponG3SG1.c index 488c6e6f..850bebbd 100644 --- a/Source/Shared/WeaponG3SG1.c +++ b/Source/Shared/WeaponG3SG1.c @@ -82,6 +82,20 @@ void WeaponG3SG1_PrimaryFire( void ) { #endif } +void WeaponG3SG1_SecondaryFire( void ) { +#ifdef SSQC + if ( self.viewzoom == 1.0 ) { + self.viewzoom = 0.45; + } else if ( self.viewzoom == 0.45 ) { + self.viewzoom = 0.15; + } else { + self.viewzoom = 1.0; + } + + self.fAttackFinished = time + 0.5; +#endif +} + void WeaponG3SG1_Reload( void ) { #ifdef SSQC if ( OpenCSGunBase_Reload() == TRUE ) { diff --git a/Source/Shared/WeaponSG550.c b/Source/Shared/WeaponSG550.c index 148e780e..a093522b 100644 --- a/Source/Shared/WeaponSG550.c +++ b/Source/Shared/WeaponSG550.c @@ -79,6 +79,20 @@ void WeaponSG550_PrimaryFire( void ) { #endif } +void WeaponSG550_SecondaryFire( void ) { +#ifdef SSQC + if ( self.viewzoom == 1.0 ) { + self.viewzoom = 0.45; + } else if ( self.viewzoom == 0.45 ) { + self.viewzoom = 0.15; + } else { + self.viewzoom = 1.0; + } + + self.fAttackFinished = time + 0.5; +#endif +} + void WeaponSG550_Reload( void ) { #ifdef SSQC if ( OpenCSGunBase_Reload() == TRUE ) { diff --git a/Source/Shared/WeaponSG552.c b/Source/Shared/WeaponSG552.c index fc466560..d014370d 100644 --- a/Source/Shared/WeaponSG552.c +++ b/Source/Shared/WeaponSG552.c @@ -88,6 +88,18 @@ void WeaponSG552_PrimaryFire( void ) { #endif } +void WeaponSG552_SecondaryFire( void ) { +#ifdef SSQC + if ( self.viewzoom != 1.0 ) { + self.viewzoom = 1.0; + } else { + self.viewzoom = 0.6; + } + + self.fAttackFinished = time + 0.5; +#endif +} + void WeaponSG552_Reload( void ) { #ifdef SSQC if ( OpenCSGunBase_Reload() == TRUE ) { diff --git a/Source/Shared/WeaponScout.c b/Source/Shared/WeaponScout.c index 956c3a8b..6fa47078 100644 --- a/Source/Shared/WeaponScout.c +++ b/Source/Shared/WeaponScout.c @@ -81,6 +81,20 @@ void WeaponSCOUT_PrimaryFire( void ) { #endif } +void WeaponSCOUT_SecondaryFire( void ) { +#ifdef SSQC + if ( self.viewzoom == 1.0 ) { + self.viewzoom = 0.45; + } else if ( self.viewzoom == 0.45 ) { + self.viewzoom = 0.15; + } else { + self.viewzoom = 1.0; + } + + self.fAttackFinished = time + 0.5; +#endif +} + void WeaponSCOUT_Reload( void ) { #ifdef SSQC if ( OpenCSGunBase_Reload() == TRUE ) { diff --git a/Source/Shared/Weapons.c b/Source/Shared/Weapons.c index edc140d7..d54da846 100644 --- a/Source/Shared/Weapons.c +++ b/Source/Shared/Weapons.c @@ -42,13 +42,13 @@ weaponfunc_t wpnFuncTable[ CS_WEAPON_COUNT ] = { { WeaponMAC10_Draw, WeaponMAC10_PrimaryFire, Temp_Nothing, WeaponMAC10_Reload }, { WeaponTMP_Draw, WeaponTMP_PrimaryFire, Temp_Nothing, WeaponTMP_Reload }, { WeaponAK47_Draw, WeaponAK47_PrimaryFire, Temp_Nothing, WeaponAK47_Reload }, - { WeaponSG552_Draw, WeaponSG552_PrimaryFire, Temp_Nothing, WeaponSG552_Reload }, + { WeaponSG552_Draw, WeaponSG552_PrimaryFire, WeaponSG552_SecondaryFire, WeaponSG552_Reload }, { WeaponM4A1_Draw, WeaponM4A1_PrimaryFire, WeaponM4A1_Secondary, WeaponM4A1_Reload }, - { WeaponAUG_Draw, WeaponAUG_PrimaryFire, Temp_Nothing, WeaponAUG_Reload }, - { WeaponSCOUT_Draw, WeaponSCOUT_PrimaryFire, Temp_Nothing, WeaponSCOUT_Reload }, - { WeaponAWP_Draw, WeaponAWP_PrimaryFire, Temp_Nothing, WeaponAWP_Reload }, - { WeaponG3SG1_Draw, WeaponG3SG1_PrimaryFire, Temp_Nothing, WeaponG3SG1_Reload }, - { WeaponSG550_Draw, WeaponSG550_PrimaryFire, Temp_Nothing, WeaponSG550_Reload }, + { WeaponAUG_Draw, WeaponAUG_PrimaryFire, WeaponAUG_SecondaryFire, WeaponAUG_Reload }, + { WeaponSCOUT_Draw, WeaponSCOUT_PrimaryFire, WeaponSCOUT_SecondaryFire, WeaponSCOUT_Reload }, + { WeaponAWP_Draw, WeaponAWP_PrimaryFire, WeaponAWP_SecondaryFire, WeaponAWP_Reload }, + { WeaponG3SG1_Draw, WeaponG3SG1_PrimaryFire, WeaponG3SG1_SecondaryFire, WeaponG3SG1_Reload }, + { WeaponSG550_Draw, WeaponSG550_PrimaryFire, WeaponSG550_SecondaryFire, WeaponSG550_Reload }, { WeaponPARA_Draw, WeaponPARA_PrimaryFire, Temp_Nothing, WeaponPARA_Reload }, { WeaponC4BOMB_Draw, WeaponC4BOMB_PrimaryFire, Temp_Nothing, Temp_Nothing } }; @@ -64,6 +64,8 @@ void Weapon_Draw( float fWeapon ) { // In case reloading logic is still going on self.think = Empty; + self.viewzoom = 1.0; + self.maxspeed = Player_GetMaxSpeed( fWeapon ); self.fAttackFinished = time + 1.0; #endif @@ -172,7 +174,7 @@ void CSEv_PlayerBuyWeapon_f( float fWeapon ) { Weapon_AddItem( fWeapon ); // Automatically fill weapons with ammo when you buy them (for free) like in CS:S - if ( cvar( "mp_fillweapons" ) == 1 ) { + if ( autocvar_mp_fillweapons == 1 ) { if ( wptTable[ fWeapon ].iSlot == SLOT_PRIMARY ) { Ammo_BuyPrimary( TRUE ); } else if ( wptTable[ fWeapon ].iSlot == SLOT_SECONDARY ) {