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