diff --git a/Source/Client/.Overview.c.un~ b/Source/Client/.Overview.c.un~ new file mode 100755 index 00000000..e12b0094 Binary files /dev/null and b/Source/Client/.Overview.c.un~ differ diff --git a/Source/Client/Defs.h b/Source/Client/Defs.h index dc4ddb8c..15a8b2db 100755 --- a/Source/Client/Defs.h +++ b/Source/Client/Defs.h @@ -45,6 +45,8 @@ var int autocvar_v_lefthanded = FALSE; var int autocvar_cl_thirdperson = FALSE; var int autocvar_cl_radar = 1; +var string autocvar_cl_logofile = "lambda"; + // Particle stuff var float PARTICLE_SPARK; var float PARTICLE_PIECES_BLACK; diff --git a/Source/Client/Entities.c b/Source/Client/Entities.c index 13b95155..8a484efd 100755 --- a/Source/Client/Entities.c +++ b/Source/Client/Entities.c @@ -80,8 +80,20 @@ void CSQC_Ent_Update( float flIsNew ) { self.origin_z = readcoord(); Effect_AnimatedSprite( self.origin, readfloat(), readfloat(), readfloat(), readfloat(), readfloat() ); + } else if ( fEntType == ENT_SPRAY ) { + self.origin_x = readcoord(); + self.origin_y = readcoord(); + self.origin_z = readcoord(); + + self.angles_x = readcoord(); + self.angles_y = readcoord(); + self.angles_z = readcoord(); + + self.model = sprintf( "logos/%s.bmp" ,getplayerkeyvalue( readbyte() - 1, "logo" ) ); + shaderforname( self.model, sprintf("{\npolygonOffset\n{\nmap %s\n}\n}\n", self.model ) ); + self.predraw = Effect_Spraypaint; + self.drawmask = MASK_ENGINE; } - } /* diff --git a/Source/Client/Init.c b/Source/Client/Init.c index 3a551584..7f03820b 100755 --- a/Source/Client/Init.c +++ b/Source/Client/Init.c @@ -69,6 +69,8 @@ void CSQC_Init(float apilevel, string enginename, float engineversion) { precache_sound( "debris/bustconcrete1.wav" ); precache_sound( "debris/bustconcrete2.wav" ); precache_sound( "debris/bustceiling.wav" ); + precache_model( "sprites/iplayerred.spr" ); + precache_model( "sprites/iplayerblue.spr" ); precache_model( "sprites/iplayervip.spr" ); precache_model( "sprites/ihostage.spr" ); @@ -80,6 +82,8 @@ void CSQC_Init(float apilevel, string enginename, float engineversion) { precache_pic( "gfx/vgui/icntlk_sv" ); precache_pic( sprintf( "overviews/%s.bmp", mapname ) ); + precache_pic( "logos/lambda.bmp" ); + for ( int i = 0; i < ( CS_WEAPON_COUNT - 1 ); i++ ) { precache_model( sViewModels[ i ] ); } @@ -96,6 +100,8 @@ void CSQC_Init(float apilevel, string enginename, float engineversion) { FONT_16 = loadfont( "16", "gfx/conchars_16", "16", -1 ); SHADER_CULLED = shaderforname( "mirror_cull" ); + + localcmd( sprintf( "setinfo logo %s\n", autocvar_cl_logofile ) ); Radio_InitSounds(); diff --git a/Source/Client/Overview.c~ b/Source/Client/Overview.c~ new file mode 100755 index 00000000..9d6cbf5d --- /dev/null +++ b/Source/Client/Overview.c~ @@ -0,0 +1,172 @@ +/* +FreeCS Project +Copyright (C) 2016, 2017 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. +*/ + +/* +The overview system was meant to support +more layers and so on. Never actually used. +Probably seemed impractical, feel free to make this +parse layers etc. properly though. +*/ + +typedef struct { + float fZoom; + vector vOrigin; + int iRotated; + float fHeight; + string sImagePath; + float fCameraHeight; + vector vVert1; + vector vVert2; + vector vVert3; + vector vVert4; +} overview_t; + +overview_t ovMap; + +/* +================= +Overview_Init + +Initializes the globals and whatnot +================= +*/ +void Overview_Init( void ) { + int *iImageSrc; + int iImageWidth = 0; + int iImageHeight = 0; + int iImageCount = 0; + string sTemp; + + ovMap.fZoom = 1.0f; + ovMap.vOrigin = '0 0 0'; + ovMap.iRotated = FALSE; + + filestream fOverview = fopen( sprintf( "overviews/%s.txt", mapname ), FILE_READ ); + if ( fOverview != -1 ) { + for ( int i = 0;; i++ ) { + sTemp = fgets( fOverview ); + if not ( sTemp ) { + break; + } + + tokenize( sTemp ); + if ( strtolower( argv( 0 ) ) == "zoom" ) { + ovMap.fZoom = stof( argv( 1 ) ); + } else if ( strtolower( argv( 0 ) ) == "origin" ) { + ovMap.vOrigin = [ stof( argv( 1 ) ), stof( argv( 2 ) ), stof( argv( 3 ) ) ]; + } else if ( strtolower( argv( 0 ) ) == "rotated" ) { + ovMap.iRotated = (int)stof( argv( 1 ) ); + } else if ( strtolower( argv( 0 ) ) == "height" ) { + ovMap.fHeight = stof( argv( 1 ) ); + } + } + fclose( fOverview ); + } else { + print( sprintf( "[OVERVIEW] Couldn't load overviews/%s.txt\n", mapname ) ); + ovMap.sImagePath = __NULL__; + return; + } + + if ( ovMap.iRotated == TRUE ) { + ovMap.vVert1 = ovMap.vOrigin -( ( 4096/ovMap.fZoom ) * '1 0.75 0' ); + ovMap.vVert4 = ovMap.vOrigin + ( 4096/ovMap.fZoom ) * '1 0.75 0'; + ovMap.vVert2 = [ ovMap.vVert1[0], ovMap.vVert4[1] ] ; + ovMap.vVert3 = [ ovMap.vVert4[0], ovMap.vVert1[1] ] ; + } else { + ovMap.vVert1 = ovMap.vOrigin -( ( 4096/ovMap.fZoom ) * '0.75 1 0' ); + ovMap.vVert4 = ovMap.vOrigin + ( 4096/ovMap.fZoom ) * '0.75 1 0'; + ovMap.vVert2 = [ ovMap.vVert1[0], ovMap.vVert4[1] ] ; + ovMap.vVert3 = [ ovMap.vVert4[0], ovMap.vVert1[1] ] ; + } + + ovMap.fCameraHeight = fabs( 4096/ovMap.fZoom ); + + ovMap.sImagePath = "overview"; + shaderforname( ovMap.sImagePath, sprintf("{\n{\nprogram default2d\nmap $rt:%s\n}\n}\n", ovMap.sImagePath ) ); + + // Read the image and get rid of the burning green + iImageSrc = r_readimage( sprintf( "overviews/%s.bmp", mapname ), iImageWidth, iImageHeight ); + if ( iImageSrc != __NULL__ ) { + for ( int i = 0; i < ( iImageWidth * iImageHeight ); i++ ) { + if ( iImageSrc[ i ] == 0xff00ff00i ) { + iImageSrc[ i ] = 0x00000000i; + } + } + r_uploadimage( ovMap.sImagePath, iImageWidth, iImageHeight, iImageSrc ); + memfree( iImageSrc ); + } +} + +void Overview_DrawLayer( void ) { + if ( ovMap.iRotated == TRUE ) { + R_BeginPolygon( ovMap.sImagePath ); + R_PolygonVertex( [ ovMap.vVert4[0], ovMap.vVert4[1], ovMap.fHeight ], '1 0', '1 1 1', 1.0f ); // Top Left + R_PolygonVertex( [ ovMap.vVert3[0], ovMap.vVert3[1], ovMap.fHeight ], '1 1', '1 1 1', 1.0f ); // Top Right + R_PolygonVertex( [ ovMap.vVert1[0], ovMap.vVert1[1], ovMap.fHeight ], '0 1', '1 1 1', 1.0f ); // Bottom right + R_PolygonVertex( [ ovMap.vVert2[0], ovMap.vVert2[1], ovMap.fHeight ], '0 0', '1 1 1', 1.0f ); // Bottom left + R_EndPolygon(); + } else { + R_BeginPolygon( ovMap.sImagePath ); + R_PolygonVertex( [ ovMap.vVert4[0], ovMap.vVert4[1], ovMap.fHeight ], '0 0', '1 1 1', 1.0f ); // Top Left + R_PolygonVertex( [ ovMap.vVert3[0], ovMap.vVert3[1], ovMap.fHeight ], '1 0', '1 1 1', 1.0f ); // Top Right + R_PolygonVertex( [ ovMap.vVert1[0], ovMap.vVert1[1], ovMap.fHeight ], '1 1', '1 1 1', 1.0f ); // Bottom right + R_PolygonVertex( [ ovMap.vVert2[0], ovMap.vVert2[1], ovMap.fHeight ], '0 1', '1 1 1', 1.0f ); // Bottom left + R_EndPolygon(); + } + + for ( entity eFind = world; ( eFind = find( eFind, classname, "player" ) ); ) { + if ( getplayerkeyvalue( eFind.entnum - 1, "*team" ) == "1" ) { + R_BeginPolygon( "sprites/iplayerred.spr_0.tga" ); + } else { + if ( getplayerkeyvalue( eFind.entnum - 1, "*dead" ) == "2" ) { + R_BeginPolygon( "sprites/iplayervip.spr_0.tga" ); + } else { + R_BeginPolygon( "sprites/iplayerblue.spr_0.tga" ); + } + } + R_PolygonVertex( [ eFind.absmax_x + 16, eFind.absmin_y - 16, ovMap.fHeight + 16 ], '1 0', '1 1 1', 1.0f ); // Top Right + R_PolygonVertex( [ eFind.absmin_x - 16, eFind.absmin_y - 16, ovMap.fHeight + 16 ], '0 0', '1 1 1', 1.0f ); // Top left + R_PolygonVertex( [ eFind.absmin_x - 16, eFind.absmax_y + 16, ovMap.fHeight + 16 ], '0 1', '1 1 1', 1.0f ); // Bottom left + R_PolygonVertex( [ eFind.absmax_x + 16, eFind.absmax_y + 16, ovMap.fHeight + 16 ], '1 1', '1 1 1', 1.0f ); // Bottom right + R_EndPolygon(); + } + +} + +/* +================= +Overview_Draw + +Draw one of two types of overviews. +This is for spectators. +================= +*/ +void Overview_Draw( void ) { + if ( ovMap.sImagePath == __NULL__ ) { + return; + } + + drawfill( vVideoMins, vVideoResolution, '0 0 0', 1.0f, 0 ); + + Overview_DrawLayer(); + + makevectors( view_angles ); + setproperty( VF_ORIGIN, ovMap.vOrigin + ( v_forward * -ovMap.fCameraHeight ) ) ; +} \ No newline at end of file diff --git a/Source/Client/VGUIScoreboard.c b/Source/Client/VGUIScoreboard.c index 490cd370..b10265a6 100755 --- a/Source/Client/VGUIScoreboard.c +++ b/Source/Client/VGUIScoreboard.c @@ -44,7 +44,7 @@ vector VGUI_Scores_DrawTeam( vector vPos, float fTeam ) { // Player loop, this one goes through ALL players but only prints the one from fTeam for ( int i = -1; i > -32; i-- ) { - if ( stof( getplayerkeyvalue( i, "*team" ) ) == fTeam ) { + if ( stof( getplayerkeyvalue( i, "*team" ) ) == fTeam ) { if ( getplayerkeyvalue( i, "name" ) ) { vColor = HUD_GetChatColor( fTeam ); diff --git a/Source/FreeCS-CE.prj b/Source/FreeCS-CE.prj old mode 100644 new mode 100755 index e37cce07..a66e5e21 --- a/Source/FreeCS-CE.prj +++ b/Source/FreeCS-CE.prj @@ -26,7 +26,7 @@ - + @@ -75,7 +75,7 @@ - + @@ -117,6 +117,7 @@ - + + diff --git a/Source/Globals.h b/Source/Globals.h index a04b9cbe..7d804b30 100755 --- a/Source/Globals.h +++ b/Source/Globals.h @@ -77,7 +77,8 @@ enum { enum { ENT_PLAYER = 1, ENT_AMBIENTSOUND, - ENT_SPRITE + ENT_SPRITE, + ENT_SPRAY }; enum { diff --git a/Source/Menu/Defs.h b/Source/Menu/Defs.h index 1ac63983..51b47535 100755 --- a/Source/Menu/Defs.h +++ b/Source/Menu/Defs.h @@ -31,6 +31,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. var vector vVideoSize; var vector vMenuOffset; var vector autocvar_menu_fgcolor = '1 0.59 0.19'; +var string autocvar_cl_logofile = "lambda"; var vector vMousePos; var float fInputKeyCode; diff --git a/Source/Server/Client.c b/Source/Server/Client.c index f32d074f..aa4ee9aa 100755 --- a/Source/Server/Client.c +++ b/Source/Server/Client.c @@ -71,7 +71,7 @@ Called when a spectator leaves the game ================= */ void SpectatorDisconnect( void ) { - + Effect_RemoveSpray( self ); } /* @@ -94,6 +94,8 @@ void ClientDisconnect( void ) { } } } + + Effect_RemoveSpray( self ); } /* diff --git a/Source/Server/FuncHostageRescue.c b/Source/Server/FuncHostageRescue.c index 7a60ae35..501f9f53 100755 --- a/Source/Server/FuncHostageRescue.c +++ b/Source/Server/FuncHostageRescue.c @@ -27,6 +27,9 @@ void func_hostage_rescue_touch( void ) { if ( ( other.classname == "player" ) && ( other.team == TEAM_CT ) ) { other.fInHostageZone = TRUE; // Note: this will be cleared every frame inside SV_RunClientCommand } else if ( other.classname == "hostage_entity" ) { + if ( self.solid == SOLID_NOT ) { + return; + } Radio_BroadcastMessage( RADIO_RESCUED ); iHostagesRescued++; diff --git a/Source/Server/Input.c b/Source/Server/Input.c index 30dcf0b8..21b8f2b8 100755 --- a/Source/Server/Input.c +++ b/Source/Server/Input.c @@ -67,5 +67,9 @@ void Input_Handle( void ) { Weapon_Release(); } + if ( self.impulse == 201 ) { + Effect_Spraypaint(); + } + self.impulse = 0; } diff --git a/Source/Server/Main.c b/Source/Server/Main.c index 75978098..f8f93625 100755 --- a/Source/Server/Main.c +++ b/Source/Server/Main.c @@ -269,6 +269,7 @@ void worldspawn( void ) { precache_sound( "player/headshot1.wav" ); precache_sound( "player/headshot2.wav" ); precache_sound( "player/headshot3.wav" ); + precache_sound( "player/sprayer.wav" ); precache_sound( "items/9mmclip1.wav" ); precache_sound( "items/tr_kevlar.wav" ); diff --git a/Source/Shared/Effects.c b/Source/Shared/Effects.c index 30106cc9..844b3bae 100755 --- a/Source/Shared/Effects.c +++ b/Source/Shared/Effects.c @@ -18,6 +18,72 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef SSQC +void Effect_RemoveSpray( entity eOwner ) { + for ( entity eFind = world; ( eFind = find( eFind, classname, "spray" ) ); ) { + if ( eFind.owner == self ) { + remove( eFind ); + } + } +} + +void Effect_Spraypaint( void ) { + static float Effect_Spraypaint_Send( entity ePVSEnt, float fChanged ) { + WriteByte( MSG_ENTITY, ENT_SPRAY ); + WriteCoord( MSG_ENTITY, self.origin_x ); + WriteCoord( MSG_ENTITY, self.origin_y ); + WriteCoord( MSG_ENTITY, self.origin_z ); + WriteCoord( MSG_ENTITY, self.angles_x ); + WriteCoord( MSG_ENTITY, self.angles_y ); + WriteCoord( MSG_ENTITY, self.angles_z ); + WriteByte( MSG_ENTITY, num_for_edict( self.owner ) ); + return TRUE; + } + vector vSrc; + vector vEnd; + makevectors( self.v_angle ); + + if ( self.health <= 0 ) { + return; + } + + Effect_RemoveSpray( self ); + + vSrc = self.origin + self.view_ofs; + vEnd = vSrc + v_forward * 128; + traceline( vSrc, vEnd, 0, self ); + + // Found a wall + if ( trace_fraction != 1.0f ) { + entity eSpray = spawn(); + eSpray.classname = "spray"; + eSpray.owner = self; + eSpray.solid = SOLID_NOT; + setorigin( eSpray, trace_endpos ); + + // Align it + vector vSprayAngles = self.angles; + vSprayAngles_x *= -1; + makevectors( vSprayAngles ); + vector vCoplanar = v_forward - ( v_forward * trace_plane_normal ) * trace_plane_normal; + eSpray.angles = vectoangles( vCoplanar, trace_plane_normal ); + + eSpray.SendEntity = Effect_Spraypaint_Send; + eSpray.SendFlags = 1; + sound( self, CHAN_VOICE, "player/sprayer.wav", 1.0, ATTN_NORM ); + } +#else +float Effect_Spraypaint( void ) { + makevectors( self.angles ); + // Temporary string, will getinfo from player later + adddecal( self.model, self.origin, v_up / 64, v_right / 64, '1 1 1', 1.0f ); + addentity( self ); + return PREDRAW_NEXT; +#endif +} + + void Effect_CreateExplosion( vector vPos ) { #ifdef SSQC vPos_z += 48; diff --git a/freecs/default.cfg b/freecs/default.cfg old mode 100644 new mode 100755 diff --git a/freecs/menu.dat b/freecs/menu.dat index e315ec28..420c8d8e 100755 Binary files a/freecs/menu.dat and b/freecs/menu.dat differ diff --git a/freecs/progs.dat b/freecs/progs.dat old mode 100644 new mode 100755 index 0f39cae3..94a1a037 Binary files a/freecs/progs.dat and b/freecs/progs.dat differ