Added repair support for misc_model_breakable

This commit is contained in:
Walter Julius Hennecke 2012-11-12 15:09:10 +01:00
parent 32d2c4c077
commit e2dfbeec15
5 changed files with 53 additions and 29 deletions

View file

@ -36,7 +36,7 @@ void breakable_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker,
eState->solid = 0;
eShared->contents = 0;
self->clipmask = 0;
if(self->spawnflags & 256) {
if(self->spawnflags & 256 && !strcmp(self->classname, "func_breakable")) {
eShared->svFlags |= SVF_NOCLIENT;
eState->eFlags |= EF_NODRAW;
}
@ -317,7 +317,7 @@ void SP_func_breakable( gentity_t *self )
level.numBrushEnts++;
}
/*QUAKED misc_model_breakable (1 0 0) (-16 -16 -16) (16 16 16) SOLID AUTOANIMATE DEADSOLID NO_DMODEL INVINCIBLE x x x x
/*QUAKED misc_model_breakable (1 0 0) (-16 -16 -16) (16 16 16) SOLID AUTOANIMATE DEADSOLID NO_DMODEL INVINCIBLE x x x REPAIRABLE
SOLID - Movement is blocked by it, if not set, can still be broken by explosions and shots if it has health
AUTOANIMATE - Will cycle it's anim
DEADSOLID - Stay solid even when destroyed (in case damage model is rather large).
@ -366,13 +366,15 @@ void SP_misc_model_breakable( gentity_t *ent )
if ( ent->spawnflags & 1 )
{//Blocks movement
eShared->contents = CONTENTS_BODY;//Was CONTENTS_SOLID, but only architecture should be this
eShared->contents = CONTENTS_BODY; //Was CONTENTS_SOLID, but only architecture should be this
}
else if ( ent->health )
{//Can only be shot
eShared->contents = CONTENTS_SHOTCLIP;
}
ent->damage = ent->health;
ent->use = breakable_use;
if ( ent->health )

View file

@ -1553,6 +1553,7 @@ qboolean IsBorg(gentity_t *ent) {
}
extern void InitBBrush(gentity_t *ent);
extern void SP_misc_model_breakable(gentity_t* self);
/*
============
G_Repair
@ -1566,7 +1567,7 @@ void G_Repair(gentity_t *ent, gentity_t *tr_ent, float rate) {
float max = 0;
// if count isn't 0 the breakable is not damaged and if target is no breakable it does not make sense to go on
if(tr_ent->count != 0 || Q_stricmp(tr_ent->classname, "func_breakable")) {
if(tr_ent->count != 0 || strstr(tr_ent->classname, "breakable") == NULL) {
return;
}
@ -1575,7 +1576,7 @@ void G_Repair(gentity_t *ent, gentity_t *tr_ent, float rate) {
}
// check if player is near the breakable
VectorSubtract(tr_ent->s.origin, ent->client->ps.origin, help);
VectorSubtract(tr_ent->s.origin, ent->r.currentOrigin, help);
distance = VectorLength(help);
for(i = 0; i < 3; i++) {
if(tr_ent->r.maxs[i] > max) {
@ -1583,6 +1584,7 @@ void G_Repair(gentity_t *ent, gentity_t *tr_ent, float rate) {
}
}
//G_Printf("goodDst=%f, curDst=%f\n", 80 + max, distance);
if(distance > 80 + max) {
return;
}
@ -1599,29 +1601,34 @@ void G_Repair(gentity_t *ent, gentity_t *tr_ent, float rate) {
// still not repaired of let's go on
tr_ent->health += rate;
} else {
// else restore it
tr_ent->s.solid = CONTENTS_BODY;
trap_SetBrushModel(tr_ent, tr_ent->model);
tr_ent->r.svFlags &= ~SVF_NOCLIENT;
tr_ent->s.eFlags &= ~EF_NODRAW;
InitBBrush(tr_ent);
tr_ent->health = tr_ent->damage;
if(!strcmp(tr_ent->classname, "func_breakable")) {
// else restore it
tr_ent->s.solid = CONTENTS_BODY;
trap_SetBrushModel(tr_ent, tr_ent->model);
tr_ent->r.svFlags &= ~SVF_NOCLIENT;
tr_ent->s.eFlags &= ~EF_NODRAW;
InitBBrush(tr_ent);
tr_ent->health = tr_ent->damage;
if(tr_ent->health) {
tr_ent->takedamage = qtrue;
}
if(tr_ent->health) {
tr_ent->takedamage = qtrue;
}
tr_ent->use = breakable_use;
tr_ent->use = breakable_use;
if(tr_ent->paintarget) {
tr_ent->pain = breakable_pain;
}
if(tr_ent->paintarget) {
tr_ent->pain = breakable_pain;
}
tr_ent->clipmask = 0;
tr_ent->count = 1;
tr_ent->clipmask = 0;
tr_ent->count = 1;
if(tr_ent->target) {
G_UseTargets2(tr_ent, tr_ent, tr_ent->target);
if(tr_ent->target) {
G_UseTargets2(tr_ent, tr_ent, tr_ent->target);
}
} else if(!strcmp(tr_ent->classname, "misc_model_breakable")) {
tr_ent->health = tr_ent->damage;
SP_misc_model_breakable(tr_ent);
}
}
}

View file

@ -819,7 +819,7 @@ void G_AddEvent( gentity_t *ent, int event, int eventParm );
void G_SetOrigin( gentity_t *ent, vec3_t origin );
void G_SetAngles( gentity_t *ent, vec3_t anlges ); //RPG-X | GSIO01 | 24.08.2009
int G_RadiusList ( vec3_t origin, float radius, gentity_t *ignore, qboolean takeDamage, gentity_t *ent_list[MAX_GENTITIES]);
int G_RadiusListOfType(char *classname, vec3_t origin, float radius, gentity_t *ignore, gentity_t *entlist[MAX_GENTITIES]);
int G_RadiusListOfTypes(char *classname[], int count, vec3_t origin, float radius, gentity_t *ignore, gentity_t *ent_list[MAX_GENTITIES]);
gentity_t *G_GetNearestEnt(char *classname, vec3_t origin, float radius, gentity_t *ignore, qboolean takeDamage);
gentity_t *G_GetNearestPlayer(vec3_t origin, float radius, gentity_t *ignore );

View file

@ -1094,7 +1094,7 @@ int G_RadiusList ( vec3_t origin, float radius, gentity_t *ignore, qboolean take
return(ent_count);
}
int G_RadiusListOfType(char *classname, vec3_t origin, float radius, gentity_t *ignore, gentity_t *ent_list[MAX_GENTITIES]) {
int G_RadiusListOfTypes(char *classname[], int count, vec3_t origin, float radius, gentity_t *ignore, gentity_t *ent_list[MAX_GENTITIES]) {
float dist;
gentity_t *ent;
int entityList[MAX_GENTITIES];
@ -1103,6 +1103,7 @@ int G_RadiusListOfType(char *classname, vec3_t origin, float radius, gentity_t *
vec3_t v;
int i, e;
int ent_count = 0;
qboolean valid = qfalse;
if ( radius < 1 )
{
@ -1121,9 +1122,19 @@ int G_RadiusListOfType(char *classname, vec3_t origin, float radius, gentity_t *
{
ent = &g_entities[entityList[e]];
if ((ent == ignore) || !(ent->inuse) || strcmp(classname, ent->classname))
if ((ent == ignore) || !(ent->inuse))
continue;
for(i = 0; i < count; i++) {
if(!strcmp(ent->classname, classname[i])) {
valid = qtrue;
}
}
if(!valid) {
continue;
}
/* find the distance from the edge of the bounding box */
for ( i = 0 ; i < 3 ; i++ )
{
@ -1149,6 +1160,7 @@ int G_RadiusListOfType(char *classname, vec3_t origin, float radius, gentity_t *
ent_list[ent_count] = ent;
ent_count++;
valid = qfalse;
}
/* we are done, return how many we found */
return(ent_count);

View file

@ -113,16 +113,19 @@ static void WP_FireHyperspanner(gentity_t *ent, qboolean alt_fire) {
float modifier;
gentity_t *validEnts[MAX_GENTITIES];
int count = 0;
int i, nearest = -1, nearestd = 512;
int i, nearest = -1;
float nearestd = 65000;
vec3_t dVec, end;
vec3_t mins = { -40, -40, -40 }, maxs = { 40, 40, 40 };
char* classnames[] = { "func_breakable", "misc_model_breakable" };
/* find all vlaid entities in range */
count = G_RadiusListOfType("func_breakable", ent->s.origin, 512, NULL, validEnts);
count = G_RadiusListOfTypes(classnames, 2, ent->r.currentOrigin, 512, NULL, validEnts);
//G_Printf("Found %d possible candidates\n", count);
if(count) {
trace_t tr;
for(i = 0; i < count; i++) {
// TODO: fix problems with small distance
VectorSubtract(ent->r.currentOrigin, validEnts[i]->s.origin, dVec);
VectorMA(validEnts[i]->s.origin, 1024, dVec, end);
//G_Printf("Checking entity: %d\n", i);
@ -131,7 +134,7 @@ static void WP_FireHyperspanner(gentity_t *ent, qboolean alt_fire) {
continue;
}
//G_Printf("Nothing is blocking view ...\n");
VectorSubtract(ent->s.origin, validEnts[i]->s.origin, dVec);
VectorSubtract(ent->r.currentOrigin, validEnts[i]->s.origin, dVec);
if(VectorLength(dVec) < nearestd) {
nearest = validEnts[i]->s.number;
nearestd = VectorLength(dVec);