summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2015-04-12 02:32:12 +0200
committerPaweł Redman <pawel.redman@gmail.com>2015-04-12 02:32:12 +0200
commit622ecb7bedeacaf4063dadc87764d3b66ad2f009 (patch)
tree6a936666d9d495d59bb7a0cc294b1077213550fe /src
parenteca487d693704aed6beb821222481724f3aeedd4 (diff)
Make force fields apply forces smoothly and continuously.
Diffstat (limited to 'src')
-rw-r--r--src/cgame/cg_predict.c17
-rw-r--r--src/game/bg_misc.c37
-rw-r--r--src/game/bg_pmove.c41
-rw-r--r--src/game/bg_public.h14
-rw-r--r--src/game/g_active.c13
-rw-r--r--src/game/g_buildable.c83
-rw-r--r--src/game/tremulous.h14
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 = &cent->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, &cent->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