mirror of
https://github.com/blendogames/thirtyflightsofloving.git
synced 2024-11-15 00:41:21 +00:00
272 lines
7.6 KiB
C
272 lines
7.6 KiB
C
|
/*
|
||
|
Copyright (C) 1997-2001 Id Software, Inc.
|
||
|
Copyright (C) 2000-2002 Mr. Hyde and Mad Dog
|
||
|
|
||
|
This program 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.
|
||
|
|
||
|
This program 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 this program; if not, write to the Free Software
|
||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include "g_local.h"
|
||
|
//
|
||
|
// mappack stuff by mr. ed, modified extensively for Tremor by dwh
|
||
|
//
|
||
|
|
||
|
//Spawns a user defined model, you can specify whether its solid, if so how big the box is, and apply nearly
|
||
|
//any effect to the entity.
|
||
|
//
|
||
|
// PLAYER set this if you want to use a player model
|
||
|
//
|
||
|
// Note : These flags override any frame settings you may have enterered
|
||
|
// ANIM01 cycle between frames 0 and 1 at 2 hz
|
||
|
// ANIM23 cycle between frames 2 and 3 at 2 hz
|
||
|
// ANIM_ALL cycle through all frames at 2hz
|
||
|
// ANIM_ALLFAST cycle through all frames at 10hz
|
||
|
//
|
||
|
// START_OFF Start inactive, when triggered display the model
|
||
|
// TOGGLE Start active, when triggered become inactive
|
||
|
// NO_MODEL Don't use a model. Usefull for placeing particle effects and
|
||
|
// dynamic lights on their own
|
||
|
//
|
||
|
// "usermodel" = The model to load (models/ is already coded)
|
||
|
// "startframe" = The starting frame : default 0
|
||
|
// "userframes" = The number of frames you want to display after startframe
|
||
|
// "solidstate" = 1 : SOLID_NOT - not solid at all
|
||
|
// 2 : SOLID_BBOX - solid and affected by gravity
|
||
|
// 3 : NO DROP - solid but not affected by gravity
|
||
|
// 4 : SOLID_NOT, but affect by gravity
|
||
|
//
|
||
|
// NOTE : if you want the model to be solid then you must enter vector values into the following fields :
|
||
|
// "bleft" = the point that is at the bottom left of the models bounding box in a model editor
|
||
|
// "tright" = the point that is at the top left of the models bounding box in a model editor
|
||
|
//
|
||
|
|
||
|
#define TOGGLE 2
|
||
|
#define PLAYER_MODEL 8
|
||
|
#define NO_MODEL 16
|
||
|
#define ANIM_ONCE 32
|
||
|
|
||
|
void model_spawn_use (edict_t *self, edict_t *other, edict_t *activator);
|
||
|
void modelspawn_think (edict_t *self)
|
||
|
{
|
||
|
self->s.frame++;
|
||
|
if (self->s.frame >= self->framenumbers)
|
||
|
{
|
||
|
self->s.frame = self->startframe;
|
||
|
if(self->spawnflags & ANIM_ONCE)
|
||
|
{
|
||
|
model_spawn_use(self,world,world);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
self->nextthink = level.time + FRAMETIME;
|
||
|
gi.linkentity(self);
|
||
|
}
|
||
|
|
||
|
void model_spawn_use (edict_t *self, edict_t *other, edict_t *activator)
|
||
|
{
|
||
|
if (self->delay) //we started off
|
||
|
{
|
||
|
self->svflags &= ~SVF_NOCLIENT;
|
||
|
self->delay = 0;
|
||
|
if(self->framenumbers > 1)
|
||
|
{
|
||
|
self->think = modelspawn_think;
|
||
|
self->nextthink = level.time + FRAMETIME;
|
||
|
}
|
||
|
self->s.sound = self->noise_index;
|
||
|
#ifdef LOOP_SOUND_ATTENUATION
|
||
|
self->s.attenuation = self->attenuation;
|
||
|
#endif
|
||
|
}
|
||
|
else //we started active
|
||
|
{
|
||
|
self->svflags |= SVF_NOCLIENT;
|
||
|
self->delay = 1;
|
||
|
self->use = model_spawn_use;
|
||
|
self->think = NULL;
|
||
|
self->nextthink = 0;
|
||
|
self->s.sound = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void model_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
|
||
|
{
|
||
|
edict_t *e, *next;
|
||
|
|
||
|
e = self->movewith_next;
|
||
|
while(e) {
|
||
|
next = e->movewith_next;
|
||
|
if(e->solid == SOLID_NOT) {
|
||
|
e->nextthink = 0;
|
||
|
G_FreeEdict(e);
|
||
|
} else
|
||
|
BecomeExplosion1 (e);
|
||
|
e = next;
|
||
|
}
|
||
|
|
||
|
BecomeExplosion1(self);
|
||
|
}
|
||
|
|
||
|
#define ANIM_MASK (EF_ANIM01|EF_ANIM23|EF_ANIM_ALL|EF_ANIM_ALLFAST)
|
||
|
|
||
|
void SP_model_spawn (edict_t *ent)
|
||
|
{
|
||
|
char modelname[256];
|
||
|
|
||
|
//paranoia checks
|
||
|
if ((!ent->usermodel) && !(ent->spawnflags & NO_MODEL) && !(ent->spawnflags & PLAYER_MODEL))
|
||
|
{
|
||
|
gi.dprintf("%s without a model at %s\n", ent->classname, vtos(ent->s.origin));
|
||
|
G_FreeEdict(ent);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
switch (ent->solidstate)
|
||
|
{
|
||
|
case 1 : ent->solid = SOLID_NOT; ent->movetype = MOVETYPE_NONE; break;
|
||
|
case 2 : ent->solid = SOLID_BBOX; ent->movetype = MOVETYPE_TOSS; break;
|
||
|
case 3 : ent->solid = SOLID_BBOX; ent->movetype = MOVETYPE_NONE; break;
|
||
|
case 4 : ent->solid = SOLID_NOT; ent->movetype = MOVETYPE_TOSS; break;
|
||
|
default: ent->solid = SOLID_NOT; ent->movetype = MOVETYPE_NONE; break;
|
||
|
}
|
||
|
if (ent->solid != SOLID_NOT ) {
|
||
|
if (ent->health > 0) {
|
||
|
ent->die = model_die;
|
||
|
ent->takedamage = DAMAGE_YES;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
switch (ent->style)
|
||
|
{
|
||
|
case 1 : ent->s.effects |= EF_ANIM01; break;
|
||
|
case 2 : ent->s.effects |= EF_ANIM23; break;
|
||
|
case 3 : ent->s.effects |= EF_ANIM_ALL; break;
|
||
|
case 4 : ent->s.effects |= EF_ANIM_ALLFAST; break;
|
||
|
}
|
||
|
|
||
|
// DWH: Rather than use one value (renderfx) we use the
|
||
|
// actual values for effects and renderfx. All may
|
||
|
// be combined.
|
||
|
ent->s.effects |= ent->effects;
|
||
|
ent->s.renderfx |= ent->renderfx;
|
||
|
|
||
|
if (ent->startframe < 0)
|
||
|
ent->startframe = 0;
|
||
|
if (!ent->framenumbers)
|
||
|
ent->framenumbers = 1;
|
||
|
// Change framenumbers to last frame to play
|
||
|
ent->framenumbers += ent->startframe;
|
||
|
|
||
|
if (ent->bleft)
|
||
|
{
|
||
|
VectorCopy (ent->bleft, ent->mins);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (ent->solid != SOLID_NOT)
|
||
|
{
|
||
|
gi.dprintf("%s solid with no bleft vector at %s\n", ent->classname, vtos(ent->s.origin));
|
||
|
ent->solid = SOLID_NOT;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ent->tright)
|
||
|
{
|
||
|
VectorCopy (ent->tright, ent->maxs);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (ent->solid != SOLID_NOT)
|
||
|
{
|
||
|
gi.dprintf("%s solid with no tright vector at %s\n", ent->classname, vtos(ent->s.origin));
|
||
|
ent->solid = SOLID_NOT;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if(ent->movewith && (ent->solid == SOLID_BBOX))
|
||
|
if(ent->movewith)
|
||
|
ent->movetype = MOVETYPE_PUSH;
|
||
|
|
||
|
if (ent->solid != SOLID_NOT)
|
||
|
ent->clipmask = CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER;
|
||
|
|
||
|
if (ent->spawnflags & NO_MODEL)
|
||
|
{ // For rendering effects to work, we MUST use a model
|
||
|
ent->s.modelindex = gi.modelindex ("sprites/point.sp2");
|
||
|
ent->movetype = MOVETYPE_NOCLIP;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (ent->spawnflags & PLAYER_MODEL) {
|
||
|
if(!ent->usermodel || !strlen(ent->usermodel))
|
||
|
ent->s.modelindex = MAX_MODELS-1;
|
||
|
else
|
||
|
{
|
||
|
if (strstr(ent->usermodel,"tris.md2"))
|
||
|
Com_sprintf(modelname, sizeof(modelname), "players/%s", ent->usermodel);
|
||
|
else
|
||
|
Com_sprintf(modelname, sizeof(modelname), "players/%s/tris.md2", ent->usermodel);
|
||
|
ent->s.modelindex = gi.modelindex(modelname);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (strstr(ent->usermodel,".sp2")) {
|
||
|
// Knightmare- check for "sprites/" already in path
|
||
|
if ( !strncmp(ent->usermodel, "sprites/", 8) )
|
||
|
Com_sprintf(modelname, sizeof(modelname), "%s", ent->usermodel);
|
||
|
else
|
||
|
Com_sprintf(modelname, sizeof(modelname), "sprites/%s", ent->usermodel);
|
||
|
}
|
||
|
else {
|
||
|
// Knightmare- check for "models/" already in path
|
||
|
if ( !strncmp(ent->usermodel, "models/", 7) )
|
||
|
Com_sprintf(modelname, sizeof(modelname), "%s", ent->usermodel);
|
||
|
else
|
||
|
Com_sprintf(modelname, sizeof(modelname), "models/%s", ent->usermodel);
|
||
|
}
|
||
|
ent->s.modelindex = gi.modelindex (modelname);
|
||
|
}
|
||
|
ent->s.frame = ent->startframe;
|
||
|
}
|
||
|
|
||
|
if (st.noise)
|
||
|
ent->noise_index = gi.soundindex (st.noise);
|
||
|
ent->s.sound = ent->noise_index;
|
||
|
#ifdef LOOP_SOUND_ATTENUATION
|
||
|
ent->s.attenuation = ent->attenuation;
|
||
|
#endif
|
||
|
|
||
|
// if (ent->skinnum) // Knightmare- selectable skin
|
||
|
// ent->s.skinnum = ent->skinnum;
|
||
|
|
||
|
if (ent->spawnflags & ANIM_ONCE)
|
||
|
ent->spawnflags |= TOGGLE;
|
||
|
|
||
|
if (ent->spawnflags & TOGGLE)
|
||
|
{
|
||
|
ent->delay = 0;
|
||
|
ent->use = model_spawn_use;
|
||
|
}
|
||
|
|
||
|
if(!(ent->s.effects & ANIM_MASK) && (ent->framenumbers > 1))
|
||
|
{
|
||
|
ent->think = modelspawn_think;
|
||
|
ent->nextthink = level.time + 2*FRAMETIME;
|
||
|
}
|
||
|
gi.linkentity (ent);
|
||
|
}
|