2016-03-27 11:49:47 +02:00
|
|
|
/*
|
|
|
|
===========================================================================
|
2024-10-21 21:59:12 +02:00
|
|
|
Copyright (C) 2024 the OpenMoHAA team
|
2016-03-27 11:49:47 +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
|
|
|
|
===========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
// barrels.cpp : Barrels
|
|
|
|
|
|
|
|
#include "barrels.h"
|
|
|
|
#include "weaputils.h"
|
2023-01-29 20:59:31 +01:00
|
|
|
#include "level.h"
|
2023-04-29 21:56:38 +02:00
|
|
|
#include "g_phys.h"
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
/*QUAKED func_barrel (0 0.25 0.5) ? INDESTRUCTABLE
|
|
|
|
Brush model barrel object
|
2024-09-19 10:52:47 +02:00
|
|
|
Bashing only makes thunk or gong sounds (depending on whether it's full or not)
|
2016-03-27 11:49:47 +02:00
|
|
|
Bullets and explosions effects are dependant apon the type of barrel.
|
|
|
|
"barreltype" sets the type of barrel that it is. Valid settings are:
|
|
|
|
- "water" makes the barrel be filled with water.
|
|
|
|
Always non-volitile. Only destroyed by explosion.
|
|
|
|
- "oil" makes the barrel be filled with oil.
|
|
|
|
Leakes oil when shot (not destroyed), shower of flames when exploded.
|
|
|
|
- "gas" makes the barrel be filled with gas.
|
|
|
|
A few bullet hits will make it explode.
|
|
|
|
Explosions will also make it explode.
|
|
|
|
- "empty" makes the barrel completely empty.
|
|
|
|
Does nothing special at all. It's just a poor empty barrel. aww :(
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
Event EV_Barrel_Think
|
2024-10-21 21:59:12 +02:00
|
|
|
(
|
2016-03-27 11:49:47 +02:00
|
|
|
"_barrel_think",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"think function for a barrel."
|
2024-10-21 21:59:12 +02:00
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
Event EV_Barrel_Setup
|
2024-10-21 21:59:12 +02:00
|
|
|
(
|
2016-03-27 11:49:47 +02:00
|
|
|
"_barrel_setup",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Does the post spawn setup of the barrel"
|
2024-10-21 21:59:12 +02:00
|
|
|
);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
Event EV_Barrel_SetType
|
2024-10-21 21:59:12 +02:00
|
|
|
(
|
2016-03-27 11:49:47 +02:00
|
|
|
"barreltype",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"type",
|
|
|
|
"Sets the barrel's type"
|
2024-10-21 21:59:12 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
CLASS_DECLARATION(Entity, BarrelObject, "func_barrel") {
|
|
|
|
{&EV_Barrel_Setup, &BarrelObject::BarrelSetup },
|
|
|
|
{&EV_Barrel_Think, &BarrelObject::BarrelThink },
|
|
|
|
{&EV_Barrel_SetType, &BarrelObject::BarrelSetType},
|
|
|
|
{&EV_Damage, &BarrelObject::BarrelDamaged},
|
|
|
|
{&EV_Killed, &BarrelObject::BarrelKilled },
|
|
|
|
{NULL, NULL }
|
2016-03-27 11:49:47 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
BarrelObject::BarrelObject()
|
|
|
|
{
|
2024-10-21 21:59:12 +02:00
|
|
|
AddWaitTill(STRING_DEATH);
|
2018-09-17 23:50:38 +02:00
|
|
|
|
2024-10-21 21:59:12 +02:00
|
|
|
if (LoadingSavegame) {
|
|
|
|
return;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2024-10-21 21:59:12 +02:00
|
|
|
edict->s.eType = ET_GENERAL;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2024-10-21 21:59:12 +02:00
|
|
|
m_iBarrelType = 0;
|
|
|
|
m_fFluidAmount = 0;
|
|
|
|
m_fHeightFluid = 0;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2024-10-21 21:59:12 +02:00
|
|
|
for (int i = 0; i < MAX_BARREL_LEAKS; i++) {
|
|
|
|
m_bLeaksActive[i] = 0;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2024-10-21 21:59:12 +02:00
|
|
|
m_fDamageSoundTime = 0;
|
|
|
|
mass = 500;
|
|
|
|
max_health = 75;
|
|
|
|
health = 75;
|
|
|
|
deadflag = DEAD_NO;
|
|
|
|
takedamage = DAMAGE_YES;
|
|
|
|
m_vJitterAngles = vec_zero;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2024-10-21 21:59:12 +02:00
|
|
|
PostEvent(EV_Barrel_Setup, EV_POSTSPAWN);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2024-10-21 21:59:12 +02:00
|
|
|
int BarrelObject::PickBarrelLeak(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2024-10-21 21:59:12 +02:00
|
|
|
int iHighest;
|
|
|
|
float fHighestHeight;
|
|
|
|
|
|
|
|
for (int i = 0; i < MAX_BARREL_LEAKS; i++) {
|
|
|
|
if (!m_bLeaksActive[i]) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fHighestHeight = m_vLeaks[0][2];
|
|
|
|
iHighest = 0;
|
|
|
|
|
|
|
|
for (int i = 1; i < MAX_BARREL_LEAKS; i++) {
|
|
|
|
if (m_vLeaks[0][2] > fHighestHeight) {
|
|
|
|
fHighestHeight = m_vLeaks[0][2];
|
|
|
|
iHighest = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return iHighest;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2024-10-21 21:59:12 +02:00
|
|
|
void BarrelObject::BarrelSetup(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2024-10-21 21:59:12 +02:00
|
|
|
setMoveType(MOVETYPE_PUSH);
|
|
|
|
setSolidType(SOLID_BSP);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2024-10-21 21:59:12 +02:00
|
|
|
m_vStartAngles = angles;
|
|
|
|
m_fJitterScale = 64.0f / size[2];
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2024-10-21 21:59:12 +02:00
|
|
|
m_fFluidAmount = size[0] * size[1] * size[2] / 150.0f;
|
|
|
|
m_fHeightFluid = m_fFluidAmount / size[2];
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2024-10-21 21:59:12 +02:00
|
|
|
// Position the barrel correctly
|
|
|
|
CheckGround();
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2024-10-21 21:59:12 +02:00
|
|
|
void BarrelObject::BarrelSetType(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2024-10-21 21:59:12 +02:00
|
|
|
str sType = ev->GetString(1);
|
|
|
|
|
|
|
|
if (!sType.icmp("oil")) {
|
|
|
|
health = 75;
|
|
|
|
m_iBarrelType = BARREL_OIL;
|
|
|
|
|
|
|
|
CacheResource("models/fx/barrel_empty_destroyed.tik");
|
|
|
|
CacheResource("models/fx/barrel_oil_destroyed.tik");
|
|
|
|
} else if (!sType.icmp("water")) {
|
|
|
|
health = 75;
|
|
|
|
m_iBarrelType = BARREL_WATER;
|
|
|
|
|
|
|
|
CacheResource("models/fx/barrel_empty_destroyed.tik");
|
|
|
|
CacheResource("models/fx/barrel_water_destroyed.tik");
|
|
|
|
} else if (!sType.icmp("gas")) {
|
|
|
|
spawnflags &= ~BARREL_INDESTRUCTABLE;
|
|
|
|
health = 75;
|
|
|
|
m_iBarrelType = BARREL_GAS;
|
|
|
|
|
|
|
|
CacheResource("models/fx/barrel_gas_destroyed.tik");
|
|
|
|
} else {
|
|
|
|
health = 75;
|
|
|
|
m_iBarrelType = BARREL_EMPTY;
|
|
|
|
|
|
|
|
CacheResource("models/fx/barrel_empty_destroyed.tik");
|
|
|
|
}
|
|
|
|
|
|
|
|
max_health = health;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2024-10-21 21:59:12 +02:00
|
|
|
void BarrelObject::BarrelThink(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2024-10-21 21:59:12 +02:00
|
|
|
int i;
|
|
|
|
int iBiggestLeak;
|
|
|
|
float fFluidTop;
|
|
|
|
|
|
|
|
iBiggestLeak = 0;
|
|
|
|
|
|
|
|
fFluidTop = m_fFluidAmount / m_fHeightFluid + (mins[2] + origin[2]);
|
|
|
|
for (i = 0; i < MAX_BARREL_LEAKS; i++) {
|
|
|
|
if (!m_bLeaksActive[i]) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send infos to clients
|
|
|
|
if (m_vLeaks[i][2] <= fFluidTop) {
|
|
|
|
gi.SetBroadcastVisible(m_vLeaks[i], m_vLeaks[i]);
|
|
|
|
|
|
|
|
if (m_vLeaks[i][2] <= fFluidTop - 1.3f) {
|
|
|
|
if (m_vLeaks[i][2] <= fFluidTop - 3.0f) {
|
|
|
|
// big leak
|
|
|
|
|
|
|
|
if (m_iBarrelType == BARREL_OIL) {
|
|
|
|
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_1));
|
|
|
|
} else {
|
|
|
|
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_5));
|
|
|
|
}
|
|
|
|
|
|
|
|
m_fFluidAmount -= 1.0f;
|
|
|
|
iBiggestLeak |= 4;
|
|
|
|
} else {
|
|
|
|
// medium leak
|
|
|
|
|
|
|
|
if (m_iBarrelType == BARREL_OIL) {
|
|
|
|
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_2));
|
|
|
|
} else {
|
|
|
|
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_6));
|
|
|
|
}
|
|
|
|
|
|
|
|
m_fFluidAmount -= 0.75f;
|
|
|
|
iBiggestLeak |= 2;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// small leak
|
|
|
|
|
|
|
|
if (m_iBarrelType == BARREL_OIL) {
|
|
|
|
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_3));
|
|
|
|
} else {
|
|
|
|
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_7));
|
|
|
|
}
|
|
|
|
|
|
|
|
m_fFluidAmount -= 0.5f;
|
|
|
|
iBiggestLeak |= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
gi.MSG_WriteCoord(m_vLeaks[i][0]);
|
|
|
|
gi.MSG_WriteCoord(m_vLeaks[i][1]);
|
|
|
|
gi.MSG_WriteCoord(m_vLeaks[i][2]);
|
|
|
|
gi.MSG_WriteDir(m_vLeakNorms[i]);
|
|
|
|
gi.MSG_EndCGM();
|
|
|
|
} else {
|
|
|
|
gi.SetBroadcastVisible(m_vLeaks[i], m_vLeaks[i]);
|
|
|
|
|
|
|
|
if (m_iBarrelType == BARREL_OIL) {
|
|
|
|
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_3));
|
|
|
|
} else {
|
|
|
|
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_7));
|
|
|
|
}
|
|
|
|
|
|
|
|
gi.MSG_WriteCoord(m_vLeaks[i][0]);
|
|
|
|
gi.MSG_WriteCoord(m_vLeaks[i][1]);
|
|
|
|
gi.MSG_WriteCoord(m_vLeaks[i][2]);
|
|
|
|
gi.MSG_WriteDir(m_vLeakNorms[i]);
|
|
|
|
gi.MSG_EndCGM();
|
|
|
|
|
|
|
|
m_bLeaksActive[i] = qfalse;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_vJitterAngles[0] == 0.0f && m_vJitterAngles[2] == 0.0f) {
|
|
|
|
if (!VectorCompare(angles, m_vStartAngles)) {
|
|
|
|
setAngles(m_vStartAngles);
|
|
|
|
}
|
|
|
|
}
|
2024-10-21 22:12:13 +02:00
|
|
|
else {
|
|
|
|
Vector ang;
|
2024-10-21 21:59:12 +02:00
|
|
|
|
2024-10-21 22:12:13 +02:00
|
|
|
ang = m_vStartAngles;
|
|
|
|
ang[0] += m_vJitterAngles[0];
|
|
|
|
ang[2] += m_vJitterAngles[2];
|
|
|
|
setAngles(ang);
|
2024-10-21 21:59:12 +02:00
|
|
|
|
2024-10-21 22:12:13 +02:00
|
|
|
if (m_vJitterAngles[0] < 0) {
|
|
|
|
m_vJitterAngles[0] += 1.f / 3.f * m_fJitterScale;
|
2024-10-21 21:59:12 +02:00
|
|
|
|
2024-10-21 22:12:13 +02:00
|
|
|
if (m_vJitterAngles[0] > 0) {
|
|
|
|
m_vJitterAngles[0] = 0;
|
|
|
|
}
|
|
|
|
} else if (m_vJitterAngles[0] > 0) {
|
|
|
|
m_vJitterAngles[0] -= 1.f / 3.f * m_fJitterScale;
|
2024-10-21 21:59:12 +02:00
|
|
|
|
2024-10-21 22:12:13 +02:00
|
|
|
if (m_vJitterAngles[0] < 0) {
|
|
|
|
m_vJitterAngles[0] = 0;
|
|
|
|
}
|
2024-10-21 21:59:12 +02:00
|
|
|
}
|
|
|
|
|
2024-10-21 22:12:13 +02:00
|
|
|
m_vJitterAngles[0] = -m_vJitterAngles[0];
|
2024-10-21 21:59:12 +02:00
|
|
|
|
2024-10-21 22:12:13 +02:00
|
|
|
if (m_vJitterAngles[2] < 0) {
|
|
|
|
m_vJitterAngles[2] += 1.f / 3.f * m_fJitterScale;
|
2024-10-21 21:59:12 +02:00
|
|
|
|
2024-10-21 22:12:13 +02:00
|
|
|
if (m_vJitterAngles[2] > 0) {
|
|
|
|
m_vJitterAngles[2] = 0;
|
|
|
|
}
|
|
|
|
} else if (m_vJitterAngles[2] > 0) {
|
|
|
|
m_vJitterAngles[2] -= 1.f / 3.f * m_fJitterScale;
|
2024-10-21 21:59:12 +02:00
|
|
|
|
2024-10-21 22:12:13 +02:00
|
|
|
if (m_vJitterAngles[2] < 0) {
|
|
|
|
m_vJitterAngles[2] = 0;
|
|
|
|
}
|
2024-10-21 21:59:12 +02:00
|
|
|
}
|
|
|
|
|
2024-10-21 22:12:13 +02:00
|
|
|
m_vJitterAngles[2] = -m_vJitterAngles[2];
|
|
|
|
}
|
2024-10-21 21:59:12 +02:00
|
|
|
|
|
|
|
// Check for at least one active leak to play a sound
|
|
|
|
for (i = 0; i < MAX_BARREL_LEAKS; i++) {
|
|
|
|
if (m_bLeaksActive[i]) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Play a leak sound
|
|
|
|
if (i != MAX_BARREL_LEAKS && iBiggestLeak) {
|
2024-10-21 22:12:13 +02:00
|
|
|
if (iBiggestLeak & 4) {
|
2024-10-21 21:59:12 +02:00
|
|
|
// big leak
|
2024-10-21 22:12:13 +02:00
|
|
|
LoopSound("liquid_leak", 1, -1, -1, 1);
|
|
|
|
} else if (iBiggestLeak & 2) {
|
|
|
|
// medium leak
|
|
|
|
LoopSound("liquid_leak", 0.6, -1, -1, 0.9);
|
|
|
|
} else {
|
|
|
|
// small leak
|
|
|
|
LoopSound("liquid_leak", 0.3, -1, -1, 0.8);
|
2024-10-21 21:59:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == MAX_BARREL_LEAKS) {
|
|
|
|
StopLoopSound();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_vJitterAngles[0] || m_vJitterAngles[2] || i < MAX_BARREL_LEAKS) {
|
|
|
|
m_fLastEffectTime += 0.075f;
|
|
|
|
|
2024-10-21 22:12:13 +02:00
|
|
|
if (m_fLastEffectTime <= level.time) {
|
2024-10-21 21:59:12 +02:00
|
|
|
m_fLastEffectTime = level.time + 0.075f;
|
|
|
|
}
|
|
|
|
|
|
|
|
PostEvent(EV_Barrel_Think, m_fLastEffectTime - level.time);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2024-10-21 21:59:12 +02:00
|
|
|
void BarrelObject::BarrelDamaged(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2024-10-21 21:59:12 +02:00
|
|
|
Vector vDir;
|
|
|
|
Vector vForward;
|
|
|
|
Vector vRight;
|
|
|
|
int iDamage;
|
|
|
|
int iMeansOfDeath;
|
|
|
|
Vector vHitPos;
|
|
|
|
Vector vHitDirection;
|
|
|
|
Vector vHitNormal;
|
|
|
|
|
|
|
|
if (!takedamage) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
iDamage = ev->GetInteger(2);
|
|
|
|
iMeansOfDeath = ev->GetInteger(9);
|
|
|
|
vHitPos = ev->GetVector(4);
|
|
|
|
vHitDirection = ev->GetVector(5);
|
|
|
|
vHitNormal = ev->GetVector(6);
|
|
|
|
|
|
|
|
vDir = (vHitDirection - vHitNormal) * 0.5f;
|
|
|
|
AngleVectors(angles, vForward, vRight, NULL);
|
|
|
|
|
|
|
|
m_vJitterAngles[0] += DotProduct(vDir, vForward) * m_fJitterScale * 0.0275f * (float)iDamage;
|
|
|
|
m_vJitterAngles[2] += DotProduct(vDir, vRight) * m_fJitterScale * 0.0275f * (float)iDamage;
|
|
|
|
|
|
|
|
if (m_vJitterAngles[0] > m_fJitterScale * 1.5f) {
|
|
|
|
m_vJitterAngles[0] = m_fJitterScale * 1.5f;
|
|
|
|
} else if (m_vJitterAngles[0] < -(m_fJitterScale * 1.5f)) {
|
|
|
|
m_vJitterAngles[0] = -(m_fJitterScale * 1.5f);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_vJitterAngles[2] > m_fJitterScale * 1.5f) {
|
|
|
|
m_vJitterAngles[2] = m_fJitterScale * 1.5f;
|
|
|
|
} else if (m_vJitterAngles[2] < -(m_fJitterScale * 1.5f)) {
|
|
|
|
m_vJitterAngles[2] = -(m_fJitterScale * 1.5f);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(spawnflags & BARREL_INDESTRUCTABLE)) {
|
|
|
|
if ((iMeansOfDeath == MOD_VEHICLE || iMeansOfDeath == MOD_ROCKET || iMeansOfDeath == MOD_GRENADE
|
|
|
|
|| iMeansOfDeath == MOD_EXPLODEWALL || iMeansOfDeath == MOD_EXPLOSION || m_iBarrelType == BARREL_GAS)
|
|
|
|
&& iMeansOfDeath != MOD_BASH) {
|
|
|
|
if (iDamage >= health) {
|
|
|
|
PostEvent(EV_Killed, 0.01f);
|
|
|
|
takedamage = DAMAGE_NO;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_iBarrelType == BARREL_GAS) {
|
|
|
|
iDamage /= 2;
|
|
|
|
|
|
|
|
health -= iDamage;
|
|
|
|
if (health < 1.0f) {
|
|
|
|
health = 1.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!EventPending(EV_Barrel_Think)) {
|
|
|
|
m_fLastEffectTime = level.time - 0.075f;
|
|
|
|
ProcessEvent(EV_Barrel_Think);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_iBarrelType <= BARREL_WATER) {
|
|
|
|
int index = PickBarrelLeak();
|
|
|
|
|
|
|
|
if (vHitPos[2] <= m_fFluidAmount / m_fHeightFluid + origin[2] + mins[2]) {
|
|
|
|
m_bLeaksActive[index] = qtrue;
|
|
|
|
m_vLeaks[index] = vHitPos;
|
|
|
|
m_vLeakNorms[index] = vHitNormal;
|
|
|
|
|
|
|
|
gi.SetBroadcastVisible(vHitPos, vHitPos);
|
|
|
|
|
|
|
|
if (m_iBarrelType == BARREL_OIL) {
|
|
|
|
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_4));
|
|
|
|
} else {
|
|
|
|
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_8));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
gi.SetBroadcastVisible(vHitPos, vHitPos);
|
|
|
|
|
|
|
|
if (m_iBarrelType == BARREL_OIL) {
|
|
|
|
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_3));
|
|
|
|
} else {
|
|
|
|
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_7));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gi.MSG_WriteCoord(vHitPos[0]);
|
|
|
|
gi.MSG_WriteCoord(vHitPos[1]);
|
|
|
|
gi.MSG_WriteCoord(vHitPos[2]);
|
|
|
|
gi.MSG_WriteDir(vHitNormal);
|
|
|
|
gi.MSG_EndCGM();
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2024-10-21 21:59:12 +02:00
|
|
|
void BarrelObject::BarrelKilled(Event *ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2024-10-21 21:59:12 +02:00
|
|
|
float fFluidTop;
|
|
|
|
Vector vPos;
|
|
|
|
str sModel;
|
|
|
|
|
|
|
|
setSolidType(SOLID_NOT);
|
|
|
|
PostEvent(EV_Remove, 0.05f);
|
|
|
|
|
|
|
|
vPos[2] = (mins[2] + origin[2]);
|
|
|
|
fFluidTop = m_fFluidAmount / m_fHeightFluid + vPos[2];
|
|
|
|
|
|
|
|
if (m_iBarrelType == BARREL_GAS) {
|
|
|
|
RadiusDamage(centroid, this, this, 200, this, MOD_EXPLOSION, 350, 24);
|
|
|
|
|
|
|
|
sModel = "models/fx/barrel_gas_destroyed.tik";
|
|
|
|
} else if (m_iBarrelType == BARREL_WATER) {
|
|
|
|
if (vPos[2] + 0.25f * maxs[2] <= fFluidTop) {
|
|
|
|
sModel = "models/fx/barrel_water_destroyed.tik";
|
|
|
|
} else {
|
|
|
|
sModel = "models/fx/barrel_empty_destroyed.tik";
|
|
|
|
}
|
|
|
|
} else if (m_iBarrelType == BARREL_OIL) {
|
|
|
|
if (vPos[2] + 0.25f * maxs[2] > fFluidTop) {
|
|
|
|
sModel = "models/fx/barrel_empty_destroyed.tik";
|
|
|
|
} else {
|
|
|
|
RadiusDamage(centroid, this, this, 200, this, MOD_EXPLOSION, 350, 24);
|
|
|
|
|
|
|
|
sModel = "models/fx/barrel_oil_destroyed.tik";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
sModel = "models/fx/barrel_empty_destroyed.tik";
|
|
|
|
}
|
|
|
|
|
|
|
|
Animate *exp = new Animate;
|
|
|
|
|
|
|
|
// Spawn an explosion effect
|
|
|
|
exp->edict->s.renderfx |= RF_DONTDRAW;
|
|
|
|
exp->setModel(sModel);
|
|
|
|
|
|
|
|
vPos = origin + (maxs + mins) * 0.5f;
|
|
|
|
|
|
|
|
exp->setAngles(Vector(-90, 0, 0));
|
|
|
|
exp->setOrigin(vPos);
|
|
|
|
exp->NewAnim("idle");
|
|
|
|
|
|
|
|
exp->PostEvent(EV_Remove, 0.1f);
|
|
|
|
exp->Unregister(STRING_DEATH);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|