diff --git a/Source/Client/Defs.h b/Source/Client/Defs.h index 62318abc..8a47a4ee 100644 --- a/Source/Client/Defs.h +++ b/Source/Client/Defs.h @@ -33,6 +33,13 @@ var float autocvar_cl_bobcycle = 0.8; var float autocvar_cl_bobup = 0.5; var float autocvar_cl_bobclassic = 0; +// Particle stuff +var float PARTICLE_SPARK; +var float PARTICLE_PIECES_BLACK; +var float PARTICLE_SMOKE_GREY; +var float PARTICLE_SMOKE_BROWN; +var float PARTICLE_BLOOD; + vector vHUDColor; // Defined in HUD_Draw (HUD.c) vector vVGUIColor; // Defined in HUD_Draw (VGUI.c) vector vCrossColor; // Defined in HUD_Draw (HUDCrosshair.c) diff --git a/Source/Client/Event.c b/Source/Client/Event.c index 3f6c2ef8..6477688c 100644 --- a/Source/Client/Event.c +++ b/Source/Client/Event.c @@ -124,6 +124,20 @@ void CSQC_Parse_Event( void ) { Radio_BroadcastMessage( readbyte() ); } else if ( fHeader == EV_ORBITUARY ) { HUD_AddOrbituaries( readbyte(), readbyte(), readbyte(), readbyte(), readbyte(), readbyte()); + } else if ( fHeader == EV_IMPACT ) { + int iType; + vector vOrigin, vNormal; + + iType = (int)readbyte(); + vOrigin_x = readcoord(); + vOrigin_y = readcoord(); + vOrigin_z = readcoord(); + + vNormal_x = readcoord(); + vNormal_y = readcoord(); + vNormal_z = readcoord(); + + Effect_Impact( iType, vOrigin, vNormal ); } } diff --git a/Source/Client/Init.c b/Source/Client/Init.c index 2d5c2c41..1733da84 100644 --- a/Source/Client/Init.c +++ b/Source/Client/Init.c @@ -46,6 +46,12 @@ void CSQC_Init(float apilevel, string enginename, float engineversion) { precache_model( sViewModels[ i ] ); } + PARTICLE_SPARK = particleeffectnum( "part_spark" ); + PARTICLE_PIECES_BLACK = particleeffectnum( "part_pieces_black" ); + PARTICLE_SMOKE_GREY = particleeffectnum( "part_smoke_grey" ); + PARTICLE_SMOKE_BROWN = particleeffectnum( "part_smoke_brown" ); + PARTICLE_BLOOD = particleeffectnum( "part_blood" ); + Radio_InitSounds(); CSQC_ConsoleCommand_Init(); diff --git a/Source/Globals.h b/Source/Globals.h index 22df69b2..c0296e34 100644 --- a/Source/Globals.h +++ b/Source/Globals.h @@ -200,6 +200,7 @@ enum { EV_WEAPON_PRIMARYATTACK, EV_WEAPON_SECONDARYATTACK, EV_WEAPON_RELOAD, + EV_IMPACT, EV_MODELGIB, EV_CAMERATRIGGER, EV_RADIOMSG, @@ -220,6 +221,18 @@ enum { MATERIAL_NONE }; +// Impact types +enum { + IMPACT_MELEE = 0, + IMPACT_EXPLOSION, + IMPACT_DEFAULT, + IMPACT_GLASS, + IMPACT_WOOD, + IMPACT_METAL, + IMPACT_FLESH, + IMPACT_ROCK, +}; + // Actually used by input_button etc. #define INPUT_BUTTON0 1 #define INPUT_BUTTON2 2 diff --git a/Source/Server/Damage.c b/Source/Server/Damage.c index 286b7dde..80b7f455 100644 --- a/Source/Server/Damage.c +++ b/Source/Server/Damage.c @@ -84,14 +84,6 @@ void Damage_Apply( entity eTarget, entity eAttacker, int iDamage, vector vHitPos bprint( sprintf( "[DEBUG] Hit Bodypart: %s\n", Damage_GetHitLocation( trace_surface_id ) ) ); - // Don't be like Q1 and make everything bleed. - if ( eTarget.iBleeds == TRUE ) { - makevectors( eAttacker.angles ); - pointparticles( EFFECT_BLOOD, vHitPos, v_forward * -1, 1 ); - } else { - pointparticles( EFFECT_GUNSHOT, trace_endpos, trace_plane_normal, 1 ); - } - // Target is dead and a client.... if ( eTarget.health <= 0 ) { if ( eTarget.flags & FL_CLIENT ) { diff --git a/Source/Server/Defs.h b/Source/Server/Defs.h index 279caa99..14668364 100644 --- a/Source/Server/Defs.h +++ b/Source/Server/Defs.h @@ -46,10 +46,6 @@ enum { BODY_LEGRIGHT }; -// Particle Fields -float EFFECT_GUNSHOT; -float EFFECT_BLOOD; - // Player specific fields .float fInBuyZone; .float fInHostageZone; @@ -145,6 +141,7 @@ void BaseMelee_Attack( void ); float Player_GetMaxSpeed( float fWeapon ); +void Effect_Impact( int iType, vector vPos, vector vNormal ); void TraceAttack_FireBullets( int iShots ); void Damage_Radius( vector vOrigin, entity eAttacker, float fDamage, float fRadius ); void Damage_Apply( entity eTarget, entity eAttacker, int iDamage, vector vHitPos ); diff --git a/Source/Server/Entities.c b/Source/Server/Entities.c index 34c3b76c..9be1c08e 100644 --- a/Source/Server/Entities.c +++ b/Source/Server/Entities.c @@ -284,4 +284,21 @@ void func_illusionary( void ){ void func_water( void ) { func_wall(); self.skin = CONTENT_WATER; + /*self.forceshader = shaderforname( "{\n" + "surfaceparm nodlight\n" + "surfaceparm nomarks\n" + "{\n" + "map $refraction\n" + "}\n" + "{\n" + "map $null\n" + "}\n" + "{\n" + "map $ripplemap\n" + "}\n" + "{\n" + "map $null\n" + "}\n" + "program altwater#RIPPLEMAP#FRESNEL=4\n" + "}\n" );*/ } diff --git a/Source/Server/Footsteps.c b/Source/Server/Footsteps.c index 7fd59cee..126889f4 100644 --- a/Source/Server/Footsteps.c +++ b/Source/Server/Footsteps.c @@ -29,7 +29,7 @@ TODO: Read sound/materials.txt and use that somehow */ void Footsteps_Update( void ) { float fForce; - float dDelay; + float fDelay; vector vStep; string sStepSound = ""; @@ -42,7 +42,7 @@ void Footsteps_Update( void ) { vStep_y = fabs( self.velocity_y ); fForce = ( vStep_x + vStep_y ); - dDelay = clamp( 0.1, 1 / ( fForce / 90 ), 1 ); + fDelay = clamp( 0.1, 1 / ( fForce / 100 ), 1 ); traceline( self.origin + self.view_ofs, self.origin + '0 0 -48', FALSE, self ); @@ -85,6 +85,6 @@ void Footsteps_Update( void ) { } sound( self, CHAN_BODY, sStepSound, 0.5, ATTN_IDLE ); - self.fSteptime = time + dDelay; + self.fSteptime = time + fDelay; } } diff --git a/Source/Server/FuncLadder.c b/Source/Server/FuncLadder.c index 34f13861..ed9785d8 100644 --- a/Source/Server/FuncLadder.c +++ b/Source/Server/FuncLadder.c @@ -35,7 +35,7 @@ void func_ladder_sound( entity target ) { } float fForce = vStep; - float dDelay = ( clamp( 0.1, 1 / (fForce / 50), 1 ) ); + float fDelay = clamp( 0.1, 1 / ( fForce / 90 ), 1 ); float fRandom = random(); if ( fRandom <= 0.25 ) { @@ -48,7 +48,7 @@ void func_ladder_sound( entity target ) { sound( target, CHAN_BODY, "player/pl_ladder4.wav", 0.5, ATTN_IDLE ); } - target.fStepTime = ( time + dDelay ); + target.fStepTime = ( time + fDelay ); } /* diff --git a/Source/Server/Main.c b/Source/Server/Main.c index 93b00f46..c6060c5c 100644 --- a/Source/Server/Main.c +++ b/Source/Server/Main.c @@ -85,9 +85,6 @@ void worldspawn( void ) { precache_model( "models/player/vip/vip.mdl" ); precache_model( "models/w_c4.mdl" ); - EFFECT_GUNSHOT = particleeffectnum( "te_gunshot" ); - EFFECT_BLOOD = particleeffectnum( "te_blood" ); - precache_sound( "hostage/hos1.wav" ); precache_sound( "hostage/hos2.wav" ); precache_sound( "hostage/hos3.wav" ); diff --git a/Source/Server/Player.c b/Source/Server/Player.c index 128320c0..f8a9b3c6 100644 --- a/Source/Server/Player.c +++ b/Source/Server/Player.c @@ -69,20 +69,23 @@ void Player_Death( void ) { if ( self.team == TEAM_T ) { iAlivePlayers_T--; - - // If the bomb has been planted, T deaths don't matter anymore - if ( ( iAlivePlayers_T == 0 ) && ( iBombPlanted == FALSE ) ) { - Rules_RoundOver( TEAM_CT, 3600, FALSE ); - } } else if ( self.team == TEAM_CT ) { iAlivePlayers_CT--; - - if ( iAlivePlayers_CT == 0 ) { - Rules_RoundOver( TEAM_T, 3600, FALSE ); - } } else if ( self.team == TEAM_VIP ) { iAlivePlayers_CT--; // For consistency Rules_RoundOver( TEAM_T, 2500, FALSE ); + return; + } + + if ( ( iAlivePlayers_T == 0 ) && ( iAlivePlayers_CT == 0 ) && ( iBombPlanted == FALSE ) ) { + Rules_RoundOver( FALSE, 3600, FALSE ); + } else { + // If the bomb has been planted, T deaths don't matter anymore + if ( ( iAlivePlayers_T == 0 ) && ( iBombPlanted == FALSE ) ) { + Rules_RoundOver( TEAM_CT, 3600, FALSE ); + } else if ( iAlivePlayers_CT == 0 ) { + Rules_RoundOver( TEAM_T, 3600, FALSE ); + } } } diff --git a/Source/Server/TraceAttack.c b/Source/Server/TraceAttack.c index 8921f446..08cb0dfe 100644 --- a/Source/Server/TraceAttack.c +++ b/Source/Server/TraceAttack.c @@ -32,8 +32,33 @@ void TraceAttack_FireBullets( int iShots ) { if (trace_fraction != 1.0) { if ( trace_ent.takedamage == DAMAGE_YES ) { Damage_Apply( trace_ent, self, wptTable[ self.weapon ].iDamage, trace_endpos ); + } + + if ( trace_ent.iBleeds == TRUE ) { + Effect_Impact( IMPACT_FLESH, trace_endpos, trace_plane_normal ); } else { - pointparticles( EFFECT_GUNSHOT, trace_endpos, trace_plane_normal, 1 ); + string sTexture = getsurfacetexture( trace_ent, getsurfacenearpoint( trace_ent, trace_endpos ) ); + + switch( (float)hash_get( hashMaterials, sTexture ) ) { + case 'M': + case 'V': + case 'G': + case 'P': + Effect_Impact( IMPACT_METAL, trace_endpos, trace_plane_normal ); + break; + case 'D': + case 'W': + Effect_Impact( IMPACT_WOOD, trace_endpos, trace_plane_normal ); + break; + case 'Y': + Effect_Impact( IMPACT_GLASS, trace_endpos, trace_plane_normal ); + break; + case 'N': + case 'T': + default: + Effect_Impact( IMPACT_DEFAULT, trace_endpos, trace_plane_normal ); + break; + } } } iShots--; diff --git a/Source/Shared/BaseMelee.c b/Source/Shared/BaseMelee.c index 9029f017..91e47520 100644 --- a/Source/Shared/BaseMelee.c +++ b/Source/Shared/BaseMelee.c @@ -42,7 +42,11 @@ void BaseMelee_Attack( void ) { Damage_Apply( trace_ent, self, wptTable[ self.weapon ].iDamage, trace_endpos ); return; } else { - pointparticles( EFFECT_GUNSHOT, trace_endpos, trace_plane_normal, 1 ); + if ( trace_ent.iBleeds == TRUE ) { + Effect_Impact( IMPACT_FLESH, trace_endpos, trace_plane_normal ); + } else { + Effect_Impact( IMPACT_MELEE, trace_endpos, trace_plane_normal ); + } } } diff --git a/Source/Shared/Effects.c b/Source/Shared/Effects.c index 6521549c..e1fad85c 100644 --- a/Source/Shared/Effects.c +++ b/Source/Shared/Effects.c @@ -45,6 +45,64 @@ void Effect_AnimatedSprite( vector vPos, float fIndex, float fFPS, float fScale, } #endif +void Effect_Impact( int iType, vector vPos, vector vNormal ) { +#ifdef SSQC + WriteByte( MSG_MULTICAST, SVC_CGAMEPACKET ); + WriteByte( MSG_MULTICAST, EV_IMPACT ); + WriteByte( MSG_MULTICAST, (float)iType ); + WriteCoord( MSG_MULTICAST, vPos_x); + WriteCoord( MSG_MULTICAST, vPos_y); + WriteCoord( MSG_MULTICAST, vPos_z); + WriteCoord( MSG_MULTICAST, vNormal_x); + WriteCoord( MSG_MULTICAST, vNormal_y); + WriteCoord( MSG_MULTICAST, vNormal_z); + msg_entity = self; + multicast( vPos, MULTICAST_PVS ); +#else + + switch ( iType ) { + case IMPACT_MELEE: + pointparticles( PARTICLE_PIECES_BLACK, vPos, vNormal, 1 ); + pointsound( vPos, "weapons/knife_hitwall1.wav", 1, ATTN_STATIC ); + break; + case IMPACT_EXPLOSION: + break; + case IMPACT_GLASS: + pointparticles( PARTICLE_PIECES_BLACK, vPos, vNormal, 1 ); + break; + case IMPACT_WOOD: + pointparticles( PARTICLE_SPARK, vPos, vNormal, 1 ); + pointparticles( PARTICLE_PIECES_BLACK, vPos, vNormal, 1 ); + pointparticles( PARTICLE_SMOKE_BROWN, vPos, vNormal, 1 ); + break; + case IMPACT_METAL: + pointparticles( PARTICLE_SPARK, vPos, vNormal, 1 ); + pointparticles( PARTICLE_SPARK, vPos, vNormal, 1 ); + pointparticles( PARTICLE_PIECES_BLACK, vPos, vNormal, 1 ); + break; + case IMPACT_FLESH: + pointparticles( PARTICLE_BLOOD, vPos, vNormal, 1 ); + break; + case IMPACT_DEFAULT: + pointparticles( PARTICLE_SPARK, vPos, vNormal, 1 ); + pointparticles( PARTICLE_PIECES_BLACK, vPos, vNormal, 1 ); + pointparticles( PARTICLE_SMOKE_GREY, vPos, vNormal, 1 ); + break; + default: + } + + switch ( iType ) { + case IMPACT_METAL: + pointsound( vPos, sprintf( "weapons/ric_metal-%d.wav", floor( ( random() * 2 ) + 1 ) ), 1, ATTN_STATIC ); + break; + default: + pointsound( vPos, sprintf( "weapons/ric%d.wav", floor( ( random() * 5 ) + 1 ) ), 1, ATTN_STATIC ); + break; + } + +#endif +} + void Effect_BreakModel( vector vMins, vector vMaxs, vector vVel, float fStyle ) { #ifdef SSQC WriteByte( MSG_MULTICAST, SVC_CGAMEPACKET ); diff --git a/opencs/csprogs.dat b/opencs/csprogs.dat index 30c0786d..4cb26fda 100644 Binary files a/opencs/csprogs.dat and b/opencs/csprogs.dat differ diff --git a/opencs/particles/default.cfg b/opencs/particles/default.cfg index 398dc72a..126dd8ad 100644 --- a/opencs/particles/default.cfg +++ b/opencs/particles/default.cfg @@ -1,10 +1,10 @@ -r_part te_gunshot +r_part part_spark { type texturedspark texture ball tcoords 1 65 31 95 256 8 32 scale 1 - count 8 + count 4 scalefactor 1 alpha 0.5 die 0.8 @@ -18,24 +18,7 @@ r_part te_gunshot gravity 800 } -r_part +te_gunshot -{ - texture ball - tcoords 1 65 31 95 256 8 32 - count 3 - scale 25 - scalefactor 1 - die 1 - alpha 0.5 - rgb 10 10 10 - blend add - spawnmode ball - spawnorg 2 - spawnvel 20 - veladd 20 -} - -r_part +te_gunshot +r_part part_pieces_black { type ball texture ball @@ -54,7 +37,41 @@ r_part +te_gunshot gravity 800 } -r_part te_blood +r_part part_smoke_brown +{ + texture ball + tcoords 1 65 31 95 256 8 32 + count 3 + scale 25 + scalefactor 1 + die 1 + alpha 0.5 + rgb 155 90 0 + blend add + spawnmode ball + spawnorg 2 + spawnvel 20 + veladd 20 +} + +r_part part_smoke_grey +{ + texture ball + tcoords 1 65 31 95 256 8 32 + count 3 + scale 25 + scalefactor 1 + die 1 + alpha 0.5 + rgb 25 25 25 + blend add + spawnmode ball + spawnorg 2 + spawnvel 20 + veladd 20 +} + +r_part part_blood { type texturedspark texture ball diff --git a/opencs/progs.dat b/opencs/progs.dat index e7d31eab..d8e41731 100644 Binary files a/opencs/progs.dat and b/opencs/progs.dat differ