summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2007-09-27 16:43:14 +0000
committerTim Angus <tim@ngus.net>2007-09-27 16:43:14 +0000
commit91fba4721971938e9e1cb443f0dcb167a9f3c175 (patch)
tree790623b7416ef3ae557c60ed72134a5ca351ea98
parentb17d871269828bbd12c2790ee5ddafa54af8ed9b (diff)
* (bug 3249) Improve repeater interaction with marked deconstruction
* (bug 3321) Allow medkits and medistats to operate simultaneously * (bug 3310) Fix odd CalcMuzzlePoint implementation * Random refactoring of g_buildable.c * Add BG_GetClientNormal
-rw-r--r--src/cgame/cg_scanner.c10
-rw-r--r--src/cgame/cg_view.c56
-rw-r--r--src/game/bg_misc.c30
-rw-r--r--src/game/bg_pmove.c23
-rw-r--r--src/game/bg_public.h1
-rw-r--r--src/game/bg_slidemove.c10
-rw-r--r--src/game/g_buildable.c295
-rw-r--r--src/game/g_combat.c5
-rw-r--r--src/game/g_local.h2
-rw-r--r--src/game/g_weapon.c11
10 files changed, 210 insertions, 233 deletions
diff --git a/src/cgame/cg_scanner.c b/src/cgame/cg_scanner.c
index 195b6d76..f9175ede 100644
--- a/src/cgame/cg_scanner.c
+++ b/src/cgame/cg_scanner.c
@@ -183,15 +183,7 @@ static void CG_DrawDir( rectDef_t *rect, vec3_t origin, vec4_t colour )
float angle;
playerState_t *ps = &cg.snap->ps;
- if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING )
- {
- if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING )
- VectorSet( normal, 0.0f, 0.0f, -1.0f );
- else
- VectorCopy( ps->grapplePoint, normal );
- }
- else
- VectorSet( normal, 0.0f, 0.0f, 1.0f );
+ BG_GetClientNormal( ps, normal );
AngleVectors( entityPositions.vangles, view, NULL, NULL );
diff --git a/src/cgame/cg_view.c b/src/cgame/cg_view.c
index 62d86cf9..781e068a 100644
--- a/src/cgame/cg_view.c
+++ b/src/cgame/cg_view.c
@@ -278,15 +278,7 @@ static void CG_OffsetThirdPersonView( void )
float forwardScale, sideScale;
vec3_t surfNormal;
- if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_WALLCLIMBING )
- {
- if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING )
- VectorSet( surfNormal, 0.0f, 0.0f, -1.0f );
- else
- VectorCopy( cg.predictedPlayerState.grapplePoint, surfNormal );
- }
- else
- VectorSet( surfNormal, 0.0f, 0.0f, 1.0f );
+ BG_GetClientNormal( &cg.predictedPlayerState, surfNormal );
VectorMA( cg.refdef.vieworg, cg.predictedPlayerState.viewheight, surfNormal, cg.refdef.vieworg );
@@ -355,19 +347,11 @@ static void CG_OffsetThirdPersonView( void )
static void CG_StepOffset( void )
{
float steptime;
- int timeDelta;
+ int timeDelta;
vec3_t normal;
playerState_t *ps = &cg.predictedPlayerState;
- if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING )
- {
- if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING )
- VectorSet( normal, 0.0f, 0.0f, -1.0f );
- else
- VectorCopy( ps->grapplePoint, normal );
- }
- else
- VectorSet( normal, 0.0f, 0.0f, 1.0f );
+ BG_GetClientNormal( ps, normal );
steptime = BG_FindSteptimeForClass( ps->stats[ STAT_PCLASS ] );
@@ -378,10 +362,7 @@ static void CG_StepOffset( void )
float stepChange = cg.stepChange
* (steptime - timeDelta) / steptime;
- if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING )
- VectorMA( cg.refdef.vieworg, -stepChange, normal, cg.refdef.vieworg );
- else
- cg.refdef.vieworg[ 2 ] -= stepChange;
+ VectorMA( cg.refdef.vieworg, -stepChange, normal, cg.refdef.vieworg );
}
}
@@ -412,16 +393,7 @@ static void CG_OffsetFirstPersonView( void )
vec3_t normal, baseOrigin;
playerState_t *ps = &cg.predictedPlayerState;
- if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING )
- {
- if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING )
- VectorSet( normal, 0.0f, 0.0f, -1.0f );
- else
- VectorCopy( ps->grapplePoint, normal );
- }
- else
- VectorSet( normal, 0.0f, 0.0f, 1.0f );
-
+ BG_GetClientNormal( ps, normal );
if( cg.snap->ps.pm_type == PM_INTERMISSION )
return;
@@ -643,11 +615,7 @@ static void CG_OffsetFirstPersonView( void )
//===================================
// add view height
- // when wall climbing the viewheight is not straight up
- if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_WALLCLIMBING )
- VectorMA( origin, ps->viewheight, normal, origin );
- else
- origin[ 2 ] += cg.predictedPlayerState.viewheight;
+ VectorMA( origin, ps->viewheight, normal, origin );
// smooth out duck height changes
timeDelta = cg.time - cg.duckTime;
@@ -663,12 +631,7 @@ static void CG_OffsetFirstPersonView( void )
if( bob > 6 )
bob = 6;
- // likewise for bob
- if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_WALLCLIMBING )
- VectorMA( origin, bob, normal, origin );
- else
- origin[ 2 ] += bob;
-
+ VectorMA( origin, bob, normal, origin );
// add fall height
delta = cg.time - cg.landTime;
@@ -943,10 +906,7 @@ static void CG_smoothWWTransitions( playerState_t *ps, const vec3_t in, vec3_t o
}
//set surfNormal
- if( !( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) )
- VectorCopy( ps->grapplePoint, surfNormal );
- else
- VectorCopy( ceilingNormal, surfNormal );
+ BG_GetClientNormal( ps, surfNormal );
AnglesToAxis( in, inAxis );
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c
index 85c1f47a..c4d374ae 100644
--- a/src/game/bg_misc.c
+++ b/src/game/bg_misc.c
@@ -5123,6 +5123,26 @@ qboolean BG_RotateAxis( vec3_t surfNormal, vec3_t inAxis[ 3 ],
/*
===============
+BG_GetClientNormal
+
+Get the normal for the surface the client is walking on
+===============
+*/
+void BG_GetClientNormal( const playerState_t *ps, vec3_t normal )
+{
+ if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING )
+ {
+ if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING )
+ VectorSet( normal, 0.0f, 0.0f, -1.0f );
+ else
+ VectorCopy( ps->grapplePoint, normal );
+ }
+ else
+ VectorSet( normal, 0.0f, 0.0f, 1.0f );
+}
+
+/*
+===============
BG_PositionBuildableRelativeToPlayer
Find a place to build a buildable
@@ -5138,15 +5158,7 @@ void BG_PositionBuildableRelativeToPlayer( const playerState_t *ps,
vec3_t angles, playerOrigin, playerNormal;
float buildDist;
- if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING )
- {
- if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING )
- VectorSet( playerNormal, 0.0f, 0.0f, -1.0f );
- else
- VectorCopy( ps->grapplePoint, playerNormal );
- }
- else
- VectorSet( playerNormal, 0.0f, 0.0f, 1.0f );
+ BG_GetClientNormal( ps, playerNormal );
VectorCopy( ps->viewangles, angles );
VectorCopy( ps->origin, playerOrigin );
diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c
index ae9e3073..80ca7715 100644
--- a/src/game/bg_pmove.c
+++ b/src/game/bg_pmove.c
@@ -658,6 +658,8 @@ PM_CheckJump
*/
static qboolean PM_CheckJump( void )
{
+ vec3_t normal;
+
if( BG_FindJumpMagnitudeForClass( pm->ps->stats[ STAT_PCLASS ] ) == 0.0f )
return qfalse;
@@ -712,18 +714,10 @@ static qboolean PM_CheckJump( void )
pm->ps->groundEntityNum = ENTITYNUM_NONE;
// jump away from wall
- if( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBING )
- {
- vec3_t normal = { 0, 0, -1 };
+ BG_GetClientNormal( pm->ps, normal );
- if( !( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) )
- VectorCopy( pm->ps->grapplePoint, normal );
-
- VectorMA( pm->ps->velocity, BG_FindJumpMagnitudeForClass( pm->ps->stats[ STAT_PCLASS ] ),
- normal, pm->ps->velocity );
- }
- else
- pm->ps->velocity[ 2 ] = BG_FindJumpMagnitudeForClass( pm->ps->stats[ STAT_PCLASS ] );
+ VectorMA( pm->ps->velocity, BG_FindJumpMagnitudeForClass( pm->ps->stats[ STAT_PCLASS ] ),
+ normal, pm->ps->velocity );
PM_AddEvent( EV_JUMP );
@@ -1716,12 +1710,7 @@ static void PM_GroundClimbTrace( void )
float ldDOTtCs, d;
vec3_t abc;
- // If we're on the ceiling then grapplePoint is a rotation normal.. otherwise its a surface normal.
- // would have been nice if Carmack had left a few random variables in the ps struct for mod makers
- if( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING )
- VectorCopy( ceilingNormal, surfNormal );
- else
- VectorCopy( pm->ps->grapplePoint, surfNormal );
+ BG_GetClientNormal( pm->ps, surfNormal );
//construct a vector which reflects the direction the player is looking wrt the surface normal
ProjectPointOnPlane( movedir, pml.forward, surfNormal );
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index 0d6caefa..a48669d6 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -1091,6 +1091,7 @@ void BG_DeactivateUpgrade( int item, int stats[ ] );
qboolean BG_UpgradeIsActive( int item, int stats[ ] );
qboolean BG_RotateAxis( vec3_t surfNormal, vec3_t inAxis[ 3 ],
vec3_t outAxis[ 3 ], qboolean inverse, qboolean ceiling );
+void BG_GetClientNormal( const playerState_t *ps, vec3_t normal );
void BG_PositionBuildableRelativeToPlayer( const playerState_t *ps,
const vec3_t mins, const vec3_t maxs,
void (*trace)( trace_t *, const vec3_t, const vec3_t,
diff --git a/src/game/bg_slidemove.c b/src/game/bg_slidemove.c
index aa32a6ae..0b3f8f0c 100644
--- a/src/game/bg_slidemove.c
+++ b/src/game/bg_slidemove.c
@@ -298,15 +298,7 @@ qboolean PM_StepSlideMove( qboolean gravity, qboolean predictive )
float stepSize;
qboolean stepped = qfalse;
- if( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBING )
- {
- if( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING )
- VectorSet( normal, 0.0f, 0.0f, -1.0f );
- else
- VectorCopy( pm->ps->grapplePoint, normal );
- }
- else
- VectorSet( normal, 0.0f, 0.0f, 1.0f );
+ BG_GetClientNormal( pm->ps, normal );
VectorCopy( pm->ps->origin, start_o );
VectorCopy( pm->ps->velocity, start_v );
diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c
index 12129699..9c36e4c8 100644
--- a/src/game/g_buildable.c
+++ b/src/game/g_buildable.c
@@ -185,7 +185,7 @@ static qboolean G_FindPower( gentity_t *self )
self->parentNode = NULL;
//iterate through entities
- for ( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ )
+ for( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ )
{
if( ent->s.eType != ET_BUILDABLE )
continue;
@@ -197,20 +197,25 @@ static qboolean G_FindPower( gentity_t *self )
VectorSubtract( self->s.origin, ent->s.origin, temp_v );
distance = VectorLength( temp_v );
- if( distance < minDistance && ent->powered &&
- ( ( ent->s.modelindex == BA_H_REACTOR &&
- distance <= REACTOR_BASESIZE ) ||
- ( ent->s.modelindex == BA_H_REPEATER &&
- distance <= REPEATER_BASESIZE ) ) ) {
-
- closestPower = ent;
- minDistance = distance;
+ // Always prefer a reactor if there is one in range
+ if( ent->s.modelindex == BA_H_REACTOR &&
+ distance <= REACTOR_BASESIZE )
+ {
+ self->parentNode = ent;
+ return qtrue;
+ }
+ else if( distance < minDistance && ent->powered &&
+ distance <= REPEATER_BASESIZE )
+ {
+ closestPower = ent;
+ minDistance = distance;
}
}
}
//if there were no power items nearby give up
- if( closestPower ) {
+ if( closestPower )
+ {
self->parentNode = closestPower;
return qtrue;
}
@@ -220,12 +225,13 @@ static qboolean G_FindPower( gentity_t *self )
/*
================
-G_IsPowered
+G_PowerEntityForPoint
-Simple wrapper to G_FindPower to check if a location has power
+Simple wrapper to G_FindPower to find the entity providing
+power for the specified point
================
*/
-qboolean G_IsPowered( vec3_t origin )
+static gentity_t *G_PowerEntityForPoint( vec3_t origin )
{
gentity_t dummy;
@@ -234,7 +240,28 @@ qboolean G_IsPowered( vec3_t origin )
dummy.s.modelindex = BA_NONE;
VectorCopy( origin, dummy.s.origin );
- return G_FindPower( &dummy );
+ if( G_FindPower( &dummy ) )
+ return dummy.parentNode;
+ else
+ return NULL;
+}
+
+/*
+================
+G_IsPowered
+
+Check if a location has power, returning the entity type
+that is providing it
+================
+*/
+buildable_t G_IsPowered( vec3_t origin )
+{
+ gentity_t *ent = G_PowerEntityForPoint( origin );
+
+ if( ent )
+ return ent->s.modelindex;
+ else
+ return BA_NONE;
}
/*
@@ -1848,9 +1875,6 @@ void HMedistat_Think( gentity_t *self )
if( self->enemy->client && self->enemy->client->ps.stats[ STAT_STATE ] & SS_POISONED )
self->enemy->client->ps.stats[ STAT_STATE ] &= ~SS_POISONED;
- if( self->enemy->client && self->enemy->client->ps.stats[ STAT_STATE ] & SS_MEDKIT_ACTIVE )
- self->enemy->client->ps.stats[ STAT_STATE ] &= ~SS_MEDKIT_ACTIVE;
-
self->enemy->health++;
//if they're completely healed, give them a medkit
@@ -2532,6 +2556,30 @@ qboolean G_BuildableRange( vec3_t origin, float r, buildable_t buildable )
}
/*
+================
+G_FindBuildable
+
+Finds a buildable of the specified type
+================
+*/
+static gentity_t *G_FindBuildable( buildable_t buildable )
+{
+ int i;
+ gentity_t *ent;
+
+ for ( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ )
+ {
+ if( ent->s.eType != ET_BUILDABLE )
+ continue;
+
+ if( ent->s.modelindex == buildable )
+ return ent;
+ }
+
+ return NULL;
+}
+
+/*
===============
G_BuildablesIntersect
@@ -2592,20 +2640,19 @@ static int G_CompareBuildablesForRemoval( const void *a, const void *b )
gentity_t *buildableA, *buildableB;
int i;
int aPrecedence = 0, bPrecedence = 0;
- qboolean aCollides = qfalse, bCollides = qfalse;
qboolean aMatches = qfalse, bMatches = qfalse;
buildableA = *(gentity_t **)a;
buildableB = *(gentity_t **)b;
// Prefer the one that collides with the thing we're building
- aCollides = G_BuildablesIntersect( cmpBuildable, cmpOrigin,
+ aMatches = G_BuildablesIntersect( cmpBuildable, cmpOrigin,
buildableA->s.modelindex, buildableA->s.origin );
- bCollides = G_BuildablesIntersect( cmpBuildable, cmpOrigin,
+ bMatches = G_BuildablesIntersect( cmpBuildable, cmpOrigin,
buildableB->s.modelindex, buildableB->s.origin );
- if( aCollides && !bCollides )
+ if( aMatches && !bMatches )
return -1;
- else if( !aCollides && bCollides )
+ else if( !aMatches && bMatches )
return 1;
// If one matches the thing we're building, prefer it
@@ -2616,9 +2663,22 @@ static int G_CompareBuildablesForRemoval( const void *a, const void *b )
else if( !aMatches && bMatches )
return 1;
- // If they're the same type then pick the one marked earliest
+ // They're the same type
if( buildableA->s.modelindex == buildableB->s.modelindex )
+ {
+ gentity_t *powerEntity = G_PowerEntityForPoint( cmpOrigin );
+
+ // Prefer the entity that is providing power for this point
+ aMatches = ( powerEntity == buildableA );
+ bMatches = ( powerEntity == buildableB );
+ if( aMatches && !bMatches )
+ return -1;
+ else if( !aMatches && bMatches )
+ return 1;
+
+ // Pick the one marked earliest
return buildableA->deconstructTime - buildableB->deconstructTime;
+ }
// Resort to preference list
for( i = 0; i < sizeof( precedence ) / sizeof( precedence[ 0 ] ); i++ )
@@ -2676,6 +2736,8 @@ static itemBuildError_t G_SufficientBPAvailable( buildable_t buildable,
int remainingBP, remainingSpawns;
qboolean collision = qfalse;
int collisionCount = 0;
+ qboolean repeaterInRange = qfalse;
+ int repeaterInRangeCount = 0;
itemBuildError_t bpError;
buildable_t spawn;
buildable_t core;
@@ -2750,6 +2812,17 @@ static itemBuildError_t G_SufficientBPAvailable( buildable_t buildable,
collisionCount++;
}
+ // Check if this is a repeater and it's in range
+ if( buildable == BA_H_REPEATER &&
+ buildable == ent->s.modelindex &&
+ Distance( ent->s.origin, origin ) < REPEATER_BASESIZE )
+ {
+ repeaterInRange = qtrue;
+ repeaterInRangeCount++;
+ }
+ else
+ repeaterInRange = qfalse;
+
if( !ent->inuse )
continue;
@@ -2772,12 +2845,20 @@ static itemBuildError_t G_SufficientBPAvailable( buildable_t buildable,
{
level.markedBuildables[ numBuildables++ ] = ent;
- if( collision )
+ // Buildables that are marked here will always end up at the front of the
+ // removal list, so just incrementing numBuildablesForRemoval is sufficient
+ if( collision || repeaterInRange )
{
- // Collided with something, so we definitely have to remove it
- // It will always end up at the front of the removal list, so
- // incrementing numBuildablesForRemoval is sufficient
- collisionCount--;
+ // Collided with something, so we definitely have to remove it or
+ // it's a repeater that intersects the new repeater's power area,
+ // so it must be removed
+
+ if( collision )
+ collisionCount--;
+
+ if( repeaterInRange )
+ repeaterInRangeCount--;
+
pointsYielded += BG_FindBuildPointsForBuildable( ent->s.modelindex );
level.numBuildablesForRemoval++;
}
@@ -2799,6 +2880,10 @@ static itemBuildError_t G_SufficientBPAvailable( buildable_t buildable,
if( collisionCount > 0 )
return IBE_NOROOM;
+ // There are one or more repeaters we can't remove
+ if( repeaterInRangeCount > 0 )
+ return IBE_RPTWARN2;
+
// Sort the list
cmpBuildable = buildable;
VectorCopy( origin, cmpOrigin );
@@ -2867,7 +2952,6 @@ itemBuildError_t G_CanBuild( gentity_t *ent, buildable_t buildable, int distance
vec3_t entity_origin, normal;
vec3_t mins, maxs;
trace_t tr1, tr2, tr3;
- int i;
itemBuildError_t reason = IBE_NONE, tempReason;
gentity_t *tempent;
float minNormal;
@@ -2909,15 +2993,13 @@ itemBuildError_t G_CanBuild( gentity_t *ent, buildable_t buildable, int distance
{
//alien criteria
- if( buildable == BA_A_HOVEL )
+ // Check there is an Overmind
+ if( buildable != BA_A_OVERMIND )
{
- vec3_t builderMins, builderMaxs;
-
- //this assumes the adv builder is the biggest thing that'll use the hovel
- BG_FindBBoxForClass( PCL_ALIEN_BUILDER0_UPG, builderMins, builderMaxs, NULL, NULL, NULL );
+ tempent = G_FindBuildable( BA_A_OVERMIND );
- if( APropHovel_Blocked( angles, origin, normal, ent ) )
- reason = IBE_HOVELEXIT;
+ if( tempent == NULL || !tempent->spawned || tempent->health <= 0 )
+ reason = IBE_OVERMIND;
}
//check there is creep near by for building on
@@ -2927,59 +3009,27 @@ itemBuildError_t G_CanBuild( gentity_t *ent, buildable_t buildable, int distance
reason = IBE_NOCREEP;
}
- //check permission to build here
- if( tr1.surfaceFlags & SURF_NOALIENBUILD || tr1.surfaceFlags & SURF_NOBUILD ||
- contents & CONTENTS_NOALIENBUILD || contents & CONTENTS_NOBUILD )
- reason = IBE_PERMISSION;
-
- //look for an Overmind
- for ( i = 1, tempent = g_entities + i; i < level.num_entities; i++, tempent++ )
- {
- if( tempent->s.eType != ET_BUILDABLE )
- continue;
- if( tempent->s.modelindex == BA_A_OVERMIND && tempent->spawned &&
- tempent->health > 0 )
- break;
- }
-
- //if none found...
- if( i >= level.num_entities && buildable != BA_A_OVERMIND )
- reason = IBE_NOOVERMIND;
-
- //can we only have one of these?
- if( BG_FindUniqueTestForBuildable( buildable ) )
+ if( buildable == BA_A_HOVEL )
{
- for ( i = 1, tempent = g_entities + i; i < level.num_entities; i++, tempent++ )
- {
- if( tempent->s.eType != ET_BUILDABLE )
- continue;
-
- if( tempent->s.modelindex == buildable && !tempent->deconstruct )
- {
- switch( buildable )
- {
- case BA_A_OVERMIND:
- reason = IBE_OVERMIND;
- break;
-
- case BA_A_HOVEL:
- reason = IBE_HOVEL;
- break;
+ vec3_t builderMins, builderMaxs;
- default:
- Com_Error( ERR_FATAL, "No reason for denying build of %d\n", buildable );
- break;
- }
+ //this assumes the adv builder is the biggest thing that'll use the hovel
+ BG_FindBBoxForClass( PCL_ALIEN_BUILDER0_UPG, builderMins, builderMaxs, NULL, NULL, NULL );
- break;
- }
- }
+ if( APropHovel_Blocked( angles, origin, normal, ent ) )
+ reason = IBE_HOVELEXIT;
}
+
+ // Check permission to build here
+ if( tr1.surfaceFlags & SURF_NOALIENBUILD || contents & CONTENTS_NOALIENBUILD )
+ reason = IBE_PERMISSION;
}
else if( ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
{
//human criteria
- if( !G_IsPowered( entity_origin ) )
+
+ // Check for power
+ if( G_IsPowered( entity_origin ) == BA_NONE )
{
//tell player to build a repeater to provide power
if( buildable != BA_H_REACTOR && buildable != BA_H_REPEATER )
@@ -2993,58 +3043,48 @@ itemBuildError_t G_CanBuild( gentity_t *ent, buildable_t buildable, int distance
//check that there is a parent reactor when building a repeater
if( buildable == BA_H_REPEATER )
{
- for ( i = 1, tempent = g_entities + i; i < level.num_entities; i++, tempent++ )
- {
- if( tempent->s.eType != ET_BUILDABLE )
- continue;
+ tempent = G_FindBuildable( BA_H_REACTOR );
- if( tempent->s.modelindex == BA_H_REACTOR )
- break;
- }
-
- if( i >= level.num_entities )
- {
- //no reactor present
-
- //check for other nearby repeaters
- for ( i = 1, tempent = g_entities + i; i < level.num_entities; i++, tempent++ )
- {
- if( tempent->s.eType != ET_BUILDABLE )
- continue;
-
- if( tempent->s.modelindex == BA_H_REPEATER &&
- Distance( tempent->s.origin, entity_origin ) < REPEATER_BASESIZE )
- {
- reason = IBE_RPTWARN2;
- break;
- }
- }
-
- if( reason == IBE_NONE )
- reason = IBE_RPTWARN;
- }
- else if( G_IsPowered( entity_origin ) )
+ if( tempent == NULL ) // No reactor
+ reason = IBE_RPTWARN;
+ else if( g_markDeconstruct.integer && G_IsPowered( entity_origin ) == BA_H_REACTOR )
+ reason = IBE_RPTWARN2;
+ else if( !g_markDeconstruct.integer && G_IsPowered( entity_origin ) )
reason = IBE_RPTWARN2;
}
- //check permission to build here
- if( tr1.surfaceFlags & SURF_NOHUMANBUILD || tr1.surfaceFlags & SURF_NOBUILD ||
- contents & CONTENTS_NOHUMANBUILD || contents & CONTENTS_NOBUILD )
+ // Check permission to build here
+ if( tr1.surfaceFlags & SURF_NOHUMANBUILD || contents & CONTENTS_NOHUMANBUILD )
reason = IBE_PERMISSION;
+ }
+
+ // Check permission to build here
+ if( tr1.surfaceFlags & SURF_NOBUILD || contents & CONTENTS_NOBUILD )
+ reason = IBE_PERMISSION;
- //can we only build one of these?
- if( BG_FindUniqueTestForBuildable( buildable ) )
+ // Can we only have one of these?
+ if( BG_FindUniqueTestForBuildable( buildable ) )
+ {
+ tempent = G_FindBuildable( buildable );
+ if( tempent && !tempent->deconstruct )
{
- for ( i = 1, tempent = g_entities + i; i < level.num_entities; i++, tempent++ )
+ switch( buildable )
{
- if( tempent->s.eType != ET_BUILDABLE )
- continue;
+ case BA_A_OVERMIND:
+ reason = IBE_OVERMIND;
+ break;
- if( tempent->s.modelindex == BA_H_REACTOR && !tempent->deconstruct )
- {
+ case BA_A_HOVEL:
+ reason = IBE_HOVEL;
+ break;
+
+ case BA_H_REACTOR:
reason = IBE_REACTOR;
break;
- }
+
+ default:
+ Com_Error( ERR_FATAL, "No reason for denying build of %d\n", buildable );
+ break;
}
}
}
@@ -3112,16 +3152,7 @@ static gentity_t *G_Build( gentity_t *builder, buildable_t buildable, vec3_t ori
else
{
// in-game building by a player
-
- if( builder->client->ps.stats[ STAT_STATE ] & SS_WALLCLIMBING )
- {
- if( builder->client->ps.stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING )
- VectorSet( normal, 0.0f, 0.0f, -1.0f );
- else
- VectorCopy( builder->client->ps.grapplePoint, normal );
- }
- else
- VectorSet( normal, 0.0f, 0.0f, 1.0f );
+ BG_GetClientNormal( &builder->client->ps, normal );
}
// when building the initial layout, spawn the entity slightly off its
diff --git a/src/game/g_combat.c b/src/game/g_combat.c
index 5f889b0e..6c8dcc2c 100644
--- a/src/game/g_combat.c
+++ b/src/game/g_combat.c
@@ -701,10 +701,7 @@ static float G_CalcDamageModifier( vec3_t point, gentity_t *targ, gentity_t *att
clientHeight = targ->r.maxs[ 2 ] - targ->r.mins[ 2 ];
- if( targ->client->ps.stats[ STAT_STATE ] & SS_WALLCLIMBING )
- VectorCopy( targ->client->ps.grapplePoint, normal );
- else
- VectorSet( normal, 0, 0, 1 );
+ BG_GetClientNormal( &targ->client->ps, normal );
VectorMA( targOrigin, targ->r.mins[ 2 ], normal, floor );
VectorSubtract( point, floor, pMINUSfloor );
diff --git a/src/game/g_local.h b/src/game/g_local.h
index 45f649d0..643757aa 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -749,7 +749,7 @@ qboolean AHovel_Blocked( gentity_t *hovel, gentity_t *player, qboolean
gentity_t *G_CheckSpawnPoint( int spawnNum, vec3_t origin, vec3_t normal,
buildable_t spawn, vec3_t spawnOrigin );
-qboolean G_IsPowered( vec3_t origin );
+buildable_t G_IsPowered( vec3_t origin );
qboolean G_IsDCCBuilt( void );
qboolean G_IsOvermindBuilt( void );
diff --git a/src/game/g_weapon.c b/src/game/g_weapon.c
index cfc7cc1f..6ff825f7 100644
--- a/src/game/g_weapon.c
+++ b/src/game/g_weapon.c
@@ -768,8 +768,9 @@ void buildFire( gentity_t *ent, dynMenu_t menu )
ent->client->ps.stats[ STAT_MISC ] +=
BG_FindBuildDelayForWeapon( ent->s.weapon ) * 2;
}
- else if( ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS && !G_IsPowered( muzzle ) &&
- ( ent->client->ps.stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT ) != BA_H_REPEATER ) //hack
+ else if( ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS &&
+ G_IsPowered( muzzle ) == BA_NONE &&
+ ( ent->client->ps.stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT ) != BA_H_REPEATER ) //hack
{
ent->client->ps.stats[ STAT_MISC ] +=
BG_FindBuildDelayForWeapon( ent->s.weapon ) * 2;
@@ -1430,10 +1431,12 @@ set muzzle location relative to pivoting eye
*/
void CalcMuzzlePoint( gentity_t *ent, vec3_t forward, vec3_t right, vec3_t up, vec3_t muzzlePoint )
{
+ vec3_t normal;
+
VectorCopy( ent->s.pos.trBase, muzzlePoint );
- muzzlePoint[ 2 ] += ent->client->ps.viewheight;
+ BG_GetClientNormal( &ent->client->ps, normal );
+ VectorMA( muzzlePoint, ent->client->ps.viewheight, normal, muzzlePoint );
VectorMA( muzzlePoint, 1, forward, muzzlePoint );
- VectorMA( muzzlePoint, 1, right, muzzlePoint );
// snap to integer coordinates for more efficient network bandwidth usage
SnapVector( muzzlePoint );
}