Modified repairing of func_breakables

func_breakables now don't need a trigger anymore to be repaired which
saves one entity for each reapairable func_breakable. Still needs a bit of
finetuning and code cleanup.
This commit is contained in:
Walter Julius Hennecke 2012-07-18 15:03:52 +02:00
parent 0d022b90e3
commit ff9d79a85a
9 changed files with 150 additions and 50 deletions

View file

@ -8,7 +8,7 @@
// because games can change separately from the main system version, we need a
// second version that must match between game and cgame
#define RPGX_VERSION "RPG-X v2.2 wc21012012"
#define RPGX_VERSION "RPG-X v2.2 wc18072012"
#define RPGX_COMPILEDATE "20/05/11"
#define RPGX_COMPILEDBY "GSIO01"
//const char GAME_VERSION[] = strcat("RPG-X v",RPGX_VERSION);

View file

@ -21,9 +21,9 @@ void breakable_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker,
self->health = 0;
}
self->pain = 0/*NULL*/;
self->die = 0/*NULL*/;
self->use = 0/*NULL*/;
self->pain = 0;
self->die = 0;
self->use = 0;
self->takedamage = qfalse;
@ -324,7 +324,7 @@ void SP_func_breakable( gentity_t *self )
VectorCopy(self->s.origin, self->pos1);
trap_LinkEntity(self);
InitBBrush( self );
breakable_spawn_trigger(self);
//breakable_spawn_trigger(self);
level.numBrushEnts++;
}
@ -677,7 +677,9 @@ void target_repair_use(gentity_t *ent, gentity_t *other, gentity_t *activator) {
target = ent->lastEnemy;
if(!(target->spawnflags & 256)) return;
if(!(target->spawnflags & 256)) {
return;
}
target->r.contents = CONTENTS_BODY;
@ -697,8 +699,8 @@ void target_repair_use(gentity_t *ent, gentity_t *other, gentity_t *activator) {
target->clipmask = 0;
target->count = 1;
if(target->touched->target)
G_UseTargets2(target->touched, target, target->touched->target);
//if(target->touched->target)
//G_UseTargets2(target->touched, target, target->touched->target);
}
/**

View file

@ -1819,54 +1819,60 @@ G_Repair
RPG-X | GSIO01 | 09/05/2009
============
*/
void G_Repair(gentity_t *ent, float rate) {
gentity_t *target, *trigger;
void G_Repair(gentity_t *ent, gentity_t *tr_ent, float rate) {
float distance;
vec3_t help, forward;
//trace_t *trace;
if(!ent->client || !ent->touched) // check whether ent is a player and check if he has touched a breakable trigger
return;
trigger = ent->touched;
if(!trigger->touched)
return;
target = trigger->touched;
int i;
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(target->count != 0 || Q_stricmp(target->classname, "func_breakable"))
if(tr_ent->count != 0 || Q_stricmp(tr_ent->classname, "func_breakable")) {
return;
if(!(target->spawnflags & 256)) { // no REPAIRABLE flag set
}
if(!(tr_ent->spawnflags & 256)) { // no REPAIRABLE flag set
return;
}
// check if player is near the breakable
VectorSubtract(target->s.origin, ent->client->ps.origin, help);
VectorSubtract(tr_ent->s.origin, ent->client->ps.origin, help);
distance = VectorLength(help);
if(distance > 80)
for(i = 0; i < 3; i++) {
if(tr_ent->r.maxs[i] > max) {
max = tr_ent->r.maxs[i];
}
}
if(distance > 80 + max) {
return;
}
// check if the player is facing it
AngleVectors(ent->client->ps.viewangles, forward, NULL, NULL);
VectorSubtract(target->s.origin, ent->client->ps.origin, help);
if(DotProduct(help, forward) < 0.4)
VectorSubtract(tr_ent->s.origin, ent->client->ps.origin, help);
if(DotProduct(help, forward) < 0.4) {
return;
// check wheter the breakable still needs to be repaired
if(target->health < target->damage)
// still not repaired of let's go on
target->health += rate;
else {
// else restore it
target->s.solid = CONTENTS_BODY;
trap_SetBrushModel(target, target->model);
target->r.svFlags &= ~SVF_NOCLIENT;
target->s.eFlags &= ~EF_NODRAW;
InitBBrush(target);
target->health = target->damage;
if(target->health)
target->takedamage = qtrue;
target->use = breakable_use;
if(target->paintarget)
target->pain = breakable_pain;
target->clipmask = 0;
target->count = 1;
if(trigger->target)
G_UseTargets2(trigger, target, trigger->target);
}
ent->touched = NULL; // make sure this is NULL
// check wheter the breakable still needs to be repaired
if(tr_ent->health < tr_ent->damage) {
// 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(tr_ent->health)
tr_ent->takedamage = qtrue;
tr_ent->use = breakable_use;
if(tr_ent->paintarget)
tr_ent->pain = breakable_pain;
tr_ent->clipmask = 0;
tr_ent->count = 1;
if(tr_ent->target)
G_UseTargets2(tr_ent, tr_ent, tr_ent->target);
}
}

View file

@ -827,6 +827,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]);
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 );
@ -846,7 +847,7 @@ void G_Damage (gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, vec3_
qboolean G_RadiusDamage (vec3_t origin, gentity_t *attacker, float damage, float radius, gentity_t *ignore, int dflags, int mod);
void body_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath );
void TossClientItems( gentity_t *self, qboolean dis_con );
void G_Repair(gentity_t *ent, float rate); //RPG-X | GSIO01 | 09/05/2009
void G_Repair(gentity_t *ent, gentity_t *tr_ent, float rate); //RPG-X | GSIO01 | 09/05/2009
// damage flags
#define DAMAGE_RADIUS 0x00000001 // damage was indirect

View file

@ -1080,6 +1080,66 @@ 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]) {
float dist;
gentity_t *ent;
int entityList[MAX_GENTITIES];
int numListedEntities;
vec3_t mins, maxs;
vec3_t v;
int i, e;
int ent_count = 0;
if ( radius < 1 )
{
radius = 1;
}
for ( i = 0 ; i < 3 ; i++ )
{
mins[i] = origin[i] - radius;
maxs[i] = origin[i] + radius;
}
numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
for ( e = 0 ; e < numListedEntities ; e++ )
{
ent = &g_entities[entityList[e]];
if ((ent == ignore) || !(ent->inuse) || strcmp(classname, ent->classname))
continue;
/* find the distance from the edge of the bounding box */
for ( i = 0 ; i < 3 ; i++ )
{
if ( origin[i] < ent->r.absmin[i] )
{
v[i] = ent->r.absmin[i] - origin[i];
} else if ( origin[i] > ent->r.absmax[i] )
{
v[i] = origin[i] - ent->r.absmax[i];
} else
{
v[i] = 0;
}
}
dist = VectorLength( v );
if ( dist >= radius )
{
continue;
}
/* ok, we are within the radius, add us to the incoming list */
ent_list[ent_count] = ent;
ent_count++;
}
/* we are done, return how many we found */
return(ent_count);
}
/**
* \brief Find the nearest entity
*

View file

@ -111,6 +111,37 @@ void SnapVectorTowards( vec3_t v, vec3_t to ) {
*/
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;
vec3_t dVec;
/* find all vlaid entities in range */
count = G_RadiusListOfType("func_breakable", ent->s.origin, 512, NULL, validEnts);
//G_Printf("Found %d possible candidates\n", count);
if(count) {
trace_t tr;
for(i = 0; i < count; i++) {
//G_Printf("Checking entity: %d\n", i);
trap_Trace(&tr, ent->s.origin, NULL, NULL, validEnts[i]->s.origin, ent->s.number, MASK_SHOT);
if(tr.entityNum != validEnts[i]->s.number && tr.entityNum != ENTITYNUM_WORLD) {
continue;
}
//G_Printf("Nothing is blocking view ...\n");
VectorSubtract(ent->s.origin, validEnts[i]->s.origin, dVec);
if(VectorLength(dVec) < nearestd) {
nearest = validEnts[i]->s.number;
nearestd = VectorLength(dVec);
//G_Printf("New nearest Entity is %d with a distance of %d\n", nearest, nearestd);
}
}
} else {
return;
}
if(nearest == -1) {
return;
}
/* determine the repair rate modifier */
if(rpg_repairModifier.value < 0) {
@ -121,9 +152,9 @@ static void WP_FireHyperspanner(gentity_t *ent, qboolean alt_fire) {
/* call G_Repair */
if(alt_fire) {
G_Repair(ent, HYPERSPANNER_ALT_RATE * modifier);
G_Repair(ent, &g_entities[nearest], HYPERSPANNER_ALT_RATE * modifier);
} else {
G_Repair(ent, HYPERSPANNER_RATE * modifier);
G_Repair(ent, &g_entities[nearest], HYPERSPANNER_RATE * modifier);
}
}

View file

@ -339,7 +339,7 @@ static int Game_Repair(lua_State *L) {
rate = (float)luaL_checknumber(L, 2);
G_Repair(lent->e, rate);
G_Repair(lent->e, NULL, rate); // FIXME ... trance ent?
return 1;
}

View file

@ -1,5 +1,5 @@
// Current version of holomatch game
#define Q3_VERSION "RPG-X v2.2 wc21012012"
#define Q3_VERSION "RPG-X v2.2 wc18072012"
// end

Binary file not shown.