2013-04-19 02:52:48 +00:00
// Copyright (C) 1999-2000 Id Software, Inc.
//
// bg_misc.c -- both games misc functions, all completely stateless
# include "q_shared.h"
# include "bg_public.h"
# include "bg_strap.h"
# ifdef QAGAME
# include "g_local.h"
# endif
# ifdef UI_EXPORTS
# include "../ui/ui_local.h"
# endif
# ifndef UI_EXPORTS
# ifndef QAGAME
# include "../cgame/cg_local.h"
# endif
# endif
# ifdef _XBOX
extern void * Z_Malloc ( int iSize , memtag_t eTag , qboolean bZeroit , int iAlign ) ;
extern void Z_Free ( void * pvAddress ) ;
# endif
# ifdef QAGAME
extern void Q3_SetParm ( int entID , int parmNum , const char * parmValue ) ;
# endif
# include "../namespace_begin.h"
const char * bgToggleableSurfaces [ BG_NUM_TOGGLEABLE_SURFACES ] =
{
" l_arm_key " , //0
" torso_canister1 " ,
" torso_canister2 " ,
" torso_canister3 " ,
" torso_tube1 " ,
" torso_tube2 " , //5
" torso_tube3 " ,
" torso_tube4 " ,
" torso_tube5 " ,
" torso_tube6 " ,
" r_arm " , //10
" l_arm " ,
" torso_shield " ,
" torso_galaktorso " ,
" torso_collar " ,
// "torso_eyes_mouth", //15
// "torso_galakhead",
// "torso_galakface",
// "torso_antenna_base_cap",
// "torso_antenna",
// "l_arm_augment", //20
// "l_arm_middle",
// "l_arm_wrist",
// "r_arm_middle", //yeah.. galak's surf stuff is no longer auto, sorry! need the space for vehicle surfs.
" r_wing1 " , //15
" r_wing2 " ,
" l_wing1 " ,
" l_wing2 " ,
" r_gear " ,
" l_gear " , //20
" nose " ,
" blah4 " ,
" blah5 " ,
" l_hand " ,
" r_hand " , //25
" helmet " ,
" head " ,
" head_concussion_charger " ,
" head_light_blaster_cann " , //29
NULL
} ;
const int bgToggleableSurfaceDebris [ BG_NUM_TOGGLEABLE_SURFACES ] =
{
0 , //0
0 ,
0 ,
0 ,
0 ,
0 , //5
0 ,
0 ,
0 ,
0 ,
0 , //10
0 ,
0 ,
0 ,
0 , //>= 2 means it should create a flame trail when destroyed (for vehicles)
3 , //15
5 , //rwing2
4 ,
6 , //lwing2
0 , //rgear
0 , //lgear //20
7 , //nose
0 , //blah
0 , //blah
0 ,
0 , //25
0 ,
0 ,
0 ,
0 , //29
- 1
} ;
const char * bg_customSiegeSoundNames [ MAX_CUSTOM_SIEGE_SOUNDS ] =
{
" *att_attack " ,
" *att_primary " ,
" *att_second " ,
" *def_guns " ,
" *def_position " ,
" *def_primary " ,
" *def_second " ,
" *reply_coming " ,
" *reply_go " ,
" *reply_no " ,
" *reply_stay " ,
" *reply_yes " ,
" *req_assist " ,
" *req_demo " ,
" *req_hvy " ,
" *req_medic " ,
" *req_sup " ,
" *req_tech " ,
" *spot_air " ,
" *spot_defenses " ,
" *spot_emplaced " ,
" *spot_sniper " ,
" *spot_troops " ,
" *tac_cover " ,
" *tac_fallback " ,
" *tac_follow " ,
" *tac_hold " ,
" *tac_split " ,
" *tac_together " ,
NULL
} ;
//rww - not putting @ in front of these because
//we don't need them in a cgame StringEd lookup.
//Let me know if this causes problems, pat.
char * forceMasteryLevels [ NUM_FORCE_MASTERY_LEVELS ] =
{
" MASTERY0 " , //"Uninitiated", // FORCE_MASTERY_UNINITIATED,
" MASTERY1 " , //"Initiate", // FORCE_MASTERY_INITIATE,
" MASTERY2 " , //"Padawan", // FORCE_MASTERY_PADAWAN,
" MASTERY3 " , //"Jedi", // FORCE_MASTERY_JEDI,
" MASTERY4 " , //"Jedi Adept", // FORCE_MASTERY_JEDI_GUARDIAN,
" MASTERY5 " , //"Jedi Guardian", // FORCE_MASTERY_JEDI_ADEPT,
" MASTERY6 " , //"Jedi Knight", // FORCE_MASTERY_JEDI_KNIGHT,
" MASTERY7 " , //"Jedi Master" // FORCE_MASTERY_JEDI_MASTER,
} ;
int forceMasteryPoints [ NUM_FORCE_MASTERY_LEVELS ] =
{
0 , // FORCE_MASTERY_UNINITIATED,
5 , // FORCE_MASTERY_INITIATE,
10 , // FORCE_MASTERY_PADAWAN,
20 , // FORCE_MASTERY_JEDI,
30 , // FORCE_MASTERY_JEDI_GUARDIAN,
50 , // FORCE_MASTERY_JEDI_ADEPT,
75 , // FORCE_MASTERY_JEDI_KNIGHT,
100 // FORCE_MASTERY_JEDI_MASTER,
} ;
int bgForcePowerCost [ NUM_FORCE_POWERS ] [ NUM_FORCE_POWER_LEVELS ] = //0 == neutral
{
{ 0 , 2 , 4 , 6 } , // Heal // FP_HEAL
{ 0 , 0 , 2 , 6 } , // Jump //FP_LEVITATION,//hold/duration
{ 0 , 2 , 4 , 6 } , // Speed //FP_SPEED,//duration
{ 0 , 1 , 3 , 6 } , // Push //FP_PUSH,//hold/duration
{ 0 , 1 , 3 , 6 } , // Pull //FP_PULL,//hold/duration
{ 0 , 4 , 6 , 8 } , // Mind Trick //FP_TELEPATHY,//instant
{ 0 , 1 , 3 , 6 } , // Grip //FP_GRIP,//hold/duration
{ 0 , 2 , 5 , 8 } , // Lightning //FP_LIGHTNING,//hold/duration
{ 0 , 4 , 6 , 8 } , // Dark Rage //FP_RAGE,//duration
{ 0 , 2 , 5 , 8 } , // Protection //FP_PROTECT,//duration
{ 0 , 1 , 3 , 6 } , // Absorb //FP_ABSORB,//duration
{ 0 , 1 , 3 , 6 } , // Team Heal //FP_TEAM_HEAL,//instant
{ 0 , 1 , 3 , 6 } , // Team Force //FP_TEAM_FORCE,//instant
{ 0 , 2 , 4 , 6 } , // Drain //FP_DRAIN,//hold/duration
{ 0 , 2 , 5 , 8 } , // Sight //FP_SEE,//duration
{ 0 , 1 , 5 , 8 } , // Saber Attack //FP_SABER_OFFENSE,
{ 0 , 1 , 5 , 8 } , // Saber Defend //FP_SABER_DEFENSE,
{ 0 , 4 , 6 , 8 } // Saber Throw //FP_SABERTHROW,
//NUM_FORCE_POWERS
} ;
int forcePowerSorted [ NUM_FORCE_POWERS ] =
{ //rww - always use this order when drawing force powers for any reason
FP_TELEPATHY ,
FP_HEAL ,
FP_ABSORB ,
FP_PROTECT ,
FP_TEAM_HEAL ,
FP_LEVITATION ,
FP_SPEED ,
FP_PUSH ,
FP_PULL ,
FP_SEE ,
FP_LIGHTNING ,
FP_DRAIN ,
FP_RAGE ,
FP_GRIP ,
FP_TEAM_FORCE ,
FP_SABER_OFFENSE ,
FP_SABER_DEFENSE ,
FP_SABERTHROW
} ;
int forcePowerDarkLight [ NUM_FORCE_POWERS ] = //0 == neutral
{ //nothing should be usable at rank 0..
FORCE_LIGHTSIDE , //FP_HEAL,//instant
0 , //FP_LEVITATION,//hold/duration
0 , //FP_SPEED,//duration
0 , //FP_PUSH,//hold/duration
0 , //FP_PULL,//hold/duration
FORCE_LIGHTSIDE , //FP_TELEPATHY,//instant
FORCE_DARKSIDE , //FP_GRIP,//hold/duration
FORCE_DARKSIDE , //FP_LIGHTNING,//hold/duration
FORCE_DARKSIDE , //FP_RAGE,//duration
FORCE_LIGHTSIDE , //FP_PROTECT,//duration
FORCE_LIGHTSIDE , //FP_ABSORB,//duration
FORCE_LIGHTSIDE , //FP_TEAM_HEAL,//instant
FORCE_DARKSIDE , //FP_TEAM_FORCE,//instant
FORCE_DARKSIDE , //FP_DRAIN,//hold/duration
0 , //FP_SEE,//duration
0 , //FP_SABER_OFFENSE,
0 , //FP_SABER_DEFENSE,
0 //FP_SABERTHROW,
//NUM_FORCE_POWERS
} ;
int WeaponReadyAnim [ WP_NUM_WEAPONS ] =
{
TORSO_DROPWEAP1 , //WP_NONE,
TORSO_WEAPONREADY3 , //WP_STUN_BATON,
TORSO_WEAPONREADY3 , //WP_MELEE,
BOTH_STAND2 , //WP_SABER,
TORSO_WEAPONREADY2 , //WP_BRYAR_PISTOL,
TORSO_WEAPONREADY3 , //WP_BLASTER,
TORSO_WEAPONREADY3 , //TORSO_WEAPONREADY4,//WP_DISRUPTOR,
TORSO_WEAPONREADY3 , //TORSO_WEAPONREADY5,//WP_BOWCASTER,
TORSO_WEAPONREADY3 , //TORSO_WEAPONREADY6,//WP_REPEATER,
TORSO_WEAPONREADY3 , //TORSO_WEAPONREADY7,//WP_DEMP2,
TORSO_WEAPONREADY3 , //TORSO_WEAPONREADY8,//WP_FLECHETTE,
TORSO_WEAPONREADY3 , //TORSO_WEAPONREADY9,//WP_ROCKET_LAUNCHER,
TORSO_WEAPONREADY10 , //WP_THERMAL,
TORSO_WEAPONREADY10 , //TORSO_WEAPONREADY11,//WP_TRIP_MINE,
TORSO_WEAPONREADY10 , //TORSO_WEAPONREADY12,//WP_DET_PACK,
TORSO_WEAPONREADY3 , //WP_CONCUSSION
TORSO_WEAPONREADY2 , //WP_BRYAR_OLD,
//NOT VALID (e.g. should never really be used):
BOTH_STAND1 , //WP_EMPLACED_GUN,
TORSO_WEAPONREADY1 //WP_TURRET,
} ;
int WeaponReadyLegsAnim [ WP_NUM_WEAPONS ] =
{
BOTH_STAND1 , //WP_NONE,
BOTH_STAND1 , //WP_STUN_BATON,
BOTH_STAND1 , //WP_MELEE,
BOTH_STAND2 , //WP_SABER,
BOTH_STAND1 , //WP_BRYAR_PISTOL,
BOTH_STAND1 , //WP_BLASTER,
BOTH_STAND1 , //TORSO_WEAPONREADY4,//WP_DISRUPTOR,
BOTH_STAND1 , //TORSO_WEAPONREADY5,//WP_BOWCASTER,
BOTH_STAND1 , //TORSO_WEAPONREADY6,//WP_REPEATER,
BOTH_STAND1 , //TORSO_WEAPONREADY7,//WP_DEMP2,
BOTH_STAND1 , //TORSO_WEAPONREADY8,//WP_FLECHETTE,
BOTH_STAND1 , //TORSO_WEAPONREADY9,//WP_ROCKET_LAUNCHER,
BOTH_STAND1 , //WP_THERMAL,
BOTH_STAND1 , //TORSO_WEAPONREADY11,//WP_TRIP_MINE,
BOTH_STAND1 , //TORSO_WEAPONREADY12,//WP_DET_PACK,
BOTH_STAND1 , //WP_CONCUSSION
BOTH_STAND1 , //WP_BRYAR_OLD,
//NOT VALID (e.g. should never really be used):
BOTH_STAND1 , //WP_EMPLACED_GUN,
BOTH_STAND1 //WP_TURRET,
} ;
int WeaponAttackAnim [ WP_NUM_WEAPONS ] =
{
BOTH_ATTACK1 , //WP_NONE, //(shouldn't happen)
BOTH_ATTACK3 , //WP_STUN_BATON,
BOTH_ATTACK3 , //WP_MELEE,
BOTH_STAND2 , //WP_SABER, //(has its own handling)
BOTH_ATTACK2 , //WP_BRYAR_PISTOL,
BOTH_ATTACK3 , //WP_BLASTER,
BOTH_ATTACK3 , //BOTH_ATTACK4,//WP_DISRUPTOR,
BOTH_ATTACK3 , //BOTH_ATTACK5,//WP_BOWCASTER,
BOTH_ATTACK3 , //BOTH_ATTACK6,//WP_REPEATER,
BOTH_ATTACK3 , //BOTH_ATTACK7,//WP_DEMP2,
BOTH_ATTACK3 , //BOTH_ATTACK8,//WP_FLECHETTE,
BOTH_ATTACK3 , //BOTH_ATTACK9,//WP_ROCKET_LAUNCHER,
BOTH_THERMAL_THROW , //WP_THERMAL,
BOTH_ATTACK3 , //BOTH_ATTACK11,//WP_TRIP_MINE,
BOTH_ATTACK3 , //BOTH_ATTACK12,//WP_DET_PACK,
BOTH_ATTACK2 , //WP_BRYAR_OLD,
//NOT VALID (e.g. should never really be used):
BOTH_STAND1 , //WP_EMPLACED_GUN,
BOTH_ATTACK1 //WP_TURRET,
} ;
qboolean BG_FileExists ( const char * fileName )
{
if ( fileName & & fileName [ 0 ] )
{
int fh = 0 ;
trap_FS_FOpenFile ( fileName , & fh , FS_READ ) ;
if ( fh > 0 )
{
trap_FS_FCloseFile ( fh ) ;
return qtrue ;
}
}
return qfalse ;
}
# ifndef UI_EXPORTS //don't need this stuff in the ui
// Following functions don't need to be in namespace, they're already
// different per-module
# include "../namespace_end.h"
# ifdef QAGAME
char * G_NewString ( const char * string ) ;
# else
char * CG_NewString ( const char * string ) ;
# endif
# include "../namespace_begin.h"
/*
= = = = = = = = = = = = = = =
BG_ParseField
Takes a key / value pair and sets the binary values
in a gentity / centity / whatever the hell you want
= = = = = = = = = = = = = = =
*/
void BG_ParseField ( BG_field_t * l_fields , const char * key , const char * value , byte * ent )
{
BG_field_t * f ;
byte * b ;
float v ;
vec3_t vec ;
for ( f = l_fields ; f - > name ; f + + ) {
if ( ! Q_stricmp ( f - > name , key ) ) {
// found it
b = ( byte * ) ent ;
switch ( f - > type ) {
case F_LSTRING :
# ifdef QAGAME
* ( char * * ) ( b + f - > ofs ) = G_NewString ( value ) ;
# else
* ( char * * ) ( b + f - > ofs ) = CG_NewString ( value ) ;
# endif
break ;
case F_VECTOR :
sscanf ( value , " %f %f %f " , & vec [ 0 ] , & vec [ 1 ] , & vec [ 2 ] ) ;
( ( float * ) ( b + f - > ofs ) ) [ 0 ] = vec [ 0 ] ;
( ( float * ) ( b + f - > ofs ) ) [ 1 ] = vec [ 1 ] ;
( ( float * ) ( b + f - > ofs ) ) [ 2 ] = vec [ 2 ] ;
break ;
case F_INT :
* ( int * ) ( b + f - > ofs ) = atoi ( value ) ;
break ;
case F_FLOAT :
* ( float * ) ( b + f - > ofs ) = atof ( value ) ;
break ;
case F_ANGLEHACK :
v = atof ( value ) ;
( ( float * ) ( b + f - > ofs ) ) [ 0 ] = 0 ;
( ( float * ) ( b + f - > ofs ) ) [ 1 ] = v ;
( ( float * ) ( b + f - > ofs ) ) [ 2 ] = 0 ;
break ;
# ifdef QAGAME
case F_PARM1 :
case F_PARM2 :
case F_PARM3 :
case F_PARM4 :
case F_PARM5 :
case F_PARM6 :
case F_PARM7 :
case F_PARM8 :
case F_PARM9 :
case F_PARM10 :
case F_PARM11 :
case F_PARM12 :
case F_PARM13 :
case F_PARM14 :
case F_PARM15 :
case F_PARM16 :
Q3_SetParm ( ( ( gentity_t * ) ( ent ) ) - > s . number , ( f - > type - F_PARM1 ) , ( char * ) value ) ;
break ;
# endif
default :
case F_IGNORE :
break ;
}
return ;
}
}
}
# endif
/*
= = = = = = = = = = = = = = = =
BG_LegalizedForcePowers
The magical function to end all functions .
This will take the force power string in powerOut and parse through it , then legalize
it based on the supposed rank and spit it into powerOut , returning true if it was legal
to begin with and false if not .
fpDisabled is actually only expected ( needed ) from the server , because the ui disables
force power selection anyway when force powers are disabled on the server .
= = = = = = = = = = = = = = = =
*/
qboolean BG_LegalizedForcePowers ( char * powerOut , int maxRank , qboolean freeSaber , int teamForce , int gametype , int fpDisabled )
{
char powerBuf [ 128 ] ;
char readBuf [ 128 ] ;
qboolean maintainsValidity = qtrue ;
int powerLen = strlen ( powerOut ) ;
int i = 0 ;
int c = 0 ;
int allowedPoints = 0 ;
int usedPoints = 0 ;
int countDown = 0 ;
int final_Side ;
int final_Powers [ NUM_FORCE_POWERS ] ;
if ( powerLen > = 128 )
{ //This should not happen. If it does, this is obviously a bogus string.
//They can have this string. Because I said so.
strcpy ( powerBuf , " 7-1-032330000000001333 " ) ;
maintainsValidity = qfalse ;
}
else
{
strcpy ( powerBuf , powerOut ) ; //copy it as the original
}
//first of all, print the max rank into the string as the rank
strcpy ( powerOut , va ( " %i- " , maxRank ) ) ;
while ( i < 128 & & powerBuf [ i ] & & powerBuf [ i ] ! = ' - ' )
{
i + + ;
}
i + + ;
while ( i < 128 & & powerBuf [ i ] & & powerBuf [ i ] ! = ' - ' )
{
readBuf [ c ] = powerBuf [ i ] ;
c + + ;
i + + ;
}
readBuf [ c ] = 0 ;
i + + ;
//at this point, readBuf contains the intended side
final_Side = atoi ( readBuf ) ;
if ( final_Side ! = FORCE_LIGHTSIDE & &
final_Side ! = FORCE_DARKSIDE )
{ //Not a valid side. You will be dark. Because I said so. (this is something that should never actually happen unless you purposely feed in an invalid config)
final_Side = FORCE_DARKSIDE ;
maintainsValidity = qfalse ;
}
if ( teamForce )
{ //If we are under force-aligned teams, make sure we're on the right side.
if ( final_Side ! = teamForce )
{
final_Side = teamForce ;
//maintainsValidity = qfalse;
//Not doing this, for now. Let them join the team with their filtered powers.
}
}
//Now we have established a valid rank, and a valid side.
//Read the force powers in, and cut them down based on the various rules supplied.
c = 0 ;
while ( i < 128 & & powerBuf [ i ] & & powerBuf [ i ] ! = ' \n ' & & c < NUM_FORCE_POWERS )
{
readBuf [ 0 ] = powerBuf [ i ] ;
readBuf [ 1 ] = 0 ;
final_Powers [ c ] = atoi ( readBuf ) ;
c + + ;
i + + ;
}
//final_Powers now contains all the stuff from the string
//Set the maximum allowed points used based on the max rank level, and count the points actually used.
allowedPoints = forceMasteryPoints [ maxRank ] ;
i = 0 ;
while ( i < NUM_FORCE_POWERS )
{ //if this power doesn't match the side we're on, then 0 it now.
if ( final_Powers [ i ] & &
forcePowerDarkLight [ i ] & &
forcePowerDarkLight [ i ] ! = final_Side )
{
final_Powers [ i ] = 0 ;
//This is only likely to happen with g_forceBasedTeams. Let it slide.
}
if ( final_Powers [ i ] & &
( fpDisabled & ( 1 < < i ) ) )
{ //if this power is disabled on the server via said server option, then we don't get it.
final_Powers [ i ] = 0 ;
}
i + + ;
}
if ( gametype < GT_TEAM )
{ //don't bother with team powers then
final_Powers [ FP_TEAM_HEAL ] = 0 ;
final_Powers [ FP_TEAM_FORCE ] = 0 ;
}
usedPoints = 0 ;
i = 0 ;
while ( i < NUM_FORCE_POWERS )
{
countDown = 0 ;
countDown = final_Powers [ i ] ;
while ( countDown > 0 )
{
usedPoints + = bgForcePowerCost [ i ] [ countDown ] ; //[fp index][fp level]
//if this is jump, or we have a free saber and it's offense or defense, take the level back down on level 1
if ( countDown = = 1 & &
( ( i = = FP_LEVITATION ) | |
( i = = FP_SABER_OFFENSE & & freeSaber ) | |
( i = = FP_SABER_DEFENSE & & freeSaber ) ) )
{
usedPoints - = bgForcePowerCost [ i ] [ countDown ] ;
}
countDown - - ;
}
i + + ;
}
if ( usedPoints > allowedPoints )
{ //Time to do the fancy stuff. (meaning, slowly cut parts off while taking a guess at what is most or least important in the config)
int attemptedCycles = 0 ;
int powerCycle = 2 ;
int minPow = 0 ;
if ( freeSaber )
{
minPow = 1 ;
}
maintainsValidity = qfalse ;
while ( usedPoints > allowedPoints )
{
c = 0 ;
while ( c < NUM_FORCE_POWERS & & usedPoints > allowedPoints )
{
if ( final_Powers [ c ] & & final_Powers [ c ] < powerCycle )
{ //kill in order of lowest powers, because the higher powers are probably more important
if ( c = = FP_SABER_OFFENSE & &
( final_Powers [ FP_SABER_DEFENSE ] > minPow | | final_Powers [ FP_SABERTHROW ] > 0 ) )
{ //if we're on saber attack, only suck it down if we have no def or throw either
int whichOne = FP_SABERTHROW ; //first try throw
if ( ! final_Powers [ whichOne ] )
{
whichOne = FP_SABER_DEFENSE ; //if no throw, drain defense
}
while ( final_Powers [ whichOne ] > 0 & & usedPoints > allowedPoints )
{
if ( final_Powers [ whichOne ] > 1 | |
( ( whichOne ! = FP_SABER_OFFENSE | | ! freeSaber ) & &
( whichOne ! = FP_SABER_DEFENSE | | ! freeSaber ) ) )
{ //don't take attack or defend down on level 1 still, if it's free
usedPoints - = bgForcePowerCost [ whichOne ] [ final_Powers [ whichOne ] ] ;
final_Powers [ whichOne ] - - ;
}
else
{
break ;
}
}
}
else
{
while ( final_Powers [ c ] > 0 & & usedPoints > allowedPoints )
{
if ( final_Powers [ c ] > 1 | |
( ( c ! = FP_LEVITATION ) & &
( c ! = FP_SABER_OFFENSE | | ! freeSaber ) & &
( c ! = FP_SABER_DEFENSE | | ! freeSaber ) ) )
{
usedPoints - = bgForcePowerCost [ c ] [ final_Powers [ c ] ] ;
final_Powers [ c ] - - ;
}
else
{
break ;
}
}
}
}
c + + ;
}
powerCycle + + ;
attemptedCycles + + ;
if ( attemptedCycles > NUM_FORCE_POWERS )
{ //I think this should be impossible. But just in case.
break ;
}
}
if ( usedPoints > allowedPoints )
{ //Still? Fine then.. we will kill all of your powers, except the freebies.
i = 0 ;
while ( i < NUM_FORCE_POWERS )
{
final_Powers [ i ] = 0 ;
if ( i = = FP_LEVITATION | |
( i = = FP_SABER_OFFENSE & & freeSaber ) | |
( i = = FP_SABER_DEFENSE & & freeSaber ) )
{
final_Powers [ i ] = 1 ;
}
i + + ;
}
usedPoints = 0 ;
}
}
if ( freeSaber )
{
if ( final_Powers [ FP_SABER_OFFENSE ] < 1 )
{
final_Powers [ FP_SABER_OFFENSE ] = 1 ;
}
if ( final_Powers [ FP_SABER_DEFENSE ] < 1 )
{
final_Powers [ FP_SABER_DEFENSE ] = 1 ;
}
}
if ( final_Powers [ FP_LEVITATION ] < 1 )
{
final_Powers [ FP_LEVITATION ] = 1 ;
}
i = 0 ;
while ( i < NUM_FORCE_POWERS )
{
if ( final_Powers [ i ] > FORCE_LEVEL_3 )
{
final_Powers [ i ] = FORCE_LEVEL_3 ;
}
i + + ;
}
if ( fpDisabled )
{ //If we specifically have attack or def disabled, force them up to level 3. It's the way
//things work for the case of all powers disabled.
//If jump is disabled, down-cap it to level 1. Otherwise don't do a thing.
if ( fpDisabled & ( 1 < < FP_LEVITATION ) )
{
final_Powers [ FP_LEVITATION ] = 1 ;
}
if ( fpDisabled & ( 1 < < FP_SABER_OFFENSE ) )
{
final_Powers [ FP_SABER_OFFENSE ] = 3 ;
}
if ( fpDisabled & ( 1 < < FP_SABER_DEFENSE ) )
{
final_Powers [ FP_SABER_DEFENSE ] = 3 ;
}
}
if ( final_Powers [ FP_SABER_OFFENSE ] < 1 )
{
final_Powers [ FP_SABER_DEFENSE ] = 0 ;
final_Powers [ FP_SABERTHROW ] = 0 ;
}
//We finally have all the force powers legalized and stored locally.
//Put them all into the string and return the result. We already have
//the rank there, so print the side and the powers now.
Q_strcat ( powerOut , 128 , va ( " %i- " , final_Side ) ) ;
i = strlen ( powerOut ) ;
c = 0 ;
while ( c < NUM_FORCE_POWERS )
{
strcpy ( readBuf , va ( " %i " , final_Powers [ c ] ) ) ;
powerOut [ i ] = readBuf [ 0 ] ;
c + + ;
i + + ;
}
powerOut [ i ] = 0 ;
return maintainsValidity ;
}
# ifdef __LCC__
// given a boltmatrix, return in vec a normalised vector for the axis requested in flags
void BG_GiveMeVectorFromMatrix ( mdxaBone_t * boltMatrix , int flags , vec3_t vec )
{
switch ( flags )
{
case ORIGIN :
vec [ 0 ] = boltMatrix - > matrix [ 0 ] [ 3 ] ;
vec [ 1 ] = boltMatrix - > matrix [ 1 ] [ 3 ] ;
vec [ 2 ] = boltMatrix - > matrix [ 2 ] [ 3 ] ;
break ;
case POSITIVE_Y :
vec [ 0 ] = boltMatrix - > matrix [ 0 ] [ 1 ] ;
vec [ 1 ] = boltMatrix - > matrix [ 1 ] [ 1 ] ;
vec [ 2 ] = boltMatrix - > matrix [ 2 ] [ 1 ] ;
break ;
case POSITIVE_X :
vec [ 0 ] = boltMatrix - > matrix [ 0 ] [ 0 ] ;
vec [ 1 ] = boltMatrix - > matrix [ 1 ] [ 0 ] ;
vec [ 2 ] = boltMatrix - > matrix [ 2 ] [ 0 ] ;
break ;
case POSITIVE_Z :
vec [ 0 ] = boltMatrix - > matrix [ 0 ] [ 2 ] ;
vec [ 1 ] = boltMatrix - > matrix [ 1 ] [ 2 ] ;
vec [ 2 ] = boltMatrix - > matrix [ 2 ] [ 2 ] ;
break ;
case NEGATIVE_Y :
vec [ 0 ] = - boltMatrix - > matrix [ 0 ] [ 1 ] ;
vec [ 1 ] = - boltMatrix - > matrix [ 1 ] [ 1 ] ;
vec [ 2 ] = - boltMatrix - > matrix [ 2 ] [ 1 ] ;
break ;
case NEGATIVE_X :
vec [ 0 ] = - boltMatrix - > matrix [ 0 ] [ 0 ] ;
vec [ 1 ] = - boltMatrix - > matrix [ 1 ] [ 0 ] ;
vec [ 2 ] = - boltMatrix - > matrix [ 2 ] [ 0 ] ;
break ;
case NEGATIVE_Z :
vec [ 0 ] = - boltMatrix - > matrix [ 0 ] [ 2 ] ;
vec [ 1 ] = - boltMatrix - > matrix [ 1 ] [ 2 ] ;
vec [ 2 ] = - boltMatrix - > matrix [ 2 ] [ 2 ] ;
break ;
}
}
# endif
/*QUAKED item_***** ( 0 0 0 ) (-16 -16 -16) (16 16 16) suspended
DO NOT USE THIS CLASS , IT JUST HOLDS GENERAL INFORMATION .
The suspended flag will allow items to hang in the air , otherwise they are dropped to the next surface .
If an item is the target of another entity , it will not spawn in until fired .
An item fires all of its targets when it is picked up . If the toucher can ' t carry it , the targets won ' t be fired .
" notfree " if set to 1 , don ' t spawn in free for all games
" notteam " if set to 1 , don ' t spawn in team games
" notsingle " if set to 1 , don ' t spawn in single player games
" wait " override the default wait before respawning . - 1 = never respawn automatically , which can be used with targeted spawning .
" random " random number of plus or minus seconds varied from the respawn time
" count " override quantity or duration on most items .
*/
gitem_t bg_itemlist [ ] =
{
{
NULL , // classname
NULL , // pickup_sound
{ NULL , // world_model[0]
NULL , // world_model[1]
0 , 0 } , // world_model[2],[3]
NULL , // view_model
/* icon */ NULL , // icon
/* pickup */ //NULL, // pickup_name
0 , // quantity
0 , // giType (IT_*)
0 , // giTag
/* precache */ " " , // precaches
/* sounds */ " " , // sounds
" " // description
} , // leave index 0 alone
//
// Pickups
//
/*QUAKED item_shield_sm_instant (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
Instant shield pickup , restores 25
*/
{
" item_shield_sm_instant " ,
" sound/player/pickupshield.wav " ,
{ " models/map_objects/mp/psd_sm.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/mp/small_shield " ,
/* pickup */ // "Shield Small",
25 ,
IT_ARMOR ,
1 , //special for shield - max on pickup is maxhealth*tag, thus small shield goes up to 100 shield
/* precache */ " " ,
/* sounds */ " "
" " // description
} ,
/*QUAKED item_shield_lrg_instant (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
Instant shield pickup , restores 100
*/
{
" item_shield_lrg_instant " ,
" sound/player/pickupshield.wav " ,
{ " models/map_objects/mp/psd.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/mp/large_shield " ,
/* pickup */ // "Shield Large",
100 ,
IT_ARMOR ,
2 , //special for shield - max on pickup is maxhealth*tag, thus large shield goes up to 200 shield
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
/*QUAKED item_medpak_instant (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
Instant medpack pickup , heals 25
*/
{
" item_medpak_instant " ,
" sound/player/pickuphealth.wav " ,
{ " models/map_objects/mp/medpac.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/i_icon_medkit " ,
/* pickup */ // "Medpack",
25 ,
IT_HEALTH ,
0 ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
//
// ITEMS
//
/*QUAKED item_seeker (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
30 seconds of seeker drone
*/
{
" item_seeker " ,
" sound/weapons/w_pkup.wav " ,
{ " models/items/remote.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/i_icon_seeker " ,
/* pickup */ // "Seeker Drone",
120 ,
IT_HOLDABLE ,
HI_SEEKER ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_AN_ATTACK_DRONE_SIMILAR " // description
} ,
/*QUAKED item_shield (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
Portable shield
*/
{
" item_shield " ,
" sound/weapons/w_pkup.wav " ,
{ " models/map_objects/mp/shield.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/i_icon_shieldwall " ,
/* pickup */ // "Forcefield",
120 ,
IT_HOLDABLE ,
HI_SHIELD ,
/* precache */ " " ,
/* sounds */ " sound/weapons/detpack/stick.wav sound/movers/doors/forcefield_on.wav sound/movers/doors/forcefield_off.wav sound/movers/doors/forcefield_lp.wav sound/effects/bumpfield.wav " ,
" @MENUS_THIS_STATIONARY_ENERGY " // description
} ,
/*QUAKED item_medpac (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
Bacta canister pickup , heals 25 on use
*/
{
" item_medpac " , //should be item_bacta
" sound/weapons/w_pkup.wav " ,
{ " models/map_objects/mp/bacta.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/i_icon_bacta " ,
/* pickup */ // "Bacta Canister",
25 ,
IT_HOLDABLE ,
HI_MEDPAC ,
/* precache */ " " ,
/* sounds */ " " ,
" @SP_INGAME_BACTA_DESC " // description
} ,
/*QUAKED item_medpac_big (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
Big bacta canister pickup , heals 50 on use
*/
{
" item_medpac_big " , //should be item_bacta
" sound/weapons/w_pkup.wav " ,
{ " models/items/big_bacta.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/i_icon_big_bacta " ,
/* pickup */ // "Bacta Canister",
25 ,
IT_HOLDABLE ,
HI_MEDPAC_BIG ,
/* precache */ " " ,
/* sounds */ " " ,
" @SP_INGAME_BACTA_DESC " // description
} ,
/*QUAKED item_binoculars (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
These will be standard equipment on the player - DO NOT PLACE
*/
{
" item_binoculars " ,
" sound/weapons/w_pkup.wav " ,
{ " models/items/binoculars.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/i_icon_zoom " ,
/* pickup */ // "Binoculars",
60 ,
IT_HOLDABLE ,
HI_BINOCULARS ,
/* precache */ " " ,
/* sounds */ " " ,
" @SP_INGAME_LA_GOGGLES_DESC " // description
} ,
/*QUAKED item_sentry_gun (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
Sentry gun inventory pickup .
*/
{
" item_sentry_gun " ,
" sound/weapons/w_pkup.wav " ,
{ " models/items/psgun.glm " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/i_icon_sentrygun " ,
/* pickup */ // "Sentry Gun",
120 ,
IT_HOLDABLE ,
HI_SENTRY_GUN ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_THIS_DEADLY_WEAPON_IS " // description
} ,
/*QUAKED item_jetpack (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
Do not place .
*/
{
" item_jetpack " ,
" sound/weapons/w_pkup.wav " ,
{ " models/items/psgun.glm " , //FIXME: no model
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/i_icon_jetpack " ,
/* pickup */ // "Sentry Gun",
120 ,
IT_HOLDABLE ,
HI_JETPACK ,
/* precache */ " effects/boba/jet.efx " ,
/* sounds */ " sound/chars/boba/JETON.wav sound/chars/boba/JETHOVER.wav sound/effects/fire_lp.wav " ,
" @MENUS_JETPACK_DESC " // description
} ,
/*QUAKED item_healthdisp (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
Do not place . For siege classes ONLY .
*/
{
" item_healthdisp " ,
" sound/weapons/w_pkup.wav " ,
{ " models/map_objects/mp/bacta.md3 " , //replace me
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/i_icon_healthdisp " ,
/* pickup */ // "Sentry Gun",
120 ,
IT_HOLDABLE ,
HI_HEALTHDISP ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
/*QUAKED item_ammodisp (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
Do not place . For siege classes ONLY .
*/
{
" item_ammodisp " ,
" sound/weapons/w_pkup.wav " ,
{ " models/map_objects/mp/bacta.md3 " , //replace me
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/i_icon_ammodisp " ,
/* pickup */ // "Sentry Gun",
120 ,
IT_HOLDABLE ,
HI_AMMODISP ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
/*QUAKED item_eweb_holdable (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
Do not place . For siege classes ONLY .
*/
{
" item_eweb_holdable " ,
" sound/interface/shieldcon_empty " ,
{ " models/map_objects/hoth/eweb_model.glm " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/i_icon_eweb " ,
/* pickup */ // "Sentry Gun",
120 ,
IT_HOLDABLE ,
HI_EWEB ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_EWEB_DESC " // description
} ,
/*QUAKED item_seeker (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
30 seconds of seeker drone
*/
{
" item_cloak " ,
" sound/weapons/w_pkup.wav " ,
{ " models/items/psgun.glm " , //FIXME: no model
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/i_icon_cloak " ,
/* pickup */ // "Seeker Drone",
120 ,
IT_HOLDABLE ,
HI_CLOAK ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_CLOAK_DESC " // description
} ,
/*QUAKED item_force_enlighten_light (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
Adds one rank to all Force powers temporarily . Only light jedi can use .
*/
{
" item_force_enlighten_light " ,
" sound/player/enlightenment.wav " ,
{ " models/map_objects/mp/jedi_enlightenment.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/mpi_jlight " ,
/* pickup */ // "Light Force Enlightenment",
25 ,
IT_POWERUP ,
PW_FORCE_ENLIGHTENED_LIGHT ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
/*QUAKED item_force_enlighten_dark (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
Adds one rank to all Force powers temporarily . Only dark jedi can use .
*/
{
" item_force_enlighten_dark " ,
" sound/player/enlightenment.wav " ,
{ " models/map_objects/mp/dk_enlightenment.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/mpi_dklight " ,
/* pickup */ // "Dark Force Enlightenment",
25 ,
IT_POWERUP ,
PW_FORCE_ENLIGHTENED_DARK ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
/*QUAKED item_force_boon (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
Unlimited Force Pool for a short time .
*/
{
" item_force_boon " ,
" sound/player/boon.wav " ,
{ " models/map_objects/mp/force_boon.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/mpi_fboon " ,
/* pickup */ // "Force Boon",
25 ,
IT_POWERUP ,
PW_FORCE_BOON ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
/*QUAKED item_ysalimari (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
A small lizard carried on the player , which prevents the possessor from using any Force power . However , he is unaffected by any Force power .
*/
{
" item_ysalimari " ,
" sound/player/ysalimari.wav " ,
{ " models/map_objects/mp/ysalimari.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/mpi_ysamari " ,
/* pickup */ // "Ysalamiri",
25 ,
IT_POWERUP ,
PW_YSALAMIRI ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
//
// WEAPONS
//
/*QUAKED weapon_stun_baton (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
Don ' t place this
*/
{
" weapon_stun_baton " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/stun_baton/baton_w.glm " ,
0 , 0 , 0 } ,
/* view */ " models/weapons2/stun_baton/baton.md3 " ,
/* icon */ " gfx/hud/w_icon_stunbaton " ,
/* pickup */ // "Stun Baton",
100 ,
IT_WEAPON ,
WP_STUN_BATON ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
/*QUAKED weapon_melee (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
Don ' t place this
*/
{
" weapon_melee " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/stun_baton/baton_w.glm " ,
0 , 0 , 0 } ,
/* view */ " models/weapons2/stun_baton/baton.md3 " ,
/* icon */ " gfx/hud/w_icon_melee " ,
/* pickup */ // "Stun Baton",
100 ,
IT_WEAPON ,
WP_MELEE ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_MELEE_DESC " // description
} ,
/*QUAKED weapon_saber (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
Don ' t place this
*/
{
" weapon_saber " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/saber/saber_w.glm " ,
0 , 0 , 0 } ,
/* view */ " models/weapons2/saber/saber_w.md3 " ,
/* icon */ " gfx/hud/w_icon_lightsaber " ,
/* pickup */ // "Lightsaber",
100 ,
IT_WEAPON ,
WP_SABER ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_AN_ELEGANT_WEAPON_FOR " // description
} ,
/*QUAKED weapon_bryar_pistol (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
Don ' t place this
*/
{
//"weapon_bryar_pistol",
" weapon_blaster_pistol " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/blaster_pistol/blaster_pistol_w.glm " , //"models/weapons2/briar_pistol/briar_pistol_w.glm",
0 , 0 , 0 } ,
/* view */ " models/weapons2/blaster_pistol/blaster_pistol.md3 " , //"models/weapons2/briar_pistol/briar_pistol.md3",
/* icon */ " gfx/hud/w_icon_blaster_pistol " , //"gfx/hud/w_icon_rifle",
/* pickup */ // "Bryar Pistol",
100 ,
IT_WEAPON ,
WP_BRYAR_PISTOL ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_BLASTER_PISTOL_DESC " // description
} ,
/*QUAKED weapon_concussion_rifle (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
" weapon_concussion_rifle " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/concussion/c_rifle_w.glm " ,
0 , 0 , 0 } ,
/* view */ " models/weapons2/concussion/c_rifle.md3 " ,
/* icon */ " gfx/hud/w_icon_c_rifle " , //"gfx/hud/w_icon_rifle",
/* pickup */ // "Concussion Rifle",
50 ,
IT_WEAPON ,
WP_CONCUSSION ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_CONC_RIFLE_DESC " // description
} ,
/*QUAKED weapon_bryar_pistol_old (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
Don ' t place this
*/
{
" weapon_bryar_pistol " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/briar_pistol/briar_pistol_w.glm " ,
0 , 0 , 0 } ,
/* view */ " models/weapons2/briar_pistol/briar_pistol.md3 " ,
/* icon */ " gfx/hud/w_icon_briar " , //"gfx/hud/w_icon_rifle",
/* pickup */ // "Bryar Pistol",
100 ,
IT_WEAPON ,
WP_BRYAR_OLD ,
/* precache */ " " ,
/* sounds */ " " ,
" @SP_INGAME_BLASTER_PISTOL " // description
} ,
/*QUAKED weapon_blaster (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
" weapon_blaster " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/blaster_r/blaster_w.glm " ,
0 , 0 , 0 } ,
/* view */ " models/weapons2/blaster_r/blaster.md3 " ,
/* icon */ " gfx/hud/w_icon_blaster " ,
/* pickup */ // "E11 Blaster Rifle",
100 ,
IT_WEAPON ,
WP_BLASTER ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_THE_PRIMARY_WEAPON_OF " // description
} ,
/*QUAKED weapon_disruptor (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
" weapon_disruptor " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/disruptor/disruptor_w.glm " ,
0 , 0 , 0 } ,
/* view */ " models/weapons2/disruptor/disruptor.md3 " ,
/* icon */ " gfx/hud/w_icon_disruptor " ,
/* pickup */ // "Tenloss Disruptor Rifle",
100 ,
IT_WEAPON ,
WP_DISRUPTOR ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_THIS_NEFARIOUS_WEAPON " // description
} ,
/*QUAKED weapon_bowcaster (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
" weapon_bowcaster " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/bowcaster/bowcaster_w.glm " ,
0 , 0 , 0 } ,
/* view */ " models/weapons2/bowcaster/bowcaster.md3 " ,
/* icon */ " gfx/hud/w_icon_bowcaster " ,
/* pickup */ // "Wookiee Bowcaster",
100 ,
IT_WEAPON ,
WP_BOWCASTER ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_THIS_ARCHAIC_LOOKING " // description
} ,
/*QUAKED weapon_repeater (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
" weapon_repeater " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/heavy_repeater/heavy_repeater_w.glm " ,
0 , 0 , 0 } ,
/* view */ " models/weapons2/heavy_repeater/heavy_repeater.md3 " ,
/* icon */ " gfx/hud/w_icon_repeater " ,
/* pickup */ // "Imperial Heavy Repeater",
100 ,
IT_WEAPON ,
WP_REPEATER ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_THIS_DESTRUCTIVE_PROJECTILE " // description
} ,
/*QUAKED weapon_demp2 (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
NOTENOTE This weapon is not yet complete . Don ' t place it .
*/
{
" weapon_demp2 " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/demp2/demp2_w.glm " ,
0 , 0 , 0 } ,
/* view */ " models/weapons2/demp2/demp2.md3 " ,
/* icon */ " gfx/hud/w_icon_demp2 " ,
/* pickup */ // "DEMP2",
100 ,
IT_WEAPON ,
WP_DEMP2 ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_COMMONLY_REFERRED_TO " // description
} ,
/*QUAKED weapon_flechette (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
" weapon_flechette " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/golan_arms/golan_arms_w.glm " ,
0 , 0 , 0 } ,
/* view */ " models/weapons2/golan_arms/golan_arms.md3 " ,
/* icon */ " gfx/hud/w_icon_flechette " ,
/* pickup */ // "Golan Arms Flechette",
100 ,
IT_WEAPON ,
WP_FLECHETTE ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_WIDELY_USED_BY_THE_CORPORATE " // description
} ,
/*QUAKED weapon_rocket_launcher (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
" weapon_rocket_launcher " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/merr_sonn/merr_sonn_w.glm " ,
0 , 0 , 0 } ,
/* view */ " models/weapons2/merr_sonn/merr_sonn.md3 " ,
/* icon */ " gfx/hud/w_icon_merrsonn " ,
/* pickup */ // "Merr-Sonn Missile System",
3 ,
IT_WEAPON ,
WP_ROCKET_LAUNCHER ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_THE_PLX_2M_IS_AN_EXTREMELY " // description
} ,
/*QUAKED ammo_thermal (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
" ammo_thermal " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/thermal/thermal_pu.md3 " ,
" models/weapons2/thermal/thermal_w.glm " , 0 , 0 } ,
/* view */ " models/weapons2/thermal/thermal.md3 " ,
/* icon */ " gfx/hud/w_icon_thermal " ,
/* pickup */ // "Thermal Detonators",
4 ,
IT_AMMO ,
AMMO_THERMAL ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_THE_THERMAL_DETONATOR " // description
} ,
/*QUAKED ammo_tripmine (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
" ammo_tripmine " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/laser_trap/laser_trap_pu.md3 " ,
" models/weapons2/laser_trap/laser_trap_w.glm " , 0 , 0 } ,
/* view */ " models/weapons2/laser_trap/laser_trap.md3 " ,
/* icon */ " gfx/hud/w_icon_tripmine " ,
/* pickup */ // "Trip Mines",
3 ,
IT_AMMO ,
AMMO_TRIPMINE ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_TRIP_MINES_CONSIST_OF " // description
} ,
/*QUAKED ammo_detpack (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
" ammo_detpack " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/detpack/det_pack_pu.md3 " , " models/weapons2/detpack/det_pack_proj.glm " , " models/weapons2/detpack/det_pack_w.glm " , 0 } ,
/* view */ " models/weapons2/detpack/det_pack.md3 " ,
/* icon */ " gfx/hud/w_icon_detpack " ,
/* pickup */ // "Det Packs",
3 ,
IT_AMMO ,
AMMO_DETPACK ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_A_DETONATION_PACK_IS " // description
} ,
/*QUAKED weapon_thermal (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
" weapon_thermal " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/thermal/thermal_w.glm " , " models/weapons2/thermal/thermal_pu.md3 " ,
0 , 0 } ,
/* view */ " models/weapons2/thermal/thermal.md3 " ,
/* icon */ " gfx/hud/w_icon_thermal " ,
/* pickup */ // "Thermal Detonator",
4 ,
IT_WEAPON ,
WP_THERMAL ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_THE_THERMAL_DETONATOR " // description
} ,
/*QUAKED weapon_trip_mine (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
" weapon_trip_mine " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/laser_trap/laser_trap_w.glm " , " models/weapons2/laser_trap/laser_trap_pu.md3 " ,
0 , 0 } ,
/* view */ " models/weapons2/laser_trap/laser_trap.md3 " ,
/* icon */ " gfx/hud/w_icon_tripmine " ,
/* pickup */ // "Trip Mine",
3 ,
IT_WEAPON ,
WP_TRIP_MINE ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_TRIP_MINES_CONSIST_OF " // description
} ,
/*QUAKED weapon_det_pack (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
" weapon_det_pack " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/detpack/det_pack_proj.glm " , " models/weapons2/detpack/det_pack_pu.md3 " , " models/weapons2/detpack/det_pack_w.glm " , 0 } ,
/* view */ " models/weapons2/detpack/det_pack.md3 " ,
/* icon */ " gfx/hud/w_icon_detpack " ,
/* pickup */ // "Det Pack",
3 ,
IT_WEAPON ,
WP_DET_PACK ,
/* precache */ " " ,
/* sounds */ " " ,
" @MENUS_A_DETONATION_PACK_IS " // description
} ,
/*QUAKED weapon_emplaced (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
" weapon_emplaced " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/blaster_r/blaster_w.glm " ,
0 , 0 , 0 } ,
/* view */ " models/weapons2/blaster_r/blaster.md3 " ,
/* icon */ " gfx/hud/w_icon_blaster " ,
/* pickup */ // "Emplaced Gun",
50 ,
IT_WEAPON ,
WP_EMPLACED_GUN ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
//NOTE: This is to keep things from messing up because the turret weapon type isn't real
{
" weapon_turretwp " ,
" sound/weapons/w_pkup.wav " ,
{ " models/weapons2/blaster_r/blaster_w.glm " ,
0 , 0 , 0 } ,
/* view */ " models/weapons2/blaster_r/blaster.md3 " ,
/* icon */ " gfx/hud/w_icon_blaster " ,
/* pickup */ // "Turret Gun",
50 ,
IT_WEAPON ,
WP_TURRET ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
//
// AMMO ITEMS
//
/*QUAKED ammo_force (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
Don ' t place this
*/
{
" ammo_force " ,
" sound/player/pickupenergy.wav " ,
{ " models/items/energy_cell.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/w_icon_blaster " ,
/* pickup */ // "Force??",
100 ,
IT_AMMO ,
AMMO_FORCE ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
/*QUAKED ammo_blaster (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
Ammo for the Bryar and Blaster pistols .
*/
{
" ammo_blaster " ,
" sound/player/pickupenergy.wav " ,
{ " models/items/energy_cell.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/i_icon_battery " ,
/* pickup */ // "Blaster Pack",
100 ,
IT_AMMO ,
AMMO_BLASTER ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
/*QUAKED ammo_powercell (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
Ammo for Tenloss Disruptor , Wookie Bowcaster , and the Destructive Electro Magnetic Pulse ( demp2 ) guns
*/
{
" ammo_powercell " ,
" sound/player/pickupenergy.wav " ,
{ " models/items/power_cell.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/mp/ammo_power_cell " ,
/* pickup */ // "Power Cell",
100 ,
IT_AMMO ,
AMMO_POWERCELL ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
/*QUAKED ammo_metallic_bolts (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
Ammo for Imperial Heavy Repeater and the Golan Arms Flechette
*/
{
" ammo_metallic_bolts " ,
" sound/player/pickupenergy.wav " ,
{ " models/items/metallic_bolts.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/mp/ammo_metallic_bolts " ,
/* pickup */ // "Metallic Bolts",
100 ,
IT_AMMO ,
AMMO_METAL_BOLTS ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
/*QUAKED ammo_rockets (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
Ammo for Merr - Sonn portable missile launcher
*/
{
" ammo_rockets " ,
" sound/player/pickupenergy.wav " ,
{ " models/items/rockets.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/mp/ammo_rockets " ,
/* pickup */ // "Rockets",
3 ,
IT_AMMO ,
AMMO_ROCKETS ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
/*QUAKED ammo_all (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
DO NOT PLACE in a map , this is only for siege classes that have ammo
dispensing ability
*/
{
" ammo_all " ,
" sound/player/pickupenergy.wav " ,
{ " models/items/battery.md3 " , //replace me
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/mp/ammo_rockets " , //replace me
/* pickup */ // "Rockets",
0 ,
IT_AMMO ,
- 1 ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
//
// POWERUP ITEMS
//
/*QUAKED team_CTF_redflag (1 0 0) (-16 -16 -16) (16 16 16)
Only in CTF games
*/
{
" team_CTF_redflag " ,
NULL ,
{ " models/flags/r_flag.md3 " ,
" models/flags/r_flag_ysal.md3 " , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/mpi_rflag " ,
/* pickup */ // "Red Flag",
0 ,
IT_TEAM ,
PW_REDFLAG ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
/*QUAKED team_CTF_blueflag (0 0 1) (-16 -16 -16) (16 16 16)
Only in CTF games
*/
{
" team_CTF_blueflag " ,
NULL ,
{ " models/flags/b_flag.md3 " ,
" models/flags/b_flag_ysal.md3 " , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " gfx/hud/mpi_bflag " ,
/* pickup */ // "Blue Flag",
0 ,
IT_TEAM ,
PW_BLUEFLAG ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
//
// PERSISTANT POWERUP ITEMS
//
/*QUAKED team_CTF_neutralflag (0 0 1) (-16 -16 -16) (16 16 16)
Only in One Flag CTF games
*/
{
" team_CTF_neutralflag " ,
NULL ,
{ " models/flags/n_flag.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " icons/iconf_neutral1 " ,
/* pickup */ // "Neutral Flag",
0 ,
IT_TEAM ,
PW_NEUTRALFLAG ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
{
" item_redcube " ,
" sound/player/pickupenergy.wav " ,
{ " models/powerups/orb/r_orb.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " icons/iconh_rorb " ,
/* pickup */ // "Red Cube",
0 ,
IT_TEAM ,
0 ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
{
" item_bluecube " ,
" sound/player/pickupenergy.wav " ,
{ " models/powerups/orb/b_orb.md3 " ,
0 , 0 , 0 } ,
/* view */ NULL ,
/* icon */ " icons/iconh_borb " ,
/* pickup */ // "Blue Cube",
0 ,
IT_TEAM ,
0 ,
/* precache */ " " ,
/* sounds */ " " ,
" " // description
} ,
// end of list marker
{ NULL }
} ;
int bg_numItems = sizeof ( bg_itemlist ) / sizeof ( bg_itemlist [ 0 ] ) - 1 ;
float vectoyaw ( const vec3_t vec ) {
float yaw ;
if ( vec [ YAW ] = = 0 & & vec [ PITCH ] = = 0 ) {
yaw = 0 ;
} else {
if ( vec [ PITCH ] ) {
yaw = ( atan2 ( vec [ YAW ] , vec [ PITCH ] ) * 180 / M_PI ) ;
} else if ( vec [ YAW ] > 0 ) {
yaw = 90 ;
} else {
yaw = 270 ;
}
if ( yaw < 0 ) {
yaw + = 360 ;
}
}
return yaw ;
}
qboolean BG_HasYsalamiri ( int gametype , playerState_t * ps )
{
if ( gametype = = GT_CTY & &
( ps - > powerups [ PW_REDFLAG ] | | ps - > powerups [ PW_BLUEFLAG ] ) )
{
return qtrue ;
}
if ( ps - > powerups [ PW_YSALAMIRI ] )
{
return qtrue ;
}
return qfalse ;
}
qboolean BG_CanUseFPNow ( int gametype , playerState_t * ps , int time , forcePowers_t power )
{
if ( BG_HasYsalamiri ( gametype , ps ) )
{
return qfalse ;
}
if ( ps - > forceRestricted | | ps - > trueNonJedi )
{
return qfalse ;
}
if ( ps - > weapon = = WP_EMPLACED_GUN )
{ //can't use any of your powers while on an emplaced weapon
return qfalse ;
}
if ( ps - > m_iVehicleNum )
{ //can't use powers while riding a vehicle (this may change, I don't know)
return qfalse ;
}
if ( ps - > duelInProgress )
{
if ( power ! = FP_SABER_OFFENSE & & power ! = FP_SABER_DEFENSE & & /*power != FP_SABERTHROW &&*/
power ! = FP_LEVITATION )
{
if ( ! ps - > saberLockFrame | | power ! = FP_PUSH )
{
return qfalse ;
}
}
}
if ( ps - > saberLockFrame | | ps - > saberLockTime > time )
{
if ( power ! = FP_PUSH )
{
return qfalse ;
}
}
if ( ps - > fallingToDeath )
{
return qfalse ;
}
if ( ( ps - > brokenLimbs & ( 1 < < BROKENLIMB_RARM ) ) | |
( ps - > brokenLimbs & ( 1 < < BROKENLIMB_LARM ) ) )
{ //powers we can't use with a broken arm
switch ( power )
{
case FP_PUSH :
case FP_PULL :
case FP_GRIP :
case FP_LIGHTNING :
case FP_DRAIN :
return qfalse ;
default :
break ;
}
}
return qtrue ;
}
/*
= = = = = = = = = = = = = =
BG_FindItemForPowerup
= = = = = = = = = = = = = =
*/
gitem_t * BG_FindItemForPowerup ( powerup_t pw ) {
int i ;
for ( i = 0 ; i < bg_numItems ; i + + ) {
if ( ( bg_itemlist [ i ] . giType = = IT_POWERUP | |
bg_itemlist [ i ] . giType = = IT_TEAM ) & &
bg_itemlist [ i ] . giTag = = pw ) {
return & bg_itemlist [ i ] ;
}
}
return NULL ;
}
/*
= = = = = = = = = = = = = =
BG_FindItemForHoldable
= = = = = = = = = = = = = =
*/
gitem_t * BG_FindItemForHoldable ( holdable_t pw ) {
int i ;
for ( i = 0 ; i < bg_numItems ; i + + ) {
if ( bg_itemlist [ i ] . giType = = IT_HOLDABLE & & bg_itemlist [ i ] . giTag = = pw ) {
return & bg_itemlist [ i ] ;
}
}
Com_Error ( ERR_DROP , " HoldableItem not found " ) ;
return NULL ;
}
/*
= = = = = = = = = = = = = = =
BG_FindItemForWeapon
= = = = = = = = = = = = = = =
*/
gitem_t * BG_FindItemForWeapon ( weapon_t weapon ) {
gitem_t * it ;
for ( it = bg_itemlist + 1 ; it - > classname ; it + + ) {
if ( it - > giType = = IT_WEAPON & & it - > giTag = = weapon ) {
return it ;
}
}
Com_Error ( ERR_DROP , " Couldn't find item for weapon %i " , weapon ) ;
return NULL ;
}
/*
= = = = = = = = = = = = = = =
BG_FindItemForAmmo
= = = = = = = = = = = = = = =
*/
gitem_t * BG_FindItemForAmmo ( ammo_t ammo ) {
gitem_t * it ;
for ( it = bg_itemlist + 1 ; it - > classname ; it + + ) {
if ( it - > giType = = IT_AMMO & & it - > giTag = = ammo ) {
return it ;
}
}
Com_Error ( ERR_DROP , " Couldn't find item for ammo %i " , ammo ) ;
return NULL ;
}
/*
= = = = = = = = = = = = = = =
BG_FindItem
= = = = = = = = = = = = = = =
*/
gitem_t * BG_FindItem ( const char * classname ) {
gitem_t * it ;
for ( it = bg_itemlist + 1 ; it - > classname ; it + + ) {
if ( ! Q_stricmp ( it - > classname , classname ) )
return it ;
}
return NULL ;
}
/*
= = = = = = = = = = = =
BG_PlayerTouchesItem
Items can be picked up without actually touching their physical bounds to make
grabbing them easier
= = = = = = = = = = = =
*/
qboolean BG_PlayerTouchesItem ( playerState_t * ps , entityState_t * item , int atTime ) {
vec3_t origin ;
BG_EvaluateTrajectory ( & item - > pos , atTime , origin ) ;
// we are ignoring ducked differences here
if ( ps - > origin [ 0 ] - origin [ 0 ] > 44
| | ps - > origin [ 0 ] - origin [ 0 ] < - 50
| | ps - > origin [ 1 ] - origin [ 1 ] > 36
| | ps - > origin [ 1 ] - origin [ 1 ] < - 36
| | ps - > origin [ 2 ] - origin [ 2 ] > 36
| | ps - > origin [ 2 ] - origin [ 2 ] < - 36 ) {
return qfalse ;
}
return qtrue ;
}
int BG_ProperForceIndex ( int power )
{
int i = 0 ;
while ( i < NUM_FORCE_POWERS )
{
if ( forcePowerSorted [ i ] = = power )
{
return i ;
}
i + + ;
}
return - 1 ;
}
void BG_CycleForce ( playerState_t * ps , int direction )
{
int i = ps - > fd . forcePowerSelected ;
int x = i ;
int presel = i ;
int foundnext = - 1 ;
if ( ! ps - > fd . forcePowersKnown & ( 1 < < x ) | |
x > = NUM_FORCE_POWERS | |
x = = - 1 )
{ //apparently we have no valid force powers
return ;
}
x = BG_ProperForceIndex ( x ) ;
presel = x ;
if ( direction = = 1 )
{ //get the next power
x + + ;
}
else
{ //get the previous power
x - - ;
}
if ( x > = NUM_FORCE_POWERS )
{ //cycled off the end.. cycle around to the first
x = 0 ;
}
if ( x < 0 )
{ //cycled off the beginning.. cycle around to the last
x = NUM_FORCE_POWERS - 1 ;
}
i = forcePowerSorted [ x ] ; //the "sorted" value of this power
while ( x ! = presel )
{ //loop around to the current force power
if ( ps - > fd . forcePowersKnown & ( 1 < < i ) & & i ! = ps - > fd . forcePowerSelected )
{ //we have the force power
if ( i ! = FP_LEVITATION & &
i ! = FP_SABER_OFFENSE & &
i ! = FP_SABER_DEFENSE & &
i ! = FP_SABERTHROW )
{ //it's selectable
foundnext = i ;
break ;
}
}
if ( direction = = 1 )
{ //next
x + + ;
}
else
{ //previous
x - - ;
}
if ( x > = NUM_FORCE_POWERS )
{ //loop around
x = 0 ;
}
if ( x < 0 )
{ //loop around
x = NUM_FORCE_POWERS - 1 ;
}
i = forcePowerSorted [ x ] ; //set to the sorted value again
}
if ( foundnext ! = - 1 )
{ //found one, select it
ps - > fd . forcePowerSelected = foundnext ;
}
}
int BG_GetItemIndexByTag ( int tag , int type )
{ //Get the itemlist index from the tag and type
int i = 0 ;
while ( i < bg_numItems )
{
if ( bg_itemlist [ i ] . giTag = = tag & &
bg_itemlist [ i ] . giType = = type )
{
return i ;
}
i + + ;
}
return 0 ;
}
//yeah..
qboolean BG_IsItemSelectable ( playerState_t * ps , int item )
{
if ( item = = HI_HEALTHDISP | | item = = HI_AMMODISP | |
item = = HI_JETPACK )
{
return qfalse ;
}
return qtrue ;
}
void BG_CycleInven ( playerState_t * ps , int direction )
{
int i ;
int dontFreeze = 0 ;
int original ;
i = bg_itemlist [ ps - > stats [ STAT_HOLDABLE_ITEM ] ] . giTag ;
original = i ;
if ( direction = = 1 )
{ //next
i + + ;
if ( i = = HI_NUM_HOLDABLE )
{
i = 1 ;
}
}
else
{ //previous
i - - ;
if ( i = = 0 )
{
i = HI_NUM_HOLDABLE - 1 ;
}
}
while ( i ! = original )
{ //go in a full loop until hitting something, if hit nothing then select nothing
if ( ps - > stats [ STAT_HOLDABLE_ITEMS ] & ( 1 < < i ) )
{ //we have it, select it.
if ( BG_IsItemSelectable ( ps , i ) )
{
ps - > stats [ STAT_HOLDABLE_ITEM ] = BG_GetItemIndexByTag ( i , IT_HOLDABLE ) ;
break ;
}
}
if ( direction = = 1 )
{ //next
i + + ;
}
else
{ //previous
i - - ;
}
if ( i < = 0 )
{ //wrap around to the last
i = HI_NUM_HOLDABLE - 1 ;
}
else if ( i > = HI_NUM_HOLDABLE )
{ //wrap around to the first
i = 1 ;
}
dontFreeze + + ;
if ( dontFreeze > = 32 )
{ //yeah, sure, whatever (it's 2 am and I'm paranoid and can't frickin think)
break ;
}
}
}
/*
= = = = = = = = = = = = = = = =
BG_CanItemBeGrabbed
Returns false if the item should not be picked up .
This needs to be the same for client side prediction and server use .
= = = = = = = = = = = = = = = =
*/
qboolean BG_CanItemBeGrabbed ( int gametype , const entityState_t * ent , const playerState_t * ps ) {
gitem_t * item ;
if ( ent - > modelindex < 1 | | ent - > modelindex > = bg_numItems ) {
Com_Error ( ERR_DROP , " BG_CanItemBeGrabbed: index out of range " ) ;
}
item = & bg_itemlist [ ent - > modelindex ] ;
if ( ps )
{
if ( ps - > trueJedi )
{ //force powers and saber only
if ( item - > giType ! = IT_TEAM //not a flag
& & item - > giType ! = IT_ARMOR //not shields
& & ( item - > giType ! = IT_WEAPON | | item - > giTag ! = WP_SABER ) //not a saber
& & ( item - > giType ! = IT_HOLDABLE | | item - > giTag ! = HI_SEEKER ) //not a seeker
& & ( item - > giType ! = IT_POWERUP | | item - > giTag = = PW_YSALAMIRI ) ) //not a force pick-up
{
return qfalse ;
}
}
else if ( ps - > trueNonJedi )
{ //can't pick up force powerups
if ( ( item - > giType = = IT_POWERUP & & item - > giTag ! = PW_YSALAMIRI ) //if a powerup, can only can pick up ysalamiri
| | ( item - > giType = = IT_HOLDABLE & & item - > giTag = = HI_SEEKER ) //if holdable, cannot pick up seeker
| | ( item - > giType = = IT_WEAPON & & item - > giTag = = WP_SABER ) ) //or if it's a saber
{
return qfalse ;
}
}
if ( ps - > isJediMaster & & item & & ( item - > giType = = IT_WEAPON | | item - > giType = = IT_AMMO ) )
{ //jedi master cannot pick up weapons
return qfalse ;
}
if ( ps - > duelInProgress )
{ //no picking stuff up while in a duel, no matter what the type is
return qfalse ;
}
}
else
{ //safety return since below code assumes a non-null ps
return qfalse ;
}
switch ( item - > giType ) {
case IT_WEAPON :
if ( ent - > generic1 = = ps - > clientNum & & ent - > powerups )
{
return qfalse ;
}
if ( ! ( ent - > eFlags & EF_DROPPEDWEAPON ) & & ( ps - > stats [ STAT_WEAPONS ] & ( 1 < < item - > giTag ) ) & &
item - > giTag ! = WP_THERMAL & & item - > giTag ! = WP_TRIP_MINE & & item - > giTag ! = WP_DET_PACK )
{ //weaponstay stuff.. if this isn't dropped, and you already have it, you don't get it.
return qfalse ;
}
if ( item - > giTag = = WP_THERMAL | | item - > giTag = = WP_TRIP_MINE | | item - > giTag = = WP_DET_PACK )
{ //check to see if full on ammo for this, if so, then..
int ammoIndex = weaponData [ item - > giTag ] . ammoIndex ;
if ( ps - > ammo [ ammoIndex ] > = ammoData [ ammoIndex ] . max )
{ //don't need it
return qfalse ;
}
}
return qtrue ; // weapons are always picked up
case IT_AMMO :
if ( item - > giTag = = - 1 )
{ //special case for "all ammo" packs
return qtrue ;
}
if ( ps - > ammo [ item - > giTag ] > = ammoData [ item - > giTag ] . max ) {
return qfalse ; // can't hold any more
}
return qtrue ;
case IT_ARMOR :
if ( ps - > stats [ STAT_ARMOR ] > = ps - > stats [ STAT_MAX_HEALTH ] /* * item->giTag*/ ) {
return qfalse ;
}
return qtrue ;
case IT_HEALTH :
// small and mega healths will go over the max, otherwise
// don't pick up if already at max
if ( ( ps - > fd . forcePowersActive & ( 1 < < FP_RAGE ) ) )
{
return qfalse ;
}
if ( item - > quantity = = 5 | | item - > quantity = = 100 ) {
if ( ps - > stats [ STAT_HEALTH ] > = ps - > stats [ STAT_MAX_HEALTH ] * 2 ) {
return qfalse ;
}
return qtrue ;
}
if ( ps - > stats [ STAT_HEALTH ] > = ps - > stats [ STAT_MAX_HEALTH ] ) {
return qfalse ;
}
return qtrue ;
case IT_POWERUP :
if ( ps & & ( ps - > powerups [ PW_YSALAMIRI ] ) )
{
if ( item - > giTag ! = PW_YSALAMIRI )
{
return qfalse ;
}
}
return qtrue ; // powerups are always picked up
case IT_TEAM : // team items, such as flags
if ( gametype = = GT_CTF | | gametype = = GT_CTY ) {
// ent->modelindex2 is non-zero on items if they are dropped
// we need to know this because we can pick up our dropped flag (and return it)
// but we can't pick up our flag at base
if ( ps - > persistant [ PERS_TEAM ] = = TEAM_RED ) {
if ( item - > giTag = = PW_BLUEFLAG | |
( item - > giTag = = PW_REDFLAG & & ent - > modelindex2 ) | |
( item - > giTag = = PW_REDFLAG & & ps - > powerups [ PW_BLUEFLAG ] ) )
return qtrue ;
} else if ( ps - > persistant [ PERS_TEAM ] = = TEAM_BLUE ) {
if ( item - > giTag = = PW_REDFLAG | |
( item - > giTag = = PW_BLUEFLAG & & ent - > modelindex2 ) | |
( item - > giTag = = PW_BLUEFLAG & & ps - > powerups [ PW_REDFLAG ] ) )
return qtrue ;
}
}
return qfalse ;
case IT_HOLDABLE :
if ( ps - > stats [ STAT_HOLDABLE_ITEMS ] & ( 1 < < item - > giTag ) )
{
return qfalse ;
}
return qtrue ;
case IT_BAD :
Com_Error ( ERR_DROP , " BG_CanItemBeGrabbed: IT_BAD " ) ;
default :
# ifndef Q3_VM
# ifndef NDEBUG // bk0001204
Com_Printf ( " BG_CanItemBeGrabbed: unknown enum %d \n " , item - > giType ) ;
# endif
# endif
break ;
}
return qfalse ;
}
//======================================================================
/*
= = = = = = = = = = = = = = = =
BG_EvaluateTrajectory
= = = = = = = = = = = = = = = =
*/
void BG_EvaluateTrajectory ( const trajectory_t * tr , int atTime , vec3_t result ) {
float deltaTime ;
float phase ;
switch ( tr - > trType ) {
case TR_STATIONARY :
case TR_INTERPOLATE :
VectorCopy ( tr - > trBase , result ) ;
break ;
case TR_LINEAR :
deltaTime = ( atTime - tr - > trTime ) * 0.001 ; // milliseconds to seconds
VectorMA ( tr - > trBase , deltaTime , tr - > trDelta , result ) ;
break ;
case TR_SINE :
deltaTime = ( atTime - tr - > trTime ) / ( float ) tr - > trDuration ;
phase = sin ( deltaTime * M_PI * 2 ) ;
VectorMA ( tr - > trBase , phase , tr - > trDelta , result ) ;
break ;
case TR_LINEAR_STOP :
if ( atTime > tr - > trTime + tr - > trDuration ) {
atTime = tr - > trTime + tr - > trDuration ;
}
deltaTime = ( atTime - tr - > trTime ) * 0.001 ; // milliseconds to seconds
if ( deltaTime < 0 ) {
deltaTime = 0 ;
}
VectorMA ( tr - > trBase , deltaTime , tr - > trDelta , result ) ;
break ;
case TR_NONLINEAR_STOP :
if ( atTime > tr - > trTime + tr - > trDuration )
{
atTime = tr - > trTime + tr - > trDuration ;
}
//new slow-down at end
if ( atTime - tr - > trTime > tr - > trDuration | | atTime - tr - > trTime < = 0 )
{
deltaTime = 0 ;
}
else
{ //FIXME: maybe scale this somehow? So that it starts out faster and stops faster?
deltaTime = tr - > trDuration * 0.001f * ( ( float ) cos ( DEG2RAD ( 90.0f - ( 90.0f * ( ( float ) atTime - tr - > trTime ) / ( float ) tr - > trDuration ) ) ) ) ;
}
VectorMA ( tr - > trBase , deltaTime , tr - > trDelta , result ) ;
break ;
case TR_GRAVITY :
deltaTime = ( atTime - tr - > trTime ) * 0.001 ; // milliseconds to seconds
VectorMA ( tr - > trBase , deltaTime , tr - > trDelta , result ) ;
result [ 2 ] - = 0.5 * DEFAULT_GRAVITY * deltaTime * deltaTime ; // FIXME: local gravity...
break ;
default :
# ifdef QAGAME
Com_Error ( ERR_DROP , " BG_EvaluateTrajectory: [GAME SIDE] unknown trType: %i " , tr - > trType ) ;
# else
Com_Error ( ERR_DROP , " BG_EvaluateTrajectory: [CLIENTGAME SIDE] unknown trType: %i " , tr - > trType ) ;
# endif
break ;
}
}
/*
= = = = = = = = = = = = = = = =
BG_EvaluateTrajectoryDelta
For determining velocity at a given time
= = = = = = = = = = = = = = = =
*/
void BG_EvaluateTrajectoryDelta ( const trajectory_t * tr , int atTime , vec3_t result ) {
float deltaTime ;
float phase ;
switch ( tr - > trType ) {
case TR_STATIONARY :
case TR_INTERPOLATE :
VectorClear ( result ) ;
break ;
case TR_LINEAR :
VectorCopy ( tr - > trDelta , result ) ;
break ;
case TR_SINE :
deltaTime = ( atTime - tr - > trTime ) / ( float ) tr - > trDuration ;
phase = cos ( deltaTime * M_PI * 2 ) ; // derivative of sin = cos
phase * = 0.5 ;
VectorScale ( tr - > trDelta , phase , result ) ;
break ;
case TR_LINEAR_STOP :
if ( atTime > tr - > trTime + tr - > trDuration ) {
VectorClear ( result ) ;
return ;
}
VectorCopy ( tr - > trDelta , result ) ;
break ;
case TR_NONLINEAR_STOP :
if ( atTime - tr - > trTime > tr - > trDuration | | atTime - tr - > trTime < = 0 )
{
VectorClear ( result ) ;
return ;
}
deltaTime = tr - > trDuration * 0.001f * ( ( float ) cos ( DEG2RAD ( 90.0f - ( 90.0f * ( ( float ) atTime - tr - > trTime ) / ( float ) tr - > trDuration ) ) ) ) ;
VectorScale ( tr - > trDelta , deltaTime , result ) ;
break ;
case TR_GRAVITY :
deltaTime = ( atTime - tr - > trTime ) * 0.001 ; // milliseconds to seconds
VectorCopy ( tr - > trDelta , result ) ;
result [ 2 ] - = DEFAULT_GRAVITY * deltaTime ; // FIXME: local gravity...
break ;
default :
Com_Error ( ERR_DROP , " BG_EvaluateTrajectoryDelta: unknown trType: %i " , tr - > trTime ) ;
break ;
}
}
char * eventnames [ ] = {
" EV_NONE " ,
" EV_CLIENTJOIN " ,
" EV_FOOTSTEP " ,
" EV_FOOTSTEP_METAL " ,
" EV_FOOTSPLASH " ,
" EV_FOOTWADE " ,
" EV_SWIM " ,
" EV_STEP_4 " ,
" EV_STEP_8 " ,
" EV_STEP_12 " ,
" EV_STEP_16 " ,
" EV_FALL " ,
" EV_JUMP_PAD " , // boing sound at origin", jump sound on player
" EV_GHOUL2_MARK " , //create a projectile impact mark on something with a client-side g2 instance.
" EV_GLOBAL_DUEL " ,
" EV_PRIVATE_DUEL " ,
" EV_JUMP " ,
" EV_ROLL " ,
" EV_WATER_TOUCH " , // foot touches
" EV_WATER_LEAVE " , // foot leaves
" EV_WATER_UNDER " , // head touches
" EV_WATER_CLEAR " , // head leaves
" EV_ITEM_PICKUP " , // normal item pickups are predictable
" EV_GLOBAL_ITEM_PICKUP " , // powerup / team sounds are broadcast to everyone
" EV_VEH_FIRE " ,
" EV_NOAMMO " ,
" EV_CHANGE_WEAPON " ,
" EV_FIRE_WEAPON " ,
" EV_ALT_FIRE " ,
" EV_SABER_ATTACK " ,
" EV_SABER_HIT " ,
" EV_SABER_BLOCK " ,
" EV_SABER_CLASHFLARE " ,
" EV_SABER_UNHOLSTER " ,
" EV_BECOME_JEDIMASTER " ,
" EV_DISRUPTOR_MAIN_SHOT " ,
" EV_DISRUPTOR_SNIPER_SHOT " ,
" EV_DISRUPTOR_SNIPER_MISS " ,
" EV_DISRUPTOR_HIT " ,
" EV_DISRUPTOR_ZOOMSOUND " ,
" EV_PREDEFSOUND " ,
" EV_TEAM_POWER " ,
" EV_SCREENSHAKE " ,
" EV_LOCALTIMER " ,
" EV_USE " , // +Use key
" EV_USE_ITEM0 " ,
" EV_USE_ITEM1 " ,
" EV_USE_ITEM2 " ,
" EV_USE_ITEM3 " ,
" EV_USE_ITEM4 " ,
" EV_USE_ITEM5 " ,
" EV_USE_ITEM6 " ,
" EV_USE_ITEM7 " ,
" EV_USE_ITEM8 " ,
" EV_USE_ITEM9 " ,
" EV_USE_ITEM10 " ,
" EV_USE_ITEM11 " ,
" EV_USE_ITEM12 " ,
" EV_USE_ITEM13 " ,
" EV_USE_ITEM14 " ,
" EV_USE_ITEM15 " ,
" EV_ITEMUSEFAIL " ,
" EV_ITEM_RESPAWN " ,
" EV_ITEM_POP " ,
" EV_PLAYER_TELEPORT_IN " ,
" EV_PLAYER_TELEPORT_OUT " ,
" EV_GRENADE_BOUNCE " , // eventParm will be the soundindex
" EV_MISSILE_STICK " ,
" EV_PLAY_EFFECT " ,
" EV_PLAY_EFFECT_ID " , //finally gave in and added it..
" EV_PLAY_PORTAL_EFFECT_ID " ,
" EV_PLAYDOORSOUND " ,
" EV_PLAYDOORLOOPSOUND " ,
" EV_BMODEL_SOUND " ,
" EV_MUTE_SOUND " ,
" EV_VOICECMD_SOUND " ,
" EV_GENERAL_SOUND " ,
" EV_GLOBAL_SOUND " , // no attenuation
" EV_GLOBAL_TEAM_SOUND " ,
" EV_ENTITY_SOUND " ,
" EV_PLAY_ROFF " ,
" EV_GLASS_SHATTER " ,
" EV_DEBRIS " ,
" EV_MISC_MODEL_EXP " ,
" EV_CONC_ALT_IMPACT " ,
" EV_MISSILE_HIT " ,
" EV_MISSILE_MISS " ,
" EV_MISSILE_MISS_METAL " ,
" EV_BULLET " , // otherEntity is the shooter
" EV_PAIN " ,
" EV_DEATH1 " ,
" EV_DEATH2 " ,
" EV_DEATH3 " ,
" EV_OBITUARY " ,
" EV_POWERUP_QUAD " ,
" EV_POWERUP_BATTLESUIT " ,
//"EV_POWERUP_REGEN",
" EV_FORCE_DRAINED " ,
" EV_GIB_PLAYER " , // gib a previously living player
" EV_SCOREPLUM " , // score plum
" EV_CTFMESSAGE " ,
" EV_BODYFADE " ,
" EV_SIEGE_ROUNDOVER " ,
" EV_SIEGE_OBJECTIVECOMPLETE " ,
" EV_DESTROY_GHOUL2_INSTANCE " ,
" EV_DESTROY_WEAPON_MODEL " ,
" EV_GIVE_NEW_RANK " ,
" EV_SET_FREE_SABER " ,
" EV_SET_FORCE_DISABLE " ,
" EV_WEAPON_CHARGE " ,
" EV_WEAPON_CHARGE_ALT " ,
" EV_SHIELD_HIT " ,
" EV_DEBUG_LINE " ,
" EV_TESTLINE " ,
" EV_STOPLOOPINGSOUND " ,
" EV_STARTLOOPINGSOUND " ,
" EV_TAUNT " ,
//fixme, added a bunch that aren't here!
} ;
/*
= = = = = = = = = = = = = = =
BG_AddPredictableEventToPlayerstate
Handles the sequence numbers
= = = = = = = = = = = = = = =
*/
//void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize );
void BG_AddPredictableEventToPlayerstate ( int newEvent , int eventParm , playerState_t * ps ) {
# ifdef _DEBUG
{
static vmCvar_t showEvents ;
static qboolean isRegistered = qfalse ;
if ( ! isRegistered )
{
trap_Cvar_Register ( & showEvents , " showevents " , " 0 " , 0 ) ;
isRegistered = qtrue ;
}
if ( showEvents . integer ! = 0 ) {
# ifdef QAGAME
Com_Printf ( " game event svt %5d -> %5d: num = %20s parm %d \n " , ps - > pmove_framecount /*ps->commandTime*/ , ps - > eventSequence , eventnames [ newEvent ] , eventParm ) ;
# else
Com_Printf ( " Cgame event svt %5d -> %5d: num = %20s parm %d \n " , ps - > pmove_framecount /*ps->commandTime*/ , ps - > eventSequence , eventnames [ newEvent ] , eventParm ) ;
# endif
}
}
# endif
ps - > events [ ps - > eventSequence & ( MAX_PS_EVENTS - 1 ) ] = newEvent ;
ps - > eventParms [ ps - > eventSequence & ( MAX_PS_EVENTS - 1 ) ] = eventParm ;
ps - > eventSequence + + ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
BG_TouchJumpPad
= = = = = = = = = = = = = = = = = = = = = = = =
*/
void BG_TouchJumpPad ( playerState_t * ps , entityState_t * jumppad ) {
vec3_t angles ;
float p ;
int effectNum ;
// spectators don't use jump pads
if ( ps - > pm_type ! = PM_NORMAL & & ps - > pm_type ! = PM_JETPACK & & ps - > pm_type ! = PM_FLOAT ) {
return ;
}
// if we didn't hit this same jumppad the previous frame
// then don't play the event sound again if we are in a fat trigger
if ( ps - > jumppad_ent ! = jumppad - > number ) {
vectoangles ( jumppad - > origin2 , angles ) ;
p = fabs ( AngleNormalize180 ( angles [ PITCH ] ) ) ;
if ( p < 45 ) {
effectNum = 0 ;
} else {
effectNum = 1 ;
}
}
// remember hitting this jumppad this frame
ps - > jumppad_ent = jumppad - > number ;
ps - > jumppad_frame = ps - > pmove_framecount ;
// give the player the velocity from the jumppad
VectorCopy ( jumppad - > origin2 , ps - > velocity ) ;
}
/*
= = = = = = = = = = = = = = = = =
BG_EmplacedView
Shared code for emplaced angle gun constriction
= = = = = = = = = = = = = = = = =
*/
int BG_EmplacedView ( vec3_t baseAngles , vec3_t angles , float * newYaw , float constraint )
{
float dif = AngleSubtract ( baseAngles [ YAW ] , angles [ YAW ] ) ;
if ( dif > constraint | |
dif < - constraint )
{
float amt ;
if ( dif > constraint )
{
amt = ( dif - constraint ) ;
dif = constraint ;
}
else if ( dif < - constraint )
{
amt = ( dif + constraint ) ;
dif = - constraint ;
}
else
{
amt = 0.0f ;
}
* newYaw = AngleSubtract ( angles [ YAW ] , - dif ) ;
if ( amt > 1.0f | | amt < - 1.0f )
{ //significant, force the view
return 2 ;
}
else
{ //just a little out of range
return 1 ;
}
}
return 0 ;
}
//To see if the client is trying to use one of the included skins not meant for MP.
//I don't much care for hardcoded strings, but this seems the best way to go.
qboolean BG_IsValidCharacterModel ( const char * modelName , const char * skinName )
{
if ( ! Q_stricmp ( skinName , " menu " ) )
{
return qfalse ;
}
else if ( ! Q_stricmp ( modelName , " kyle " ) )
{
if ( ! Q_stricmp ( skinName , " fpls " ) )
{
return qfalse ;
}
else if ( ! Q_stricmp ( skinName , " fpls2 " ) )
{
return qfalse ;
}
else if ( ! Q_stricmp ( skinName , " fpls3 " ) )
{
return qfalse ;
}
}
return qtrue ;
}
qboolean BG_ValidateSkinForTeam ( const char * modelName , char * skinName , int team , float * colors )
{
if ( ! Q_stricmpn ( modelName , " jedi_ " , 5 ) )
{ //argh, it's a custom player skin!
if ( team = = TEAM_RED & & colors )
{
colors [ 0 ] = 1.0f ;
colors [ 1 ] = 0.0f ;
colors [ 2 ] = 0.0f ;
}
else if ( team = = TEAM_BLUE & & colors )
{
colors [ 0 ] = 0.0f ;
colors [ 1 ] = 0.0f ;
colors [ 2 ] = 1.0f ;
}
return qtrue ;
}
if ( team = = TEAM_RED )
{
if ( Q_stricmp ( " red " , skinName ) ! = 0 )
{ //not "red"
if ( Q_stricmp ( " blue " , skinName ) = = 0
| | Q_stricmp ( " default " , skinName ) = = 0
| | strchr ( skinName , ' | ' ) //a multi-skin playerModel
| | ! BG_IsValidCharacterModel ( modelName , skinName ) )
{
Q_strncpyz ( skinName , " red " , MAX_QPATH ) ;
return qfalse ;
}
else
{ //need to set it to red
int len = strlen ( skinName ) ;
if ( len < 3 )
{ //too short to be "red"
Q_strcat ( skinName , MAX_QPATH , " _red " ) ;
}
else
{
char * start = & skinName [ len - 3 ] ;
if ( Q_strncmp ( " red " , start , 3 ) ! = 0 )
{ //doesn't already end in "red"
if ( len + 4 > = MAX_QPATH )
{ //too big to append "_red"
Q_strncpyz ( skinName , " red " , MAX_QPATH ) ;
return qfalse ;
}
else
{
Q_strcat ( skinName , MAX_QPATH , " _red " ) ;
}
}
}
//if file does not exist, set to "red"
if ( ! BG_FileExists ( va ( " models/players/%s/model_%s.skin " , modelName , skinName ) ) )
{
Q_strncpyz ( skinName , " red " , MAX_QPATH ) ;
}
return qfalse ;
}
}
}
else if ( team = = TEAM_BLUE )
{
if ( Q_stricmp ( " blue " , skinName ) ! = 0 )
{
if ( Q_stricmp ( " red " , skinName ) = = 0
| | Q_stricmp ( " default " , skinName ) = = 0
| | strchr ( skinName , ' | ' ) //a multi-skin playerModel
| | ! BG_IsValidCharacterModel ( modelName , skinName ) )
{
Q_strncpyz ( skinName , " blue " , MAX_QPATH ) ;
return qfalse ;
}
else
{ //need to set it to blue
int len = strlen ( skinName ) ;
if ( len < 4 )
{ //too short to be "blue"
Q_strcat ( skinName , MAX_QPATH , " _blue " ) ;
}
else
{
char * start = & skinName [ len - 4 ] ;
if ( Q_strncmp ( " blue " , start , 4 ) ! = 0 )
{ //doesn't already end in "blue"
if ( len + 5 > = MAX_QPATH )
{ //too big to append "_blue"
Q_strncpyz ( skinName , " blue " , MAX_QPATH ) ;
return qfalse ;
}
else
{
Q_strcat ( skinName , MAX_QPATH , " _blue " ) ;
}
}
}
//if file does not exist, set to "blue"
if ( ! BG_FileExists ( va ( " models/players/%s/model_%s.skin " , modelName , skinName ) ) )
{
Q_strncpyz ( skinName , " blue " , MAX_QPATH ) ;
}
return qfalse ;
}
}
}
return qtrue ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
BG_PlayerStateToEntityState
This is done after each set of usercmd_t on the server ,
and after local prediction on the client
= = = = = = = = = = = = = = = = = = = = = = = =
*/
void BG_PlayerStateToEntityState ( playerState_t * ps , entityState_t * s , qboolean snap ) {
int i ;
if ( ps - > pm_type = = PM_INTERMISSION | | ps - > pm_type = = PM_SPECTATOR ) {
s - > eType = ET_INVISIBLE ;
} else if ( ps - > stats [ STAT_HEALTH ] < = GIB_HEALTH ) {
s - > eType = ET_INVISIBLE ;
} else {
s - > eType = ET_PLAYER ;
}
s - > number = ps - > clientNum ;
s - > pos . trType = TR_INTERPOLATE ;
VectorCopy ( ps - > origin , s - > pos . trBase ) ;
if ( snap ) {
SnapVector ( s - > pos . trBase ) ;
}
// set the trDelta for flag direction
VectorCopy ( ps - > velocity , s - > pos . trDelta ) ;
s - > apos . trType = TR_INTERPOLATE ;
VectorCopy ( ps - > viewangles , s - > apos . trBase ) ;
if ( snap ) {
SnapVector ( s - > apos . trBase ) ;
}
s - > trickedentindex = ps - > fd . forceMindtrickTargetIndex ;
s - > trickedentindex2 = ps - > fd . forceMindtrickTargetIndex2 ;
s - > trickedentindex3 = ps - > fd . forceMindtrickTargetIndex3 ;
s - > trickedentindex4 = ps - > fd . forceMindtrickTargetIndex4 ;
s - > forceFrame = ps - > saberLockFrame ;
s - > emplacedOwner = ps - > electrifyTime ;
s - > speed = ps - > speed ;
s - > genericenemyindex = ps - > genericEnemyIndex ;
s - > activeForcePass = ps - > activeForcePass ;
s - > angles2 [ YAW ] = ps - > movementDir ;
s - > legsAnim = ps - > legsAnim ;
s - > torsoAnim = ps - > torsoAnim ;
s - > legsFlip = ps - > legsFlip ;
s - > torsoFlip = ps - > torsoFlip ;
s - > clientNum = ps - > clientNum ; // ET_PLAYER looks here instead of at number
// so corpses can also reference the proper config
s - > eFlags = ps - > eFlags ;
s - > eFlags2 = ps - > eFlags2 ;
s - > saberInFlight = ps - > saberInFlight ;
s - > saberEntityNum = ps - > saberEntityNum ;
s - > saberMove = ps - > saberMove ;
s - > forcePowersActive = ps - > fd . forcePowersActive ;
if ( ps - > duelInProgress )
{
s - > bolt1 = 1 ;
}
else
{
s - > bolt1 = 0 ;
}
s - > otherEntityNum2 = ps - > emplacedIndex ;
s - > saberHolstered = ps - > saberHolstered ;
if ( ps - > genericEnemyIndex ! = - 1 )
{
s - > eFlags | = EF_SEEKERDRONE ;
}
if ( ps - > stats [ STAT_HEALTH ] < = 0 ) {
s - > eFlags | = EF_DEAD ;
} else {
s - > eFlags & = ~ EF_DEAD ;
}
if ( ps - > externalEvent ) {
s - > event = ps - > externalEvent ;
s - > eventParm = ps - > externalEventParm ;
} else if ( ps - > entityEventSequence < ps - > eventSequence ) {
int seq ;
if ( ps - > entityEventSequence < ps - > eventSequence - MAX_PS_EVENTS ) {
ps - > entityEventSequence = ps - > eventSequence - MAX_PS_EVENTS ;
}
seq = ps - > entityEventSequence & ( MAX_PS_EVENTS - 1 ) ;
s - > event = ps - > events [ seq ] | ( ( ps - > entityEventSequence & 3 ) < < 8 ) ;
s - > eventParm = ps - > eventParms [ seq ] ;
ps - > entityEventSequence + + ;
}
s - > weapon = ps - > weapon ;
s - > groundEntityNum = ps - > groundEntityNum ;
s - > powerups = 0 ;
for ( i = 0 ; i < MAX_POWERUPS ; i + + ) {
if ( ps - > powerups [ i ] ) {
s - > powerups | = 1 < < i ;
}
}
s - > loopSound = ps - > loopSound ;
s - > generic1 = ps - > generic1 ;
//NOT INCLUDED IN ENTITYSTATETOPLAYERSTATE:
s - > modelindex2 = ps - > weaponstate ;
s - > constantLight = ps - > weaponChargeTime ;
VectorCopy ( ps - > lastHitLoc , s - > origin2 ) ;
s - > isJediMaster = ps - > isJediMaster ;
s - > time2 = ps - > holocronBits ;
s - > fireflag = ps - > fd . saberAnimLevel ;
s - > heldByClient = ps - > heldByClient ;
s - > ragAttach = ps - > ragAttach ;
s - > iModelScale = ps - > iModelScale ;
s - > brokenLimbs = ps - > brokenLimbs ;
s - > hasLookTarget = ps - > hasLookTarget ;
s - > lookTarget = ps - > lookTarget ;
s - > customRGBA [ 0 ] = ps - > customRGBA [ 0 ] ;
s - > customRGBA [ 1 ] = ps - > customRGBA [ 1 ] ;
s - > customRGBA [ 2 ] = ps - > customRGBA [ 2 ] ;
s - > customRGBA [ 3 ] = ps - > customRGBA [ 3 ] ;
s - > m_iVehicleNum = ps - > m_iVehicleNum ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
BG_PlayerStateToEntityStateExtraPolate
This is done after each set of usercmd_t on the server ,
and after local prediction on the client
= = = = = = = = = = = = = = = = = = = = = = = =
*/
void BG_PlayerStateToEntityStateExtraPolate ( playerState_t * ps , entityState_t * s , int time , qboolean snap ) {
int i ;
if ( ps - > pm_type = = PM_INTERMISSION | | ps - > pm_type = = PM_SPECTATOR ) {
s - > eType = ET_INVISIBLE ;
} else if ( ps - > stats [ STAT_HEALTH ] < = GIB_HEALTH ) {
s - > eType = ET_INVISIBLE ;
} else {
s - > eType = ET_PLAYER ;
}
s - > number = ps - > clientNum ;
s - > pos . trType = TR_LINEAR_STOP ;
VectorCopy ( ps - > origin , s - > pos . trBase ) ;
if ( snap ) {
SnapVector ( s - > pos . trBase ) ;
}
// set the trDelta for flag direction and linear prediction
VectorCopy ( ps - > velocity , s - > pos . trDelta ) ;
// set the time for linear prediction
s - > pos . trTime = time ;
// set maximum extra polation time
s - > pos . trDuration = 50 ; // 1000 / sv_fps (default = 20)
s - > apos . trType = TR_INTERPOLATE ;
VectorCopy ( ps - > viewangles , s - > apos . trBase ) ;
if ( snap ) {
SnapVector ( s - > apos . trBase ) ;
}
s - > trickedentindex = ps - > fd . forceMindtrickTargetIndex ;
s - > trickedentindex2 = ps - > fd . forceMindtrickTargetIndex2 ;
s - > trickedentindex3 = ps - > fd . forceMindtrickTargetIndex3 ;
s - > trickedentindex4 = ps - > fd . forceMindtrickTargetIndex4 ;
s - > forceFrame = ps - > saberLockFrame ;
s - > emplacedOwner = ps - > electrifyTime ;
s - > speed = ps - > speed ;
s - > genericenemyindex = ps - > genericEnemyIndex ;
s - > activeForcePass = ps - > activeForcePass ;
s - > angles2 [ YAW ] = ps - > movementDir ;
s - > legsAnim = ps - > legsAnim ;
s - > torsoAnim = ps - > torsoAnim ;
s - > legsFlip = ps - > legsFlip ;
s - > torsoFlip = ps - > torsoFlip ;
s - > clientNum = ps - > clientNum ; // ET_PLAYER looks here instead of at number
// so corpses can also reference the proper config
s - > eFlags = ps - > eFlags ;
s - > eFlags2 = ps - > eFlags2 ;
s - > saberInFlight = ps - > saberInFlight ;
s - > saberEntityNum = ps - > saberEntityNum ;
s - > saberMove = ps - > saberMove ;
s - > forcePowersActive = ps - > fd . forcePowersActive ;
if ( ps - > duelInProgress )
{
s - > bolt1 = 1 ;
}
else
{
s - > bolt1 = 0 ;
}
s - > otherEntityNum2 = ps - > emplacedIndex ;
s - > saberHolstered = ps - > saberHolstered ;
if ( ps - > genericEnemyIndex ! = - 1 )
{
s - > eFlags | = EF_SEEKERDRONE ;
}
if ( ps - > stats [ STAT_HEALTH ] < = 0 ) {
s - > eFlags | = EF_DEAD ;
} else {
s - > eFlags & = ~ EF_DEAD ;
}
if ( ps - > externalEvent ) {
s - > event = ps - > externalEvent ;
s - > eventParm = ps - > externalEventParm ;
} else if ( ps - > entityEventSequence < ps - > eventSequence ) {
int seq ;
if ( ps - > entityEventSequence < ps - > eventSequence - MAX_PS_EVENTS ) {
ps - > entityEventSequence = ps - > eventSequence - MAX_PS_EVENTS ;
}
seq = ps - > entityEventSequence & ( MAX_PS_EVENTS - 1 ) ;
s - > event = ps - > events [ seq ] | ( ( ps - > entityEventSequence & 3 ) < < 8 ) ;
s - > eventParm = ps - > eventParms [ seq ] ;
ps - > entityEventSequence + + ;
}
s - > weapon = ps - > weapon ;
s - > groundEntityNum = ps - > groundEntityNum ;
s - > powerups = 0 ;
for ( i = 0 ; i < MAX_POWERUPS ; i + + ) {
if ( ps - > powerups [ i ] ) {
s - > powerups | = 1 < < i ;
}
}
s - > loopSound = ps - > loopSound ;
s - > generic1 = ps - > generic1 ;
//NOT INCLUDED IN ENTITYSTATETOPLAYERSTATE:
s - > modelindex2 = ps - > weaponstate ;
s - > constantLight = ps - > weaponChargeTime ;
VectorCopy ( ps - > lastHitLoc , s - > origin2 ) ;
s - > isJediMaster = ps - > isJediMaster ;
s - > time2 = ps - > holocronBits ;
s - > fireflag = ps - > fd . saberAnimLevel ;
s - > heldByClient = ps - > heldByClient ;
s - > ragAttach = ps - > ragAttach ;
s - > iModelScale = ps - > iModelScale ;
s - > brokenLimbs = ps - > brokenLimbs ;
s - > hasLookTarget = ps - > hasLookTarget ;
s - > lookTarget = ps - > lookTarget ;
s - > customRGBA [ 0 ] = ps - > customRGBA [ 0 ] ;
s - > customRGBA [ 1 ] = ps - > customRGBA [ 1 ] ;
s - > customRGBA [ 2 ] = ps - > customRGBA [ 2 ] ;
s - > customRGBA [ 3 ] = ps - > customRGBA [ 3 ] ;
s - > m_iVehicleNum = ps - > m_iVehicleNum ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
PLAYER ANGLES
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
//perform the appropriate model precache routine
# ifdef QAGAME //game
extern int trap_G2API_InitGhoul2Model ( void * * ghoul2Ptr , const char * fileName , int modelIndex , qhandle_t customSkin ,
qhandle_t customShader , int modelFlags , int lodBias ) ; //exists on game/cgame/ui, only used on game
extern void trap_G2API_CleanGhoul2Models ( void * * ghoul2Ptr ) ; //exists on game/cgame/ui, only used on game
# else //cgame/ui
extern qhandle_t trap_R_RegisterModel ( const char * name ) ; //exists on cgame/ui
# endif
//game/cgame/ui
extern qhandle_t trap_R_RegisterSkin ( const char * name ) ; //exists on game/cgame/ui
int BG_ModelCache ( const char * modelName , const char * skinName )
{
# ifdef QAGAME
void * g2 = NULL ;
if ( skinName & & skinName [ 0 ] )
{
trap_R_RegisterSkin ( skinName ) ;
}
//I could hook up a precache ghoul2 function, but oh well, this works
trap_G2API_InitGhoul2Model ( & g2 , modelName , 0 , 0 , 0 , 0 , 0 ) ;
if ( g2 )
{ //now get rid of it
trap_G2API_CleanGhoul2Models ( & g2 ) ;
}
return 0 ;
# else
if ( skinName & & skinName [ 0 ] )
{
trap_R_RegisterSkin ( skinName ) ;
}
return trap_R_RegisterModel ( modelName ) ;
# endif
}
# ifdef _XBOX // Hacky BG_Alloc replacement
// This file claims to be stateless. Yeah, right. Regardless, I'm not setting
// aside 5.5 MB of static buffers for this crap. Let's use Z_Malloc. Of course,
// we still need to deal with the fact that any code using BG_Malloc is almost
// certainly leaking memory like a sieve.
// Dave addendum - TAG_BG_ALLOC is entirely freed when the level starts.
void * BG_Alloc ( int size )
{
return Z_Malloc ( size , TAG_BG_ALLOC , qfalse , 4 ) ;
}
void * BG_AllocUnaligned ( int size )
{
// Ignore the unaligned hint, this function isn't called anyway
return Z_Malloc ( size , TAG_BG_ALLOC , qfalse , 4 ) ;
}
// Because the interface to BG_TempAlloc/BG_TempFree is brain-dead, we need
// to remember our last few temporary allocations performed.
# define MAX_TEMP_ALLOCS 3
static void * tempAllocPointers [ MAX_TEMP_ALLOCS ] = { 0 } ;
static int tempAllocSizes [ MAX_TEMP_ALLOCS ] = { 0 } ;
void * BG_TempAlloc ( int size )
{
int i ;
// Do we have a free spot?
for ( i = 0 ; i < MAX_TEMP_ALLOCS ; + + i )
if ( ! tempAllocPointers [ i ] )
break ;
if ( i = = MAX_TEMP_ALLOCS )
{
assert ( ! " No space for TempAlloc -> Increase MAX_TEMP_ALLOCS " ) ;
return NULL ;
}
tempAllocPointers [ i ] = Z_Malloc ( size , TAG_TEMP_WORKSPACE , qfalse , 4 ) ;
tempAllocSizes [ i ] = size ;
return tempAllocPointers [ i ] ;
}
void BG_TempFree ( int size )
{
int i ;
// Find the allocation
for ( i = MAX_TEMP_ALLOCS - 1 ; i > = 0 ; - - i )
if ( tempAllocPointers [ i ] & & ( tempAllocSizes [ i ] = = size ) )
break ;
if ( i < 0 )
{
assert ( ! " BG_TempFree doesn't match a call to BG_TempAlloc " ) ;
return ;
}
Z_Free ( tempAllocPointers [ i ] ) ;
tempAllocPointers [ i ] = 0 ;
tempAllocSizes [ i ] = 0 ;
return ;
}
char * BG_StringAlloc ( const char * source )
{
char * dest ;
dest = ( char * ) BG_Alloc ( strlen ( source ) + 1 ) ;
strcpy ( dest , source ) ;
return dest ;
}
qboolean BG_OutOfMemory ( void )
{
// Never called
return qfalse ;
}
# else // _XBOX
# ifdef QAGAME
# define MAX_POOL_SIZE 3000000 //1024000
# elif defined CGAME //don't need as much for cgame stuff. 2mb will be fine.
# define MAX_POOL_SIZE 2048000
# else //And for the ui the only thing we'll be using this for anyway is allocating anim data for g2 menu models
# define MAX_POOL_SIZE 512000
# endif
//I am using this for all the stuff like NPC client structures on server/client and
//non-humanoid animations as well until/if I can get dynamic memory working properly
//with casted datatypes, which is why it is so large.
static char bg_pool [ MAX_POOL_SIZE ] ;
static int bg_poolSize = 0 ;
static int bg_poolTail = MAX_POOL_SIZE ;
void * BG_Alloc ( int size )
{
bg_poolSize = ( ( bg_poolSize + 0x00000003 ) & 0xfffffffc ) ;
if ( bg_poolSize + size > bg_poolTail )
{
Com_Error ( ERR_DROP , " BG_Alloc: buffer exceeded tail (%d > %d) " , bg_poolSize + size , bg_poolTail ) ;
return 0 ;
}
bg_poolSize + = size ;
return & bg_pool [ bg_poolSize - size ] ;
}
void * BG_AllocUnaligned ( int size )
{
if ( bg_poolSize + size > bg_poolTail )
{
Com_Error ( ERR_DROP , " BG_AllocUnaligned: buffer exceeded tail (%d > %d) " , bg_poolSize + size , bg_poolTail ) ;
return 0 ;
}
bg_poolSize + = size ;
return & bg_pool [ bg_poolSize - size ] ;
}
void * BG_TempAlloc ( int size )
{
size = ( ( size + 0x00000003 ) & 0xfffffffc ) ;
if ( bg_poolTail - size < bg_poolSize )
{
Com_Error ( ERR_DROP , " BG_TempAlloc: buffer exceeded head (%d > %d) " , bg_poolTail - size , bg_poolSize ) ;
return 0 ;
}
bg_poolTail - = size ;
return & bg_pool [ bg_poolTail ] ;
}
void BG_TempFree ( int size )
{
size = ( ( size + 0x00000003 ) & 0xfffffffc ) ;
if ( bg_poolTail + size > MAX_POOL_SIZE )
{
Com_Error ( ERR_DROP , " BG_TempFree: tail greater than size (%d > %d) " , bg_poolTail + size , MAX_POOL_SIZE ) ;
}
bg_poolTail + = size ;
}
char * BG_StringAlloc ( const char * source )
{
char * dest ;
dest = BG_Alloc ( strlen ( source ) + 1 ) ;
strcpy ( dest , source ) ;
return dest ;
}
qboolean BG_OutOfMemory ( void )
{
return bg_poolSize > = MAX_POOL_SIZE ;
}
# endif // _XBOX && QAGAME
# include "../namespace_end.h"