diff options
| -rw-r--r-- | assets/scripts/headshot.particle | 37 | ||||
| -rw-r--r-- | assets/scripts/marks/blood_mrk.shader | 21 | ||||
| -rw-r--r-- | assets/scripts/wound_bleed.particle | 79 | ||||
| -rw-r--r-- | assets/sound/edge/blood_splat.wav | bin | 0 -> 47886 bytes | |||
| -rw-r--r-- | src/cgame/cg_event.c | 57 | ||||
| -rw-r--r-- | src/cgame/cg_local.h | 7 | ||||
| -rw-r--r-- | src/cgame/cg_main.c | 8 | ||||
| -rw-r--r-- | src/cgame/cg_particles.c | 13 | ||||
| -rw-r--r-- | src/game/bg_misc.c | 1 | ||||
| -rw-r--r-- | src/game/bg_public.h | 3 | ||||
| -rw-r--r-- | src/game/g_active.c | 48 | ||||
| -rw-r--r-- | src/game/g_combat.c | 12 | ||||
| -rw-r--r-- | src/game/g_local.h | 2 | 
13 files changed, 281 insertions, 7 deletions
diff --git a/assets/scripts/headshot.particle b/assets/scripts/headshot.particle new file mode 100644 index 0000000..42c7295 --- /dev/null +++ b/assets/scripts/headshot.particle @@ -0,0 +1,37 @@ +headShotPS +{ +  ejector +  { +    particle +    { +      shader sync gfx/sprites/blood + +      displacement 0 0 20 ~2 +      parentVelocityFraction 1.0 + +      velocityType      static_transform +      velocityDir       linear +      velocityMagnitude 150~75% +      velocity          -1 0 1 ~60 + +      accelerationType      static +      accelerationDir       linear +      accelerationMagnitude 800 +      acceleration          0 0 -1 ~30 + +      radius 0 4.0 10.0 +      alpha  0 1.0 0.0 +      rotation 0 ~360 - +      //bounce 0.2 +      bounce cull +      bounceMark 1~1 10 gfx/marks/blood_mrk +      bounceSound ~0.7 sound/edge/blood_splat.wav + +      lifeTime 1000~100% +    } + +    count 50 +    delay 0 +    period 10 - ~0% +  } +} diff --git a/assets/scripts/marks/blood_mrk.shader b/assets/scripts/marks/blood_mrk.shader new file mode 100644 index 0000000..e1dc7b9 --- /dev/null +++ b/assets/scripts/marks/blood_mrk.shader @@ -0,0 +1,21 @@ +gfx/marks/blood_mrk +{ +  polygonOffset +  { +    map gfx/marks/blood_mrk.tga +    blendFunc blend +    rgbGen identityLighting +    alphaGen vertex +  } +} + +gfx/marks/ablood_mrk +{ +  polygonOffset +  { +    map gfx/sprites/green_acid.tga // TODO +    blendFunc blend +    rgbGen identityLighting +    alphaGen vertex +  } +} diff --git a/assets/scripts/wound_bleed.particle b/assets/scripts/wound_bleed.particle new file mode 100644 index 0000000..53d1f15 --- /dev/null +++ b/assets/scripts/wound_bleed.particle @@ -0,0 +1,79 @@ +humanWoundBleedPS +{ +  ejector +  { +    particle +    { +      shader sync gfx/sprites/blood + +      displacement 0 0 0 ~2 +      parentVelocityFraction 1.0 + +      velocityType      static_transform +      velocityDir       linear +      velocityMagnitude 50~100% +      velocity          -0.5 0 -1 ~30 + +      accelerationType      static +      accelerationDir       linear +      accelerationMagnitude 800 +      acceleration          0 0 -1 ~30 + +      radius 0 4.0 10.0 +      alpha  0 1.0 0.0 +      rotation 0 ~360 - +      //bounce 0.2 +      bounce cull +      bounceMark 1~1 10 gfx/marks/blood_mrk +      //bounceSound ~1 sound/edge/blood_splat.wav + +      overdrawProtection + +      lifeTime 5000~50% +    } + +    count 3 +    delay 0 +    period 1000 - ~100% +  } +} + +alienWoundBleedPS +{ +  ejector +  { +    particle +    { +      shader sync gfx/sprites/green_acid // TODO? + +      displacement 0 0 0 ~2 +      parentVelocityFraction 1.0 + +      velocityType      static_transform +      velocityDir       linear +      velocityMagnitude 50~100% +      velocity          -0.5 0 -1 ~30 + +      accelerationType      static +      accelerationDir       linear +      accelerationMagnitude 800 +      acceleration          0 0 -1 ~30 + +      radius 0 4.0 10.0 +      alpha  0 1.0 0.0 +      rotation 0 ~360 - +      //bounce 0.2 +      bounce cull +      bounceMark 1~1 10 gfx/marks/ablood_mrk +      //bounceSound ~1 sound/edge/blood_splat.wav // TODO? + +      overdrawProtection + +      lifeTime 5000~50% +    } + +    count 3 +    delay 0 +    period 1000 - ~100% +  } +} diff --git a/assets/sound/edge/blood_splat.wav b/assets/sound/edge/blood_splat.wav Binary files differnew file mode 100644 index 0000000..16d255e --- /dev/null +++ b/assets/sound/edge/blood_splat.wav diff --git a/src/cgame/cg_event.c b/src/cgame/cg_event.c index aa84609..49dec3f 100644 --- a/src/cgame/cg_event.c +++ b/src/cgame/cg_event.c @@ -532,6 +532,30 @@ void CG_PainEvent( centity_t *cent, int health )  }  /* +================ +CG_HeadShotEvent + +Also called by playerstate transition +================ +*/ +void CG_HeadShotEvent( centity_t *cent, int health ) +{ +  particleSystem_t *ps; + +  if( !cg_bleedSelfHeadShots.integer && +      cent->currentState.number == cg.snap->ps.clientNum ) +    return; + +  ps = CG_SpawnNewParticleSystem( cgs.media.headShotPS ); +  if( CG_IsParticleSystemValid( &ps ) ) +  { +    CG_SetAttachmentCent( &ps->attachment, cent ); +    CG_AttachToCent( &ps->attachment ); +  } +  //trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.humanGibSound ); +} + +/*  =========================  CG_Level2Zap  ========================= @@ -1074,10 +1098,15 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )        break;      case EV_PAIN: -      // local player sounds are triggered in CG_CheckLocalSounds, -      // so ignore events on the player -      if( cent->currentState.number != cg.snap->ps.clientNum ) -        CG_PainEvent( cent, es->eventParm ); +      { +        const int health = es->eventParm & ~EVENT_HEADSHOT_BIT; +        // local player sounds are triggered in CG_CheckLocalSounds, +        // so ignore events on the player +        if( cent->currentState.number != cg.snap->ps.clientNum ) +          CG_PainEvent( cent, health ); +        if( es->eventParm & EVENT_HEADSHOT_BIT ) +          CG_HeadShotEvent( cent, health ); +      }        break;      case EV_DEATH1: @@ -1085,6 +1114,8 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )      case EV_DEATH3:        trap_S_StartSound( NULL, es->number, CHAN_VOICE,            CG_CustomSound( es->number, va( "*death%i.wav", event - EV_DEATH1 + 1 ) ) ); +      if( es->eventParm & EVENT_HEADSHOT_BIT ) +        CG_HeadShotEvent( cent, 0 );        break;      case EV_OBITUARY: @@ -1095,6 +1126,24 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )        // no gibbing        break; +    case EV_BLEED: +      if( cg_bleedSelfWounds.integer || +          cent->currentState.number != cg.snap->ps.clientNum ) +      { +        particleSystem_t *ps = NULL; +        if( ci->team == TEAM_ALIENS ) +          ps = CG_SpawnNewParticleSystem( cgs.media.alienWoundsBleedPS ); +        else if( ci->team == TEAM_HUMANS ) +          ps = CG_SpawnNewParticleSystem( cgs.media.humanWoundsBleedPS ); + +        if( ( ps != NULL ) && CG_IsParticleSystemValid( &ps ) ) +        { +          CG_SetAttachmentCent( &ps->attachment, cent ); +          CG_AttachToCent( &ps->attachment ); +        } +      } +      break; +      case EV_STOPLOOPINGSOUND:        trap_S_StopLoopingSound( es->number );        es->loopSound = 0; diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h index 1498af9..a477336 100644 --- a/src/cgame/cg_local.h +++ b/src/cgame/cg_local.h @@ -1331,6 +1331,11 @@ typedef struct    qhandle_t   healthCross3X;    qhandle_t   healthCrossMedkit;    qhandle_t   healthCrossPoisoned; + +  sfxHandle_t humanGibSound; +  qhandle_t   headShotPS; +  qhandle_t   humanWoundsBleedPS; +  qhandle_t   alienWoundsBleedPS;  } cgMedia_t;  typedef struct @@ -1540,6 +1545,8 @@ extern  vmCvar_t    cg_disableBuildDialogs;  extern  vmCvar_t    cg_disableCommandDialogs;  extern  vmCvar_t    cg_disableScannerPlane;  extern  vmCvar_t    cg_tutorial; +extern  vmCvar_t    cg_bleedSelfWounds; +extern  vmCvar_t    cg_bleedSelfHeadShots;  extern  vmCvar_t    cg_painBlendUpRate;  extern  vmCvar_t    cg_painBlendDownRate; diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c index 1bd5c7f..c7b470c 100644 --- a/src/cgame/cg_main.c +++ b/src/cgame/cg_main.c @@ -190,6 +190,8 @@ vmCvar_t  cg_disableBuildDialogs;  vmCvar_t  cg_disableCommandDialogs;  vmCvar_t  cg_disableScannerPlane;  vmCvar_t  cg_tutorial; +vmCvar_t  cg_bleedSelfWounds; +vmCvar_t  cg_bleedSelfHeadShots;  vmCvar_t  cg_painBlendUpRate;  vmCvar_t  cg_painBlendDownRate; @@ -317,6 +319,8 @@ static cvarTable_t cvarTable[ ] =    { &cg_disableCommandDialogs, "cg_disableCommandDialogs", "0", CVAR_ARCHIVE },    { &cg_disableScannerPlane, "cg_disableScannerPlane", "0", CVAR_ARCHIVE },    { &cg_tutorial, "cg_tutorial", "1", CVAR_ARCHIVE }, +  { &cg_bleedSelfWounds, "cg_bleedSelfWounds", "1", CVAR_ARCHIVE }, +  { &cg_bleedSelfHeadShots, "cg_bleedSelfHeadShots", "1", CVAR_ARCHIVE },    { &cg_hudFiles, "cg_hudFiles", "ui/hud.txt", CVAR_ARCHIVE},    { &cg_hudFilesEnable, "cg_hudFilesEnable", "0", CVAR_ARCHIVE},    { NULL, "cg_alienConfig", "", CVAR_ARCHIVE }, @@ -858,6 +862,10 @@ static void CG_RegisterGraphics( void )    cgs.media.alienSpiteful_AbcessDestroyedPS = CG_RegisterParticleSystem( "alienSpiteful_AbcessDestroyedPS" ); +  cgs.media.alienWoundsBleedPS        = CG_RegisterParticleSystem( "alienWoundBleedPS" ); +  cgs.media.humanWoundsBleedPS        = CG_RegisterParticleSystem( "humanWoundBleedPS" ); +  cgs.media.headShotPS                = CG_RegisterParticleSystem( "headShotPS" ); +    CG_BuildableStatusParse( "ui/assets/human/buildstat.cfg", &cgs.humanBuildStat );    CG_BuildableStatusParse( "ui/assets/alien/buildstat.cfg", &cgs.alienBuildStat ); diff --git a/src/cgame/cg_particles.c b/src/cgame/cg_particles.c index c2374c7..b718600 100644 --- a/src/cgame/cg_particles.c +++ b/src/cgame/cg_particles.c @@ -2156,6 +2156,19 @@ static void CG_EvaluateParticlePhysics( particle_t *p )      return;    } +  if( bp->bounceMarkName[ 0 ] && p->bounceMarkCount > 0 ) +  { +    CG_ImpactMark( bp->bounceMark, trace.endpos, trace.plane.normal, +        random( ) * 360, 1, 1, 1, 1, qtrue, bp->bounceMarkRadius, qfalse ); +    p->bounceMarkCount--; +  } + +  if( bp->bounceSoundName[ 0 ] && p->bounceSoundCount > 0 ) +  { +    trap_S_StartSound( trace.endpos, ENTITYNUM_WORLD, CHAN_AUTO, bp->bounceSound ); +    p->bounceSoundCount--; +  } +    //remove particles that get into a CONTENTS_NODROP brush    if( ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) ||        ( bp->cullOnStartSolid && trace.startsolid ) ) diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c index 71f5507..1597194 100644 --- a/src/game/bg_misc.c +++ b/src/game/bg_misc.c @@ -4315,6 +4315,7 @@ char *eventnames[ ] =    "EV_DEATH3",    "EV_OBITUARY",    "EV_GIB_PLAYER",      // gib a previously living player +  "EV_BLEED",    "EV_BUILD_CONSTRUCT",    "EV_BUILD_DESTROY",    "EV_BUILD_DELAY",     // can't build yet diff --git a/src/game/bg_public.h b/src/game/bg_public.h index 9109a35..886d29b 100644 --- a/src/game/bg_public.h +++ b/src/game/bg_public.h @@ -478,6 +478,8 @@ typedef enum  #define EVENT_VALID_MSEC  300 +#define EVENT_HEADSHOT_BIT 0x80 +  const char *BG_EventName( int num );  typedef enum @@ -538,6 +540,7 @@ typedef enum    EV_DEATH3,    EV_OBITUARY,    EV_GIB_PLAYER,      // gib a previously living player +  EV_BLEED,    EV_BUILD_CONSTRUCT,    EV_BUILD_DESTROY,    EV_BUILD_DELAY,     // can't build yet diff --git a/src/game/g_active.c b/src/game/g_active.c index 2f7f906..3c888a6 100644 --- a/src/game/g_active.c +++ b/src/game/g_active.c @@ -76,8 +76,14 @@ void P_DamageFeedback( gentity_t *player )    // play an apropriate pain sound    if( ( level.time > player->pain_debounce_time ) && !( player->flags & FL_GODMODE ) )    { +    int param;      player->pain_debounce_time = level.time + 700; -    G_AddEvent( player, EV_PAIN, player->health > 255 ? 255 : player->health ); +    param = player->health; +    if( param >= EVENT_HEADSHOT_BIT ) +      param = EVENT_HEADSHOT_BIT - 1; +    if( client->damage_headshot ) +      param |= EVENT_HEADSHOT_BIT; +    G_AddEvent( player, EV_PAIN, param );      client->ps.damageEvent++;    } @@ -90,11 +96,48 @@ void P_DamageFeedback( gentity_t *player )    client->damage_blood = 0;    client->damage_armor = 0;    client->damage_knockback = 0; +  client->damage_headshot = 0;  }  /* +=============== +P_WoundsBleed + +=============== +*/ +void P_WoundsBleed( gentity_t *player ) +{ +  gclient_t *client; +  int       maxHealth; +  int       health; + +  if( player->nextBleedTime > level.time ) +    return; + +  client = player->client; +  health = player->health; +  maxHealth = client->ps.stats[ STAT_MAX_HEALTH ]; +  if( maxHealth > 100 ) +    maxHealth = 100; +  maxHealth = maxHealth * 3 / 4; +  if( ( health > maxHealth ) || ( health < 0 ) ) { +    player->nextBleedTime = level.time + 2000; +    return; +  } + +  G_AddEvent( player, EV_BLEED, ( health > 255 ) ? 255 : health ); + +  if( health < 20 ) +    health = 20; +  player->nextBleedTime = level.time + 2000 * health / maxHealth; +} + + + + +/*  =============  P_WorldEffects @@ -2292,6 +2335,9 @@ void ClientEndFrame( gentity_t *ent )    // burn from lava, etc    P_WorldEffects( ent ); +  // bleeding wounds +  P_WoundsBleed( ent ); +    // apply all the damage taken this frame    P_DamageFeedback( ent ); diff --git a/src/game/g_combat.c b/src/game/g_combat.c index c79594d..073c00c 100644 --- a/src/game/g_combat.c +++ b/src/game/g_combat.c @@ -687,8 +687,12 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int      }      // use own entityid if killed by non-client to prevent uint8_t overflow -    G_AddEvent( self, EV_DEATH1 + i, -      ( killer < MAX_CLIENTS ) ? killer : self - g_entities ); +    { +      int param = ( killer < MAX_CLIENTS ) ? killer : self - g_entities; +      if( self->client->damage_headshot ) +        param |= EVENT_HEADSHOT_BIT; +      G_AddEvent( self, EV_DEATH1 + i, param ); +    }      // globally cycle through the different death animations      i = ( i + 1 ) % 3; @@ -1069,6 +1073,10 @@ static float G_CalcDamageModifier( vec3_t point, gentity_t *targ, gentity_t *att                                       g_numDamageRegions[ class ],                                       hitRotation, hitRatio ); +  // For headshots done by an enemy, make a client event +  if( ( modifier >= 1.2f ) && !OnSameTeam( targ, attacker ) ) +    targ->client->damage_headshot ++; +    for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )    {      if( BG_InventoryContainsUpgrade( i, targ->client->ps.stats ) ) diff --git a/src/game/g_local.h b/src/game/g_local.h index 7052fe4..4f03aad 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -245,6 +245,7 @@ struct gentity_s    int               lastDamageTime;    int               nextRegenTime; +  int               nextBleedTime;    qboolean          ownerClear;                     // used for missle tracking @@ -399,6 +400,7 @@ struct gclient_s    int                 damage_knockback; // impact damage    vec3_t              damage_from;      // origin for vector calculation    qboolean            damage_fromWorld; // if true, don't use the damage_from vector +  int                 damage_headshot;  // the number of head-shots taken in a frame    //    int                 lastkilled_client;// last client that this client killed  | 
