diff options
| author | Paweł Redman <pawel.redman@gmail.com> | 2020-03-29 19:59:19 +0200 | 
|---|---|---|
| committer | Paweł Redman <pawel.redman@gmail.com> | 2020-03-29 20:09:17 +0200 | 
| commit | d9e9bb2d95483cbf2ca5d6cf5ac7b9f490d40204 (patch) | |
| tree | c71483e197da36ebf8b11fec3e05df5608c7dc78 | |
| parent | 36ebcd1cc0933ee0bfe9f6ac15879286d3199046 (diff) | |
Implement coronavirus
| -rw-r--r-- | sound/player/cough0.wav | bin | 0 -> 66692 bytes | |||
| -rw-r--r-- | sound/player/cough1.wav | bin | 0 -> 71250 bytes | |||
| -rw-r--r-- | sound/player/cough2.wav | bin | 0 -> 35824 bytes | |||
| -rw-r--r-- | sound/player/cough3.wav | bin | 0 -> 55062 bytes | |||
| -rw-r--r-- | sound/player/cough4.wav | bin | 0 -> 41476 bytes | |||
| -rw-r--r-- | src/cgame/cg_event.c | 8 | ||||
| -rw-r--r-- | src/cgame/cg_local.h | 3 | ||||
| -rw-r--r-- | src/cgame/cg_main.c | 3 | ||||
| -rw-r--r-- | src/game/bg_public.h | 8 | ||||
| -rw-r--r-- | src/game/g_active.c | 156 | ||||
| -rw-r--r-- | src/game/g_client.c | 10 | ||||
| -rw-r--r-- | src/game/g_combat.c | 5 | ||||
| -rw-r--r-- | src/game/g_local.h | 14 | 
13 files changed, 203 insertions, 4 deletions
diff --git a/sound/player/cough0.wav b/sound/player/cough0.wav Binary files differnew file mode 100644 index 0000000..0150d90 --- /dev/null +++ b/sound/player/cough0.wav diff --git a/sound/player/cough1.wav b/sound/player/cough1.wav Binary files differnew file mode 100644 index 0000000..dc2e2ba --- /dev/null +++ b/sound/player/cough1.wav diff --git a/sound/player/cough2.wav b/sound/player/cough2.wav Binary files differnew file mode 100644 index 0000000..4578b47 --- /dev/null +++ b/sound/player/cough2.wav diff --git a/sound/player/cough3.wav b/sound/player/cough3.wav Binary files differnew file mode 100644 index 0000000..d767fb7 --- /dev/null +++ b/sound/player/cough3.wav diff --git a/sound/player/cough4.wav b/sound/player/cough4.wav Binary files differnew file mode 100644 index 0000000..803aabc --- /dev/null +++ b/sound/player/cough4.wav diff --git a/src/cgame/cg_event.c b/src/cgame/cg_event.c index 07bcea9..c06a05c 100644 --- a/src/cgame/cg_event.c +++ b/src/cgame/cg_event.c @@ -132,6 +132,9 @@ static void CG_Obituary( entityState_t *ent )      case MOD_SWARM:        message = "was hunted down by the swarm";        break; +    case MOD_CORONAVIRUS: +      message = "died of viral lung infection"; +      break;      default:        message = NULL;        break; @@ -658,6 +661,11 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )        trap_S_StartSound( NULL, es->number, CHAN_AUTO, CG_CustomSound( es->number, "*gasp.wav" ) );        break; +    case EV_COUGH: +      DEBUGNAME( "EV_COUGH" ); +      trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.coughingSounds[ rand ( ) % NUM_COUGHING_SOUNDS ] ); +      break; +      //      // weapon events      // diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h index 83c3162..f35c438 100644 --- a/src/cgame/cg_local.h +++ b/src/cgame/cg_local.h @@ -1142,6 +1142,7 @@ typedef struct    int           ping;  } cg_t; +#define NUM_COUGHING_SOUNDS 5  // all of the model, shader, and sound references that are  // loaded at gamestate time are stored in cgMedia_t @@ -1273,6 +1274,8 @@ typedef struct    qhandle_t   buildWeaponTimerPie[ 8 ];    qhandle_t   upgradeClassIconShader; + +  sfxHandle_t coughingSounds[ NUM_COUGHING_SOUNDS ];  } cgMedia_t;  typedef struct diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c index c2e55b8..45e2506 100644 --- a/src/cgame/cg_main.c +++ b/src/cgame/cg_main.c @@ -953,6 +953,9 @@ static void CG_RegisterSounds( void )    cgs.media.buildableRepairedSound  = trap_S_RegisterSound( "sound/buildables/human/repaired.wav", qfalse );    cgs.media.lCannonWarningSound     = trap_S_RegisterSound( "models/weapons/lcannon/warning.wav", qfalse ); + +  for( i = 0; i < NUM_COUGHING_SOUNDS; i++ ) +    cgs.media.coughingSounds[ i ] = trap_S_RegisterSound( va( "sound/player/cough%d.wav", i ), qfalse );  } diff --git a/src/game/bg_public.h b/src/game/bg_public.h index 69967a1..b04b681 100644 --- a/src/game/bg_public.h +++ b/src/game/bg_public.h @@ -579,7 +579,9 @@ typedef enum    EV_DCC_ATTACK,      //TA: dcc under attack -  EV_RPTUSE_SOUND     //TA: trigger a sound +  EV_RPTUSE_SOUND,     //TA: trigger a sound + +  EV_COUGH  } entity_event_t;  typedef enum @@ -894,7 +896,9 @@ typedef enum    MOD_ASPAWN,    MOD_ATUBE,    MOD_OVERMIND, -  MOD_SLAP +  MOD_SLAP, + +  MOD_CORONAVIRUS  } meansOfDeath_t; diff --git a/src/game/g_active.c b/src/game/g_active.c index 1a67020..4059259 100644 --- a/src/game/g_active.c +++ b/src/game/g_active.c @@ -73,7 +73,8 @@ void P_DamageFeedback( gentity_t *player )    if( ( level.time > player->pain_debounce_time ) && !( player->flags & FL_GODMODE ) )    {      player->pain_debounce_time = level.time + 700; -    G_AddEvent( player, EV_PAIN, player->health > 255 ? 255 : player->health ); +    if( player->lastDamageMOD != MOD_CORONAVIRUS ) +      G_AddEvent( player, EV_PAIN, player->health > 255 ? 255 : player->health );      client->ps.damageEvent++;    } @@ -563,6 +564,157 @@ qboolean ClientInactivityTimer( gclient_t *client )  /*  ================== +G_ContractCoronavirus + +Called once per player when contracting the virus. +There's a chance this is called at spawn. +================== +*/ + +void G_ContractCoronavirus( gentity_t *ent ) +{ +  float rng; + +  rng = random( ); + +  if ( rng < 0.3f ) +    ent->client->covidKind = COVID_ASYMPTOMATIC; +  else if ( rng < 0.5f ) // 20% chance +    ent->client->covidKind = COVID_SEVERE; +  else +    ent->client->covidKind = COVID_MODERATE; + +  trap_SendServerCommand( (int)( ent - g_entities ), +    va("print \"^1COVID: ^7You contracted COVID of kind ^1%d^7.\n\"", ent->client->covidKind ) ); +} + + +/* +================== +G_Coronavirus + +Runs every second, spreads the disease and causes symptoms. +================== +*/ + +#define COVID_RANGE 300.0f +#define COVID_INCUBATION_PERIOD 60.0f +#define COVID_AVERAGE_LENGTH    240.0f + +void G_Coronavirus( gentity_t *ent ) +{ +  int       entityList[ MAX_GENTITIES ]; +  vec3_t    range = { COVID_RANGE, COVID_RANGE, COVID_RANGE }; +  vec3_t    mins, maxs; +  int       i, num; +  gclient_t *client = ent->client; + +  if( client->covidKind == COVID_NONE +      || client->covidKind == COVID_RECOVERED ) +    return; + +  VectorAdd( client->ps.origin, range, maxs ); +  VectorSubtract( client->ps.origin, range, mins ); + +  // Infect nearby players + +  num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES ); +  for( i = 0; i < num; i++ ) +  { +    gentity_t *target; +    trace_t   tr; +    float     chance = 0.001f; // to spread the disease +    float     distance; + +    target = g_entities + entityList[ i ]; + +    if( !target->client || target->health < 0 ) +      continue; + +    if( target->client->covidKind != COVID_NONE ) +      continue; + +    trap_Trace( &tr, ent->s.origin, NULL, NULL, target->s.origin, target->s.number, MASK_SHOT ); +    if( tr.entityNum == ENTITYNUM_WORLD ) +        continue; + +    if( client->pers.teamSelection == target->client->pers.teamSelection ) +      chance *= 10.0f; + +    if( BG_InventoryContainsUpgrade( UP_HELMET, target->client->ps.stats ) ) +      chance /= 2.0f; + +    if( BG_InventoryContainsUpgrade( UP_BATTLESUIT, target->client->ps.stats ) ) +      chance /= 8.0f;     + +    distance = Distance(ent->s.origin, target->s.origin); + +    if( distance < COVID_RANGE / 10.0f ) +      chance *= 100.0f; +    else if( distance < COVID_RANGE / 5.0f ) +      chance *= 20.0f; +    else if( distance < COVID_RANGE / 3.0f ) +      chance *= 5.0f; +    else if( distance < COVID_RANGE / 2.0f ) +      chance *= 2.0f; + +    trap_SendServerCommand( (int)( ent - g_entities ), va( "print \"^1COVID:^7 Chance to infect %s^7 is ^1%f^7\n\"", +      target->client->pers.netname, chance ) ); + +    if( random( ) < chance ) +    { +      trap_SendServerCommand( (int)( ent - g_entities ), va( "print \"^1COVID:^7 You spread the virus.\n\"" ) ); +      G_ContractCoronavirus( target ); +    } +  } + +  // Progression of the disease + +  client->covidProgress += 2.0f * random( ) / COVID_AVERAGE_LENGTH; +  if( client->covidProgress > COVID_INCUBATION_PERIOD / COVID_AVERAGE_LENGTH ) +  { +    float factor; + +    factor = 1 - 2 * COVID_INCUBATION_PERIOD / COVID_AVERAGE_LENGTH / 3 - client->covidProgress; +    client->covidSeverity += 0.4f * factor * client->covidSeverity + 0.01f * factor; +  } + +  if( client->covidKind == COVID_ASYMPTOMATIC ) +    client->covidSeverity *= 0.8f; +  else if( client->covidKind == COVID_MODERATE ) +    client->covidSeverity *= 0.91f; +  else +    client->covidSeverity *= 0.935f; + +  if( client->covidProgress > 0.75f && client->covidSeverity < 0.01f ) +  { +    client->covidKind = COVID_RECOVERED; +    return; +  } + +  // Symptoms + +  if( random( ) < client->covidSeverity / 4.0f ) +  { +    G_AddEvent( ent, EV_COUGH, 0 ); +  } +    +  client->covidDamage += client->covidSeverity; +  if( client->covidDamage > 1.0f ) +  { +    int damage; + +    damage = floor( client->covidDamage ); +    client->covidDamage -= damage; +    G_Damage( ent, NULL, NULL, NULL, NULL, damage, DAMAGE_NO_PROTECTION, MOD_CORONAVIRUS ); +  } + +  trap_SendServerCommand( (int)( ent - g_entities ), va( "print \"^1COVID^7: Kind=^1%d^7, progress=^1%f^7, severity=^1%f^7.\n\"", +    client->covidKind, client->covidProgress, client->covidSeverity) ); +} + +/* +==================  ClientTimerActions  Actions that happen once a second @@ -970,6 +1122,8 @@ void ClientTimerActions( gentity_t *ent, int msec )      if ( client->man_bad > 0 )        client->man_bad--; + +    G_Coronavirus( ent );    }    while( client->time10000 >= 10000 ) diff --git a/src/game/g_client.c b/src/game/g_client.c index d204831..9f6710c 100644 --- a/src/game/g_client.c +++ b/src/game/g_client.c @@ -1907,6 +1907,16 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles    ent->client->ps.stats[ STAT_STATE ] = 0;    VectorSet( ent->client->ps.grapplePoint, 0.0f, 0.0f, 1.0f ); +  client->covidKind = COVID_NONE; +  client->covidProgress = 0.0f; +  client->covidSeverity = 0.0f; +  client->covidDamage = 0.0f; +   +  // 1 in 10 chance they spawn sick  +  //if( rand( ) % 10 == 0 ) +  if( client->pers.classSelection != PCL_NONE ) +    G_ContractCoronavirus( ent ); +    // health will count down towards max_health    ent->health = client->ps.stats[ STAT_HEALTH ] = client->ps.stats[ STAT_MAX_HEALTH ]; //* 1.25; diff --git a/src/game/g_combat.c b/src/game/g_combat.c index 4d5d3d3..4df883c 100644 --- a/src/game/g_combat.c +++ b/src/game/g_combat.c @@ -118,7 +118,9 @@ char *modNames[ ] =    "MOD_ASPAWN",    "MOD_ATUBE",    "MOD_OVERMIND", -  "MOD_SLAP" +  "MOD_SLAP", + +  "MOD_CORONAVIRUS"  };  /* @@ -1488,6 +1490,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,        targ->client->ps.stats[ STAT_HEALTH ] = targ->health;      targ->lastDamageTime = level.time; +    targ->lastDamageMOD = mod;      //TA: add to the attackers "account" on the target      if( targ->client && attacker->client ) diff --git a/src/game/g_local.h b/src/game/g_local.h index 1720c4c..a088551 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -256,6 +256,7 @@ struct gentity_s    int               suicideTime;                    // when the client will suicide    int               lastDamageTime; +  int               lastDamageMOD;    int               bdnumb;     // buildlog entry ID @@ -469,6 +470,14 @@ typedef struct {  	float rangeBoost;  } adminRangeBoosts_t; +enum { +	COVID_NONE, +	COVID_ASYMPTOMATIC, +	COVID_MODERATE, +	COVID_SEVERE, +	COVID_RECOVERED +}; +  // this structure is cleared on each ClientSpawn(),  // except for 'client->pers' and 'client->sess'  struct gclient_s @@ -571,6 +580,10 @@ struct gclient_s    adminRangeBoosts_t newRange;    int                 man_bad; +  int                 covidKind; +  float               covidProgress; +  float               covidSeverity; +  float               covidDamage;  }; @@ -1172,6 +1185,7 @@ void G_UnlaggedClear( gentity_t *ent );  void G_UnlaggedCalc( int time, gentity_t *skipEnt );  void G_UnlaggedOn( gentity_t *attacker, vec3_t muzzle, float range );  void G_UnlaggedOff( void ); +void G_ContractCoronavirus( gentity_t *ent );  void ClientThink( int clientNum );  void ClientEndFrame( gentity_t *ent );  void G_RunClient( gentity_t *ent );  | 
