diff options
-rw-r--r-- | src/game/g_buildable.c | 3 | ||||
-rw-r--r-- | src/game/g_combat.c | 194 | ||||
-rw-r--r-- | src/game/g_local.h | 16 | ||||
-rw-r--r-- | src/game/g_main.c | 3 |
4 files changed, 214 insertions, 2 deletions
diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c index d688a416..ef210767 100644 --- a/src/game/g_buildable.c +++ b/src/game/g_buildable.c @@ -592,7 +592,8 @@ itemBuildError_t itemFits( gentity_t *ent, buildable_t buildable, int distance ) int i; itemBuildError_t reason = IBE_NONE; gentity_t *tempent, *closestPower; - int minDistance, templength; + int minDistance = 10000; + int templength; VectorCopy( ent->s.apos.trBase, angles ); angles[PITCH] = 0; // always forward diff --git a/src/game/g_combat.c b/src/game/g_combat.c index 69c65d60..f0a441e8 100644 --- a/src/game/g_combat.c +++ b/src/game/g_combat.c @@ -28,6 +28,8 @@ #include "g_local.h" +damageRegion_t g_damageRegions[ PCL_NUM_CLASSES ][ MAX_LOCDAMAGE_REGIONS ]; +int g_numDamageRegions[ PCL_NUM_CLASSES ]; /* ============ @@ -625,6 +627,197 @@ int RaySphereIntersections( vec3_t origin, float radius, vec3_t point, vec3_t di } +////////TA: locdamage + +/* +=============== +G_ParseDmgScript +=============== +*/ +void G_ParseDmgScript( char *buf, int class ) +{ + char *token; + int count; + + count = 0; + + while( 1 ) + { + token = COM_Parse( &buf ); + + if( !token[0] ) + break; + + if( strcmp( token, "{" ) ) + { + G_Printf( "Missing { in locdamage file\n" ); + break; + } + + if( count == MAX_LOCDAMAGE_REGIONS ) + { + G_Printf( "Max damage regions exceeded in locdamage file\n" ); + break; + } + + while( 1 ) + { + token = COM_ParseExt( &buf, qtrue ); + + if( !token[0] ) + { + G_Printf( "Unexpected end of locdamage file\n" ); + break; + } + + if( !Q_stricmp( token, "}" ) ) + { + break; + } + else if( !strcmp( token, "minHeight" ) ) + { + token = COM_ParseExt( &buf, qfalse ); + + if ( !token[0] ) + strcpy( token, "0" ); + + g_damageRegions[ class ][ count ].minHeight = atof( token ); + } + else if( !strcmp( token, "maxHeight" ) ) + { + token = COM_ParseExt( &buf, qfalse ); + + if ( !token[0] ) + strcpy( token, "100" ); + + g_damageRegions[ class ][ count ].maxHeight = atof( token ); + } + else if( !strcmp( token, "minAngle" ) ) + { + token = COM_ParseExt( &buf, qfalse ); + + if ( !token[0] ) + strcpy( token, "0" ); + + g_damageRegions[ class ][ count ].minAngle = atoi( token ); + } + else if( !strcmp( token, "maxAngle" ) ) + { + token = COM_ParseExt( &buf, qfalse ); + + if ( !token[0] ) + strcpy( token, "360" ); + + g_damageRegions[ class ][ count ].maxAngle = atoi( token ); + } + else if( !strcmp( token, "modifier" ) ) + { + token = COM_ParseExt( &buf, qfalse ); + + if ( !token[0] ) + strcpy( token, "1.0" ); + + g_damageRegions[ class ][ count ].modifier = atof( token ); + } + } + + g_numDamageRegions[ class ]++; + count++; + } +} + + +/* +============ +G_CalcModifier +============ +*/ +float G_CalcModifier( vec3_t point, gentity_t *targ, gentity_t *attacker, int class ) +{ + vec3_t bulletPath; + vec3_t bulletAngle; + + float clientHeight, hitRelative, hitRatio; + int bulletRotation, clientRotation, hitRotation; + float modifier = 1.0; + int i; + + clientHeight = targ->r.maxs[ 2 ] - targ->r.mins[ 2 ]; + + hitRelative = point[ 2 ] - targ->r.currentOrigin[ 2 ] - targ->r.mins[ 2 ]; + + if( hitRelative < 0.0 ) hitRelative = 0.0; + if( hitRelative > clientHeight ) hitRelative = clientHeight; + + hitRatio = hitRelative / clientHeight; + + VectorSubtract( targ->r.currentOrigin, point, bulletPath ); + vectoangles( bulletPath, bulletAngle ); + + clientRotation = targ->client->ps.viewangles[ YAW ]; + bulletRotation = bulletAngle[ YAW ]; + + hitRotation = abs( clientRotation - bulletRotation ); + + hitRotation = hitRotation % 360; // Keep it in the 0-359 range + + for( i = 0; i < g_numDamageRegions[ class ]; i++ ) + { + if( hitRotation > g_damageRegions[ class ][ i ].minAngle && + hitRotation <= g_damageRegions[ class ][ i ].maxAngle && + hitRatio > g_damageRegions[ class ][ i ].minHeight && + hitRatio <= g_damageRegions[ class ][ i ].maxHeight ) + modifier *= g_damageRegions[ class ][ i ].modifier; + } + + return modifier; +} + + +/* +============ +G_InitDamageLocations +============ +*/ +void G_InitDamageLocations( ) +{ + char *modelName; + char filename[ MAX_QPATH ]; + int i; + int len; + fileHandle_t fileHandle; + char buffer[ MAX_LOCDAMAGE_TEXT ]; + + for( i = PCL_NONE + 1; i < PCL_NUM_CLASSES; i++ ) + { + modelName = BG_FindModelNameForClass( i ); + Com_sprintf( filename, sizeof( filename ), "models/players/%s/locdamage.cfg", modelName ); + + len = trap_FS_FOpenFile( filename, &fileHandle, FS_READ ); + if ( !fileHandle ) + { + G_Printf( va( S_COLOR_RED "file not found: %s\n", filename ) ); + continue; + } + + if ( len >= MAX_LOCDAMAGE_TEXT ) + { + G_Printf( va( S_COLOR_RED "file too large: %s is %i, max allowed is %i", filename, len, MAX_LOCDAMAGE_TEXT ) ); + trap_FS_FCloseFile( fileHandle ); + continue; + } + + trap_FS_Read( buffer, len, fileHandle ); + buffer[len] = 0; + trap_FS_FCloseFile( fileHandle ); + + G_ParseDmgScript( buffer, i ); + } +} + +////////TA: locdamage + + /* ============ T_Damage @@ -839,6 +1032,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, // set the last client who damaged the target targ->client->lasthurt_client = attacker->s.number; targ->client->lasthurt_mod = mod; + take = (int)( (float)take * G_CalcModifier( point, targ, attacker, client->ps.stats[ STAT_PCLASS ] ) ); } // do the damage diff --git a/src/game/g_local.h b/src/game/g_local.h index 66aa53de..da8da039 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -329,6 +329,18 @@ struct gclient_s { gentity_t *infestBody; //TA: body that is being infested. must be persistant }; +#define MAX_LOCDAMAGE_TEXT 8192 +#define MAX_LOCDAMAGE_REGIONS 32 + +//TA: store locational damage regions +typedef struct damageRegion_s +{ + float minHeight, maxHeight; + int minAngle, maxAngle; + + float modifier; +} damageRegion_t; + // // this structure is cleared as each map is entered // @@ -429,7 +441,6 @@ typedef struct { int humanBuildPointsPowered; } level_locals_t; - // // g_spawn.c // @@ -542,6 +553,9 @@ qboolean G_SelectiveRadiusDamage (vec3_t origin, gentity_t *attacker, float dama void body_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath ); void TossClientItems( gentity_t *self ); +//TA: +void G_InitDamageLocations( ); + // damage flags #define DAMAGE_RADIUS 0x00000001 // damage was indirect #define DAMAGE_NO_ARMOR 0x00000002 // armour does not protect from this damage diff --git a/src/game/g_main.c b/src/game/g_main.c index 897a1c89..f2dee3ca 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -475,7 +475,10 @@ void G_InitGame( int levelTime, int randomSeed, int restart ) { } SaveRegisteredItems(); + + //TA: G_RegisterPlayerModels(); + G_InitDamageLocations(); G_Printf ("-----------------------------------\n"); |