q3rally/engine/code/game/g_rally_hazard.c
2011-03-08 09:07:05 +00:00

381 lines
8.4 KiB
C

/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2002-2009 Q3Rally Team (Per Thormann - perle@q3rally.com)
This file is part of q3rally source code.
q3rally 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.
q3rally 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 q3rally; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "g_local.h"
#define SPLASH_RADIUS_SCALE 16.0f
#define MAX_SPLASH_RADIUS 14.0f
qboolean G_FrictionCalc( const carPoint_t *point, float *sCOF, float *kCOF )
{
gentity_t *ent;
int entityList[MAX_GENTITIES];
int numListedEntities;
vec3_t mins, maxs;
float radius;
int i;
radius = point->radius + SPLASH_RADIUS_SCALE * MAX_SPLASH_RADIUS;
for ( i = 0 ; i < 3 ; i++ ) {
mins[i] = point->r[i] - radius;
maxs[i] = point->r[i] + radius;
}
numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
for ( i = 0 ; i < numListedEntities ; i++ ) {
ent = &g_entities[entityList[ i ]];
if( ent->s.eType != ET_EVENTS + EV_HAZARD ) continue;
if( ent->s.weapon != HT_OIL ) continue;
radius = ( ent->splashRadius * SPLASH_RADIUS_SCALE ) + point->radius;
radius *= radius;
if( DistanceSquared( ent->r.currentOrigin, point->r ) > radius ) continue;
*sCOF = CP_OIL_SCOF;
*kCOF = CP_OIL_KCOF;
return qtrue;
}
return qfalse;
}
/*
============
FireHazard_Think
============
*/
void FireHazard_Think (gentity_t *self ){
self->nextthink = level.time + 200;
if (self->freeAfterTime < level.time){
self->think = G_FreeEntity;
return;
}
G_RadiusDamage_NoKnockBack(self->r.currentOrigin, self, self->damage, SPLASH_RADIUS_SCALE * self->splashRadius, self, MOD_FIRE);
}
/*
============
CreateFireHazard
owner - the entity that caused this hazard. If the hazard is from a weapon
the owner is the player who fired the weapon.
============
*/
void CreateFireHazard (gentity_t *owner, vec3_t origin){
gentity_t *ent;
gentity_t *other;
vec3_t dist;
other = NULL;
while ((other = G_Find(other, FOFS(classname), "fire")) != NULL){
VectorSubtract(other->r.currentOrigin, origin, dist);
if (VectorLength(dist) < 16){
// G_FreeEntity(other);
other->freeAfterTime = level.time + 10000;
return;
}
}
ent = G_TempRallyEntity( origin, EV_HAZARD );
ent->splashRadius = 1;
ent->s.weapon = HT_FIRE;
ent->s.otherEntityNum = owner->s.number;
ent->parent = owner;
ent->classname = "fire";
ent->think = FireHazard_Think;
ent->damage = 15;
ent->nextthink = level.time;
ent->freeAfterTime = level.time + 10000;
}
/*
============
BioHazard_Think
============
*/
void BioHazard_Think (gentity_t *self ){
self->nextthink = level.time + 200;
if (self->freeAfterTime < level.time){
self->think = G_FreeEntity;
return;
}
G_RadiusDamage_NoKnockBack(self->r.currentOrigin, self, self->damage, 0.75f * SPLASH_RADIUS_SCALE * self->splashRadius, self, MOD_BIOHAZARD);
}
/*
============
CreateBioHazard
owner - the entity that caused this hazard. If the hazard is from a weapon
the owner is the player who fired the weapon.
============
*/
void CreateBioHazard (gentity_t *owner, vec3_t origin){
gentity_t *ent;
gentity_t *other;
vec3_t dist;
int highest;
other = NULL;
highest = 0;
while ((other = G_Find(other, FOFS(classname), "radiation")) != NULL){
VectorSubtract(other->r.currentOrigin, origin, dist);
if (VectorLength(dist) < other->splashRadius * 8){
if (other->splashRadius > highest)
highest = other->splashRadius;
G_FreeEntity(other);
}
}
ent = G_TempRallyEntity( origin, EV_HAZARD );
if (highest){
ent->splashRadius = highest + 1;
if (ent->splashRadius > MAX_SPLASH_RADIUS)
ent->splashRadius = MAX_SPLASH_RADIUS;
}
else {
ent->splashRadius = 4;
}
ent->s.eventParm = ent->splashRadius;
ent->s.weapon = HT_BIO;
ent->s.otherEntityNum = owner->s.number;
ent->parent = owner;
ent->classname = "radiation";
ent->think = BioHazard_Think;
ent->damage = 10;
ent->nextthink = level.time;
ent->freeAfterTime = level.time + 10000;
}
/*
============
CheckForOil
============
*/
void CheckForOil(vec3_t origin, float radius){
gentity_t *other;
vec3_t dist;
vec3_t newOrigin;
float length;
other = NULL;
while ((other = G_Find(other, FOFS(classname), "oil")) != NULL){
if (other->count > 5) continue;
VectorSubtract(origin, other->r.currentOrigin, dist);
length = VectorLength(dist);
if (length < radius + MAX_SPLASH_RADIUS * SPLASH_RADIUS_SCALE){
if (length < other->splashRadius * SPLASH_RADIUS_SCALE){
CreateFireHazard(other, origin);
other->count++;
}
else if (length < radius + other->splashRadius * SPLASH_RADIUS_SCALE){
VectorMA(other->r.currentOrigin, length / (radius + other->splashRadius * SPLASH_RADIUS_SCALE), dist, newOrigin);
CreateFireHazard(other, newOrigin);
other->count++;
}
}
}
}
/*
============
OilHazard_Think
============
*/
void OilHazard_Think (gentity_t *self ){
self->nextthink = level.time + 200;
if (self->freeAfterTime < level.time){
self->think = G_FreeEntity;
return;
}
}
/*
============
CreateOilHazard
owner - the entity that caused this hazard. If the hazard is from a weapon
the owner is the player who fired the weapon.
============
*/
void CreateOilHazard (gentity_t *owner, vec3_t origin){
gentity_t *ent;
gentity_t *other;
vec3_t dist;
int highest;
other = NULL;
highest = 0;
ent = G_TempRallyEntity( origin, EV_HAZARD );
while ((other = G_Find(other, FOFS(classname), "oil")) != NULL){
VectorSubtract(other->r.currentOrigin, origin, dist);
if (VectorLength(dist) < other->splashRadius * 8){
if (other->splashRadius > highest){
highest = other->splashRadius;
// ent->count = other->count;
}
G_FreeEntity(other);
}
}
if (highest){
ent->splashRadius = highest + 1;
if (ent->splashRadius > MAX_SPLASH_RADIUS)
ent->splashRadius = MAX_SPLASH_RADIUS;
}
else {
ent->splashRadius = 4;
}
ent->s.eventParm = ent->splashRadius;
ent->s.weapon = HT_OIL;
ent->s.otherEntityNum = owner->s.number;
ent->parent = owner;
ent->classname = "oil";
ent->think = OilHazard_Think;
ent->nextthink = level.time;
ent->freeAfterTime = level.time + 10000;
}
/*
============
PoisonHazard_Think
============
*/
void PoisonHazard_Think (gentity_t *self ){
self->nextthink = level.time + 200;
if (self->freeAfterTime < level.time){
self->think = G_FreeEntity;
return;
}
G_RadiusDamage_NoKnockBack(self->r.currentOrigin, self, self->damage, SPLASH_RADIUS_SCALE * self->splashRadius, self, MOD_POISON);
}
/*
============
CreatePoisonHazard
owner - the entity that caused this hazard. If the hazard is from a weapon
the owner is the player who fired the weapon.
used with rear weapons
============
*/
void CreatePoisonHazard (gentity_t *owner, vec3_t origin){
gentity_t *ent;
ent = G_TempRallyEntity( origin, EV_HAZARD );
ent->splashRadius = 3;
ent->s.weapon = HT_POISON;
ent->s.otherEntityNum = owner->s.number;
ent->parent = owner;
ent->classname = "poison";
ent->think = PoisonHazard_Think;
ent->damage = 2;
ent->nextthink = level.time;
ent->freeAfterTime = level.time + 10000;
}
/*
============
CreatePoisonCloudHazard
owner - the entity that caused this hazard. If the hazard is from a weapon
the owner is the player who fired the weapon.
used with barrels
============
*/
void CreatePoisonCloudHazard (gentity_t *owner, vec3_t origin) {
gentity_t *ent;
ent = G_TempEntity( origin, EV_HAZARD );
ent->s.weapon = HT_POISON;
}
/*
============
CreateSmokeHazard
owner - the entity that caused this hazard. If the hazard is from a weapon
the owner is the player who fired the weapon.
used with barrels
============
*/
void CreateSmokeHazard (gentity_t *owner, vec3_t origin) {
gentity_t *ent;
ent = G_TempEntity( origin, EV_HAZARD );
ent->s.weapon = HT_SMOKE;
}