2023-04-30 00:02:16 +02:00
|
|
|
/*
|
|
|
|
===========================================================================
|
|
|
|
Copyright (C) 2023 the OpenMoHAA team
|
|
|
|
|
|
|
|
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:
|
|
|
|
// Special Effects code
|
|
|
|
|
|
|
|
#include "cg_local.h"
|
|
|
|
#include "cg_commands.h"
|
2023-04-30 14:51:44 +02:00
|
|
|
#include "surfaceflags.h"
|
2023-05-01 15:10:17 +02:00
|
|
|
#include "cg_specialfx.h"
|
2023-04-30 00:02:16 +02:00
|
|
|
|
|
|
|
extern refEntity_t *current_entity;
|
2023-07-05 21:24:23 +02:00
|
|
|
extern dtiki_t *current_tiki;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
static vec3_t g_vFootstepMins = {-4, -4, 0};
|
|
|
|
static vec3_t g_vFootstepMaxs = {4, 4, 2};
|
2023-05-01 15:10:17 +02:00
|
|
|
static vec3_t g_vLadderstepMins;
|
|
|
|
static vec3_t g_vLadderstepMaxs;
|
|
|
|
|
|
|
|
ClientSpecialEffectsManager sfxManager;
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
Event EV_SFX_EffectDelay(
|
|
|
|
"effectdelay",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"iivvvvv",
|
|
|
|
"iEffect iCurrEmitter vPos vAngles vAxisA vAxisB vAxisC",
|
|
|
|
"Resumes the execution of iEffect effect from its iCurrEmitter emitter."
|
2023-05-01 15:10:17 +02:00
|
|
|
);
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
CLASS_DECLARATION(Listener, ClientSpecialEffectsManager, NULL) {
|
|
|
|
{&EV_SFX_EffectDelay, &ClientSpecialEffectsManager::ContinueEffectExecution},
|
|
|
|
{NULL, NULL }
|
2023-05-01 15:10:17 +02:00
|
|
|
};
|
|
|
|
|
2023-05-01 15:40:39 +02:00
|
|
|
specialeffectcommand_t::specialeffectcommand_t()
|
|
|
|
{
|
2023-07-05 21:24:23 +02:00
|
|
|
emitter = NULL;
|
|
|
|
fCommandTime = 0.0f;
|
|
|
|
endfcn = NULL;
|
2023-05-01 15:40:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
specialeffect_t::specialeffect_t()
|
|
|
|
{
|
2023-07-05 21:24:23 +02:00
|
|
|
m_iCommandCount = 0;
|
2023-05-01 15:40:39 +02:00
|
|
|
}
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
specialeffectcommand_t *specialeffect_t::AddNewCommand()
|
2023-05-06 23:36:27 +02:00
|
|
|
{
|
|
|
|
if (m_iCommandCount == MAX_SPECIAL_EFFECT_COMMANDS - 1) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_commands[m_iCommandCount] = new specialeffectcommand_t;
|
|
|
|
return m_commands[m_iCommandCount++];
|
|
|
|
}
|
|
|
|
|
2023-05-01 15:10:17 +02:00
|
|
|
ClientSpecialEffectsManager::ClientSpecialEffectsManager()
|
|
|
|
{
|
2023-07-05 21:24:23 +02:00
|
|
|
m_bEffectsLoaded = 0;
|
2023-05-01 15:10:17 +02:00
|
|
|
m_iNumPendingEvents = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClientSpecialEffectsManager::LoadEffects()
|
|
|
|
{
|
2023-07-05 21:24:23 +02:00
|
|
|
int i, j, k;
|
|
|
|
const char *szEffectModel;
|
|
|
|
float axis[3][3];
|
|
|
|
specialeffect_t *pEffect;
|
|
|
|
|
|
|
|
if (m_bEffectsLoaded) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cgi.DPrintf("Loading Special Effects...\n");
|
|
|
|
AxisClear(axis);
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_SPECIAL_EFFECTS; i++) {
|
|
|
|
switch (i) {
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_PAPER_LITE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_paper_lite.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_PAPER_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_paper_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_WOOD_LITE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_wood_lite.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_WOOD_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_wood_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_METAL_LITE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_metal_lite.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_METAL_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_metal_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_STONE_LITE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_stone_lite.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_STONE_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_stone_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_DIRT_LITE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_dirt_lite.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_DIRT_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_dirt_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_GRILL_LITE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_metal_lite.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_GRILL_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_metal_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_GRASS_LITE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_grass_lite.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_GRASS_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_grass_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_MUD_LITE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_mud_lite.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_MUD_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_mud_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_PUDDLE_LITE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_water_lite.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_PUDDLE_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_water_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_GLASS_LITE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_glass_lite.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_GLASS_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_glass_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_GRAVEL_LITE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_stone_lite.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_GRAVEL_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_stone_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_SAND_LITE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_sand_lite.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_SAND_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_sand_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_FOLIAGE_LITE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_foliage_lite.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_FOLIAGE_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_foliage_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_SNOW_LITE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_snow_lite.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_SNOW_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_snow_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_CARPET_LITE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_carpet_lite.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_CARPET_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_carpet_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_HUMAN_UNIFORM_LITE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_human_uniform_lite.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_BHIT_HUMAN_UNIFORM_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_human_uniform_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_WATER_TRAIL_BUBBLE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/water_trail_bubble.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_VFX_PAPER_LITE:
|
|
|
|
case SFX_VFX_PAPER_HARD:
|
|
|
|
case SFX_VFX_WOOD_LITE:
|
|
|
|
case SFX_VFX_WOOD_HARD:
|
|
|
|
case SFX_VFX_METAL_LITE:
|
|
|
|
case SFX_VFX_METAL_HARD:
|
|
|
|
case SFX_VFX_STONE_LITE:
|
|
|
|
case SFX_VFX_STONE_HARD:
|
|
|
|
case SFX_VFX_DIRT_LITE:
|
|
|
|
case SFX_VFX_DIRT_HARD:
|
|
|
|
case SFX_VFX_GRILL_LITE:
|
|
|
|
case SFX_VFX_GRILL_HARD:
|
|
|
|
case SFX_VFX_GRASS_LITE:
|
|
|
|
case SFX_VFX_GRASS_HARD:
|
|
|
|
case SFX_VFX_MUD_LITE:
|
|
|
|
case SFX_VFX_MUD_HARD:
|
|
|
|
case SFX_VFX_PUDDLE_LITE:
|
|
|
|
case SFX_VFX_PUDDLE_HARD:
|
|
|
|
case SFX_VFX_GLASS_LITE:
|
|
|
|
case SFX_VFX_GLASS_HARD:
|
|
|
|
case SFX_VFX_GRAVEL_LITE:
|
|
|
|
case SFX_VFX_GRAVEL_HARD:
|
|
|
|
case SFX_VFX_SAND_LITE:
|
|
|
|
case SFX_VFX_SAND_HARD:
|
|
|
|
case SFX_VFX_FOLIAGE_LITE:
|
|
|
|
case SFX_VFX_FOLIAGE_HARD:
|
|
|
|
case SFX_VFX_SNOW_LITE:
|
|
|
|
case SFX_VFX_SNOW_HARD:
|
|
|
|
case SFX_VFX_CARPET_LITE:
|
|
|
|
case SFX_VFX_CARPET_HARD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bh_stone_hard.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_GREN_BASE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/grenexp_base.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_BAZOOKA_BASE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/bazookaexp_base.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_HEAVYSHELL_BASE:
|
|
|
|
szEffectModel = "models/fx/heavyshellexp_base.tik";
|
|
|
|
break;
|
|
|
|
case SFX_EXP_TANK_BASE:
|
|
|
|
szEffectModel = "models/fx/tankexp_base.tik";
|
|
|
|
break;
|
|
|
|
case SFX_EXP_GREN_PAPER:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/grenexp_paper.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_GREN_WOOD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/grenexp_wood.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_GREN_METAL:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/grenexp_metal.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_GREN_STONE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/grenexp_stone.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_GREN_DIRT:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/grenexp_dirt.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_GREN_GRILL:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/grenexp_metal.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_GREN_GRASS:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/grenexp_grass.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_GREN_MUD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/grenexp_mud.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_GREN_PUDDLE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/grenexp_water.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_GREN_GLASS:
|
|
|
|
case SFX_TEST_EFFECT:
|
2023-05-05 21:12:09 +02:00
|
|
|
continue;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_GREN_GRAVEL:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/grenexp_gravel.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_GREN_SAND:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/grenexp_sand.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_GREN_FOLIAGE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/grenexp_foliage.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_GREN_SNOW:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/grenexp_snow.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_GREN_CARPET:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/grenexp_carpet.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_EXP_HEAVYSHELL_DIRT:
|
|
|
|
szEffectModel = "models/fx/heavyshellexp_dirt.tik";
|
|
|
|
break;
|
|
|
|
case SFX_EXP_HEAVYSHELL_STONE:
|
|
|
|
szEffectModel = "models/fx/heavyshellexp_stone.tik";
|
|
|
|
break;
|
|
|
|
case SFX_EXP_HEAVYSHELL_SNOW:
|
|
|
|
szEffectModel = "models/fx/heavyshellexp_snow.tik";
|
|
|
|
break;
|
|
|
|
case SFX_EXP_TANK_DIRT:
|
|
|
|
szEffectModel = "models/fx/tankexp_dirt.tik";
|
|
|
|
break;
|
|
|
|
case SFX_EXP_TANK_STONE:
|
|
|
|
szEffectModel = "models/fx/tankexp_stone.tik";
|
|
|
|
break;
|
|
|
|
case SFX_EXP_TANK_SNOW:
|
|
|
|
szEffectModel = "models/fx/tankexp_snow.tik";
|
|
|
|
break;
|
|
|
|
case SFX_EXP_BAZOOKA_DIRT:
|
|
|
|
szEffectModel = "models/fx/bazookaexp_dirt.tik";
|
|
|
|
break;
|
|
|
|
case SFX_EXP_BAZOOKA_STONE:
|
|
|
|
szEffectModel = "models/fx/bazookaexp_stone.tik";
|
|
|
|
break;
|
|
|
|
case SFX_EXP_BAZOOKA_SNOW:
|
|
|
|
szEffectModel = "models/fx/bazookaexp_snow.tik";
|
|
|
|
break;
|
|
|
|
case SFX_WATER_RIPPLE_STILL:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/water_ripple_still.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_WATER_RIPPLE_MOVING:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/water_ripple_moving.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_OIL_LEAK_BIG:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/barrel_oil_leak_big.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_OIL_LEAK_MEDIUM:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/barrel_oil_leak_medium.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_OIL_LEAK_SMALL:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/barrel_oil_leak_small.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_OIL_LEAK_SPLAT:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/barrel_oil_leak_splat.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_WATER_LEAK_BIG:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/barrel_water_leak_big.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_WATER_LEAK_MEDIUM:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/barrel_water_leak_medium.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_WATER_LEAK_SMALL:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/barrel_water_leak_small.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_WATER_LEAK_SPLAT:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/barrel_water_leak_splat.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_FOOT_LIGHT_DUST:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/fs_light_dust.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_FOOT_HEAVY_DUST:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/fs_heavy_dust.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_FOOT_DIRT:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/fs_dirt.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_FOOT_GRASS:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/fs_grass.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_FOOT_MUD:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/fs_mud.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_FOOT_PUDDLE:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/fs_puddle.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_FOOT_SAND:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/fs_sand.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_FOOT_SNOW:
|
2023-05-05 21:12:09 +02:00
|
|
|
szEffectModel = "models/fx/fs_snow.tik";
|
|
|
|
break;
|
2023-07-22 17:35:02 +02:00
|
|
|
case SFX_FENCE_WOOD:
|
|
|
|
szEffectModel = "models/fx/fx_fence_wood.tik";
|
|
|
|
break;
|
2023-05-05 21:12:09 +02:00
|
|
|
default:
|
|
|
|
szEffectModel = "models/fx/bh_stone_hard.tik";
|
2023-07-22 17:35:02 +02:00
|
|
|
break;
|
2023-07-05 21:24:23 +02:00
|
|
|
}
|
2023-05-05 21:12:09 +02:00
|
|
|
|
|
|
|
pEffect = &m_effects[i];
|
|
|
|
commandManager.SetCurrentSFX(pEffect);
|
|
|
|
cgi.R_SpawnEffectModel(szEffectModel, vec_zero, axis);
|
|
|
|
commandManager.ClearCurrentSFX();
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
for (j = 0; j < pEffect->m_iCommandCount - 1; j++) {
|
|
|
|
for (k = 0; k < j; k++) {
|
|
|
|
if (pEffect->m_commands[k]->fCommandTime > pEffect->m_commands[k + 1]->fCommandTime) {
|
|
|
|
specialeffectcommand_t *pCur = pEffect->m_commands[k];
|
|
|
|
pEffect->m_commands[k] = pEffect->m_commands[k + 1];
|
|
|
|
pEffect->m_commands[k + 1] = pCur;
|
2023-05-05 21:12:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-07-05 21:24:23 +02:00
|
|
|
}
|
2023-05-05 21:12:09 +02:00
|
|
|
|
|
|
|
m_bEffectsLoaded = qtrue;
|
2023-05-01 15:10:17 +02:00
|
|
|
}
|
|
|
|
|
2023-05-01 15:40:39 +02:00
|
|
|
void CG_InitializeSpecialEffectsManager()
|
|
|
|
{
|
2023-07-05 21:24:23 +02:00
|
|
|
sfxManager.LoadEffects();
|
2023-04-30 14:51:44 +02:00
|
|
|
}
|
|
|
|
|
2023-05-01 15:10:17 +02:00
|
|
|
void CG_AddPendingEffects()
|
|
|
|
{
|
2023-07-05 21:24:23 +02:00
|
|
|
if (sfxManager.EffectsPending()) {
|
|
|
|
sfxManager.ProcessPendingEvents();
|
|
|
|
}
|
2023-05-01 15:10:17 +02:00
|
|
|
}
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
void ClientSpecialEffectsManager::ContinueEffectExecution(Event *ev)
|
2023-05-01 15:10:17 +02:00
|
|
|
{
|
2023-07-05 21:24:23 +02:00
|
|
|
Vector norm;
|
|
|
|
float axis[3][3];
|
2023-05-01 15:40:39 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
norm = ev->GetVector(5);
|
2023-05-01 15:40:39 +02:00
|
|
|
VectorCopy(norm, axis[0]);
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
norm = ev->GetVector(6);
|
2023-05-01 15:40:39 +02:00
|
|
|
VectorCopy(norm, axis[1]);
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
norm = ev->GetVector(7);
|
2023-05-01 15:40:39 +02:00
|
|
|
VectorCopy(norm, axis[2]);
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
ExecuteEffect(ev->GetInteger(1), ev->GetInteger(2), ev->GetVector(3), ev->GetVector(4), axis);
|
2023-05-01 15:10:17 +02:00
|
|
|
}
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
void ClientSpecialEffectsManager::ExecuteEffect(
|
|
|
|
int iEffect, int iStartCommand, Vector vPos, Vector vAngles, float axis[3][3]
|
|
|
|
)
|
2023-05-01 15:10:17 +02:00
|
|
|
{
|
2023-07-05 21:24:23 +02:00
|
|
|
int i;
|
|
|
|
int iCommandCount;
|
|
|
|
float fStartCommandTime;
|
|
|
|
specialeffect_t *pEffect;
|
|
|
|
specialeffectcommand_t *pCommand;
|
|
|
|
refEntity_t *old_entity;
|
|
|
|
dtiki_t *old_tiki;
|
|
|
|
refEntity_t tmpEntity;
|
|
|
|
|
|
|
|
memset(&tmpEntity, 0, sizeof(tmpEntity));
|
|
|
|
VectorCopy(((const float *)vPos), tmpEntity.origin);
|
|
|
|
tmpEntity.scale = 1.0;
|
|
|
|
tmpEntity.renderfx = 0;
|
|
|
|
tmpEntity.shaderRGBA[3] = -1;
|
|
|
|
|
|
|
|
pEffect = &this->m_effects[iEffect];
|
|
|
|
iCommandCount = pEffect->m_iCommandCount;
|
|
|
|
if (pEffect->m_iCommandCount) {
|
|
|
|
old_entity = current_entity;
|
|
|
|
old_tiki = current_tiki;
|
|
|
|
current_entity = NULL;
|
|
|
|
current_tiki = NULL;
|
|
|
|
pCommand = pEffect->m_commands[iStartCommand];
|
2023-05-05 20:43:57 +02:00
|
|
|
|
|
|
|
fStartCommandTime = pCommand->fCommandTime;
|
2023-07-05 21:24:23 +02:00
|
|
|
for (i = iStartCommand; i < iCommandCount; i++) {
|
|
|
|
pCommand = pEffect->m_commands[i];
|
|
|
|
if (pCommand->fCommandTime > fStartCommandTime) {
|
|
|
|
Event ev1(EV_SFX_EffectDelay);
|
|
|
|
ev1.AddInteger(iEffect);
|
|
|
|
ev1.AddInteger(i);
|
|
|
|
ev1.AddVector(vPos);
|
|
|
|
ev1.AddVector(vAngles);
|
2023-05-05 20:43:57 +02:00
|
|
|
ev1.AddVector(axis[0]);
|
|
|
|
ev1.AddVector(axis[1]);
|
|
|
|
ev1.AddVector(axis[2]);
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
PostEvent(ev1, pCommand->fCommandTime - fStartCommandTime);
|
2023-07-22 17:35:02 +02:00
|
|
|
m_iNumPendingEvents++;
|
2023-05-05 20:43:57 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
}
|
2023-05-05 20:43:57 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (pCommand->pEvent) {
|
|
|
|
current_entity = &tmpEntity;
|
|
|
|
current_tiki = tmpEntity.tiki;
|
2023-05-07 14:45:23 +02:00
|
|
|
// give a reference to it so the event doesn't get deleted
|
2023-07-05 21:24:23 +02:00
|
|
|
commandManager.ProcessEvent(*pCommand->pEvent);
|
|
|
|
} else if (pCommand->emitter && pCommand->endfcn) {
|
|
|
|
current_entity = NULL;
|
|
|
|
current_tiki = NULL;
|
|
|
|
|
|
|
|
pCommand->emitter->cgd.origin = vPos;
|
|
|
|
if (pCommand->emitter->cgd.flags & T_ANGLES) {
|
2023-05-05 20:43:57 +02:00
|
|
|
pCommand->emitter->cgd.angles = vAngles;
|
2023-07-05 21:24:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
AxisCopy(axis, pCommand->emitter->axis);
|
|
|
|
AxisCopy(axis, pCommand->emitter->tag_axis);
|
|
|
|
pCommand->emitter->cgd.createTime = cg.time;
|
|
|
|
commandManager.SetSpawnthing(pCommand->emitter);
|
2023-07-22 17:35:02 +02:00
|
|
|
|
|
|
|
(commandManager.*pCommand->endfcn)();
|
2023-07-05 21:24:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
current_entity = old_entity;
|
|
|
|
current_tiki = old_tiki;
|
|
|
|
}
|
2023-05-01 15:10:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientSpecialEffectsManager::MakeEffect_Normal(int iEffect, Vector vPos, Vector vNormal)
|
|
|
|
{
|
2023-07-05 21:24:23 +02:00
|
|
|
Vector vAngles;
|
|
|
|
float axis[3][3];
|
2023-05-05 20:43:57 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
vAngles = vNormal.toAngles();
|
2023-05-05 20:43:57 +02:00
|
|
|
AnglesToAxis(vAngles, axis);
|
|
|
|
ClientSpecialEffectsManager::ExecuteEffect(iEffect, 0, vPos, vAngles, axis);
|
2023-05-01 15:10:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientSpecialEffectsManager::MakeEffect_Angles(int iEffect, Vector vPos, Vector vAngles)
|
|
|
|
{
|
2023-05-01 15:40:39 +02:00
|
|
|
float axis[3][3];
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
AnglesToAxis((const float *)vAngles, axis);
|
2023-05-01 15:40:39 +02:00
|
|
|
ClientSpecialEffectsManager::ExecuteEffect(iEffect, 0, vPos, vAngles, axis);
|
2023-05-01 15:10:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientSpecialEffectsManager::MakeEffect_Axis(int iEffect, Vector vPos, float axis[3][3])
|
|
|
|
{
|
2023-05-01 15:40:39 +02:00
|
|
|
Vector vAngles;
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
MatrixToEulerAngles(axis, (float *)vAngles);
|
2023-05-01 15:40:39 +02:00
|
|
|
ClientSpecialEffectsManager::ExecuteEffect(iEffect, 0, vPos, vAngles, axis);
|
2023-05-01 15:10:17 +02:00
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
/*
|
|
|
|
==============================================================
|
|
|
|
|
|
|
|
FOOTSTEP CODE
|
|
|
|
|
|
|
|
==============================================================
|
|
|
|
*/
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
#define GROUND_DISTANCE 8
|
2023-05-04 23:27:00 +02:00
|
|
|
#define WATER_NO_SPLASH_HEIGHT 16
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
static void CG_FootstepMain(trace_t *trace, int iRunning, int iEquipment)
|
2023-05-01 20:31:51 +02:00
|
|
|
{
|
2023-07-05 21:24:23 +02:00
|
|
|
int contents;
|
|
|
|
int surftype;
|
|
|
|
int iEffectNum;
|
|
|
|
float fVolume;
|
|
|
|
vec3_t vPos;
|
|
|
|
vec3_t midlegs;
|
|
|
|
str sSoundName;
|
|
|
|
|
|
|
|
iEffectNum = -1;
|
|
|
|
|
|
|
|
VectorCopy(trace->endpos, vPos);
|
|
|
|
sSoundName = "snd_step_";
|
|
|
|
|
|
|
|
contents = CG_PointContents(trace->endpos, -1);
|
|
|
|
if (contents & MASK_WATER) {
|
|
|
|
// take our ground position and trace upwards
|
|
|
|
VectorCopy(trace->endpos, midlegs);
|
|
|
|
midlegs[2] += WATER_NO_SPLASH_HEIGHT;
|
|
|
|
contents = CG_PointContents(midlegs, -1);
|
|
|
|
if (contents & MASK_WATER) {
|
|
|
|
sSoundName += "wade";
|
|
|
|
} else {
|
|
|
|
sSoundName += "puddle";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_PUDDLE;
|
2023-07-05 21:24:23 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
surftype = trace->surfaceFlags & MASK_SURF_TYPE;
|
|
|
|
switch (surftype) {
|
|
|
|
case SURF_FOLIAGE:
|
|
|
|
sSoundName += "foliage";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_GRASS;
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_SNOW:
|
|
|
|
sSoundName += "snow";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_SNOW;
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_CARPET:
|
|
|
|
sSoundName += "carpet";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_LIGHT_DUST;
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_SAND:
|
|
|
|
sSoundName += "sand";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_SAND;
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_PUDDLE:
|
|
|
|
sSoundName += "puddle";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_PUDDLE;
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_GLASS:
|
2023-05-04 23:27:00 +02:00
|
|
|
sSoundName += "glass";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_LIGHT_DUST;
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_GRAVEL:
|
2023-05-04 23:27:00 +02:00
|
|
|
sSoundName += "gravel";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_HEAVY_DUST;
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_MUD:
|
2023-05-04 23:27:00 +02:00
|
|
|
sSoundName += "mud";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_MUD;
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_DIRT:
|
2023-05-04 23:27:00 +02:00
|
|
|
sSoundName += "dirt";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_DIRT;
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_GRILL:
|
2023-05-04 23:27:00 +02:00
|
|
|
sSoundName += "grill";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_LIGHT_DUST;
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_GRASS:
|
2023-05-04 23:27:00 +02:00
|
|
|
sSoundName += "grass";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_GRASS;
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_ROCK:
|
2023-05-04 23:27:00 +02:00
|
|
|
sSoundName += "stone";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_HEAVY_DUST;
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_PAPER:
|
2023-05-04 23:27:00 +02:00
|
|
|
sSoundName += "paper";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_LIGHT_DUST;
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_WOOD:
|
2023-05-04 23:27:00 +02:00
|
|
|
sSoundName += "wood";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_LIGHT_DUST;
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
case SURF_METAL:
|
2023-05-04 23:27:00 +02:00
|
|
|
sSoundName += "metal";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_LIGHT_DUST;
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
sSoundName += "stone";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_HEAVY_DUST;
|
2023-07-05 21:24:23 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cg_debugFootsteps->integer) {
|
|
|
|
cgi.DPrintf("Footstep: %s running = %i effect = %i\n", sSoundName.c_str(), iRunning, surftype);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iRunning) {
|
|
|
|
if (iRunning == -1) {
|
|
|
|
fVolume = 0.5;
|
|
|
|
} else {
|
|
|
|
fVolume = 1.0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
fVolume = 0.25;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!iRunning && cgs.gametype == GT_SINGLE_PLAYER) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
commandManager.PlaySound(sSoundName, vPos, -1, fVolume, -1, -1, 1);
|
|
|
|
|
|
|
|
if (iEquipment && random() < 0.3) {
|
2023-05-04 23:27:00 +02:00
|
|
|
// also play equipment sound
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
commandManager.PlaySound("snd_step_equipment", vPos, -1, fVolume, -1, -1, 1);
|
|
|
|
}
|
2023-05-01 20:31:51 +02:00
|
|
|
}
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
void CG_Footstep(const char *szTagName, centity_t *ent, refEntity_t *pREnt, int iRunning, int iEquipment)
|
2023-05-01 20:31:51 +02:00
|
|
|
{
|
2023-07-05 21:24:23 +02:00
|
|
|
int i;
|
|
|
|
int iTagNum;
|
|
|
|
vec3_t vStart, vEnd;
|
|
|
|
vec3_t midlegs;
|
|
|
|
vec3_t vMins, vMaxs;
|
|
|
|
str sSoundName;
|
|
|
|
trace_t trace;
|
|
|
|
orientation_t oTag;
|
|
|
|
|
|
|
|
// send a trace down from the player to the ground
|
|
|
|
VectorCopy(ent->lerpOrigin, vStart);
|
|
|
|
vStart[2] += GROUND_DISTANCE;
|
|
|
|
|
|
|
|
if (szTagName) {
|
|
|
|
iTagNum = cgi.Tag_NumForName(pREnt->tiki, szTagName);
|
|
|
|
if (iTagNum != -1) {
|
|
|
|
oTag = cgi.TIKI_Orientation(pREnt, iTagNum);
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++) {
|
2023-05-04 23:27:00 +02:00
|
|
|
VectorMA(vStart, oTag.origin[i], pREnt->axis[i], vStart);
|
2023-07-05 21:24:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-05-01 20:31:51 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (iRunning == -1) {
|
2023-05-01 20:31:51 +02:00
|
|
|
AngleVectors(ent->lerpAngles, midlegs, NULL, NULL);
|
2023-05-04 23:27:00 +02:00
|
|
|
VectorMA(vStart, -16, midlegs, vStart);
|
|
|
|
VectorMA(vStart, 64, midlegs, vEnd);
|
2023-05-01 20:31:51 +02:00
|
|
|
|
|
|
|
VectorSet(vMins, -2, -2, -8);
|
|
|
|
VectorSet(vMaxs, 2, 2, 8);
|
2023-07-05 21:24:23 +02:00
|
|
|
} else {
|
2023-05-01 20:31:51 +02:00
|
|
|
VectorSet(vMins, -4, -4, 0);
|
|
|
|
VectorSet(vMaxs, 4, 4, 2);
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
// add 16 units above feets
|
2023-05-01 20:31:51 +02:00
|
|
|
vStart[2] += 16.0;
|
2023-07-05 21:24:23 +02:00
|
|
|
VectorCopy(vStart, vEnd);
|
|
|
|
vEnd[2] -= 64.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ent->currentState.eType == ET_PLAYER) {
|
|
|
|
CG_Trace(
|
|
|
|
&trace,
|
|
|
|
vStart,
|
|
|
|
vMins,
|
|
|
|
vMaxs,
|
|
|
|
vEnd,
|
|
|
|
ent->currentState.number,
|
|
|
|
MASK_PLAYERSOLID,
|
|
|
|
qtrue,
|
|
|
|
qtrue,
|
|
|
|
"Player Footsteps"
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
CG_Trace(
|
|
|
|
&trace,
|
|
|
|
vStart,
|
|
|
|
vMins,
|
|
|
|
vMaxs,
|
|
|
|
vEnd,
|
|
|
|
ent->currentState.number,
|
|
|
|
MASK_MONSTERSOLID,
|
|
|
|
qfalse,
|
|
|
|
qfalse,
|
|
|
|
"Monster Footsteps"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (trace.fraction == 1.0f) {
|
2023-05-01 20:31:51 +02:00
|
|
|
if (cg_debugFootsteps->integer) {
|
|
|
|
cgi.DPrintf("Footstep: missed floor\n");
|
|
|
|
}
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
return;
|
|
|
|
}
|
2023-05-01 20:31:51 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
CG_FootstepMain(&trace, iRunning, iEquipment);
|
2023-05-01 20:31:51 +02:00
|
|
|
}
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
void CG_MeleeImpact(vec3_t vStart, vec3_t vEnd)
|
|
|
|
{
|
|
|
|
vec3_t vMins, vMaxs;
|
|
|
|
trace_t trace;
|
2023-05-01 19:21:44 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
VectorSet(vMins, -4, -4, 0);
|
|
|
|
VectorSet(vMaxs, 4, 4, 2);
|
|
|
|
CG_Trace(&trace, vStart, vMins, vMaxs, vEnd, ENTITYNUM_NONE, MASK_PLAYERSOLID, qtrue, qtrue, "CG_MeleeImpact");
|
2023-05-01 19:21:44 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (trace.fraction != 1.0) {
|
|
|
|
CG_FootstepMain(&trace, qtrue, qfalse);
|
|
|
|
}
|
2023-05-01 19:21:44 +02:00
|
|
|
}
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
void CG_LandingSound(centity_t *ent, refEntity_t *pREnt, float volume, int iEquipment)
|
2023-05-01 19:21:44 +02:00
|
|
|
{
|
2023-07-05 21:24:23 +02:00
|
|
|
int contents;
|
|
|
|
int surftype;
|
|
|
|
int iEffectNum;
|
|
|
|
vec3_t vStart, vEnd;
|
|
|
|
vec3_t midlegs;
|
|
|
|
str sSoundName;
|
|
|
|
trace_t trace;
|
2023-05-04 23:45:01 +02:00
|
|
|
|
2023-05-16 23:49:44 +02:00
|
|
|
iEffectNum = -1;
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (ent->iNextLandTime > cg.time) {
|
|
|
|
ent->iNextLandTime = cg.time + 200;
|
|
|
|
return;
|
|
|
|
}
|
2023-05-04 23:45:01 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
ent->iNextLandTime = cg.time + 200;
|
|
|
|
VectorCopy(ent->lerpOrigin, vStart);
|
|
|
|
vStart[2] += GROUND_DISTANCE;
|
2023-05-04 23:45:01 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
VectorCopy(vStart, vEnd);
|
|
|
|
vEnd[2] -= 64.0;
|
2023-05-04 23:45:01 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (ent->currentState.eType == ET_PLAYER) {
|
2023-05-04 23:45:01 +02:00
|
|
|
CG_Trace(
|
|
|
|
&trace,
|
|
|
|
vStart,
|
|
|
|
g_vFootstepMins,
|
2023-07-05 21:24:23 +02:00
|
|
|
g_vFootstepMaxs,
|
2023-05-04 23:45:01 +02:00
|
|
|
vEnd,
|
|
|
|
ent->currentState.number,
|
|
|
|
MASK_PLAYERSOLID,
|
|
|
|
qtrue,
|
|
|
|
qtrue,
|
|
|
|
"Player Footsteps"
|
|
|
|
);
|
2023-07-05 21:24:23 +02:00
|
|
|
} else {
|
2023-05-04 23:45:01 +02:00
|
|
|
CG_Trace(
|
|
|
|
&trace,
|
|
|
|
vStart,
|
2023-07-05 21:24:23 +02:00
|
|
|
g_vFootstepMins,
|
|
|
|
g_vFootstepMaxs,
|
2023-05-04 23:45:01 +02:00
|
|
|
vEnd,
|
|
|
|
ent->currentState.number,
|
|
|
|
MASK_MONSTERSOLID,
|
|
|
|
qfalse,
|
|
|
|
qfalse,
|
|
|
|
"Monster Footsteps"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (trace.fraction == 1.0) {
|
|
|
|
return;
|
|
|
|
}
|
2023-05-04 23:45:01 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
sSoundName += "snd_landing_";
|
2023-05-04 23:45:01 +02:00
|
|
|
|
|
|
|
contents = CG_PointContents(trace.endpos, -1);
|
2023-07-05 21:24:23 +02:00
|
|
|
if (contents & MASK_WATER) {
|
|
|
|
// take our ground position and trace upwards
|
2023-05-04 23:45:01 +02:00
|
|
|
VectorCopy(trace.endpos, midlegs);
|
|
|
|
midlegs[2] += WATER_NO_SPLASH_HEIGHT;
|
|
|
|
contents = CG_PointContents(midlegs, -1);
|
2023-07-05 21:24:23 +02:00
|
|
|
if (contents & MASK_WATER) {
|
2023-05-04 23:45:01 +02:00
|
|
|
sSoundName += "wade";
|
2023-07-05 21:24:23 +02:00
|
|
|
} else {
|
2023-05-04 23:45:01 +02:00
|
|
|
sSoundName += "puddle";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_PUDDLE;
|
2023-05-04 23:45:01 +02:00
|
|
|
}
|
2023-07-05 21:24:23 +02:00
|
|
|
} else {
|
2023-05-04 23:45:01 +02:00
|
|
|
surftype = trace.surfaceFlags & MASK_SURF_TYPE;
|
2023-07-05 21:24:23 +02:00
|
|
|
switch (surftype) {
|
2023-05-04 23:45:01 +02:00
|
|
|
case SURF_FOLIAGE:
|
|
|
|
sSoundName += "foliage";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_GRASS;
|
2023-05-04 23:45:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_SNOW:
|
|
|
|
sSoundName += "snow";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_SNOW;
|
2023-05-04 23:45:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_CARPET:
|
|
|
|
sSoundName += "carpet";
|
|
|
|
break;
|
|
|
|
case SURF_SAND:
|
|
|
|
sSoundName += "sand";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_SAND;
|
2023-05-04 23:45:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_PUDDLE:
|
|
|
|
sSoundName += "puddle";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_PUDDLE;
|
2023-05-04 23:45:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_GLASS:
|
|
|
|
sSoundName += "glass";
|
|
|
|
break;
|
|
|
|
case SURF_GRAVEL:
|
|
|
|
sSoundName += "gravel";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_HEAVY_DUST;
|
2023-05-04 23:45:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_MUD:
|
|
|
|
sSoundName += "mud";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_MUD;
|
2023-05-04 23:45:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_DIRT:
|
|
|
|
sSoundName += "dirt";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_DIRT;
|
2023-05-04 23:45:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_GRILL:
|
|
|
|
sSoundName += "grill";
|
|
|
|
break;
|
|
|
|
case SURF_GRASS:
|
|
|
|
sSoundName += "grass";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_GRASS;
|
2023-05-04 23:45:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_ROCK:
|
|
|
|
sSoundName += "stone";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_LIGHT_DUST;
|
2023-05-04 23:45:01 +02:00
|
|
|
break;
|
|
|
|
case SURF_PAPER:
|
|
|
|
sSoundName += "paper";
|
|
|
|
break;
|
|
|
|
case SURF_WOOD:
|
|
|
|
sSoundName += "wood";
|
|
|
|
break;
|
|
|
|
case SURF_METAL:
|
|
|
|
sSoundName += "metal";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
sSoundName += "stone";
|
2023-07-22 17:35:02 +02:00
|
|
|
iEffectNum = SFX_FOOT_LIGHT_DUST;
|
2023-05-04 23:45:01 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cg_debugFootsteps->integer) {
|
|
|
|
cgi.DPrintf("Landing: %s volume: %.2f effect = %i\n", sSoundName.c_str(), volume, contents);
|
2023-07-05 21:24:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
commandManager.PlaySound(sSoundName, trace.endpos, -1, volume, -1, -1, 1);
|
2023-05-04 23:45:01 +02:00
|
|
|
|
|
|
|
if (iEquipment && random() < 0.5) {
|
2023-07-05 21:24:23 +02:00
|
|
|
commandManager.PlaySound("snd_step_equipment", ent->lerpOrigin, -1, volume, -1, -1, 1);
|
|
|
|
}
|
2023-05-04 23:45:01 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (iEffectNum != -1) {
|
|
|
|
sfxManager.MakeEffect_Angles(iEffectNum, trace.endpos, Vector(270, 0, 0));
|
|
|
|
}
|
2023-05-01 19:21:44 +02:00
|
|
|
}
|
2023-05-06 17:26:28 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
void CG_BodyFallSound(centity_t *ent, refEntity_t *pREnt, float volume)
|
2023-05-06 17:26:28 +02:00
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
|
|
|
}
|
|
|
|
|
2023-04-30 00:02:16 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
CG_Splash
|
|
|
|
|
|
|
|
Draw a mark at the water surface
|
|
|
|
===============
|
|
|
|
*/
|
2023-07-05 21:24:23 +02:00
|
|
|
void CG_Splash(centity_t *cent)
|
|
|
|
{
|
|
|
|
vec3_t start, end, diff;
|
|
|
|
trace_t trace;
|
|
|
|
int contents;
|
|
|
|
float dist;
|
|
|
|
float time_required;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
spawnthing_t m_ripple;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (!cg_shadows->integer) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
VectorSubtract(cent->currentState.origin, cent->nextState.origin, diff);
|
|
|
|
diff[2] = 0;
|
2023-07-22 17:35:02 +02:00
|
|
|
dist = VectorNormalize(diff);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
// See if enough time has passed to add another ripple
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (dist >= 1) {
|
2023-07-22 17:35:02 +02:00
|
|
|
time_required = 60 - dist;
|
2023-07-05 21:24:23 +02:00
|
|
|
} else {
|
2023-07-22 17:35:02 +02:00
|
|
|
time_required = 175;
|
2023-07-05 21:24:23 +02:00
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-22 17:35:02 +02:00
|
|
|
if (time_required < 5) {
|
|
|
|
time_required = 5;
|
2023-07-05 21:24:23 +02:00
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (cent->splash_last_spawn_time + time_required > cg.time) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
// Save the current time
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
cent->splash_last_spawn_time = cg.time;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
// Make sure the entity is moving
|
|
|
|
if (dist < 1) {
|
|
|
|
if (cent->splash_still_count >= 0) {
|
|
|
|
cent->splash_still_count++;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (cent->splash_still_count > 2) {
|
|
|
|
cent->splash_still_count = 0;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
VectorCopy(cent->lerpOrigin, end);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
// if the feet aren't in liquid, don't make a mark
|
|
|
|
// this won't handle moving water brushes, but they wouldn't draw right anyway...
|
|
|
|
contents = cgi.CM_PointContents(end, 0);
|
|
|
|
if (!(contents & (CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA))) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
VectorCopy(cent->lerpOrigin, start);
|
2023-07-22 17:35:02 +02:00
|
|
|
start[2] += 72;
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
// if the head isn't out of liquid, don't make a mark
|
|
|
|
contents = cgi.CM_PointContents(start, 0);
|
|
|
|
if (contents & (CONTENTS_SOLID | CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA)) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
// trace down to find the surface
|
|
|
|
cgi.CM_BoxTrace(
|
|
|
|
&trace, start, end, vec3_origin, vec3_origin, 0, (CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA), qfalse
|
|
|
|
);
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
if (trace.fraction == 1.0) {
|
|
|
|
return;
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
|
2023-07-22 17:35:02 +02:00
|
|
|
if (dist > 0) {
|
|
|
|
vectoangles(diff, start);
|
|
|
|
start[0] = -90.0;
|
|
|
|
|
|
|
|
dist /= cg.frametime;
|
|
|
|
if (dist < 0) {
|
|
|
|
dist = 0;
|
|
|
|
} else if (dist > 8192) {
|
|
|
|
dist = 8192;
|
|
|
|
}
|
|
|
|
|
|
|
|
VectorMA(trace.endpos, dist, diff, end);
|
|
|
|
sfxManager.MakeEffect_Angles(81, end, start);
|
|
|
|
} else {
|
|
|
|
start[0] = 90;
|
|
|
|
start[1] = 0;
|
|
|
|
start[2] = 0;
|
|
|
|
|
|
|
|
sfxManager.MakeEffect_Angles(80, trace.endpos, start);
|
|
|
|
}
|
2023-04-30 00:02:16 +02:00
|
|
|
}
|
2023-05-01 15:10:17 +02:00
|
|
|
|
|
|
|
qboolean ClientSpecialEffectsManager::EffectsPending()
|
|
|
|
{
|
2023-07-05 21:24:23 +02:00
|
|
|
return sfxManager.m_iNumPendingEvents > 0;
|
2023-05-01 15:10:17 +02:00
|
|
|
}
|
|
|
|
|
2023-07-05 21:24:23 +02:00
|
|
|
specialeffect_t *ClientSpecialEffectsManager::GetTestEffectPointer()
|
2023-05-01 15:10:17 +02:00
|
|
|
{
|
|
|
|
return &m_effects[SPECIAL_EFFECT_TEST];
|
|
|
|
}
|