diff options
author | Paweł Redman <pawel.redman@gmail.com> | 2015-04-12 02:32:12 +0200 |
---|---|---|
committer | Paweł Redman <pawel.redman@gmail.com> | 2015-04-12 02:32:12 +0200 |
commit | 622ecb7bedeacaf4063dadc87764d3b66ad2f009 (patch) | |
tree | 6a936666d9d495d59bb7a0cc294b1077213550fe | |
parent | eca487d693704aed6beb821222481724f3aeedd4 (diff) |
Make force fields apply forces smoothly and continuously.
-rw-r--r-- | src/cgame/cg_predict.c | 17 | ||||
-rw-r--r-- | src/game/bg_misc.c | 37 | ||||
-rw-r--r-- | src/game/bg_pmove.c | 41 | ||||
-rw-r--r-- | src/game/bg_public.h | 14 | ||||
-rw-r--r-- | src/game/g_active.c | 13 | ||||
-rw-r--r-- | src/game/g_buildable.c | 83 | ||||
-rw-r--r-- | src/game/tremulous.h | 14 |
7 files changed, 151 insertions, 68 deletions
diff --git a/src/cgame/cg_predict.c b/src/cgame/cg_predict.c index 9baab8b..bba333c 100644 --- a/src/cgame/cg_predict.c +++ b/src/cgame/cg_predict.c @@ -620,6 +620,23 @@ void CG_PredictPlayerState( void ) cg_pmove.noFootsteps = 0; +/* for( i = 0; i < cg.snap->numEntities; i++ ) + { + cent = &cg_entities[ cg.snap->entities[ i ].number ]; + es = ¢->currentState;*/ + + for( cg_pmove.numForceFields = 0, i = 0; i < cg.snap->numEntities; i++ ) + { + centity_t *cent = cg_entities + cg.snap->entities[ i ].number; + + if( BG_ForceFieldForEntity( &cg.predictedPlayerState, ¢->currentState, + cg_pmove.forceFields + cg_pmove.numForceFields ) ) + cg_pmove.numForceFields++; + + if( cg_pmove.numForceFields == MAX_FORCE_FIELDS ) + break; + } + // save the state before the pmove so we can detect transitions oldPlayerState = cg.predictedPlayerState; diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c index b1c7550..7971aa8 100644 --- a/src/game/bg_misc.c +++ b/src/game/bg_misc.c @@ -5449,3 +5449,40 @@ int cmdcmp( const void *a, const void *b ) { return Q_stricmp( (const char *)a, ((dummyCmd_t *)b)->name ); } + +/* +============ +BG_ForceFieldForEntity +============ +*/ +qboolean BG_ForceFieldForEntity( playerState_t *ps, entityState_t *es, forceField_t *ff ) +{ + if( es->eType == ET_BUILDABLE ) + { + if( !( es->eFlags & EF_B_POWERED ) ) + return qfalse; + + if( !( es->eFlags & EF_B_SPAWNED ) ) + return qfalse; + + // health + if( es->generic1 <= 0 ) + return qfalse; + + switch( es->modelindex ) + { + case BA_H_LIGHT: //force field + if( ps && ps->stats[ STAT_TEAM ] != TEAM_ALIENS ) + return qfalse; + + ff->type = 0; + VectorCopy( es->origin, ff->origin ); + ff->range = LIGHT_RANGE; + ff->force = LIGHT_FORCE; + + return qtrue; + } + } + + return qfalse; +} diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c index ecdaccf..b19dd68 100644 --- a/src/game/bg_pmove.c +++ b/src/game/bg_pmove.c @@ -3901,6 +3901,45 @@ void PM_UpdateViewAngles( playerState_t *ps, const usercmd_t *cmd ) } } +/* +================ +PM_ForceFields +================ +*/ + +void PM_ForceFields( void ) +{ + int i; + float dt = pml.msec * 0.001f; + forceField_t *ff; + vec3_t total = { 0 }; + + for( i = 0; i < pm->numForceFields; i++ ) + { + vec3_t delta; + float distance, force; + trace_t tr; + + ff = pm->forceFields + i; + + VectorSubtract( ff->origin, pm->ps->origin, delta ); + distance = VectorNormalize( delta ); + + if( distance > ff->range ) + continue; + + pm->trace( &tr, pm->ps->origin, NULL, NULL, ff->origin, pm->ps->clientNum, MASK_SOLID ); + + if( tr.fraction < 1.0f ) + continue; + + force = ff->force / distance * ( 1.0f - distance / ff->range ); + + VectorMA( total, force, delta, total ); + } + + VectorMA( pm->ps->velocity, dt, total, pm->ps->velocity ); +} /* ================ @@ -4062,6 +4101,8 @@ void PmoveSingle( pmove_t *pmove ) PM_DropTimers( ); + PM_ForceFields( ); + if( pm->ps->pm_type == PM_JETPACK ) PM_JetPackMove( ); else if( pm->ps->pm_type == PM_HUMMEL ) diff --git a/src/game/bg_public.h b/src/game/bg_public.h index 1e9d23c..ba7c701 100644 --- a/src/game/bg_public.h +++ b/src/game/bg_public.h @@ -161,6 +161,15 @@ typedef enum #define PMF_ALL_TIMES (PMF_TIME_WATERJUMP|PMF_TIME_LAND|PMF_TIME_KNOCKBACK|PMF_TIME_WALLJUMP) +#define MAX_FORCE_FIELDS 100 +typedef struct +{ + int type; + vec3_t origin; + float force; + float range; +} forceField_t; + typedef struct { int pouncePayload; @@ -205,6 +214,9 @@ typedef struct pmove_s int (*pointcontents)( const vec3_t point, int passEntityNum ); + + forceField_t forceFields[ MAX_FORCE_FIELDS ]; + int numForceFields; } pmove_t; // if a full pmove isn't done on the client, you can just update the angles @@ -1249,3 +1261,5 @@ int cmdcmp( const void *a, const void *b ); #define DIF_BUILDABLE 0x0002 // has to be 2 #define DIF_FRIENDLY 0x0004 #define DIF_PERSISTENT 0x0008 // poison and infection + +qboolean BG_ForceFieldForEntity( playerState_t *ps, entityState_t *es, forceField_t *ff ); diff --git a/src/game/g_active.c b/src/game/g_active.c index 0c84f57..1f0d121 100644 --- a/src/game/g_active.c +++ b/src/game/g_active.c @@ -1663,6 +1663,7 @@ void ClientThink_real( gentity_t *ent ) int oldEventSequence; int msec; usercmd_t *ucmd; + int i; client = ent->client; @@ -1992,6 +1993,18 @@ void ClientThink_real( gentity_t *ent ) pm.debugLevel = g_debugMove.integer; pm.noFootsteps = 0; + for( i = 0; i < level.num_entities; i++ ) + { + gentity_t *ent = g_entities + i; + + if( BG_ForceFieldForEntity( pm.ps, &ent->s, + pm.forceFields + pm.numForceFields ) ) + pm.numForceFields++; + + if( pm.numForceFields == MAX_FORCE_FIELDS ) + break; + } + pm.pmove_fixed = pmove_fixed.integer | client->pers.pmoveFixed; pm.pmove_msec = pmove_msec.integer; diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c index 21f5424..e6d4dd5 100644 --- a/src/game/g_buildable.c +++ b/src/game/g_buildable.c @@ -1642,13 +1642,8 @@ for forcefield */ void G_Push( gentity_t *self ) { -#define PUSH_REPEAT 400 -#define PUSH_RANGE 140 -#define PUSH_FORCE -900 -#define WEAK_PUSH_FORCE -675 - int entityList[ MAX_GENTITIES ]; - vec3_t range = { PUSH_RANGE, PUSH_RANGE, PUSH_RANGE }; + vec3_t range = { LIGHT_RANGE, LIGHT_RANGE, LIGHT_RANGE }; vec3_t mins, maxs; int i, num; gentity_t *enemy; @@ -1656,7 +1651,7 @@ void G_Push( gentity_t *self ) float force; qboolean active = qfalse; - self->nextthink = level.time + PUSH_REPEAT; + self->nextthink = level.time + 500; VectorAdd( self->s.origin, range, maxs ); VectorSubtract( self->s.origin, range, mins ); @@ -1682,80 +1677,44 @@ void G_Push( gentity_t *self ) if( enemy->flags & FL_NOTARGET ) continue; + if( !G_Visible( self, enemy, CONTENTS_SOLID ) ) - continue; + continue; + if (enemy->client && enemy->client->notrackEndTime >= level.time) - continue; + continue; + + if( Distance( enemy->r.currentOrigin, self->r.currentOrigin ) > LIGHT_RANGE ) + continue; if( enemy->client && enemy->client->ps.stats[ STAT_TEAM ] != TEAM_HUMANS ) { - if (enemy == self) - continue; + if (enemy == self) + continue; - if (!enemy->client) - continue; + if (!enemy->client) + continue; - if (enemy == self->parent) - continue; + if (enemy == self->parent) + continue; - if (!enemy->takedamage) - continue; + if (!enemy->takedamage) + continue; - active = qtrue; - break; + active = qtrue; + break; } } if (active) { - for( i = 0; i < num; i++ ) - { - enemy = &g_entities[ entityList[ i ] ]; - - if( enemy->flags & FL_NOTARGET ) - continue; - - if( !G_Visible( self, enemy, CONTENTS_SOLID ) ) - continue; - - if (enemy->client && enemy->client->notrackEndTime >= level.time) - continue; - - if( enemy->client && enemy->client->ps.stats[ STAT_TEAM ] != TEAM_NONE ) - { - if (enemy == self) - continue; - - if (!enemy->client) - continue; - - if (enemy == self->parent) - continue; - - if (!enemy->takedamage) - continue; - - if ( enemy->client->ps.stats[ STAT_CLASS ] == PCL_ALIEN_LEVEL5 ) - force = PUSH_FORCE; - else - force = WEAK_PUSH_FORCE; - - VectorCopy(enemy->r.currentOrigin, start); - VectorCopy(self->r.currentOrigin, end); - VectorSubtract(end, start, dir); - VectorNormalize(dir); - VectorScale(dir, force, enemy->client->ps.velocity); - VectorCopy(dir, enemy->movedir); - } - } - // start the attack animation G_AddEvent( self, EV_FORCE_FIELD, DirToByte( self->s.origin2 ) ); if( level.time >= self->timestamp + 500 ) { - self->timestamp = level.time; - G_SetBuildableAnim( self, BANIM_ATTACK1, qfalse ); + self->timestamp = level.time; + G_SetBuildableAnim( self, BANIM_ATTACK1, qfalse ); } } } diff --git a/src/game/tremulous.h b/src/game/tremulous.h index f5a4bf7..7800bb3 100644 --- a/src/game/tremulous.h +++ b/src/game/tremulous.h @@ -1111,12 +1111,14 @@ TREMULOUS EDGE MOD SRC FILE #define BARREL_SPLASHRADIUS 150 #define BARREL_VALUE HBVM(BARREL_BP) -#define LIGHT_BP 12 -#define LIGHT_BT 12000 -#define LIGHT_HEALTH HBHM(200) -#define LIGHT_SPLASHDAMAGE 15 -#define LIGHT_SPLASHRADIUS 180 -#define LIGHT_VALUE HBVM(LIGHT_BP) +#define LIGHT_BP 12 +#define LIGHT_BT 12000 +#define LIGHT_HEALTH HBHM(200) +#define LIGHT_SPLASHDAMAGE 15 +#define LIGHT_SPLASHRADIUS 180 +#define LIGHT_VALUE HBVM(LIGHT_BP) +#define LIGHT_RANGE 220 +#define LIGHT_FORCE -1.5e+6 #define COVER_BP 20 #define COVER_BT 20000 |