From e2dfbeec15ddfbf5ecb769e4b29216f8b6f3bfee Mon Sep 17 00:00:00 2001 From: Walter Julius Hennecke Date: Mon, 12 Nov 2012 15:09:10 +0100 Subject: [PATCH] Added repair support for misc_model_breakable --- code/game/g_breakable.c | 8 ++++--- code/game/g_combat.c | 47 +++++++++++++++++++++++------------------ code/game/g_local.h | 2 +- code/game/g_utils.c | 16 ++++++++++++-- code/game/g_weapon.c | 9 +++++--- 5 files changed, 53 insertions(+), 29 deletions(-) diff --git a/code/game/g_breakable.c b/code/game/g_breakable.c index 67e8167..f2f0a25 100644 --- a/code/game/g_breakable.c +++ b/code/game/g_breakable.c @@ -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 ) diff --git a/code/game/g_combat.c b/code/game/g_combat.c index 4068c38..e9ea2cb 100644 --- a/code/game/g_combat.c +++ b/code/game/g_combat.c @@ -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); } } } diff --git a/code/game/g_local.h b/code/game/g_local.h index e5723db..98b639a 100644 --- a/code/game/g_local.h +++ b/code/game/g_local.h @@ -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 ); diff --git a/code/game/g_utils.c b/code/game/g_utils.c index cce243d..8e961a3 100644 --- a/code/game/g_utils.c +++ b/code/game/g_utils.c @@ -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); diff --git a/code/game/g_weapon.c b/code/game/g_weapon.c index fa95e7a..d6a1878 100644 --- a/code/game/g_weapon.c +++ b/code/game/g_weapon.c @@ -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);