2023-04-30 14:15:14 +02:00
|
|
|
/*
|
|
|
|
===========================================================================
|
2024-06-09 20:16:14 +02:00
|
|
|
Copyright (C) 2024 the OpenMoHAA team
|
2023-04-30 14:15:14 +02:00
|
|
|
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
|
|
|
|
OpenMoHAA source code 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.
|
|
|
|
|
|
|
|
OpenMoHAA source code 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 OpenMoHAA source code; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
===========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
// DESCRIPTION:
|
|
|
|
// CGM buffer parser
|
2023-05-01 00:08:43 +02:00
|
|
|
|
|
|
|
#include "cg_local.h"
|
|
|
|
#include "cg_parsemsg.h"
|
2023-05-04 20:30:52 +02:00
|
|
|
#include "cg_specialfx.h"
|
2024-09-10 19:45:56 +02:00
|
|
|
#include "cg_radar.h"
|
2023-05-04 20:30:52 +02:00
|
|
|
|
|
|
|
#include "str.h"
|
|
|
|
|
|
|
|
extern int current_entity_number;
|
|
|
|
|
|
|
|
typedef struct {
|
2023-07-05 21:24:23 +02:00
|
|
|
vec3_t i_vBarrel;
|
|
|
|
vec3_t i_vStart;
|
|
|
|
vec3_t *i_vEnd;
|
|
|
|
int i_iNumBullets;
|
2023-05-04 20:30:52 +02:00
|
|
|
qboolean iLarge;
|
2023-11-15 21:02:34 +01:00
|
|
|
float alpha;
|
2023-07-05 21:24:23 +02:00
|
|
|
int iTracerVisible;
|
2023-05-04 20:30:52 +02:00
|
|
|
qboolean bIgnoreEntities;
|
|
|
|
} bullet_tracer_t;
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
#define MAX_BULLET_TRACERS 32
|
2023-05-04 21:07:44 +02:00
|
|
|
#define MAX_BULLET_TRACE_BULLETS 1024
|
2023-07-05 21:24:23 +02:00
|
|
|
#define MAX_IMPACTS 64
|
2023-07-10 21:11:01 +02:00
|
|
|
static constexpr unsigned int BULLET_TRAVEL_DIST = 9216;
|
2023-05-04 20:30:52 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
static int bullet_tracers_count;
|
|
|
|
static int bullet_tracer_bullets_count;
|
|
|
|
static int wall_impact_count;
|
|
|
|
static int flesh_impact_count;
|
2023-05-04 21:07:44 +02:00
|
|
|
static bullet_tracer_t bullet_tracers[MAX_BULLET_TRACERS];
|
2023-07-05 21:24:23 +02:00
|
|
|
static vec3_t bullet_tracer_bullets[MAX_BULLET_TRACE_BULLETS];
|
|
|
|
static vec3_t wall_impact_pos[MAX_IMPACTS];
|
|
|
|
static vec3_t wall_impact_norm[MAX_IMPACTS];
|
|
|
|
static int wall_impact_large[MAX_IMPACTS];
|
|
|
|
static int wall_impact_type[MAX_IMPACTS];
|
|
|
|
static vec3_t flesh_impact_pos[MAX_IMPACTS];
|
|
|
|
static vec3_t flesh_impact_norm[MAX_IMPACTS];
|
|
|
|
static int flesh_impact_large[MAX_IMPACTS];
|
|
|
|
|
2023-11-15 21:02:34 +01:00
|
|
|
void CG_MakeBulletHoleSound(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, trace_t *pPreTrace)
|
|
|
|
{
|
|
|
|
int iSurfType;
|
|
|
|
float fVolume;
|
|
|
|
str sSoundName;
|
|
|
|
vec3_t vFrom, vDest;
|
2023-07-10 23:58:05 +02:00
|
|
|
trace_t trace;
|
|
|
|
|
|
|
|
if (pPreTrace) {
|
|
|
|
trace = *pPreTrace;
|
2023-11-15 21:02:34 +01:00
|
|
|
} else {
|
2023-07-10 23:58:05 +02:00
|
|
|
VectorMA(i_vPos, 2.0f, i_vNorm, vFrom);
|
|
|
|
VectorMA(i_vPos, -4.0f, i_vNorm, vDest);
|
2023-11-15 21:02:34 +01:00
|
|
|
CG_Trace(
|
|
|
|
&trace, vFrom, vec_zero, vec_zero, vDest, ENTITYNUM_NONE, MASK_SHOT, qfalse, qtrue, "CG_MakeBulletHole"
|
|
|
|
);
|
2023-07-10 23:58:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
iSurfType = trace.surfaceFlags & MASK_SURF_TYPE;
|
|
|
|
if (trace.contents & CONTENTS_WATER) {
|
|
|
|
iSurfType = SURF_PUDDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (trace.fraction == 1.0f || trace.startsolid || (trace.surfaceFlags & SURF_SKY)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VectorAdd(trace.endpos, trace.plane.normal, vFrom);
|
|
|
|
sSoundName = "snd_bh_";
|
|
|
|
|
|
|
|
switch (iSurfType) {
|
|
|
|
case SURF_FOLIAGE:
|
|
|
|
sSoundName += "foliage";
|
|
|
|
break;
|
|
|
|
case SURF_SNOW:
|
|
|
|
sSoundName += "snow";
|
|
|
|
break;
|
|
|
|
case SURF_CARPET:
|
|
|
|
sSoundName += "carpet";
|
|
|
|
break;
|
|
|
|
case SURF_SAND:
|
|
|
|
sSoundName += "sand";
|
|
|
|
break;
|
|
|
|
case SURF_PUDDLE:
|
|
|
|
sSoundName += "puddle";
|
|
|
|
break;
|
|
|
|
case SURF_GLASS:
|
|
|
|
sSoundName += "glass";
|
|
|
|
break;
|
|
|
|
case SURF_GRAVEL:
|
|
|
|
sSoundName += "gravel";
|
|
|
|
break;
|
|
|
|
case SURF_MUD:
|
|
|
|
sSoundName += "mud";
|
|
|
|
break;
|
|
|
|
case SURF_DIRT:
|
|
|
|
sSoundName += "dirt";
|
|
|
|
break;
|
|
|
|
case SURF_GRILL:
|
|
|
|
sSoundName += "grill";
|
|
|
|
break;
|
|
|
|
case SURF_GRASS:
|
|
|
|
sSoundName += "grass";
|
|
|
|
break;
|
|
|
|
case SURF_ROCK:
|
|
|
|
sSoundName += "stone";
|
|
|
|
break;
|
|
|
|
case SURF_PAPER:
|
|
|
|
sSoundName += "paper";
|
|
|
|
break;
|
|
|
|
case SURF_WOOD:
|
|
|
|
sSoundName += "wood";
|
|
|
|
break;
|
|
|
|
case SURF_METAL:
|
|
|
|
sSoundName += "metal";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
sSoundName += "stone";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iLarge) {
|
|
|
|
fVolume = 1.0f;
|
|
|
|
} else {
|
|
|
|
fVolume = 0.75f;
|
|
|
|
}
|
|
|
|
|
|
|
|
commandManager.PlaySound(sSoundName, vFrom, -1, fVolume, -1.f, -1.f, 1);
|
2023-05-07 19:46:10 +02:00
|
|
|
}
|
|
|
|
|
2023-11-15 21:02:34 +01:00
|
|
|
static void CG_MakeBulletHoleType(
|
|
|
|
const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, int iEffectNum, float fRadius, qboolean bMakeSound
|
|
|
|
)
|
|
|
|
{
|
2023-07-10 21:11:01 +02:00
|
|
|
if (bMakeSound) {
|
2023-11-15 21:02:34 +01:00
|
|
|
str sBulletHole = "snd_bh_";
|
2023-07-10 21:11:01 +02:00
|
|
|
float fVolume;
|
|
|
|
|
|
|
|
switch (iEffectNum) {
|
2024-02-12 00:17:30 +01:00
|
|
|
case SFX_BHIT_PAPER_LITE:
|
2023-07-10 21:11:01 +02:00
|
|
|
sBulletHole += "paper";
|
|
|
|
break;
|
2024-02-12 00:17:30 +01:00
|
|
|
case SFX_BHIT_WOOD_LITE:
|
2023-07-10 21:11:01 +02:00
|
|
|
sBulletHole += "wood";
|
|
|
|
break;
|
2024-02-12 00:17:30 +01:00
|
|
|
case SFX_BHIT_METAL_LITE:
|
2023-07-10 21:11:01 +02:00
|
|
|
sBulletHole += "metal";
|
|
|
|
break;
|
2024-02-12 00:17:30 +01:00
|
|
|
case SFX_BHIT_STONE_LITE:
|
2023-07-10 21:11:01 +02:00
|
|
|
sBulletHole += "stone";
|
|
|
|
break;
|
2024-02-12 00:17:30 +01:00
|
|
|
case SFX_BHIT_DIRT_LITE:
|
2023-07-10 21:11:01 +02:00
|
|
|
sBulletHole += "dirt";
|
|
|
|
break;
|
2024-02-12 00:17:30 +01:00
|
|
|
case SFX_BHIT_GRILL_LITE:
|
2023-07-10 21:11:01 +02:00
|
|
|
sBulletHole += "grill";
|
|
|
|
break;
|
2024-02-12 00:17:30 +01:00
|
|
|
case SFX_BHIT_GRASS_LITE:
|
2023-07-10 21:11:01 +02:00
|
|
|
sBulletHole += "grass";
|
|
|
|
break;
|
2024-02-12 00:17:30 +01:00
|
|
|
case SFX_BHIT_MUD_LITE:
|
2023-07-10 21:11:01 +02:00
|
|
|
sBulletHole += "mud";
|
|
|
|
break;
|
2024-02-12 00:17:30 +01:00
|
|
|
case SFX_BHIT_PUDDLE_LITE:
|
2023-07-10 21:11:01 +02:00
|
|
|
sBulletHole += "puddle";
|
|
|
|
break;
|
2024-02-12 00:17:30 +01:00
|
|
|
case SFX_BHIT_GLASS_LITE:
|
2023-07-10 21:11:01 +02:00
|
|
|
sBulletHole += "glass";
|
|
|
|
break;
|
2024-02-12 00:17:30 +01:00
|
|
|
case SFX_BHIT_GRAVEL_LITE:
|
2023-07-10 21:11:01 +02:00
|
|
|
sBulletHole += "gravel";
|
|
|
|
break;
|
2024-02-12 00:17:30 +01:00
|
|
|
case SFX_BHIT_SAND_LITE:
|
2023-07-10 21:11:01 +02:00
|
|
|
sBulletHole += "sand";
|
|
|
|
break;
|
2024-02-12 00:17:30 +01:00
|
|
|
case SFX_BHIT_FOLIAGE_LITE:
|
2023-07-10 21:11:01 +02:00
|
|
|
sBulletHole += "foliage";
|
|
|
|
break;
|
2024-02-12 00:17:30 +01:00
|
|
|
case SFX_BHIT_SNOW_LITE:
|
2023-07-10 21:11:01 +02:00
|
|
|
sBulletHole += "snow";
|
|
|
|
break;
|
2024-02-12 00:17:30 +01:00
|
|
|
case SFX_BHIT_CARPET_LITE:
|
2023-07-10 21:11:01 +02:00
|
|
|
sBulletHole += "carpet";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
sBulletHole += "stone";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iLarge) {
|
|
|
|
fVolume = 1.0f;
|
|
|
|
} else {
|
|
|
|
fVolume = 0.75f;
|
|
|
|
}
|
|
|
|
|
|
|
|
commandManager.PlaySound(sBulletHole, i_vPos, -1, fVolume, -1.f, -1.f, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iLarge) {
|
|
|
|
iEffectNum++;
|
|
|
|
}
|
|
|
|
|
|
|
|
sfxManager.MakeEffect_Normal(iEffectNum, i_vPos, i_vNorm);
|
|
|
|
}
|
|
|
|
|
2023-11-15 21:02:34 +01:00
|
|
|
static void
|
|
|
|
CG_MakeBulletHole(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, trace_t *pPreTrace, qboolean bMakeSound)
|
2023-07-10 21:11:01 +02:00
|
|
|
{
|
2023-11-15 21:02:34 +01:00
|
|
|
int iSurfType;
|
|
|
|
int iEffect;
|
|
|
|
float fRadius;
|
|
|
|
str sEffectModel;
|
|
|
|
str sBulletHole;
|
|
|
|
vec3_t vFrom, vDest;
|
2023-07-10 21:11:01 +02:00
|
|
|
trace_t trace;
|
|
|
|
|
|
|
|
if (pPreTrace) {
|
|
|
|
trace = *pPreTrace;
|
|
|
|
} else {
|
|
|
|
VectorMA(i_vPos, 2.0f, i_vNorm, vFrom);
|
|
|
|
VectorMA(i_vPos, -4.0f, i_vNorm, vDest);
|
2023-11-15 21:02:34 +01:00
|
|
|
CG_Trace(
|
|
|
|
&trace, vFrom, vec_zero, vec_zero, vDest, ENTITYNUM_NONE, MASK_SHOT, qfalse, qtrue, "CG_MakeBulletHole"
|
|
|
|
);
|
2023-07-10 21:11:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
iSurfType = trace.surfaceFlags & MASK_SURF_TYPE;
|
|
|
|
if (trace.contents & CONTENTS_WATER) {
|
|
|
|
iSurfType = SURF_PUDDLE;
|
|
|
|
}
|
|
|
|
|
2023-07-10 23:58:05 +02:00
|
|
|
if (trace.fraction == 1.0f || trace.startsolid || (trace.surfaceFlags & SURF_SKY)) {
|
2023-07-10 21:11:01 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VectorAdd(trace.endpos, trace.plane.normal, vFrom);
|
2023-11-15 21:02:34 +01:00
|
|
|
fRadius = 2.0f;
|
2023-07-10 21:11:01 +02:00
|
|
|
sBulletHole = "bhole_";
|
|
|
|
|
|
|
|
switch (iSurfType) {
|
|
|
|
case SURF_FOLIAGE:
|
|
|
|
fRadius = 0.f;
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffect = SFX_BHIT_FOLIAGE_LITE;
|
2023-07-10 21:11:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_SNOW:
|
|
|
|
sBulletHole += "snow";
|
2024-02-21 20:17:01 +01:00
|
|
|
iEffect = SFX_BHIT_SNOW_LITE;
|
2023-07-10 21:11:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_CARPET:
|
|
|
|
sBulletHole += "carpet";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffect = SFX_BHIT_CARPET_LITE;
|
2023-07-10 21:11:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_SAND:
|
|
|
|
fRadius = 0.f;
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffect = SFX_BHIT_SAND_LITE;
|
2023-07-10 21:11:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_PUDDLE:
|
|
|
|
fRadius = 0.f;
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffect = SFX_BHIT_PUDDLE_LITE;
|
2023-07-10 21:11:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_GLASS:
|
|
|
|
sBulletHole += "glass";
|
2024-02-12 00:18:18 +01:00
|
|
|
iEffect = SFX_BHIT_GLASS_LITE;
|
2023-07-10 21:11:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_GRAVEL:
|
|
|
|
fRadius = 0.f;
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffect = SFX_BHIT_GRAVEL_LITE;
|
2023-07-10 21:11:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_MUD:
|
|
|
|
sBulletHole += "mud";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffect = SFX_BHIT_MUD_LITE;
|
2023-07-10 21:11:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_DIRT:
|
|
|
|
sBulletHole += "dirt";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffect = SFX_BHIT_DIRT_LITE;
|
2023-07-10 21:11:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_GRILL:
|
|
|
|
sBulletHole += "grill";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffect = SFX_BHIT_GRILL_LITE;
|
2023-07-10 21:11:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_GRASS:
|
|
|
|
sBulletHole += "grass";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffect = SFX_BHIT_GRASS_LITE;
|
2023-07-10 21:11:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_ROCK:
|
|
|
|
sBulletHole += "stone";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffect = SFX_BHIT_STONE_LITE;
|
2023-07-10 21:11:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_PAPER:
|
|
|
|
sBulletHole += "paper";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffect = SFX_BHIT_PAPER_LITE;
|
2023-07-10 21:11:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_WOOD:
|
|
|
|
sBulletHole += "wood";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffect = SFX_BHIT_WOOD_LITE;
|
2023-07-10 21:11:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_METAL:
|
|
|
|
fRadius -= 0.25f;
|
|
|
|
sBulletHole += "metal";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffect = SFX_BHIT_METAL_LITE;
|
2023-07-10 21:11:01 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
sBulletHole += "stone";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffect = SFX_BHIT_STONE_LITE;
|
2023-07-10 21:11:01 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fRadius && CG_CheckMakeMarkOnEntity(trace.entityNum)) {
|
2023-07-18 00:09:02 +02:00
|
|
|
fRadius *= 1.f + crandom() * 0.2f;
|
2023-07-10 21:11:01 +02:00
|
|
|
|
|
|
|
CG_ImpactMarkSimple(
|
|
|
|
cgi.R_RegisterShader(sBulletHole.c_str()),
|
|
|
|
trace.endpos,
|
|
|
|
trace.plane.normal,
|
|
|
|
0.f,
|
|
|
|
fRadius,
|
|
|
|
1.f,
|
|
|
|
1.f,
|
|
|
|
1.f,
|
|
|
|
1.f,
|
|
|
|
qfalse,
|
|
|
|
qfalse,
|
|
|
|
qtrue,
|
|
|
|
qfalse
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
CG_MakeBulletHoleType(vFrom, i_vNorm, iLarge, iEffect, fRadius, bMakeSound);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void CG_MakeBubbleTrail(const vec3_t i_vStart, const vec3_t i_vEnd, int iLarge, float alpha = 1.0f)
|
2023-05-07 19:46:10 +02:00
|
|
|
{
|
2023-07-10 23:08:27 +02:00
|
|
|
vec3_t vDir;
|
|
|
|
vec3_t vPos;
|
2023-11-15 21:02:34 +01:00
|
|
|
float fDist;
|
|
|
|
float fMove;
|
2023-07-10 23:08:27 +02:00
|
|
|
|
|
|
|
VectorSubtract(i_vEnd, i_vStart, vDir);
|
|
|
|
fDist = VectorNormalize(vDir);
|
|
|
|
VectorCopy(i_vStart, vPos);
|
|
|
|
|
2023-11-15 21:02:34 +01:00
|
|
|
fMove = random() * 8.f * alpha;
|
2023-07-10 23:08:27 +02:00
|
|
|
fDist -= fMove;
|
|
|
|
while (fDist > 0.f) {
|
|
|
|
VectorMA(vPos, fMove, vDir, vPos);
|
2024-02-12 00:17:30 +01:00
|
|
|
sfxManager.MakeEffect_Angles(SFX_WATER_TRAIL_BUBBLE, vPos, vec_zero);
|
2023-07-10 23:08:27 +02:00
|
|
|
|
2023-11-15 21:02:34 +01:00
|
|
|
fMove = 16.f + crandom() * 8.f * alpha;
|
2023-07-10 23:08:27 +02:00
|
|
|
fDist -= fMove;
|
|
|
|
}
|
2023-05-07 19:46:10 +02:00
|
|
|
}
|
|
|
|
|
2023-11-15 21:02:34 +01:00
|
|
|
static void CG_BulletTracerEffect(const vec3_t i_vStart, const vec3_t i_vEnd, int iLarge, float alpha)
|
2023-05-07 19:46:10 +02:00
|
|
|
{
|
2023-11-15 21:02:34 +01:00
|
|
|
int iLife;
|
|
|
|
int iTracerLength;
|
|
|
|
float fLength, fDist;
|
2023-07-10 23:08:27 +02:00
|
|
|
vec4_t fTracerColor;
|
|
|
|
vec3_t vDir, vNewStart;
|
2023-11-15 21:02:34 +01:00
|
|
|
float alphaMult;
|
|
|
|
float scale;
|
2023-07-10 23:08:27 +02:00
|
|
|
|
|
|
|
iTracerLength = 450.0f + random() * 150.f;
|
|
|
|
VectorSubtract(i_vEnd, i_vStart, vDir);
|
|
|
|
fLength = VectorNormalize(vDir);
|
2023-11-15 21:02:34 +01:00
|
|
|
|
|
|
|
if (iLarge > 1) {
|
|
|
|
alphaMult = random() * 0.2f + 0.9f;
|
|
|
|
scale = iLarge * 2;
|
|
|
|
} else {
|
|
|
|
alphaMult = 1;
|
|
|
|
scale = 1;
|
|
|
|
}
|
|
|
|
|
2023-07-10 23:08:27 +02:00
|
|
|
fDist = 450.0f + random() * 150.f;
|
2023-11-15 21:02:34 +01:00
|
|
|
|
2023-07-10 23:08:27 +02:00
|
|
|
if (fLength < fDist + 150.f) {
|
|
|
|
float fFrac;
|
|
|
|
|
|
|
|
if (fLength < 150.f) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-11-15 21:02:34 +01:00
|
|
|
fFrac = fLength / (fDist + 150.0);
|
2023-07-10 23:08:27 +02:00
|
|
|
iTracerLength = (int)((float)iTracerLength * fFrac + 0.5f);
|
|
|
|
fDist *= fFrac;
|
|
|
|
}
|
|
|
|
|
2023-11-15 21:02:34 +01:00
|
|
|
iLife = (int)((fLength - fDist) / 12000.f * 1000.f / (alpha * alphaMult));
|
|
|
|
if (iLife < 20) {
|
|
|
|
iLife = 20;
|
|
|
|
}
|
2023-07-10 23:08:27 +02:00
|
|
|
|
|
|
|
VectorMA(i_vStart, fDist, vDir, vNewStart);
|
|
|
|
fTracerColor[0] = 1.f;
|
|
|
|
fTracerColor[1] = 1.f;
|
|
|
|
fTracerColor[2] = 1.f;
|
|
|
|
fTracerColor[3] = 1.f;
|
|
|
|
|
|
|
|
CG_CreateBeam(
|
|
|
|
vNewStart,
|
|
|
|
vec_zero,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
1.0,
|
2024-11-12 00:09:29 +01:00
|
|
|
scale,
|
2023-07-10 23:08:27 +02:00
|
|
|
BEAM_INVERTED,
|
|
|
|
1000.0,
|
|
|
|
iLife,
|
|
|
|
qtrue,
|
|
|
|
i_vEnd,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
"tracer",
|
|
|
|
fTracerColor,
|
|
|
|
0,
|
|
|
|
0.0,
|
|
|
|
iTracerLength,
|
|
|
|
1.0,
|
|
|
|
0,
|
|
|
|
"tracereffect"
|
|
|
|
);
|
2023-05-07 19:46:10 +02:00
|
|
|
}
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
static void CG_MakeBulletTracerInternal(
|
2023-11-15 21:02:34 +01:00
|
|
|
const vec3_t i_vBarrel,
|
|
|
|
const vec3_t i_vStart,
|
|
|
|
const vec3_t *i_vEnd,
|
|
|
|
int i_iNumBullets,
|
|
|
|
qboolean iLarge,
|
|
|
|
int iTracerVisible,
|
|
|
|
qboolean bIgnoreEntities,
|
|
|
|
float alpha
|
2023-07-05 21:24:23 +02:00
|
|
|
)
|
2023-05-07 19:46:10 +02:00
|
|
|
{
|
2023-11-15 21:02:34 +01:00
|
|
|
vec3_t vPos;
|
|
|
|
int iBullet;
|
|
|
|
int iContinueCount;
|
|
|
|
int iDist;
|
|
|
|
int iHeadDist;
|
|
|
|
int iTravelDist;
|
|
|
|
float fLen, fDist;
|
|
|
|
trace_t trace;
|
|
|
|
qboolean bStartInWater, bInWater;
|
|
|
|
qboolean bBulletDone;
|
|
|
|
qboolean bMadeTracer;
|
|
|
|
vec3_t vDir;
|
|
|
|
vec3_t vTrailStart;
|
|
|
|
vec3_t vTraceStart;
|
|
|
|
vec3_t vTraceEnd;
|
|
|
|
vec3_t vTmp;
|
|
|
|
int iNumImpacts;
|
|
|
|
trace_t tImpacts[128];
|
|
|
|
float fImpSndDistRA;
|
2023-07-09 23:36:21 +02:00
|
|
|
static float fImpSndDistLA;
|
2023-11-15 21:02:34 +01:00
|
|
|
float fImpSndDistRB;
|
|
|
|
float fImpSndDistLB;
|
|
|
|
int iImpSndIndexRA;
|
|
|
|
int iImpSndIndexRB;
|
|
|
|
int iImpSndIndexLB;
|
|
|
|
float fVolume;
|
|
|
|
float fPitch;
|
|
|
|
float fZingDistA, fZingDistB, fZingDistC;
|
|
|
|
vec3_t vZingPosA, vZingPosB, vZingPosC;
|
|
|
|
|
|
|
|
fZingDistB = 9999.0;
|
|
|
|
fZingDistA = 9999.0;
|
|
|
|
fZingDistC = 9999.0;
|
2023-07-10 21:11:01 +02:00
|
|
|
iNumImpacts = 0;
|
|
|
|
|
|
|
|
// check to see if it starts in water
|
|
|
|
bStartInWater = (cgi.CM_PointContents(i_vStart, 0) & CONTENTS_FLUID) != 0;
|
2023-11-15 21:02:34 +01:00
|
|
|
|
2023-07-10 21:11:01 +02:00
|
|
|
for (iBullet = 0; iBullet < i_iNumBullets; iBullet++) {
|
|
|
|
bInWater = bStartInWater;
|
|
|
|
VectorCopy(i_vBarrel, vTrailStart);
|
|
|
|
VectorSubtract(i_vEnd[iBullet], i_vStart, vDir);
|
|
|
|
fLen = VectorNormalize(vDir);
|
|
|
|
|
|
|
|
trace.fraction = 0;
|
2023-11-15 21:02:34 +01:00
|
|
|
iDist = (int)fLen + 32;
|
|
|
|
bBulletDone = qfalse;
|
2023-07-10 21:11:01 +02:00
|
|
|
iContinueCount = 0;
|
|
|
|
|
|
|
|
if (bStartInWater) {
|
|
|
|
bMadeTracer = qtrue;
|
|
|
|
} else if (!iTracerVisible) {
|
|
|
|
bMadeTracer = qtrue;
|
|
|
|
} else {
|
|
|
|
bMadeTracer = qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
iTravelDist = 0;
|
|
|
|
VectorCopy(i_vStart, vTraceEnd);
|
|
|
|
|
|
|
|
if (iDist > 0) {
|
|
|
|
do {
|
|
|
|
if (iDist > BULLET_TRAVEL_DIST) {
|
|
|
|
iTravelDist += BULLET_TRAVEL_DIST;
|
|
|
|
iDist -= BULLET_TRAVEL_DIST;
|
2023-11-15 21:02:34 +01:00
|
|
|
} else {
|
2023-07-10 21:11:01 +02:00
|
|
|
iTravelDist += iDist;
|
|
|
|
iDist = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&trace, 0, sizeof(trace));
|
2023-07-10 23:58:05 +02:00
|
|
|
VectorCopy(vTraceEnd, vTraceStart);
|
2023-07-10 21:11:01 +02:00
|
|
|
VectorMA(i_vStart, iTravelDist, vDir, vTraceEnd);
|
|
|
|
|
|
|
|
while (trace.fraction < 1) {
|
|
|
|
if (bIgnoreEntities) {
|
2024-02-12 00:17:30 +01:00
|
|
|
cgi.CM_BoxTrace(&trace, vTraceStart, vTraceEnd, vec_zero, vec_zero, 0, MASK_SHOT_FLUID, qfalse);
|
2023-07-10 21:11:01 +02:00
|
|
|
|
|
|
|
if (trace.fraction == 1.0f) {
|
|
|
|
trace.entityNum = ENTITYNUM_NONE;
|
|
|
|
} else {
|
|
|
|
trace.entityNum = ENTITYNUM_WORLD;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (trace.startsolid) {
|
|
|
|
trace.entityNum = ENTITYNUM_WORLD;
|
|
|
|
}
|
2023-11-15 21:02:34 +01:00
|
|
|
} else {
|
2023-07-10 21:11:01 +02:00
|
|
|
CG_Trace(
|
|
|
|
&trace,
|
|
|
|
vTraceStart,
|
|
|
|
vec_zero,
|
|
|
|
vec_zero,
|
|
|
|
vTraceStart,
|
|
|
|
ENTITYNUM_NONE,
|
2024-02-12 00:18:18 +01:00
|
|
|
MASK_SHOT_FLUID,
|
2023-07-10 21:11:01 +02:00
|
|
|
qfalse,
|
|
|
|
qfalse,
|
|
|
|
"CG_MakeBulletTracerInternal"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (trace.contents & CONTENTS_FLUID) {
|
|
|
|
fDist = DotProduct(vDir, trace.plane.normal) * -2.0f;
|
|
|
|
VectorMA(vDir, fDist, trace.plane.normal, vTmp);
|
2024-02-12 00:17:30 +01:00
|
|
|
VectorMA(trace.plane.normal, 2.0, vTmp, trace.plane.normal);
|
2023-07-10 21:11:01 +02:00
|
|
|
VectorNormalizeFast(trace.plane.normal);
|
|
|
|
}
|
|
|
|
|
2024-02-12 00:17:30 +01:00
|
|
|
if (!bInWater && trace.fraction < 1.0f && iNumImpacts < ARRAY_LEN(tImpacts)) {
|
2023-07-10 21:11:01 +02:00
|
|
|
memcpy(&tImpacts[iNumImpacts], &trace, sizeof(trace_t));
|
|
|
|
iNumImpacts++;
|
|
|
|
}
|
|
|
|
|
2023-11-15 21:02:34 +01:00
|
|
|
if (iTracerVisible && !bMadeTracer) {
|
|
|
|
CG_BulletTracerEffect(vTrailStart, trace.endpos, iLarge, alpha);
|
2023-07-10 21:11:01 +02:00
|
|
|
bMadeTracer = qtrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (trace.fraction < 1.0f) {
|
2023-11-15 21:02:34 +01:00
|
|
|
if (((trace.surfaceFlags & (SURF_HINT | SURF_NODLIGHT | SURF_SNOW | SURF_FOLIAGE | SURF_DIRT))
|
|
|
|
|| (trace.contents & CONTENTS_WATER))
|
|
|
|
&& iContinueCount < 5) {
|
|
|
|
if (bInWater) {
|
2025-01-28 20:03:02 +01:00
|
|
|
VectorMA(trace.endpos, -1.0, vDir, vTmp);
|
|
|
|
|
2023-11-15 21:02:34 +01:00
|
|
|
if (!(trace.contents & CONTENTS_FLUID) && !(trace.surfaceFlags & SURF_PUDDLE)
|
|
|
|
&& !(cgi.CM_PointContents(vTmp, 0) & CONTENTS_FLUID)) {
|
|
|
|
CG_MakeBubbleTrail(vTrailStart, trace.endpos, iLarge, alpha);
|
2023-07-10 21:11:01 +02:00
|
|
|
VectorCopy(trace.endpos, vTrailStart);
|
|
|
|
bInWater = qfalse;
|
|
|
|
}
|
2023-11-15 21:02:34 +01:00
|
|
|
} else if ((trace.contents & CONTENTS_FLUID) || (trace.surfaceFlags & SURF_PUDDLE)) {
|
2023-07-10 21:11:01 +02:00
|
|
|
VectorCopy(trace.endpos, vTrailStart);
|
|
|
|
bInWater = qtrue;
|
|
|
|
}
|
|
|
|
|
2025-01-28 20:03:02 +01:00
|
|
|
VectorMA(trace.endpos, 2.0, vDir, vTraceStart);
|
2023-07-10 21:11:01 +02:00
|
|
|
|
|
|
|
iContinueCount++;
|
2023-11-15 21:02:34 +01:00
|
|
|
} else {
|
2023-07-10 21:11:01 +02:00
|
|
|
trace.fraction = 1.0f;
|
2023-11-15 21:02:34 +01:00
|
|
|
bBulletDone = qtrue;
|
2023-07-10 21:11:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (!bBulletDone && iDist > 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bInWater) {
|
2023-11-15 21:02:34 +01:00
|
|
|
CG_MakeBubbleTrail(vTraceStart, trace.endpos, iLarge, alpha);
|
2023-07-10 21:11:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (iTracerVisible) {
|
|
|
|
iTracerVisible--;
|
|
|
|
}
|
|
|
|
|
2023-11-15 21:02:34 +01:00
|
|
|
fLen = ProjectPointOnLine(i_vStart, i_vEnd[iBullet], cg.SoundOrg, vPos);
|
2023-07-10 21:11:01 +02:00
|
|
|
iHeadDist = (int)Distance(vPos, cg.SoundOrg);
|
|
|
|
if (iHeadDist > 255) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iHeadDist >= fZingDistA && iHeadDist >= fZingDistB && iHeadDist >= fZingDistC) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
fDist = Distance(i_vStart, i_vEnd[iBullet]);
|
|
|
|
if (fLen <= 128.0f || fLen >= fDist - 128.0f) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fLen < 0.f) {
|
|
|
|
VectorCopy(i_vStart, vPos);
|
2023-11-15 21:02:34 +01:00
|
|
|
} else if (fDist >= fLen) {
|
2023-07-10 21:11:01 +02:00
|
|
|
VectorCopy(i_vEnd[iBullet], vPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iHeadDist < fZingDistA) {
|
|
|
|
VectorCopy(vZingPosB, vZingPosC);
|
|
|
|
VectorCopy(vZingPosA, vZingPosB);
|
|
|
|
fZingDistC = fZingDistB;
|
|
|
|
fZingDistB = fZingDistA;
|
|
|
|
VectorCopy(vPos, vZingPosA);
|
|
|
|
fZingDistA = iHeadDist;
|
|
|
|
} else if (iHeadDist < fZingDistB) {
|
|
|
|
VectorCopy(vZingPosB, vZingPosC);
|
|
|
|
fZingDistC = fZingDistB;
|
|
|
|
VectorCopy(vPos, vZingPosB);
|
|
|
|
fZingDistB = iHeadDist;
|
|
|
|
} else {
|
|
|
|
VectorCopy(vPos, vZingPosC);
|
|
|
|
fZingDistC = iHeadDist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iNumImpacts > 2) {
|
2023-11-15 21:02:34 +01:00
|
|
|
fImpSndDistRA = 9999.0f;
|
|
|
|
fImpSndDistRB = 9999.0f;
|
2023-07-10 21:11:01 +02:00
|
|
|
iImpSndIndexRA = 0;
|
|
|
|
iImpSndIndexRB = 0;
|
2023-11-15 21:02:34 +01:00
|
|
|
fImpSndDistLB = 9999.0f;
|
2023-07-10 21:11:01 +02:00
|
|
|
iImpSndIndexLB = 0;
|
|
|
|
|
|
|
|
for (iBullet = 0; iBullet < iNumImpacts; iBullet++) {
|
|
|
|
CG_MakeBulletHole(
|
|
|
|
tImpacts[iImpSndIndexLB].endpos,
|
|
|
|
tImpacts[iImpSndIndexLB].plane.normal,
|
|
|
|
iLarge,
|
|
|
|
&tImpacts[iImpSndIndexLB],
|
|
|
|
qfalse
|
|
|
|
);
|
|
|
|
|
|
|
|
VectorSubtract(tImpacts[iImpSndIndexLB].endpos, cg.SoundOrg, vTmp);
|
|
|
|
iHeadDist = VectorLength(vTmp);
|
|
|
|
|
2023-11-15 21:02:34 +01:00
|
|
|
if (DotProduct(vTmp, cg.SoundAxis[1]) <= 0.f) {
|
2023-07-10 21:11:01 +02:00
|
|
|
if (iHeadDist < 9999.0f || iHeadDist < fImpSndDistLB) {
|
|
|
|
if (iHeadDist < 9999.0f) {
|
2023-11-15 21:02:34 +01:00
|
|
|
fImpSndDistRA = iHeadDist;
|
|
|
|
fImpSndDistLB = 9999.0;
|
2023-07-10 21:11:01 +02:00
|
|
|
iImpSndIndexRA = iBullet;
|
|
|
|
} else if (iHeadDist < fImpSndDistLB) {
|
|
|
|
fImpSndDistLB = iHeadDist;
|
|
|
|
}
|
|
|
|
}
|
2023-11-15 21:02:34 +01:00
|
|
|
} else {
|
|
|
|
if (iHeadDist < fImpSndDistRA || iHeadDist < fImpSndDistRB) {
|
2023-07-10 21:11:01 +02:00
|
|
|
if (iHeadDist < fImpSndDistRA) {
|
|
|
|
iImpSndIndexRB = iImpSndIndexRA;
|
|
|
|
iImpSndIndexRA = iBullet;
|
|
|
|
} else if (iHeadDist < fImpSndDistRB) {
|
2023-11-15 21:02:34 +01:00
|
|
|
fImpSndDistRB = iHeadDist;
|
2023-07-10 21:11:01 +02:00
|
|
|
iImpSndIndexRB = iBullet;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
iImpSndIndexLB++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fImpSndDistRA < 9999.0f) {
|
|
|
|
CG_MakeBulletHoleSound(
|
|
|
|
tImpacts[iImpSndIndexRA].endpos,
|
|
|
|
tImpacts[iImpSndIndexRA].plane.normal,
|
|
|
|
iLarge,
|
|
|
|
&tImpacts[iImpSndIndexRA]
|
|
|
|
);
|
|
|
|
|
|
|
|
if (fImpSndDistRB < 9999.0f) {
|
|
|
|
CG_MakeBulletHoleSound(
|
|
|
|
tImpacts[iImpSndIndexRB].endpos,
|
|
|
|
tImpacts[iImpSndIndexRB].plane.normal,
|
|
|
|
iLarge,
|
|
|
|
&tImpacts[iImpSndIndexRB]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (iBullet = 0; iBullet < iNumImpacts; iBullet++) {
|
|
|
|
CG_MakeBulletHole(
|
2023-11-15 21:02:34 +01:00
|
|
|
tImpacts[iBullet].endpos, tImpacts[iBullet].plane.normal, iNumImpacts, &tImpacts[iBullet], qtrue
|
2023-07-10 21:11:01 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fZingDistA < 9999.0f) {
|
|
|
|
if (iLarge) {
|
|
|
|
fVolume = 1.0f;
|
2023-11-15 21:02:34 +01:00
|
|
|
fPitch = 0.8f;
|
2023-07-10 21:11:01 +02:00
|
|
|
} else {
|
|
|
|
fVolume = 0.8f;
|
2023-11-15 21:02:34 +01:00
|
|
|
fPitch = 1.0f;
|
2023-07-10 21:11:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
commandManager.PlaySound("snd_b_zing", vZingPosA, -1, fVolume, -1.0f, fPitch, 1);
|
2024-09-16 17:39:15 +02:00
|
|
|
|
|
|
|
if (fZingDistB != 9999) {
|
|
|
|
commandManager.PlaySound("snd_b_zing", vZingPosB, -1, fVolume, -1.0f, fPitch, 1);
|
|
|
|
|
|
|
|
if (fZingDistC != 9999) {
|
|
|
|
commandManager.PlaySound("snd_b_zing", vZingPosC, -1, fVolume, -1.0f, fPitch, 1);
|
|
|
|
}
|
|
|
|
}
|
2023-07-10 21:11:01 +02:00
|
|
|
}
|
2023-05-07 19:46:10 +02:00
|
|
|
}
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
static void CG_MakeBulletTracer(
|
|
|
|
vec3_t i_vBarrel,
|
|
|
|
vec3_t i_vStart,
|
|
|
|
vec3_t *i_vEnd,
|
|
|
|
int i_iNumBullets,
|
|
|
|
qboolean iLarge,
|
|
|
|
int iTracerVisible,
|
|
|
|
qboolean bIgnoreEntities,
|
|
|
|
float alpha = 1.0f
|
|
|
|
)
|
|
|
|
{
|
|
|
|
bullet_tracer_t *bullet_tracer;
|
|
|
|
int i;
|
2023-05-04 21:07:44 +02:00
|
|
|
|
2023-05-04 23:26:17 +02:00
|
|
|
if (bullet_tracer_bullets_count >= MAX_BULLET_TRACERS) {
|
2023-05-04 21:07:44 +02:00
|
|
|
Com_Printf("CG_MakeBulletTracer: MAX_BULLET_TRACERS exceeded\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i_iNumBullets + bullet_tracers_count >= MAX_BULLET_TRACE_BULLETS) {
|
|
|
|
Com_Printf("CG_MakeBulletTracerInternal: MAX_BULLET_TRACE_BULLETS exceeded\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bullet_tracer = &bullet_tracers[bullet_tracer_bullets_count++];
|
|
|
|
VectorCopy(i_vBarrel, bullet_tracer->i_vBarrel);
|
|
|
|
VectorCopy(i_vStart, bullet_tracer->i_vStart);
|
2023-07-05 21:24:23 +02:00
|
|
|
bullet_tracer->i_vEnd = &bullet_tracer_bullets[bullet_tracers_count];
|
2023-05-04 21:07:44 +02:00
|
|
|
bullet_tracer->i_iNumBullets = i_iNumBullets;
|
|
|
|
|
2023-11-15 21:02:34 +01:00
|
|
|
for (i = 0; i < i_iNumBullets; i++, bullet_tracers_count++) {
|
|
|
|
bullet_tracer_bullets[bullet_tracers_count][0] = i_vEnd[i][0];
|
|
|
|
bullet_tracer_bullets[bullet_tracers_count][1] = i_vEnd[i][1];
|
|
|
|
bullet_tracer_bullets[bullet_tracers_count][2] = i_vEnd[i][2];
|
2023-05-04 21:07:44 +02:00
|
|
|
}
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
bullet_tracer->iLarge = iLarge;
|
2023-11-15 21:02:34 +01:00
|
|
|
bullet_tracer->alpha = alpha;
|
2023-07-05 21:24:23 +02:00
|
|
|
bullet_tracer->iTracerVisible = iTracerVisible;
|
2023-05-04 21:07:44 +02:00
|
|
|
bullet_tracer->bIgnoreEntities = bIgnoreEntities;
|
2023-05-04 20:30:52 +02:00
|
|
|
}
|
|
|
|
|
2023-05-01 15:10:26 +02:00
|
|
|
void CG_AddBulletTracers()
|
|
|
|
{
|
2023-05-07 19:46:10 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < bullet_tracer_bullets_count; ++i) {
|
|
|
|
CG_MakeBulletTracerInternal(
|
|
|
|
bullet_tracers[i].i_vBarrel,
|
|
|
|
bullet_tracers[i].i_vStart,
|
|
|
|
bullet_tracers[i].i_vEnd,
|
|
|
|
bullet_tracers[i].i_iNumBullets,
|
|
|
|
bullet_tracers[i].iLarge,
|
|
|
|
bullet_tracers[i].iTracerVisible,
|
2023-11-15 21:02:34 +01:00
|
|
|
bullet_tracers[i].bIgnoreEntities,
|
|
|
|
bullet_tracers[i].alpha
|
2023-05-07 19:46:10 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
bullet_tracer_bullets_count = 0;
|
2023-07-05 21:24:23 +02:00
|
|
|
bullet_tracers_count = 0;
|
2023-05-01 15:10:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CG_AddBulletImpacts()
|
|
|
|
{
|
2023-11-15 21:02:34 +01:00
|
|
|
int i;
|
|
|
|
int iHeadDist;
|
|
|
|
float fVolume;
|
|
|
|
float fImpSndDistRA;
|
2023-07-10 23:08:27 +02:00
|
|
|
static float fImpSndDistLA = 9999.f;
|
2023-11-15 21:02:34 +01:00
|
|
|
float fImpSndDistRB;
|
|
|
|
float fImpSndDistLB;
|
|
|
|
int iImpSndIndexRA;
|
|
|
|
int iImpSndIndexRB;
|
|
|
|
int iImpSndIndexLB;
|
|
|
|
vec3_t vTmp;
|
|
|
|
str sSoundName;
|
|
|
|
|
|
|
|
if (wall_impact_count) {
|
|
|
|
if (wall_impact_count > 4) {
|
|
|
|
fImpSndDistRA = fImpSndDistLA;
|
|
|
|
fImpSndDistRB = fImpSndDistLA;
|
|
|
|
fImpSndDistLB = fImpSndDistLA;
|
2023-07-10 23:08:27 +02:00
|
|
|
iImpSndIndexRA = 0;
|
|
|
|
iImpSndIndexRB = 0;
|
|
|
|
iImpSndIndexLB = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < wall_impact_count; i++) {
|
|
|
|
VectorSubtract(wall_impact_pos[i], cg.SoundOrg, vTmp);
|
|
|
|
iHeadDist = VectorLength(vTmp);
|
2023-11-15 21:02:34 +01:00
|
|
|
|
|
|
|
if (DotProduct(vTmp, cg.SoundAxis[1]) > 0.f) {
|
|
|
|
if (iHeadDist < fImpSndDistRA || iHeadDist < fImpSndDistRB) {
|
2023-07-10 23:08:27 +02:00
|
|
|
if (iHeadDist < fImpSndDistRA) {
|
2023-11-15 21:02:34 +01:00
|
|
|
fImpSndDistRB = fImpSndDistRA;
|
|
|
|
fImpSndDistRA = iHeadDist;
|
2023-07-10 23:08:27 +02:00
|
|
|
iImpSndIndexRB = iImpSndIndexRA;
|
|
|
|
iImpSndIndexRA = i;
|
|
|
|
} else if (iHeadDist < fImpSndDistRB) {
|
2023-11-15 21:02:34 +01:00
|
|
|
fImpSndDistRB = iHeadDist;
|
2023-07-10 23:08:27 +02:00
|
|
|
iImpSndIndexRB = i;
|
|
|
|
}
|
|
|
|
}
|
2023-11-15 21:02:34 +01:00
|
|
|
} else {
|
|
|
|
if (iHeadDist < fImpSndDistLA || iHeadDist < fImpSndDistLB) {
|
2023-07-10 23:08:27 +02:00
|
|
|
if (iHeadDist < fImpSndDistLA) {
|
2023-11-15 21:02:34 +01:00
|
|
|
fImpSndDistRA = iHeadDist;
|
|
|
|
fImpSndDistLB = fImpSndDistLA;
|
2023-07-10 23:08:27 +02:00
|
|
|
iImpSndIndexLB = 0;
|
|
|
|
iImpSndIndexRA = i;
|
|
|
|
} else if (iHeadDist < fImpSndDistLB) {
|
2023-11-15 21:02:34 +01:00
|
|
|
fImpSndDistLB = iHeadDist;
|
2023-07-10 23:08:27 +02:00
|
|
|
iImpSndIndexLB = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fImpSndDistRA < fImpSndDistLA) {
|
2024-06-14 21:26:44 +02:00
|
|
|
if (wall_impact_type[iImpSndIndexRA] != SFX_BHIT_PAPER_LITE) {
|
2023-07-10 23:08:27 +02:00
|
|
|
if (wall_impact_large[iImpSndIndexRA]) {
|
|
|
|
fVolume = 1.f;
|
|
|
|
} else {
|
|
|
|
fVolume = 0.75f;
|
|
|
|
}
|
|
|
|
|
2024-09-10 19:40:53 +02:00
|
|
|
if (wall_impact_type[iImpSndIndexRA] == SFX_BHIT_WOOD_LITE
|
|
|
|
|| wall_impact_type[iImpSndIndexRA] == SFX_BHIT_WOOD_HARD) {
|
2023-07-10 23:08:27 +02:00
|
|
|
sSoundName = "snd_bh_metal";
|
|
|
|
} else {
|
|
|
|
sSoundName = "snd_bh_wood";
|
|
|
|
}
|
|
|
|
|
|
|
|
commandManager.PlaySound(sSoundName, wall_impact_pos[iImpSndIndexRA], -1, fVolume, -1, -1, 1);
|
|
|
|
|
|
|
|
sfxManager.MakeEffect_Normal(
|
|
|
|
wall_impact_type[iImpSndIndexRA],
|
|
|
|
wall_impact_pos[iImpSndIndexRA],
|
|
|
|
wall_impact_norm[iImpSndIndexRA]
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
CG_MakeBulletHole(
|
|
|
|
wall_impact_pos[iImpSndIndexRA],
|
|
|
|
wall_impact_norm[iImpSndIndexRA],
|
|
|
|
wall_impact_large[iImpSndIndexRA],
|
|
|
|
NULL,
|
|
|
|
qtrue
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fImpSndDistRB < fImpSndDistLA) {
|
|
|
|
if (wall_impact_type[iImpSndIndexRB]) {
|
|
|
|
if (wall_impact_large[iImpSndIndexRB]) {
|
|
|
|
fVolume = 1.f;
|
|
|
|
} else {
|
|
|
|
fVolume = 0.75f;
|
|
|
|
}
|
|
|
|
|
2024-09-10 19:40:53 +02:00
|
|
|
if (wall_impact_type[iImpSndIndexRB] == SFX_BHIT_WOOD_LITE
|
|
|
|
|| wall_impact_type[iImpSndIndexRB] == SFX_BHIT_WOOD_HARD) {
|
2023-07-10 23:08:27 +02:00
|
|
|
sSoundName = "snd_bh_metal";
|
2023-11-15 21:02:34 +01:00
|
|
|
} else {
|
2023-07-10 23:08:27 +02:00
|
|
|
sSoundName = "snd_bh_wood";
|
|
|
|
}
|
|
|
|
|
|
|
|
commandManager.PlaySound(sSoundName, wall_impact_pos[iImpSndIndexRB], -1, fVolume, -1, -1, 1);
|
|
|
|
|
|
|
|
sfxManager.MakeEffect_Normal(
|
|
|
|
wall_impact_type[iImpSndIndexRB],
|
|
|
|
wall_impact_pos[iImpSndIndexRB],
|
|
|
|
wall_impact_norm[iImpSndIndexRB]
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
CG_MakeBulletHole(
|
|
|
|
wall_impact_pos[iImpSndIndexRB],
|
|
|
|
wall_impact_norm[iImpSndIndexRB],
|
|
|
|
wall_impact_large[iImpSndIndexRB],
|
|
|
|
NULL,
|
|
|
|
qtrue
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fImpSndDistLA > 9999.0f) {
|
2024-06-14 21:26:44 +02:00
|
|
|
if (wall_impact_type[0] != SFX_BHIT_PAPER_LITE) {
|
2023-07-10 23:08:27 +02:00
|
|
|
if (wall_impact_large[0]) {
|
|
|
|
fVolume = 1.f;
|
|
|
|
} else {
|
|
|
|
fVolume = 0.75f;
|
|
|
|
}
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
if (wall_impact_type[0] == SFX_BHIT_WOOD_LITE || wall_impact_type[0] == SFX_BHIT_WOOD_HARD) {
|
2023-07-10 23:08:27 +02:00
|
|
|
sSoundName = "snd_bh_metal";
|
2023-11-15 21:02:34 +01:00
|
|
|
} else {
|
2023-07-10 23:08:27 +02:00
|
|
|
sSoundName = "snd_bh_wood";
|
|
|
|
}
|
|
|
|
|
|
|
|
commandManager.PlaySound(sSoundName, wall_impact_pos[0], -1, fVolume, -1, -1, 1);
|
|
|
|
|
2023-11-15 21:02:34 +01:00
|
|
|
sfxManager.MakeEffect_Normal(wall_impact_type[0], wall_impact_pos[0], wall_impact_norm[0]);
|
2023-07-10 23:08:27 +02:00
|
|
|
} else {
|
2023-11-15 21:02:34 +01:00
|
|
|
CG_MakeBulletHole(wall_impact_pos[0], wall_impact_norm[0], wall_impact_large[0], NULL, qtrue);
|
2023-07-10 23:08:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fImpSndDistLB < fImpSndDistLA) {
|
2024-06-14 21:26:44 +02:00
|
|
|
if (wall_impact_type[iImpSndIndexLB] != SFX_BHIT_PAPER_LITE) {
|
2023-07-10 23:08:27 +02:00
|
|
|
if (wall_impact_large[iImpSndIndexLB]) {
|
|
|
|
fVolume = 1.f;
|
2023-11-15 21:02:34 +01:00
|
|
|
} else {
|
2023-07-10 23:08:27 +02:00
|
|
|
fVolume = 0.75f;
|
|
|
|
}
|
|
|
|
|
2024-09-10 19:40:53 +02:00
|
|
|
if (wall_impact_type[iImpSndIndexLB] == SFX_BHIT_WOOD_LITE
|
|
|
|
|| wall_impact_type[iImpSndIndexLB] == SFX_BHIT_WOOD_HARD) {
|
2023-07-10 23:08:27 +02:00
|
|
|
sSoundName = "snd_bh_metal";
|
2023-11-15 21:02:34 +01:00
|
|
|
} else {
|
2023-07-10 23:08:27 +02:00
|
|
|
sSoundName = "snd_bh_wood";
|
|
|
|
}
|
|
|
|
|
|
|
|
commandManager.PlaySound(sSoundName, wall_impact_pos[iImpSndIndexLB], -1, fVolume, -1, -1, 1);
|
|
|
|
|
|
|
|
sfxManager.MakeEffect_Normal(
|
|
|
|
wall_impact_type[iImpSndIndexLB],
|
|
|
|
wall_impact_pos[iImpSndIndexLB],
|
|
|
|
wall_impact_norm[iImpSndIndexLB]
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
CG_MakeBulletHole(
|
|
|
|
wall_impact_pos[iImpSndIndexLB],
|
|
|
|
wall_impact_norm[iImpSndIndexLB],
|
|
|
|
wall_impact_large[iImpSndIndexLB],
|
|
|
|
NULL,
|
|
|
|
qtrue
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2023-11-15 21:02:34 +01:00
|
|
|
} else {
|
2023-07-10 23:08:27 +02:00
|
|
|
for (i = 0; i < wall_impact_count; i++) {
|
2023-11-15 21:02:34 +01:00
|
|
|
CG_MakeBulletHole(wall_impact_pos[i], wall_impact_norm[i], wall_impact_large[i], NULL, qtrue);
|
2023-07-10 23:08:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-10 23:58:05 +02:00
|
|
|
wall_impact_count = 0;
|
2023-07-10 23:08:27 +02:00
|
|
|
}
|
|
|
|
|
2023-11-15 21:02:34 +01:00
|
|
|
if (flesh_impact_count) {
|
|
|
|
if (flesh_impact_count > 1) {
|
|
|
|
fImpSndDistRA = 9999.0;
|
2024-08-31 17:57:28 +02:00
|
|
|
fImpSndDistRB = 9999.0;
|
2023-07-10 23:08:27 +02:00
|
|
|
iImpSndIndexRA = 0;
|
2024-08-31 17:57:28 +02:00
|
|
|
iImpSndIndexRB = 0;
|
2023-07-10 23:08:27 +02:00
|
|
|
|
|
|
|
for (i = 0; i < flesh_impact_count; i++) {
|
2024-08-31 17:57:28 +02:00
|
|
|
VectorSubtract(flesh_impact_pos[i], cg.SoundOrg, vTmp);
|
2023-07-10 23:08:27 +02:00
|
|
|
iHeadDist = VectorLength(vTmp);
|
2023-11-15 21:02:34 +01:00
|
|
|
|
|
|
|
if (DotProduct(vTmp, cg.SoundAxis[1]) > 0.f) {
|
2024-08-31 17:57:28 +02:00
|
|
|
if (iHeadDist < fImpSndDistRB) {
|
2023-11-15 21:02:34 +01:00
|
|
|
fImpSndDistRA = iHeadDist;
|
2023-07-10 23:08:27 +02:00
|
|
|
iImpSndIndexRA = i;
|
|
|
|
}
|
2023-11-15 21:02:34 +01:00
|
|
|
} else if (iHeadDist < fImpSndDistLA) {
|
|
|
|
fImpSndDistRA = iHeadDist;
|
2023-07-10 23:08:27 +02:00
|
|
|
iImpSndIndexRA = i;
|
|
|
|
}
|
|
|
|
}
|
2024-08-31 17:57:28 +02:00
|
|
|
|
|
|
|
if (fImpSndDistRA < 9999) {
|
|
|
|
sfxManager.MakeEffect_Normal(
|
|
|
|
flesh_impact_large[iImpSndIndexRA] ? SFX_BHIT_HUMAN_UNIFORM_HARD : SFX_BHIT_HUMAN_UNIFORM_LITE,
|
|
|
|
flesh_impact_pos[iImpSndIndexRA],
|
|
|
|
flesh_impact_norm[iImpSndIndexRA]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fImpSndDistRB < 9999) {
|
|
|
|
sfxManager.MakeEffect_Normal(
|
|
|
|
flesh_impact_large[iImpSndIndexRB] ? SFX_BHIT_HUMAN_UNIFORM_HARD : SFX_BHIT_HUMAN_UNIFORM_LITE,
|
|
|
|
flesh_impact_pos[iImpSndIndexRB],
|
|
|
|
flesh_impact_norm[iImpSndIndexRB]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < flesh_impact_count; i++) {
|
|
|
|
sfxManager.MakeEffect_Normal(
|
|
|
|
flesh_impact_large[i] ? SFX_BHIT_HUMAN_UNIFORM_HARD : SFX_BHIT_HUMAN_UNIFORM_LITE,
|
|
|
|
flesh_impact_pos[i],
|
|
|
|
flesh_impact_norm[i]
|
|
|
|
);
|
|
|
|
}
|
2023-07-10 23:08:27 +02:00
|
|
|
}
|
|
|
|
|
2023-07-10 23:58:05 +02:00
|
|
|
flesh_impact_count = 0;
|
|
|
|
}
|
2023-05-01 15:10:26 +02:00
|
|
|
}
|
|
|
|
|
2023-07-18 00:09:02 +02:00
|
|
|
void CG_MakeExplosionEffect(const vec3_t vPos, int iType)
|
2023-07-05 21:24:23 +02:00
|
|
|
{
|
|
|
|
int iSurfType;
|
|
|
|
int iBaseEffect;
|
|
|
|
int iSurfEffect;
|
|
|
|
float fRadius;
|
|
|
|
vec3_t vEnd;
|
|
|
|
str sMark;
|
|
|
|
trace_t trace;
|
2023-05-05 20:43:23 +02:00
|
|
|
qhandle_t shader;
|
|
|
|
|
|
|
|
vEnd[0] = vPos[0];
|
|
|
|
vEnd[1] = vPos[1];
|
|
|
|
vEnd[2] = vPos[2] - 64.0;
|
|
|
|
fRadius = 64.0;
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if ((CG_PointContents(vPos, 0)) & MASK_WATER) {
|
2023-07-22 17:35:02 +02:00
|
|
|
iBaseEffect = SFX_EXP_GREN_PUDDLE;
|
2023-05-05 20:43:23 +02:00
|
|
|
sfxManager.MakeEffect_Normal(iBaseEffect, vPos, Vector(0, 0, 1));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-06-09 20:16:14 +02:00
|
|
|
if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) {
|
|
|
|
switch (iType) {
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_EXPLOSION_EFFECT_1:
|
2024-06-09 20:16:14 +02:00
|
|
|
iBaseEffect = SFX_EXP_GREN_BASE;
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_EXPLOSION_EFFECT_2:
|
2024-06-09 20:16:14 +02:00
|
|
|
iBaseEffect = SFX_EXP_BAZOOKA_BASE;
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_EXPLOSION_EFFECT_3:
|
2024-06-09 20:16:14 +02:00
|
|
|
iBaseEffect = SFX_EXP_HEAVYSHELL_BASE;
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_EXPLOSION_EFFECT_4:
|
2024-06-09 20:16:14 +02:00
|
|
|
iBaseEffect = SFX_EXP_TANK_BASE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
iBaseEffect = SFX_EXP_GREN_BASE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch (iType) {
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_EXPLOSION_EFFECT_2:
|
2024-06-09 20:16:14 +02:00
|
|
|
iBaseEffect = SFX_EXP_BAZOOKA_BASE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
iBaseEffect = SFX_EXP_GREN_BASE;
|
|
|
|
break;
|
|
|
|
}
|
2023-05-05 20:43:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CG_Trace(
|
2023-07-05 21:24:23 +02:00
|
|
|
&trace, vPos, vec_zero, vec_zero, vEnd, ENTITYNUM_NONE, MASK_EXPLOSION, qfalse, qtrue, "CG_MakeExplosionEffect"
|
2023-05-05 20:43:23 +02:00
|
|
|
);
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (trace.fraction == 1.0 || trace.startsolid) {
|
2023-05-05 20:43:23 +02:00
|
|
|
// exploded in the air
|
|
|
|
sfxManager.MakeEffect_Normal(iBaseEffect, vPos, Vector(0, 0, 1));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-07-18 00:09:02 +02:00
|
|
|
VectorMA(trace.endpos, 32.0, trace.plane.normal, vEnd);
|
2023-05-05 20:43:23 +02:00
|
|
|
|
|
|
|
iSurfType = trace.surfaceFlags & MASK_SURF_TYPE;
|
2023-07-05 21:24:23 +02:00
|
|
|
switch (iSurfType) {
|
2023-05-05 20:43:23 +02:00
|
|
|
case SURF_FOLIAGE:
|
2023-07-22 17:35:02 +02:00
|
|
|
iSurfEffect = SFX_EXP_GREN_FOLIAGE;
|
2023-07-05 21:24:23 +02:00
|
|
|
fRadius = 0;
|
2023-05-05 20:43:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_SNOW:
|
2023-11-15 21:02:34 +01:00
|
|
|
switch (iBaseEffect) {
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_TANK_BASE:
|
|
|
|
iSurfEffect = SFX_EXP_TANK_SNOW;
|
|
|
|
break;
|
|
|
|
case SFX_EXP_BAZOOKA_BASE:
|
|
|
|
iSurfEffect = SFX_EXP_BAZOOKA_SNOW;
|
2024-06-09 20:16:14 +02:00
|
|
|
if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) {
|
|
|
|
iBaseEffect = -1;
|
|
|
|
}
|
2023-07-22 17:35:02 +02:00
|
|
|
break;
|
|
|
|
case SFX_EXP_HEAVYSHELL_BASE:
|
|
|
|
iSurfEffect = SFX_EXP_HEAVYSHELL_SNOW;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
iSurfEffect = SFX_EXP_GREN_SNOW;
|
2024-06-09 20:16:14 +02:00
|
|
|
if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) {
|
|
|
|
iBaseEffect = -1;
|
|
|
|
}
|
2023-07-22 17:35:02 +02:00
|
|
|
break;
|
|
|
|
}
|
2023-11-15 21:02:34 +01:00
|
|
|
fRadius = 0;
|
2023-05-05 20:43:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_CARPET:
|
2023-07-22 17:35:02 +02:00
|
|
|
iSurfEffect = SFX_EXP_GREN_CARPET;
|
2023-05-05 20:43:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_SAND:
|
2023-07-22 17:35:02 +02:00
|
|
|
iSurfEffect = SFX_EXP_GREN_SAND;
|
2023-07-05 21:24:23 +02:00
|
|
|
fRadius = 0;
|
2023-05-05 20:43:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_PUDDLE:
|
|
|
|
iSurfEffect = -1;
|
2023-07-05 21:24:23 +02:00
|
|
|
fRadius = 0;
|
2023-05-05 20:43:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_GLASS:
|
|
|
|
iSurfEffect = -1;
|
2023-07-05 21:24:23 +02:00
|
|
|
fRadius = 0;
|
2023-05-05 20:43:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_GRAVEL:
|
2023-07-22 17:35:02 +02:00
|
|
|
iSurfEffect = SFX_EXP_GREN_GRAVEL;
|
2023-05-05 20:43:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_MUD:
|
2023-07-22 17:35:02 +02:00
|
|
|
iSurfEffect = SFX_EXP_GREN_MUD;
|
2023-07-05 21:24:23 +02:00
|
|
|
fRadius = 0;
|
2023-05-05 20:43:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_DIRT:
|
2023-11-15 21:02:34 +01:00
|
|
|
switch (iBaseEffect) {
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_TANK_BASE:
|
|
|
|
iSurfEffect = SFX_EXP_TANK_DIRT;
|
|
|
|
break;
|
|
|
|
case SFX_EXP_BAZOOKA_BASE:
|
|
|
|
iSurfEffect = SFX_EXP_BAZOOKA_DIRT;
|
2024-06-09 20:16:14 +02:00
|
|
|
if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) {
|
|
|
|
iBaseEffect = -1;
|
|
|
|
}
|
2023-07-22 17:35:02 +02:00
|
|
|
break;
|
|
|
|
case SFX_EXP_HEAVYSHELL_BASE:
|
|
|
|
iSurfEffect = SFX_EXP_HEAVYSHELL_DIRT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
iSurfEffect = SFX_EXP_GREN_DIRT;
|
2024-06-09 20:16:14 +02:00
|
|
|
if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) {
|
|
|
|
iBaseEffect = -1;
|
|
|
|
}
|
2023-07-22 17:35:02 +02:00
|
|
|
break;
|
|
|
|
}
|
2023-11-15 21:02:34 +01:00
|
|
|
fRadius = 0;
|
2023-05-05 20:43:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_GRILL:
|
2023-07-22 17:35:02 +02:00
|
|
|
iSurfEffect = SFX_EXP_GREN_GRILL;
|
2023-07-05 21:24:23 +02:00
|
|
|
fRadius = 0;
|
2023-05-05 20:43:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_GRASS:
|
2023-11-15 21:02:34 +01:00
|
|
|
switch (iBaseEffect) {
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_TANK_BASE:
|
|
|
|
iSurfEffect = SFX_EXP_TANK_DIRT;
|
|
|
|
break;
|
|
|
|
case SFX_EXP_BAZOOKA_BASE:
|
|
|
|
iSurfEffect = SFX_EXP_BAZOOKA_DIRT;
|
|
|
|
break;
|
|
|
|
case SFX_EXP_HEAVYSHELL_BASE:
|
|
|
|
iSurfEffect = SFX_EXP_HEAVYSHELL_DIRT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
iSurfEffect = SFX_EXP_GREN_GRASS;
|
2024-06-09 20:16:14 +02:00
|
|
|
if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) {
|
|
|
|
iBaseEffect = -1;
|
|
|
|
}
|
2023-07-22 17:35:02 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
fRadius = 0;
|
2023-05-05 20:43:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_ROCK:
|
2023-11-15 21:02:34 +01:00
|
|
|
switch (iBaseEffect) {
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_TANK_BASE:
|
|
|
|
iSurfEffect = SFX_EXP_TANK_STONE;
|
|
|
|
break;
|
|
|
|
case SFX_EXP_BAZOOKA_BASE:
|
|
|
|
iSurfEffect = SFX_EXP_BAZOOKA_STONE;
|
2024-06-09 20:16:14 +02:00
|
|
|
if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) {
|
|
|
|
iBaseEffect = -1;
|
|
|
|
}
|
2023-07-22 17:35:02 +02:00
|
|
|
break;
|
|
|
|
case SFX_EXP_HEAVYSHELL_BASE:
|
|
|
|
iSurfEffect = SFX_EXP_HEAVYSHELL_STONE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
iSurfEffect = SFX_EXP_GREN_STONE;
|
2024-06-09 20:16:14 +02:00
|
|
|
if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) {
|
|
|
|
iBaseEffect = -1;
|
|
|
|
}
|
2023-07-22 17:35:02 +02:00
|
|
|
break;
|
|
|
|
}
|
2023-05-05 20:43:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_PAPER:
|
2023-07-22 17:35:02 +02:00
|
|
|
iSurfEffect = SFX_EXP_GREN_PAPER;
|
2023-05-05 20:43:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_WOOD:
|
2023-07-22 17:35:02 +02:00
|
|
|
iSurfEffect = SFX_EXP_GREN_WOOD;
|
2023-05-05 20:43:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_METAL:
|
2023-07-22 17:35:02 +02:00
|
|
|
iSurfEffect = SFX_EXP_GREN_METAL;
|
2023-05-05 20:43:23 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
iSurfEffect = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sMark = "blastmark";
|
2023-07-05 21:24:23 +02:00
|
|
|
if (fRadius) {
|
2023-07-18 00:09:02 +02:00
|
|
|
fRadius *= 1.f + crandom() * 0.1;
|
2023-05-05 20:43:23 +02:00
|
|
|
shader = cgi.R_RegisterShader(sMark.c_str());
|
|
|
|
|
|
|
|
CG_ImpactMarkSimple(
|
|
|
|
shader,
|
|
|
|
trace.endpos,
|
|
|
|
trace.plane.normal,
|
|
|
|
random() * 360.0,
|
|
|
|
fRadius,
|
2023-07-05 21:24:23 +02:00
|
|
|
1,
|
|
|
|
1,
|
|
|
|
1,
|
|
|
|
1,
|
2023-05-05 20:43:23 +02:00
|
|
|
qfalse,
|
|
|
|
qfalse,
|
|
|
|
qtrue,
|
|
|
|
qfalse
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-07-18 00:09:02 +02:00
|
|
|
VectorMA(vEnd, 1.0, trace.plane.normal, vEnd);
|
2023-05-05 20:43:23 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (iSurfEffect != -1) {
|
2023-05-05 20:43:23 +02:00
|
|
|
sfxManager.MakeEffect_Normal(
|
2023-07-05 21:24:23 +02:00
|
|
|
iSurfEffect, Vector(trace.endpos) + Vector(trace.plane.normal), trace.plane.normal
|
2023-05-05 20:43:23 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-06-09 20:16:14 +02:00
|
|
|
if (iBaseEffect != -1) {
|
|
|
|
sfxManager.MakeEffect_Normal(iBaseEffect, vEnd, trace.plane.normal);
|
|
|
|
}
|
2023-05-05 20:43:23 +02:00
|
|
|
}
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
void CG_MakeVehicleEffect(vec3_t i_vStart, vec3_t i_vEnd, vec3_t i_vDir)
|
|
|
|
{
|
|
|
|
vec3_t vDir, vFrom, vDest;
|
2023-05-05 20:43:23 +02:00
|
|
|
trace_t trace;
|
|
|
|
|
|
|
|
VectorSubtract(i_vEnd, i_vStart, vDir);
|
|
|
|
VectorNormalizeFast(vDir);
|
|
|
|
VectorMA(i_vEnd, -16.0, vDir, vFrom);
|
|
|
|
VectorMA(i_vEnd, 16.0, vDir, vDest);
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
CG_Trace(
|
|
|
|
&trace, vFrom, vec_zero, vec_zero, vDest, ENTITYNUM_NONE, MASK_PLAYERSOLID, qfalse, qtrue, "CG_MakeBulletHole"
|
|
|
|
);
|
2023-05-05 20:43:23 +02:00
|
|
|
cgi.R_DebugLine(vFrom, trace.endpos, 1.0, 1.0, 1.0, 1.0);
|
2023-05-04 20:30:52 +02:00
|
|
|
}
|
|
|
|
|
2023-07-01 21:17:59 +02:00
|
|
|
void CG_ParseCGMessage_ver_15()
|
2023-05-21 19:59:36 +02:00
|
|
|
{
|
2023-07-05 21:24:23 +02:00
|
|
|
int i;
|
|
|
|
int iType;
|
|
|
|
int iLarge;
|
|
|
|
int iInfo;
|
|
|
|
int iCount;
|
|
|
|
char *szTmp;
|
|
|
|
vec3_t vStart, vEnd, vTmp;
|
|
|
|
vec3_t vEndArray[MAX_IMPACTS];
|
|
|
|
float alpha;
|
|
|
|
|
|
|
|
qboolean bMoreCGameMessages = qtrue;
|
|
|
|
while (bMoreCGameMessages) {
|
|
|
|
iType = cgi.MSG_ReadBits(6);
|
|
|
|
|
|
|
|
switch (iType) {
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_BULLET_1:
|
|
|
|
case CGM_BULLET_2:
|
|
|
|
case CGM_BULLET_5:
|
|
|
|
if (iType == CGM_BULLET_1) {
|
2023-07-05 21:24:23 +02:00
|
|
|
vTmp[0] = cgi.MSG_ReadCoord();
|
|
|
|
vTmp[1] = cgi.MSG_ReadCoord();
|
|
|
|
vTmp[2] = cgi.MSG_ReadCoord();
|
|
|
|
}
|
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
if (iType != CGM_BULLET_1) {
|
2023-07-05 21:24:23 +02:00
|
|
|
vTmp[0] = vStart[0];
|
|
|
|
vTmp[1] = vStart[1];
|
|
|
|
vTmp[2] = vStart[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
vEndArray[0][0] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[0][1] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[0][2] = cgi.MSG_ReadCoord();
|
|
|
|
iLarge = cgi.MSG_ReadBits(2);
|
2023-05-21 19:59:36 +02:00
|
|
|
if (cgi.MSG_ReadBits(1)) {
|
|
|
|
int iAlpha = cgi.MSG_ReadBits(10);
|
2023-07-05 21:24:23 +02:00
|
|
|
alpha = (float)iAlpha / 512.0;
|
2023-07-10 21:11:01 +02:00
|
|
|
if (alpha < 0.002f) {
|
|
|
|
alpha = 0.002f;
|
2023-05-21 19:59:36 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
alpha = 1.0f;
|
|
|
|
}
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
if (iType == CGM_BULLET_1) {
|
|
|
|
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qtrue, qtrue, alpha);
|
|
|
|
} else if (iType == CGM_BULLET_2) {
|
2023-07-05 21:24:23 +02:00
|
|
|
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue, alpha);
|
|
|
|
} else {
|
|
|
|
CG_MakeBubbleTrail(vStart, vEndArray[0], iLarge, alpha);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_BULLET_3:
|
|
|
|
case CGM_BULLET_4:
|
|
|
|
if (iType == CGM_BULLET_3) {
|
2023-07-05 21:24:23 +02:00
|
|
|
vTmp[0] = cgi.MSG_ReadCoord();
|
|
|
|
vTmp[1] = cgi.MSG_ReadCoord();
|
|
|
|
vTmp[2] = cgi.MSG_ReadCoord();
|
|
|
|
iInfo = cgi.MSG_ReadBits(6);
|
|
|
|
} else {
|
|
|
|
iInfo = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
iLarge = cgi.MSG_ReadBits(2);
|
|
|
|
if (cgi.MSG_ReadBits(1)) {
|
|
|
|
int iAlpha = cgi.MSG_ReadBits(10);
|
|
|
|
alpha = (float)iAlpha / 512.0;
|
2023-07-10 21:11:01 +02:00
|
|
|
if (alpha < 0.002f) {
|
|
|
|
alpha = 0.002f;
|
2023-07-05 21:24:23 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
alpha = 1.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
iCount = cgi.MSG_ReadBits(6);
|
|
|
|
for (i = 0; i < iCount; ++i) {
|
|
|
|
vEndArray[i][0] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[i][1] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[i][2] = cgi.MSG_ReadCoord();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iCount) {
|
|
|
|
CG_MakeBulletTracer(vTmp, vStart, vEndArray, iCount, iLarge, iInfo, qtrue, alpha);
|
|
|
|
}
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_BULLET_6:
|
|
|
|
case CGM_BULLET_7:
|
|
|
|
case CGM_BULLET_8:
|
|
|
|
case CGM_BULLET_9:
|
|
|
|
case CGM_BULLET_10:
|
|
|
|
case CGM_BULLET_11:
|
2023-07-05 21:24:23 +02:00
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
cgi.MSG_ReadDir(vEnd);
|
|
|
|
iLarge = cgi.MSG_ReadBits(2);
|
|
|
|
|
|
|
|
switch (iType) {
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_BULLET_6:
|
2023-07-05 21:24:23 +02:00
|
|
|
if (wall_impact_count < MAX_IMPACTS) {
|
|
|
|
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
|
|
|
|
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
|
|
|
|
wall_impact_large[wall_impact_count] = iLarge;
|
|
|
|
wall_impact_type[wall_impact_count] = -1;
|
|
|
|
wall_impact_count++;
|
|
|
|
}
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_BULLET_7:
|
2023-07-05 21:24:23 +02:00
|
|
|
if (wall_impact_count < MAX_IMPACTS) {
|
|
|
|
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
|
|
|
|
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
|
|
|
|
wall_impact_large[wall_impact_count] = iLarge;
|
2024-06-14 21:26:44 +02:00
|
|
|
wall_impact_type[wall_impact_count] = SFX_BHIT_STONE_LITE;
|
2023-07-05 21:24:23 +02:00
|
|
|
wall_impact_count++;
|
|
|
|
}
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_BULLET_8:
|
2023-07-05 21:24:23 +02:00
|
|
|
if (flesh_impact_count < MAX_IMPACTS) {
|
|
|
|
// negative
|
|
|
|
VectorNegate(vEnd, vEnd);
|
|
|
|
VectorCopy(vStart, flesh_impact_pos[flesh_impact_count]);
|
|
|
|
VectorCopy(vEnd, flesh_impact_norm[flesh_impact_count]);
|
|
|
|
flesh_impact_large[flesh_impact_count] = iLarge;
|
|
|
|
flesh_impact_count++;
|
|
|
|
}
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_BULLET_9:
|
2023-07-05 21:24:23 +02:00
|
|
|
if (flesh_impact_count < MAX_IMPACTS) {
|
|
|
|
// negative
|
|
|
|
VectorNegate(vEnd, vEnd);
|
|
|
|
VectorCopy(vStart, flesh_impact_pos[flesh_impact_count]);
|
|
|
|
VectorCopy(vEnd, flesh_impact_norm[flesh_impact_count]);
|
|
|
|
flesh_impact_large[flesh_impact_count] = iLarge;
|
|
|
|
flesh_impact_count++;
|
|
|
|
}
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_BULLET_10:
|
2023-07-05 21:24:23 +02:00
|
|
|
if (wall_impact_count < MAX_IMPACTS) {
|
|
|
|
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
|
|
|
|
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
|
|
|
|
wall_impact_large[wall_impact_count] = iLarge;
|
2024-06-14 21:26:44 +02:00
|
|
|
wall_impact_type[wall_impact_count] = SFX_BHIT_WOOD_LITE;
|
2023-07-05 21:24:23 +02:00
|
|
|
wall_impact_count++;
|
|
|
|
}
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_BULLET_11:
|
2023-07-05 21:24:23 +02:00
|
|
|
if (wall_impact_count < MAX_IMPACTS) {
|
|
|
|
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
|
|
|
|
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
|
|
|
|
wall_impact_large[wall_impact_count] = iLarge;
|
2024-06-14 21:26:44 +02:00
|
|
|
wall_impact_type[wall_impact_count] = SFX_BHIT_METAL_LITE;
|
2023-07-05 21:24:23 +02:00
|
|
|
wall_impact_count++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_MELEE_IMPACT:
|
2023-07-05 21:24:23 +02:00
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
vEnd[0] = cgi.MSG_ReadCoord();
|
|
|
|
vEnd[1] = cgi.MSG_ReadCoord();
|
|
|
|
vEnd[2] = cgi.MSG_ReadCoord();
|
|
|
|
CG_MeleeImpact(vStart, vEnd);
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_EXPLOSION_EFFECT_1:
|
|
|
|
case CGM_EXPLOSION_EFFECT_2:
|
|
|
|
case CGM_EXPLOSION_EFFECT_3:
|
|
|
|
case CGM_EXPLOSION_EFFECT_4:
|
2023-07-05 21:24:23 +02:00
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
CG_MakeExplosionEffect(vStart, iType);
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_MAKE_EFFECT_1:
|
|
|
|
case CGM_MAKE_EFFECT_2:
|
|
|
|
case CGM_MAKE_EFFECT_3:
|
|
|
|
case CGM_MAKE_EFFECT_4:
|
|
|
|
case CGM_MAKE_EFFECT_5:
|
|
|
|
case CGM_MAKE_EFFECT_6:
|
|
|
|
case CGM_MAKE_EFFECT_7:
|
|
|
|
case CGM_MAKE_EFFECT_8:
|
2023-07-05 21:24:23 +02:00
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
cgi.MSG_ReadDir(vEnd);
|
|
|
|
|
2024-11-22 18:18:27 +01:00
|
|
|
sfxManager.MakeEffect_Normal((iType - CGM_MAKE_EFFECT_1) + SFX_OIL_LEAK_BIG, vStart, vEnd);
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_MAKE_CRATE_DEBRIS:
|
|
|
|
case CGM_MAKE_WINDOW_DEBRIS:
|
2023-07-05 21:24:23 +02:00
|
|
|
{
|
|
|
|
str sEffect;
|
|
|
|
char cTmp[8];
|
|
|
|
vec3_t axis[3];
|
|
|
|
|
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
iLarge = cgi.MSG_ReadByte();
|
|
|
|
// get the integer as string
|
|
|
|
snprintf(cTmp, sizeof(cTmp), "%d", iLarge);
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
if (iType == CGM_MAKE_CRATE_DEBRIS) {
|
2023-07-05 21:24:23 +02:00
|
|
|
sEffect = "models/fx/crates/debris_";
|
|
|
|
} else {
|
|
|
|
sEffect = "models/fx/windows/debris_";
|
|
|
|
}
|
|
|
|
|
|
|
|
sEffect += cTmp;
|
|
|
|
sEffect += ".tik";
|
|
|
|
|
|
|
|
VectorSet(axis[0], 0, 0, 1);
|
|
|
|
VectorSet(axis[1], 0, 1, 0);
|
|
|
|
VectorSet(axis[2], 1, 0, 0);
|
|
|
|
|
|
|
|
cgi.R_SpawnEffectModel(sEffect.c_str(), vStart, axis);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_BULLET_NO_BARREL_1:
|
2023-07-05 21:24:23 +02:00
|
|
|
vTmp[0] = cgi.MSG_ReadCoord();
|
|
|
|
vTmp[1] = cgi.MSG_ReadCoord();
|
|
|
|
vTmp[2] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[0][0] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[0][1] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[0][2] = cgi.MSG_ReadCoord();
|
|
|
|
iLarge = cgi.MSG_ReadBits(2);
|
2024-06-14 21:26:44 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (cgi.MSG_ReadBits(1)) {
|
|
|
|
int iAlpha = cgi.MSG_ReadBits(10);
|
|
|
|
alpha = (float)iAlpha / 512.0;
|
2023-07-10 21:11:01 +02:00
|
|
|
if (alpha < 0.002f) {
|
|
|
|
alpha = 0.002f;
|
2023-07-05 21:24:23 +02:00
|
|
|
}
|
2023-05-21 19:59:36 +02:00
|
|
|
} else {
|
|
|
|
alpha = 1.0f;
|
|
|
|
}
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qtrue, qtrue, alpha);
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_BULLET_NO_BARREL_2:
|
2023-07-05 21:24:23 +02:00
|
|
|
memset(vTmp, 0, sizeof(vTmp));
|
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[0][0] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[0][1] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[0][2] = cgi.MSG_ReadCoord();
|
|
|
|
iLarge = cgi.MSG_ReadBits(1);
|
2024-06-14 21:26:44 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (cgi.MSG_ReadBits(1)) {
|
|
|
|
int iAlpha = cgi.MSG_ReadBits(10);
|
|
|
|
alpha = (float)iAlpha / 512.0;
|
2023-07-10 21:11:01 +02:00
|
|
|
if (alpha < 0.002f) {
|
|
|
|
alpha = 0.002f;
|
2023-07-05 21:24:23 +02:00
|
|
|
}
|
2023-05-21 19:59:36 +02:00
|
|
|
} else {
|
|
|
|
alpha = 1.0f;
|
|
|
|
}
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue, alpha);
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_HUDDRAW_SHADER:
|
2023-07-05 21:24:23 +02:00
|
|
|
iInfo = cgi.MSG_ReadByte();
|
2024-10-02 20:10:29 +02:00
|
|
|
Q_strncpyz(
|
|
|
|
cgi.HudDrawElements[iInfo].shaderName,
|
|
|
|
cgi.MSG_ReadString(),
|
|
|
|
sizeof(cgi.HudDrawElements[iInfo].shaderName)
|
|
|
|
);
|
2023-07-05 21:24:23 +02:00
|
|
|
cgi.HudDrawElements[iInfo].string[0] = 0;
|
|
|
|
cgi.HudDrawElements[iInfo].pFont = NULL;
|
|
|
|
cgi.HudDrawElements[iInfo].fontName[0] = 0;
|
|
|
|
// set the shader
|
|
|
|
CG_HudDrawShader(iInfo);
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_HUDDRAW_ALIGN:
|
2023-07-05 21:24:23 +02:00
|
|
|
iInfo = cgi.MSG_ReadByte();
|
|
|
|
cgi.HudDrawElements[iInfo].iHorizontalAlign = cgi.MSG_ReadBits(2);
|
|
|
|
cgi.HudDrawElements[iInfo].iVerticalAlign = cgi.MSG_ReadBits(2);
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_HUDDRAW_RECT:
|
2023-07-05 21:24:23 +02:00
|
|
|
iInfo = cgi.MSG_ReadByte();
|
|
|
|
cgi.HudDrawElements[iInfo].iX = cgi.MSG_ReadShort();
|
|
|
|
cgi.HudDrawElements[iInfo].iY = cgi.MSG_ReadShort();
|
|
|
|
cgi.HudDrawElements[iInfo].iWidth = cgi.MSG_ReadShort();
|
|
|
|
cgi.HudDrawElements[iInfo].iHeight = cgi.MSG_ReadShort();
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_HUDDRAW_VIRTUALSIZE:
|
2023-07-05 21:24:23 +02:00
|
|
|
iInfo = cgi.MSG_ReadByte();
|
|
|
|
cgi.HudDrawElements[iInfo].bVirtualScreen = cgi.MSG_ReadBits(1);
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_HUDDRAW_COLOR:
|
2023-07-05 21:24:23 +02:00
|
|
|
iInfo = cgi.MSG_ReadByte();
|
|
|
|
cgi.HudDrawElements[iInfo].vColor[0] = cgi.MSG_ReadByte() / 255.0;
|
|
|
|
cgi.HudDrawElements[iInfo].vColor[1] = cgi.MSG_ReadByte() / 255.0;
|
|
|
|
cgi.HudDrawElements[iInfo].vColor[2] = cgi.MSG_ReadByte() / 255.0;
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_HUDDRAW_ALPHA:
|
2023-07-05 21:24:23 +02:00
|
|
|
iInfo = cgi.MSG_ReadByte();
|
|
|
|
cgi.HudDrawElements[iInfo].vColor[3] = cgi.MSG_ReadByte() / 255.0;
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_HUDDRAW_STRING:
|
2023-07-05 21:24:23 +02:00
|
|
|
iInfo = cgi.MSG_ReadByte();
|
|
|
|
cgi.HudDrawElements[iInfo].hShader = 0;
|
2024-10-02 20:10:29 +02:00
|
|
|
Q_strncpyz(
|
|
|
|
cgi.HudDrawElements[iInfo].string, cgi.MSG_ReadString(), sizeof(cgi.HudDrawElements[iInfo].string)
|
|
|
|
);
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_HUDDRAW_FONT:
|
2023-07-05 21:24:23 +02:00
|
|
|
iInfo = cgi.MSG_ReadByte();
|
2024-10-02 20:10:29 +02:00
|
|
|
Q_strncpyz(
|
|
|
|
cgi.HudDrawElements[iInfo].fontName, cgi.MSG_ReadString(), sizeof(cgi.HudDrawElements[iInfo].fontName)
|
|
|
|
);
|
2023-07-05 21:24:23 +02:00
|
|
|
cgi.HudDrawElements[iInfo].hShader = 0;
|
|
|
|
cgi.HudDrawElements[iInfo].shaderName[0] = 0;
|
|
|
|
// load the font
|
|
|
|
CG_HudDrawFont(iInfo);
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_NOTIFY_KILL:
|
|
|
|
case CGM_NOTIFY_HIT:
|
2024-10-02 20:10:29 +02:00
|
|
|
if (cg.snap) {
|
|
|
|
const char *soundName;
|
|
|
|
int iOldEnt;
|
|
|
|
|
|
|
|
iOldEnt = current_entity_number;
|
2023-07-05 21:24:23 +02:00
|
|
|
|
|
|
|
current_entity_number = cg.snap->ps.clientNum;
|
2024-06-14 21:26:44 +02:00
|
|
|
if (iType == CGM_NOTIFY_HIT) {
|
2024-09-10 19:45:56 +02:00
|
|
|
soundName = "dm_kill_notify";
|
2023-07-05 21:24:23 +02:00
|
|
|
} else {
|
2024-09-10 19:45:56 +02:00
|
|
|
soundName = "dm_hit_notify";
|
2023-07-05 21:24:23 +02:00
|
|
|
}
|
2024-09-10 19:45:56 +02:00
|
|
|
commandManager.PlaySound(soundName, NULL, CHAN_LOCAL, 2.0, -1, -1, 1);
|
2023-07-05 21:24:23 +02:00
|
|
|
|
|
|
|
current_entity_number = iOldEnt;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_VOICE_CHAT:
|
2023-07-05 21:24:23 +02:00
|
|
|
{
|
|
|
|
int iOldEnt;
|
|
|
|
|
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
iLarge = cgi.MSG_ReadBits(1);
|
|
|
|
iInfo = cgi.MSG_ReadBits(6);
|
|
|
|
szTmp = cgi.MSG_ReadString();
|
|
|
|
|
|
|
|
iOldEnt = current_entity_number;
|
|
|
|
|
|
|
|
if (iLarge) {
|
|
|
|
current_entity_number = iInfo;
|
|
|
|
|
2024-09-10 19:45:56 +02:00
|
|
|
commandManager.PlaySound(szTmp, vStart, CHAN_AUTO, -1, -1, -1, 0);
|
|
|
|
} else if (cg.snap) {
|
2023-07-05 21:24:23 +02:00
|
|
|
current_entity_number = cg.snap->ps.clientNum;
|
|
|
|
|
2024-09-10 19:45:56 +02:00
|
|
|
commandManager.PlaySound(szTmp, vStart, CHAN_LOCAL, -1, -1, -1, 1);
|
2023-07-05 21:24:23 +02:00
|
|
|
}
|
|
|
|
|
2024-09-10 19:45:56 +02:00
|
|
|
CG_RadarClientSpeaks(iInfo);
|
2023-07-05 21:24:23 +02:00
|
|
|
current_entity_number = iOldEnt;
|
|
|
|
}
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM_FENCEPOST:
|
2024-09-10 19:40:53 +02:00
|
|
|
{
|
|
|
|
int iHalf;
|
|
|
|
vec3_t vForward, vRight, vUp;
|
|
|
|
float fLength;
|
|
|
|
|
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
vEnd[0] = cgi.MSG_ReadCoord();
|
|
|
|
vEnd[1] = cgi.MSG_ReadCoord();
|
|
|
|
vEnd[2] = cgi.MSG_ReadCoord();
|
|
|
|
iHalf = cgi.MSG_ReadByte();
|
|
|
|
cgi.MSG_ReadByte();
|
2023-05-21 19:59:36 +02:00
|
|
|
|
2024-09-10 19:40:53 +02:00
|
|
|
VectorSubtract(vEnd, vStart, vForward);
|
|
|
|
fLength = VectorNormalize(vForward);
|
|
|
|
iCount = fLength / 2.0;
|
|
|
|
|
|
|
|
MakeNormalVectors(vForward, vRight, vUp);
|
|
|
|
|
|
|
|
for (i = 0; i < iCount; i++) {
|
|
|
|
vec3_t vOrg;
|
|
|
|
vec3_t vNormal;
|
|
|
|
|
|
|
|
VectorCopy(vStart, vOrg);
|
|
|
|
|
|
|
|
VectorMA(vOrg, random(), vForward, vOrg);
|
|
|
|
VectorMA(vOrg, crandom() * iHalf, vRight, vOrg);
|
|
|
|
VectorMA(vOrg, crandom() * iHalf, vUp, vOrg);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Spawn the fence wood effect
|
|
|
|
//
|
|
|
|
|
|
|
|
VectorSubtract(vStart, vOrg, vNormal);
|
|
|
|
VectorNormalize(vNormal);
|
|
|
|
|
|
|
|
sfxManager.MakeEffect_Normal(SFX_FENCE_WOOD, vOrg, vNormal);
|
|
|
|
}
|
|
|
|
}
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cgi.Error(ERR_DROP, "CG_ParseCGMessage: Unknown CGM message type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
bMoreCGameMessages = cgi.MSG_ReadBits(1);
|
|
|
|
}
|
2023-05-21 19:59:36 +02:00
|
|
|
}
|
|
|
|
|
2023-07-01 21:17:59 +02:00
|
|
|
void CG_ParseCGMessage_ver_6()
|
2023-05-01 00:08:43 +02:00
|
|
|
{
|
2023-07-05 21:24:23 +02:00
|
|
|
int i;
|
|
|
|
int iType;
|
|
|
|
int iLarge;
|
|
|
|
int iInfo;
|
|
|
|
int iCount;
|
|
|
|
char *szTmp;
|
2023-05-04 20:30:52 +02:00
|
|
|
vec3_t vStart, vEnd, vTmp;
|
|
|
|
vec3_t vEndArray[MAX_IMPACTS];
|
|
|
|
|
|
|
|
qboolean bMoreCGameMessages = qtrue;
|
|
|
|
while (bMoreCGameMessages) {
|
|
|
|
iType = cgi.MSG_ReadBits(6);
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
switch (iType) {
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_BULLET_1:
|
|
|
|
case CGM6_BULLET_2:
|
|
|
|
case CGM6_BULLET_5:
|
|
|
|
if (iType == CGM6_BULLET_1) {
|
2023-05-04 20:30:52 +02:00
|
|
|
vTmp[0] = cgi.MSG_ReadCoord();
|
|
|
|
vTmp[1] = cgi.MSG_ReadCoord();
|
|
|
|
vTmp[2] = cgi.MSG_ReadCoord();
|
|
|
|
}
|
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
if (iType != CGM6_BULLET_1) {
|
2023-05-04 20:30:52 +02:00
|
|
|
vTmp[0] = vStart[0];
|
|
|
|
vTmp[1] = vStart[1];
|
|
|
|
vTmp[2] = vStart[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
vEndArray[0][0] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[0][1] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[0][2] = cgi.MSG_ReadCoord();
|
2023-07-05 21:24:23 +02:00
|
|
|
iLarge = cgi.MSG_ReadBits(1);
|
2023-05-04 20:30:52 +02:00
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
if (iType == CGM6_BULLET_1) {
|
2024-09-02 00:18:49 +02:00
|
|
|
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qtrue, qtrue);
|
2024-06-14 21:26:44 +02:00
|
|
|
} else if (iType == CGM6_BULLET_2) {
|
2023-05-04 20:30:52 +02:00
|
|
|
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue);
|
2023-07-05 21:24:23 +02:00
|
|
|
} else {
|
2023-05-04 20:30:52 +02:00
|
|
|
CG_MakeBubbleTrail(vStart, vEndArray[0], iLarge);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_BULLET_3:
|
|
|
|
case CGM6_BULLET_4:
|
|
|
|
if (iType == CGM6_BULLET_3) {
|
2023-05-04 20:30:52 +02:00
|
|
|
vTmp[0] = cgi.MSG_ReadCoord();
|
|
|
|
vTmp[1] = cgi.MSG_ReadCoord();
|
|
|
|
vTmp[2] = cgi.MSG_ReadCoord();
|
2023-07-05 21:24:23 +02:00
|
|
|
iInfo = cgi.MSG_ReadBits(6);
|
|
|
|
} else {
|
2023-05-04 20:30:52 +02:00
|
|
|
iInfo = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
2023-07-05 21:24:23 +02:00
|
|
|
iLarge = cgi.MSG_ReadBits(1);
|
|
|
|
iCount = cgi.MSG_ReadBits(6);
|
|
|
|
for (i = 0; i < iCount; ++i) {
|
2023-05-04 20:30:52 +02:00
|
|
|
vEndArray[i][0] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[i][1] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[i][2] = cgi.MSG_ReadCoord();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iCount) {
|
|
|
|
CG_MakeBulletTracer(vTmp, vStart, vEndArray, iCount, iLarge, iInfo, qtrue);
|
|
|
|
}
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_BULLET_6:
|
|
|
|
case CGM6_BULLET_7:
|
|
|
|
case CGM6_BULLET_8:
|
|
|
|
case CGM6_BULLET_9:
|
|
|
|
case CGM6_BULLET_10:
|
2023-05-04 20:30:52 +02:00
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
cgi.MSG_ReadDir(vEnd);
|
|
|
|
iLarge = cgi.MSG_ReadBits(1);
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
switch (iType) {
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_BULLET_6:
|
2023-07-05 21:24:23 +02:00
|
|
|
if (wall_impact_count < MAX_IMPACTS) {
|
2023-05-04 20:30:52 +02:00
|
|
|
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
|
|
|
|
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
|
|
|
|
wall_impact_large[wall_impact_count] = iLarge;
|
2024-06-14 21:26:44 +02:00
|
|
|
wall_impact_type[wall_impact_count] = SFX_BHIT_PAPER_LITE;
|
2023-05-04 20:30:52 +02:00
|
|
|
wall_impact_count++;
|
|
|
|
}
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_BULLET_7:
|
2023-07-05 21:24:23 +02:00
|
|
|
if (flesh_impact_count < MAX_IMPACTS) {
|
2023-05-04 20:30:52 +02:00
|
|
|
// negative
|
|
|
|
VectorNegate(vEnd, vEnd);
|
|
|
|
VectorCopy(vStart, flesh_impact_pos[flesh_impact_count]);
|
|
|
|
VectorCopy(vEnd, flesh_impact_norm[flesh_impact_count]);
|
|
|
|
flesh_impact_large[flesh_impact_count] = iLarge;
|
|
|
|
flesh_impact_count++;
|
|
|
|
}
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_BULLET_8:
|
2023-07-05 21:24:23 +02:00
|
|
|
if (flesh_impact_count < MAX_IMPACTS) {
|
2023-05-04 20:30:52 +02:00
|
|
|
// negative
|
|
|
|
VectorNegate(vEnd, vEnd);
|
|
|
|
VectorCopy(vStart, flesh_impact_pos[flesh_impact_count]);
|
|
|
|
VectorCopy(vEnd, flesh_impact_norm[flesh_impact_count]);
|
|
|
|
flesh_impact_large[flesh_impact_count] = iLarge;
|
|
|
|
flesh_impact_count++;
|
|
|
|
}
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_BULLET_9:
|
2023-07-05 21:24:23 +02:00
|
|
|
if (wall_impact_count < MAX_IMPACTS) {
|
2023-05-04 20:30:52 +02:00
|
|
|
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
|
|
|
|
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
|
|
|
|
wall_impact_large[wall_impact_count] = iLarge;
|
2024-06-14 21:26:44 +02:00
|
|
|
wall_impact_type[wall_impact_count] = iLarge ? SFX_BHIT_WOOD_HARD : SFX_BHIT_WOOD_LITE;
|
2023-05-04 20:30:52 +02:00
|
|
|
wall_impact_count++;
|
|
|
|
}
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_BULLET_10:
|
2023-07-05 21:24:23 +02:00
|
|
|
if (wall_impact_count < MAX_IMPACTS) {
|
2023-05-04 20:30:52 +02:00
|
|
|
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
|
|
|
|
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
|
|
|
|
wall_impact_large[wall_impact_count] = iLarge;
|
2024-06-14 21:26:44 +02:00
|
|
|
wall_impact_type[wall_impact_count] = iLarge ? SFX_BHIT_METAL_HARD : SFX_BHIT_METAL_LITE;
|
2023-05-04 20:30:52 +02:00
|
|
|
wall_impact_count++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_MELEE_IMPACT:
|
2023-05-04 20:30:52 +02:00
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
2023-07-05 21:24:23 +02:00
|
|
|
vEnd[0] = cgi.MSG_ReadCoord();
|
|
|
|
vEnd[1] = cgi.MSG_ReadCoord();
|
|
|
|
vEnd[2] = cgi.MSG_ReadCoord();
|
2023-05-04 20:30:52 +02:00
|
|
|
CG_MeleeImpact(vStart, vEnd);
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_EXPLOSION_EFFECT_1:
|
|
|
|
case CGM6_EXPLOSION_EFFECT_2:
|
2023-05-04 20:30:52 +02:00
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
CG_MakeExplosionEffect(vStart, iType);
|
|
|
|
break;
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_MAKE_EFFECT_1:
|
|
|
|
case CGM6_MAKE_EFFECT_2:
|
|
|
|
case CGM6_MAKE_EFFECT_3:
|
|
|
|
case CGM6_MAKE_EFFECT_4:
|
|
|
|
case CGM6_MAKE_EFFECT_5:
|
|
|
|
case CGM6_MAKE_EFFECT_6:
|
|
|
|
case CGM6_MAKE_EFFECT_7:
|
|
|
|
case CGM6_MAKE_EFFECT_8:
|
2023-05-04 20:30:52 +02:00
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
cgi.MSG_ReadDir(vEnd);
|
|
|
|
|
2024-11-22 18:18:27 +01:00
|
|
|
sfxManager.MakeEffect_Normal((iType - CGM6_MAKE_EFFECT_1) + SFX_OIL_LEAK_BIG, vStart, vEnd);
|
2023-05-04 20:30:52 +02:00
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_MAKE_CRATE_DEBRIS:
|
|
|
|
case CGM6_MAKE_WINDOW_DEBRIS:
|
2023-07-05 21:24:23 +02:00
|
|
|
{
|
|
|
|
str sEffect;
|
|
|
|
char cTmp[8];
|
|
|
|
vec3_t axis[3];
|
|
|
|
|
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
iLarge = cgi.MSG_ReadByte();
|
|
|
|
// get the integer as string
|
|
|
|
snprintf(cTmp, sizeof(cTmp), "%d", iLarge);
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
if (iType == CGM6_MAKE_CRATE_DEBRIS) {
|
2023-07-05 21:24:23 +02:00
|
|
|
sEffect = "models/fx/crates/debris_";
|
|
|
|
} else {
|
|
|
|
sEffect = "models/fx/windows/debris_";
|
|
|
|
}
|
2023-05-04 20:30:52 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
sEffect += cTmp;
|
|
|
|
sEffect += ".tik";
|
2023-05-04 20:30:52 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
VectorSet(axis[0], 0, 0, 1);
|
|
|
|
VectorSet(axis[1], 0, 1, 0);
|
|
|
|
VectorSet(axis[2], 1, 0, 0);
|
2023-05-04 20:30:52 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
cgi.R_SpawnEffectModel(sEffect.c_str(), vStart, axis);
|
|
|
|
}
|
|
|
|
break;
|
2023-05-04 20:30:52 +02:00
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_BULLET_NO_BARREL_1:
|
2023-07-05 21:24:23 +02:00
|
|
|
vTmp[0] = cgi.MSG_ReadCoord();
|
|
|
|
vTmp[1] = cgi.MSG_ReadCoord();
|
|
|
|
vTmp[2] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
2023-05-04 20:30:52 +02:00
|
|
|
vEndArray[0][0] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[0][1] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[0][2] = cgi.MSG_ReadCoord();
|
2023-07-05 21:24:23 +02:00
|
|
|
iLarge = cgi.MSG_ReadBits(1);
|
2023-05-04 20:30:52 +02:00
|
|
|
|
|
|
|
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qtrue, qtrue);
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_BULLET_NO_BARREL_2:
|
2023-05-04 20:30:52 +02:00
|
|
|
memset(vTmp, 0, sizeof(vTmp));
|
2023-07-05 21:24:23 +02:00
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
2023-05-04 20:30:52 +02:00
|
|
|
vEndArray[0][0] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[0][1] = cgi.MSG_ReadCoord();
|
|
|
|
vEndArray[0][2] = cgi.MSG_ReadCoord();
|
2023-07-05 21:24:23 +02:00
|
|
|
iLarge = cgi.MSG_ReadBits(1);
|
2023-05-04 20:30:52 +02:00
|
|
|
|
|
|
|
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue);
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_HUDDRAW_SHADER:
|
2023-05-04 20:30:52 +02:00
|
|
|
iInfo = cgi.MSG_ReadByte();
|
2024-10-02 20:10:29 +02:00
|
|
|
Q_strncpyz(
|
|
|
|
cgi.HudDrawElements[iInfo].shaderName,
|
|
|
|
cgi.MSG_ReadString(),
|
|
|
|
sizeof(cgi.HudDrawElements[iInfo].shaderName)
|
|
|
|
);
|
2023-07-05 21:24:23 +02:00
|
|
|
cgi.HudDrawElements[iInfo].string[0] = 0;
|
|
|
|
cgi.HudDrawElements[iInfo].pFont = NULL;
|
2023-05-04 20:30:52 +02:00
|
|
|
cgi.HudDrawElements[iInfo].fontName[0] = 0;
|
|
|
|
// set the shader
|
|
|
|
CG_HudDrawShader(iInfo);
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_HUDDRAW_ALIGN:
|
2023-07-05 21:24:23 +02:00
|
|
|
iInfo = cgi.MSG_ReadByte();
|
2023-05-04 20:30:52 +02:00
|
|
|
cgi.HudDrawElements[iInfo].iHorizontalAlign = cgi.MSG_ReadBits(2);
|
2023-07-05 21:24:23 +02:00
|
|
|
cgi.HudDrawElements[iInfo].iVerticalAlign = cgi.MSG_ReadBits(2);
|
2023-05-04 20:30:52 +02:00
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_HUDDRAW_RECT:
|
2023-07-05 21:24:23 +02:00
|
|
|
iInfo = cgi.MSG_ReadByte();
|
|
|
|
cgi.HudDrawElements[iInfo].iX = cgi.MSG_ReadShort();
|
|
|
|
cgi.HudDrawElements[iInfo].iY = cgi.MSG_ReadShort();
|
|
|
|
cgi.HudDrawElements[iInfo].iWidth = cgi.MSG_ReadShort();
|
2023-05-04 20:30:52 +02:00
|
|
|
cgi.HudDrawElements[iInfo].iHeight = cgi.MSG_ReadShort();
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_HUDDRAW_VIRTUALSIZE:
|
2023-07-05 21:24:23 +02:00
|
|
|
iInfo = cgi.MSG_ReadByte();
|
2023-05-04 20:30:52 +02:00
|
|
|
cgi.HudDrawElements[iInfo].bVirtualScreen = cgi.MSG_ReadBits(1);
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_HUDDRAW_COLOR:
|
2023-07-05 21:24:23 +02:00
|
|
|
iInfo = cgi.MSG_ReadByte();
|
2023-05-04 20:30:52 +02:00
|
|
|
cgi.HudDrawElements[iInfo].vColor[0] = cgi.MSG_ReadByte() / 255.0;
|
|
|
|
cgi.HudDrawElements[iInfo].vColor[1] = cgi.MSG_ReadByte() / 255.0;
|
|
|
|
cgi.HudDrawElements[iInfo].vColor[2] = cgi.MSG_ReadByte() / 255.0;
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_HUDDRAW_ALPHA:
|
2023-07-05 21:24:23 +02:00
|
|
|
iInfo = cgi.MSG_ReadByte();
|
2023-05-04 20:30:52 +02:00
|
|
|
cgi.HudDrawElements[iInfo].vColor[3] = cgi.MSG_ReadByte() / 255.0;
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_HUDDRAW_STRING:
|
2023-07-05 21:24:23 +02:00
|
|
|
iInfo = cgi.MSG_ReadByte();
|
2023-05-04 20:30:52 +02:00
|
|
|
cgi.HudDrawElements[iInfo].hShader = 0;
|
2024-10-02 20:10:29 +02:00
|
|
|
Q_strncpyz(
|
|
|
|
cgi.HudDrawElements[iInfo].string, cgi.MSG_ReadString(), sizeof(cgi.HudDrawElements[iInfo].string)
|
|
|
|
);
|
2023-05-04 20:30:52 +02:00
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_HUDDRAW_FONT:
|
2023-05-04 20:30:52 +02:00
|
|
|
iInfo = cgi.MSG_ReadByte();
|
2024-10-02 20:10:29 +02:00
|
|
|
Q_strncpyz(
|
|
|
|
cgi.HudDrawElements[iInfo].fontName, cgi.MSG_ReadString(), sizeof(cgi.HudDrawElements[iInfo].fontName)
|
|
|
|
);
|
2023-07-05 21:24:23 +02:00
|
|
|
cgi.HudDrawElements[iInfo].hShader = 0;
|
2023-05-04 20:30:52 +02:00
|
|
|
cgi.HudDrawElements[iInfo].shaderName[0] = 0;
|
|
|
|
// load the font
|
|
|
|
CG_HudDrawFont(iInfo);
|
|
|
|
break;
|
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_NOTIFY_KILL:
|
|
|
|
case CGM6_NOTIFY_HIT:
|
2024-10-02 20:10:29 +02:00
|
|
|
if (cg.snap) {
|
2023-07-05 21:24:23 +02:00
|
|
|
int iOldEnt;
|
2023-05-04 20:30:52 +02:00
|
|
|
|
2024-10-02 20:10:29 +02:00
|
|
|
iOldEnt = current_entity_number;
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
current_entity_number = cg.snap->ps.clientNum;
|
2024-06-14 21:26:44 +02:00
|
|
|
if (iType == CGM6_NOTIFY_HIT) {
|
2023-07-05 21:24:23 +02:00
|
|
|
commandManager.PlaySound("dm_kill_notify", NULL, CHAN_LOCAL, 2.0, -1, -1, 1);
|
|
|
|
} else {
|
|
|
|
commandManager.PlaySound("dm_hit_notify", NULL, CHAN_LOCAL, 2.0, -1, -1, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
current_entity_number = iOldEnt;
|
|
|
|
}
|
|
|
|
break;
|
2023-05-04 20:30:52 +02:00
|
|
|
|
2024-06-14 21:26:44 +02:00
|
|
|
case CGM6_VOICE_CHAT:
|
2023-07-05 21:24:23 +02:00
|
|
|
{
|
|
|
|
int iOldEnt;
|
2023-05-04 20:30:52 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
vStart[0] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[1] = cgi.MSG_ReadCoord();
|
|
|
|
vStart[2] = cgi.MSG_ReadCoord();
|
|
|
|
iLarge = cgi.MSG_ReadBits(1);
|
|
|
|
iInfo = cgi.MSG_ReadBits(6);
|
|
|
|
szTmp = cgi.MSG_ReadString();
|
2023-05-04 20:30:52 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
iOldEnt = current_entity_number;
|
2023-05-04 20:30:52 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (iLarge) {
|
|
|
|
current_entity_number = iInfo;
|
|
|
|
|
|
|
|
commandManager.PlaySound(szTmp, vStart, CHAN_LOCAL, -1, -1, -1, 0);
|
2024-10-19 20:39:57 +02:00
|
|
|
} else if (cg.snap) {
|
2023-07-05 21:24:23 +02:00
|
|
|
current_entity_number = cg.snap->ps.clientNum;
|
|
|
|
|
2024-10-19 20:39:57 +02:00
|
|
|
commandManager.PlaySound(szTmp, vStart, CHAN_LOCAL, -1, -1, -1, 1);
|
2023-07-05 21:24:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
current_entity_number = iOldEnt;
|
|
|
|
}
|
2023-05-04 20:30:52 +02:00
|
|
|
break;
|
2023-05-21 19:59:36 +02:00
|
|
|
default:
|
|
|
|
cgi.Error(ERR_DROP, "CG_ParseCGMessage: Unknown CGM message type");
|
|
|
|
break;
|
2023-05-04 20:30:52 +02:00
|
|
|
}
|
2023-05-04 21:07:44 +02:00
|
|
|
|
|
|
|
bMoreCGameMessages = cgi.MSG_ReadBits(1);
|
2023-05-04 20:30:52 +02:00
|
|
|
}
|
2023-05-01 00:08:43 +02:00
|
|
|
}
|
2023-07-01 21:17:59 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
void CG_InitCGMessageAPI(clientGameExport_t *cge)
|
2023-07-02 19:18:37 +02:00
|
|
|
{
|
|
|
|
if (cg_protocol >= PROTOCOL_MOHTA_MIN) {
|
2023-07-05 21:24:23 +02:00
|
|
|
cge->CG_ParseCGMessage = &CG_ParseCGMessage_ver_15;
|
2023-07-01 21:17:59 +02:00
|
|
|
} else {
|
2023-07-05 21:24:23 +02:00
|
|
|
cge->CG_ParseCGMessage = &CG_ParseCGMessage_ver_6;
|
|
|
|
}
|
2023-07-01 21:17:59 +02:00
|
|
|
}
|