jediacademy/codemp/game/bg_saberLoad.c

3012 lines
72 KiB
C

//bg_saberLoad.c
#include "q_shared.h"
#include "bg_public.h"
#include "bg_local.h"
#include "w_saber.h"
extern stringID_table_t animTable [MAX_ANIMATIONS+1];
//Could use strap stuff but I don't particularly care at the moment anyway.
#include "../namespace_begin.h"
extern int trap_FS_FOpenFile( const char *qpath, fileHandle_t *f, fsMode_t mode );
extern void trap_FS_Read( void *buffer, int len, fileHandle_t f );
extern void trap_FS_Write( const void *buffer, int len, fileHandle_t f );
extern void trap_FS_FCloseFile( fileHandle_t f );
extern int trap_FS_GetFileList( const char *path, const char *extension, char *listbuf, int bufsize );
extern qhandle_t trap_R_RegisterSkin( const char *name );
#include "../namespace_end.h"
#ifdef QAGAME
extern int G_SoundIndex( const char *name );
#elif defined CGAME
#include "../namespace_begin.h"
sfxHandle_t trap_S_RegisterSound( const char *sample);
qhandle_t trap_R_RegisterShader( const char *name ); // returns all white if not found
int trap_FX_RegisterEffect(const char *file);
#include "../namespace_end.h"
#endif
#include "../namespace_begin.h"
int BG_SoundIndex(char *sound)
{
#ifdef QAGAME
return G_SoundIndex(sound);
#elif defined CGAME
return trap_S_RegisterSound(sound);
#endif
}
extern stringID_table_t FPTable[];
#define MAX_SABER_DATA_SIZE 0x80000
static char SaberParms[MAX_SABER_DATA_SIZE];
stringID_table_t SaberTable[] =
{
ENUM2STRING(SABER_NONE),
ENUM2STRING(SABER_SINGLE),
ENUM2STRING(SABER_STAFF),
ENUM2STRING(SABER_BROAD),
ENUM2STRING(SABER_PRONG),
ENUM2STRING(SABER_DAGGER),
ENUM2STRING(SABER_ARC),
ENUM2STRING(SABER_SAI),
ENUM2STRING(SABER_CLAW),
ENUM2STRING(SABER_LANCE),
ENUM2STRING(SABER_STAR),
ENUM2STRING(SABER_TRIDENT),
"", -1
};
stringID_table_t SaberMoveTable[] =
{
ENUM2STRING(LS_NONE),
// Attacks
ENUM2STRING(LS_A_TL2BR),
ENUM2STRING(LS_A_L2R),
ENUM2STRING(LS_A_BL2TR),
ENUM2STRING(LS_A_BR2TL),
ENUM2STRING(LS_A_R2L),
ENUM2STRING(LS_A_TR2BL),
ENUM2STRING(LS_A_T2B),
ENUM2STRING(LS_A_BACKSTAB),
ENUM2STRING(LS_A_BACK),
ENUM2STRING(LS_A_BACK_CR),
ENUM2STRING(LS_ROLL_STAB),
ENUM2STRING(LS_A_LUNGE),
ENUM2STRING(LS_A_JUMP_T__B_),
ENUM2STRING(LS_A_FLIP_STAB),
ENUM2STRING(LS_A_FLIP_SLASH),
ENUM2STRING(LS_JUMPATTACK_DUAL),
ENUM2STRING(LS_JUMPATTACK_ARIAL_LEFT),
ENUM2STRING(LS_JUMPATTACK_ARIAL_RIGHT),
ENUM2STRING(LS_JUMPATTACK_CART_LEFT),
ENUM2STRING(LS_JUMPATTACK_CART_RIGHT),
ENUM2STRING(LS_JUMPATTACK_STAFF_LEFT),
ENUM2STRING(LS_JUMPATTACK_STAFF_RIGHT),
ENUM2STRING(LS_BUTTERFLY_LEFT),
ENUM2STRING(LS_BUTTERFLY_RIGHT),
ENUM2STRING(LS_A_BACKFLIP_ATK),
ENUM2STRING(LS_SPINATTACK_DUAL),
ENUM2STRING(LS_SPINATTACK),
ENUM2STRING(LS_LEAP_ATTACK),
ENUM2STRING(LS_SWOOP_ATTACK_RIGHT),
ENUM2STRING(LS_SWOOP_ATTACK_LEFT),
ENUM2STRING(LS_TAUNTAUN_ATTACK_RIGHT),
ENUM2STRING(LS_TAUNTAUN_ATTACK_LEFT),
ENUM2STRING(LS_KICK_F),
ENUM2STRING(LS_KICK_B),
ENUM2STRING(LS_KICK_R),
ENUM2STRING(LS_KICK_L),
ENUM2STRING(LS_KICK_S),
ENUM2STRING(LS_KICK_BF),
ENUM2STRING(LS_KICK_RL),
ENUM2STRING(LS_KICK_F_AIR),
ENUM2STRING(LS_KICK_B_AIR),
ENUM2STRING(LS_KICK_R_AIR),
ENUM2STRING(LS_KICK_L_AIR),
ENUM2STRING(LS_STABDOWN),
ENUM2STRING(LS_STABDOWN_STAFF),
ENUM2STRING(LS_STABDOWN_DUAL),
ENUM2STRING(LS_DUAL_SPIN_PROTECT),
ENUM2STRING(LS_STAFF_SOULCAL),
ENUM2STRING(LS_A1_SPECIAL),
ENUM2STRING(LS_A2_SPECIAL),
ENUM2STRING(LS_A3_SPECIAL),
ENUM2STRING(LS_UPSIDE_DOWN_ATTACK),
ENUM2STRING(LS_PULL_ATTACK_STAB),
ENUM2STRING(LS_PULL_ATTACK_SWING),
ENUM2STRING(LS_SPINATTACK_ALORA),
ENUM2STRING(LS_DUAL_FB),
ENUM2STRING(LS_DUAL_LR),
ENUM2STRING(LS_HILT_BASH),
"", -1
};
//Also used in npc code
qboolean BG_ParseLiteral( const char **data, const char *string )
{
const char *token;
token = COM_ParseExt( data, qtrue );
if ( token[0] == 0 )
{
Com_Printf( "unexpected EOF\n" );
return qtrue;
}
if ( Q_stricmp( token, string ) )
{
Com_Printf( "required string '%s' missing\n", string );
return qtrue;
}
return qfalse;
}
saber_colors_t TranslateSaberColor( const char *name )
{
if ( !Q_stricmp( name, "red" ) )
{
return SABER_RED;
}
if ( !Q_stricmp( name, "orange" ) )
{
return SABER_ORANGE;
}
if ( !Q_stricmp( name, "yellow" ) )
{
return SABER_YELLOW;
}
if ( !Q_stricmp( name, "green" ) )
{
return SABER_GREEN;
}
if ( !Q_stricmp( name, "blue" ) )
{
return SABER_BLUE;
}
if ( !Q_stricmp( name, "purple" ) )
{
return SABER_PURPLE;
}
if ( !Q_stricmp( name, "random" ) )
{
return ((saber_colors_t)(Q_irand( SABER_ORANGE, SABER_PURPLE )));
}
return SABER_BLUE;
}
saber_styles_t TranslateSaberStyle( const char *name )
{
if ( !Q_stricmp( name, "fast" ) )
{
return SS_FAST;
}
if ( !Q_stricmp( name, "medium" ) )
{
return SS_MEDIUM;
}
if ( !Q_stricmp( name, "strong" ) )
{
return SS_STRONG;
}
if ( !Q_stricmp( name, "desann" ) )
{
return SS_DESANN;
}
if ( !Q_stricmp( name, "tavion" ) )
{
return SS_TAVION;
}
if ( !Q_stricmp( name, "dual" ) )
{
return SS_DUAL;
}
if ( !Q_stricmp( name, "staff" ) )
{
return SS_STAFF;
}
return SS_NONE;
}
qboolean WP_SaberBladeUseSecondBladeStyle( saberInfo_t *saber, int bladeNum )
{
if ( saber )
{
if ( saber->bladeStyle2Start > 0 )
{
if ( bladeNum >= saber->bladeStyle2Start )
{
return qtrue;
}
}
}
return qfalse;
}
qboolean WP_SaberBladeDoTransitionDamage( saberInfo_t *saber, int bladeNum )
{
if ( !WP_SaberBladeUseSecondBladeStyle( saber, bladeNum )
&& (saber->saberFlags2&SFL2_TRANSITION_DAMAGE) )
{//use first blade style for this blade
return qtrue;
}
else if ( WP_SaberBladeUseSecondBladeStyle( saber, bladeNum )
&& (saber->saberFlags2&SFL2_TRANSITION_DAMAGE2) )
{//use second blade style for this blade
return qtrue;
}
return qfalse;
}
qboolean WP_UseFirstValidSaberStyle( saberInfo_t *saber1, saberInfo_t *saber2, int saberHolstered, int *saberAnimLevel )
{
qboolean styleInvalid = qfalse;
qboolean saber1Active;
qboolean saber2Active;
qboolean dualSabers = qfalse;
int validStyles = 0, styleNum;
if ( saber2 && saber2->model && saber2->model[0] )
{
dualSabers = qtrue;
}
if ( dualSabers )
{//dual
if ( saberHolstered > 1 )
{
saber1Active = saber2Active = qfalse;
}
else if ( saberHolstered > 0 )
{
saber1Active = qtrue;
saber2Active = qfalse;
}
else
{
saber1Active = saber2Active = qtrue;
}
}
else
{
saber2Active = qfalse;
if ( !saber1
|| !saber1->model
|| !saber1->model[0] )
{
saber1Active = qfalse;
}
else if ( saber1->numBlades > 1 )
{//staff
if ( saberHolstered > 1 )
{
saber1Active = qfalse;
}
else
{
saber1Active = qtrue;
}
}
else
{//single
if ( saberHolstered )
{
saber1Active = qfalse;
}
else
{
saber1Active = qtrue;
}
}
}
//initially, all styles are valid
for ( styleNum = SS_NONE+1; styleNum < SS_NUM_SABER_STYLES; styleNum++ )
{
validStyles |= (1<<styleNum);
}
if ( saber1Active
&& saber1
&& saber1->model
&& saber1->model[0]
&& saber1->stylesForbidden )
{
if ( (saber1->stylesForbidden&(1<<*saberAnimLevel)) )
{//not a valid style for first saber!
styleInvalid = qtrue;
validStyles &= ~saber1->stylesForbidden;
}
}
if ( dualSabers )
{//check second saber, too
if ( saber2Active
&& saber2->stylesForbidden )
{
if ( (saber2->stylesForbidden&(1<<*saberAnimLevel)) )
{//not a valid style for second saber!
styleInvalid = qtrue;
//only the ones both sabers allow is valid
validStyles &= ~saber2->stylesForbidden;
}
}
}
if ( styleInvalid && validStyles )
{//using an invalid style and have at least one valid style to use, so switch to it
int styleNum;
for ( styleNum = SS_FAST; styleNum < SS_NUM_SABER_STYLES; styleNum++ )
{
if ( (validStyles&(1<<styleNum)) )
{
*saberAnimLevel = styleNum;
return qtrue;
}
}
}
return qfalse;
}
qboolean WP_SaberStyleValidForSaber( saberInfo_t *saber1, saberInfo_t *saber2, int saberHolstered, int saberAnimLevel )
{
qboolean saber1Active;
qboolean saber2Active;
qboolean dualSabers = qfalse;
if ( saber2 && saber2->model && saber2->model[0] )
{
dualSabers = qtrue;
}
if ( dualSabers )
{//dual
if ( saberHolstered > 1 )
{
saber1Active = saber2Active = qfalse;
}
else if ( saberHolstered > 0 )
{
saber1Active = qtrue;
saber2Active = qfalse;
}
else
{
saber1Active = saber2Active = qtrue;
}
}
else
{
saber2Active = qfalse;
if ( !saber1
|| !saber1->model
|| !saber1->model[0] )
{
saber1Active = qfalse;
}
else if ( saber1->numBlades > 1 )
{//staff
if ( saberHolstered > 1 )
{
saber1Active = qfalse;
}
else
{
saber1Active = qtrue;
}
}
else
{//single
if ( saberHolstered )
{
saber1Active = qfalse;
}
else
{
saber1Active = qtrue;
}
}
}
if ( saber1Active
&& saber1
&& saber1->model
&& saber1->model[0]
&& saber1->stylesForbidden )
{
if ( (saber1->stylesForbidden&(1<<saberAnimLevel)) )
{//not a valid style for first saber!
return qfalse;
}
}
if ( dualSabers
&& saber2Active
&& saber2
&& saber2->model
&& saber2->model[0] )
{
if ( saber2->stylesForbidden )
{//check second saber, too
if ( (saber2->stylesForbidden&(1<<saberAnimLevel)) )
{//not a valid style for second saber!
return qfalse;
}
}
//now: if using dual sabers, only dual and tavion (if given with this saber) are allowed
if ( saberAnimLevel != SS_DUAL )
{//dual is okay
if ( saberAnimLevel != SS_TAVION )
{//tavion might be okay, all others are not
return qfalse;
}
else
{//see if "tavion" style is okay
if ( saber1Active
&& saber1
&& saber1->model
&& saber1->model[0]
&& (saber1->stylesLearned&(1<<SS_TAVION)) )
{//okay to use tavion style, first saber gave it to us
}
else if ( (saber2->stylesLearned&(1<<SS_TAVION)) )
{//okay to use tavion style, second saber gave it to us
}
else
{//tavion style is not allowed because neither of the sabers we're using gave it to us (I know, doesn't quite make sense, but...)
return qfalse;
}
}
}
}
return qtrue;
}
qboolean WP_SaberCanTurnOffSomeBlades( saberInfo_t *saber )
{
if ( saber->bladeStyle2Start > 0
&& saber->numBlades > saber->bladeStyle2Start )
{
if ( (saber->saberFlags2&SFL2_NO_MANUAL_DEACTIVATE)
&& (saber->saberFlags2&SFL2_NO_MANUAL_DEACTIVATE2) )
{//all blades are always on
return qfalse;
}
}
else
{
if ( (saber->saberFlags2&SFL2_NO_MANUAL_DEACTIVATE) )
{//all blades are always on
return qfalse;
}
}
//you can turn some off
return qtrue;
}
void WP_SaberSetDefaults( saberInfo_t *saber )
{
int i;
//Set defaults so that, if it fails, there's at least something there
for ( i = 0; i < MAX_BLADES; i++ )
{
saber->blade[i].color = SABER_RED;
saber->blade[i].radius = SABER_RADIUS_STANDARD;
saber->blade[i].lengthMax = 32;
}
strcpy(saber->name, "default");
strcpy(saber->fullName, "lightsaber");
strcpy(saber->model, "models/weapons2/saber_reborn/saber_w.glm");
saber->skin = 0;
saber->soundOn = BG_SoundIndex( "sound/weapons/saber/enemy_saber_on.wav" );
saber->soundLoop = BG_SoundIndex( "sound/weapons/saber/saberhum3.wav" );
saber->soundOff = BG_SoundIndex( "sound/weapons/saber/enemy_saber_off.wav" );
saber->numBlades = 1;
saber->type = SABER_SINGLE;
saber->stylesLearned = 0;
saber->stylesForbidden = 0;//allow all styles
saber->maxChain = 0;//0 = use default behavior
saber->forceRestrictions = 0;
saber->lockBonus = 0;
saber->parryBonus = 0;
saber->breakParryBonus = 0;
saber->breakParryBonus2 = 0;
saber->disarmBonus = 0;
saber->disarmBonus2 = 0;
saber->singleBladeStyle = SS_NONE;//makes it so that you use a different style if you only have the first blade active
// saber->brokenSaber1 = NULL;//if saber is actually hit by another saber, it can be cut in half/broken and will be replaced with this saber in your right hand
// saber->brokenSaber2 = NULL;//if saber is actually hit by another saber, it can be cut in half/broken and will be replaced with this saber in your left hand
//===NEW========================================================================================
//done in cgame (client-side code)
saber->saberFlags = 0; //see all the SFL_ flags
saber->saberFlags2 = 0; //see all the SFL2_ flags
saber->spinSound = 0; //none - if set, plays this sound as it spins when thrown
saber->swingSound[0] = 0; //none - if set, plays one of these 3 sounds when swung during an attack - NOTE: must provide all 3!!!
saber->swingSound[1] = 0; //none - if set, plays one of these 3 sounds when swung during an attack - NOTE: must provide all 3!!!
saber->swingSound[2] = 0; //none - if set, plays one of these 3 sounds when swung during an attack - NOTE: must provide all 3!!!
//done in game (server-side code)
saber->moveSpeedScale = 1.0f; //1.0 - you move faster/slower when using this saber
saber->animSpeedScale = 1.0f; //1.0 - plays normal attack animations faster/slower
saber->kataMove = LS_INVALID; //LS_INVALID - if set, player will execute this move when they press both attack buttons at the same time
saber->lungeAtkMove = LS_INVALID; //LS_INVALID - if set, player will execute this move when they crouch+fwd+attack
saber->jumpAtkUpMove = LS_INVALID; //LS_INVALID - if set, player will execute this move when they jump+attack
saber->jumpAtkFwdMove = LS_INVALID; //LS_INVALID - if set, player will execute this move when they jump+fwd+attack
saber->jumpAtkBackMove = LS_INVALID; //LS_INVALID - if set, player will execute this move when they jump+back+attack
saber->jumpAtkRightMove = LS_INVALID; //LS_INVALID - if set, player will execute this move when they jump+rightattack
saber->jumpAtkLeftMove = LS_INVALID; //LS_INVALID - if set, player will execute this move when they jump+left+attack
saber->readyAnim = -1; //-1 - anim to use when standing idle
saber->drawAnim = -1; //-1 - anim to use when drawing weapon
saber->putawayAnim = -1; //-1 - anim to use when putting weapon away
saber->tauntAnim = -1; //-1 - anim to use when hit "taunt"
saber->bowAnim = -1; //-1 - anim to use when hit "bow"
saber->meditateAnim = -1; //-1 - anim to use when hit "meditate"
saber->flourishAnim = -1; //-1 - anim to use when hit "flourish"
saber->gloatAnim = -1; //-1 - anim to use when hit "gloat"
//***NOTE: you can only have a maximum of 2 "styles" of blades, so this next value, "bladeStyle2Start" is the number of the first blade to use these value on... all blades before this use the normal values above, all blades at and after this number use the secondary values below***
saber->bladeStyle2Start = 0; //0 - if set, blades from this number and higher use the following values (otherwise, they use the normal values already set)
//***The following can be different for the extra blades - not setting them individually defaults them to the value for the whole saber (and first blade)***
//===PRIMARY BLADES=====================
//done in cgame (client-side code)
saber->trailStyle = 0; //0 - default (0) is normal, 1 is a motion blur and 2 is no trail at all (good for real-sword type mods)
saber->g2MarksShader = 0; //none - if set, the game will use this shader for marks on enemies instead of the default "gfx/damage/saberglowmark"
saber->g2WeaponMarkShader = 0; //none - if set, the game will use this shader for marks on enemies instead of the default "gfx/damage/saberglowmark"
//saber->bladeShader = 0; //none - if set, overrides the shader used for the saber blade?
//saber->trailShader = 0; //none - if set, overrides the shader used for the saber trail?
saber->hitSound[0] = 0; //none - if set, plays one of these 3 sounds when saber hits a person - NOTE: must provide all 3!!!
saber->hitSound[1] = 0; //none - if set, plays one of these 3 sounds when saber hits a person - NOTE: must provide all 3!!!
saber->hitSound[2] = 0; //none - if set, plays one of these 3 sounds when saber hits a person - NOTE: must provide all 3!!!
saber->blockSound[0] = 0; //none - if set, plays one of these 3 sounds when saber/sword hits another saber/sword - NOTE: must provide all 3!!!
saber->blockSound[1] = 0; //none - if set, plays one of these 3 sounds when saber/sword hits another saber/sword - NOTE: must provide all 3!!!
saber->blockSound[2] = 0; //none - if set, plays one of these 3 sounds when saber/sword hits another saber/sword - NOTE: must provide all 3!!!
saber->bounceSound[0] = 0; //none - if set, plays one of these 3 sounds when saber/sword hits a wall and bounces off (must set bounceOnWall to 1 to use these sounds) - NOTE: must provide all 3!!!
saber->bounceSound[1] = 0; //none - if set, plays one of these 3 sounds when saber/sword hits a wall and bounces off (must set bounceOnWall to 1 to use these sounds) - NOTE: must provide all 3!!!
saber->bounceSound[2] = 0; //none - if set, plays one of these 3 sounds when saber/sword hits a wall and bounces off (must set bounceOnWall to 1 to use these sounds) - NOTE: must provide all 3!!!
saber->blockEffect = 0; //none - if set, plays this effect when the saber/sword hits another saber/sword (instead of "saber/saber_block.efx")
saber->hitPersonEffect = 0; //none - if set, plays this effect when the saber/sword hits a person (instead of "saber/blood_sparks_mp.efx")
saber->hitOtherEffect = 0; //none - if set, plays this effect when the saber/sword hits something else damagable (instead of "saber/saber_cut.efx")
saber->bladeEffect = 0; //none - if set, plays this effect at the blade tag
//done in game (server-side code)
saber->knockbackScale = 0; //0 - if non-zero, uses damage done to calculate an appropriate amount of knockback
saber->damageScale = 1.0f; //1 - scale up or down the damage done by the saber
saber->splashRadius = 0.0f; //0 - radius of splashDamage
saber->splashDamage = 0; //0 - amount of splashDamage, 100% at a distance of 0, 0% at a distance = splashRadius
saber->splashKnockback = 0.0f; //0 - amount of splashKnockback, 100% at a distance of 0, 0% at a distance = splashRadius
//===SECONDARY BLADES===================
//done in cgame (client-side code)
saber->trailStyle2 = 0; //0 - default (0) is normal, 1 is a motion blur and 2 is no trail at all (good for real-sword type mods)
saber->g2MarksShader2 = 0; //none - if set, the game will use this shader for marks on enemies instead of the default "gfx/damage/saberglowmark"
saber->g2WeaponMarkShader2 = 0; //none - if set, the game will use this shader for marks on enemies instead of the default "gfx/damage/saberglowmark"
//saber->bladeShader = 0; //none - if set, overrides the shader used for the saber blade?
//saber->trailShader = 0; //none - if set, overrides the shader used for the saber trail?
saber->hit2Sound[0] = 0; //none - if set, plays one of these 3 sounds when saber hits a person - NOTE: must provide all 3!!!
saber->hit2Sound[1] = 0; //none - if set, plays one of these 3 sounds when saber hits a person - NOTE: must provide all 3!!!
saber->hit2Sound[2] = 0; //none - if set, plays one of these 3 sounds when saber hits a person - NOTE: must provide all 3!!!
saber->block2Sound[0] = 0; //none - if set, plays one of these 3 sounds when saber/sword hits another saber/sword - NOTE: must provide all 3!!!
saber->block2Sound[1] = 0; //none - if set, plays one of these 3 sounds when saber/sword hits another saber/sword - NOTE: must provide all 3!!!
saber->block2Sound[2] = 0; //none - if set, plays one of these 3 sounds when saber/sword hits another saber/sword - NOTE: must provide all 3!!!
saber->bounce2Sound[0] = 0; //none - if set, plays one of these 3 sounds when saber/sword hits a wall and bounces off (must set bounceOnWall to 1 to use these sounds) - NOTE: must provide all 3!!!
saber->bounce2Sound[1] = 0; //none - if set, plays one of these 3 sounds when saber/sword hits a wall and bounces off (must set bounceOnWall to 1 to use these sounds) - NOTE: must provide all 3!!!
saber->bounce2Sound[2] = 0; //none - if set, plays one of these 3 sounds when saber/sword hits a wall and bounces off (must set bounceOnWall to 1 to use these sounds) - NOTE: must provide all 3!!!
saber->blockEffect2 = 0; //none - if set, plays this effect when the saber/sword hits another saber/sword (instead of "saber/saber_block.efx")
saber->hitPersonEffect2 = 0; //none - if set, plays this effect when the saber/sword hits a person (instead of "saber/blood_sparks_mp.efx")
saber->hitOtherEffect2 = 0; //none - if set, plays this effect when the saber/sword hits something else damagable (instead of "saber/saber_cut.efx")
saber->bladeEffect2 = 0; //none - if set, plays this effect at the blade tag
//done in game (server-side code)
saber->knockbackScale2 = 0; //0 - if non-zero, uses damage done to calculate an appropriate amount of knockback
saber->damageScale2 = 1.0f; //1 - scale up or down the damage done by the saber
saber->splashRadius2 = 0.0f; //0 - radius of splashDamage
saber->splashDamage2 = 0; //0 - amount of splashDamage, 100% at a distance of 0, 0% at a distance = splashRadius
saber->splashKnockback2 = 0.0f; //0 - amount of splashKnockback, 100% at a distance of 0, 0% at a distance = splashRadius
//=========================================================================================================================================
}
#define DEFAULT_SABER "Kyle"
qboolean WP_SaberParseParms( const char *SaberName, saberInfo_t *saber )
{
const char *token;
const char *value;
const char *p;
char useSaber[1024];
float f;
int n;
qboolean triedDefault = qfalse;
int saberMove = LS_INVALID;
int anim = -1;
if ( !saber )
{
return qfalse;
}
//Set defaults so that, if it fails, there's at least something there
WP_SaberSetDefaults( saber );
if ( !SaberName || !SaberName[0] )
{
strcpy(useSaber, DEFAULT_SABER); //default
triedDefault = qtrue;
}
else
{
strcpy(useSaber, SaberName);
}
//try to parse it out
p = SaberParms;
COM_BeginParseSession("saberinfo");
// look for the right saber
while ( p )
{
token = COM_ParseExt( &p, qtrue );
if ( token[0] == 0 )
{
if (!triedDefault)
{ //fall back to default and restart, should always be there
p = SaberParms;
COM_BeginParseSession("saberinfo");
strcpy(useSaber, DEFAULT_SABER);
triedDefault = qtrue;
}
else
{
return qfalse;
}
}
if ( !Q_stricmp( token, useSaber ) )
{
break;
}
SkipBracedSection( &p );
}
if ( !p )
{ //even the default saber isn't found?
return qfalse;
}
//got the name we're using for sure
strcpy(saber->name, useSaber);
if ( BG_ParseLiteral( &p, "{" ) )
{
return qfalse;
}
// parse the saber info block
while ( 1 )
{
token = COM_ParseExt( &p, qtrue );
if ( !token[0] )
{
Com_Printf( S_COLOR_RED"ERROR: unexpected EOF while parsing '%s'\n", useSaber );
return qfalse;
}
if ( !Q_stricmp( token, "}" ) )
{
break;
}
//saber fullName
if ( !Q_stricmp( token, "name" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
strcpy(saber->fullName, value);
continue;
}
//saber type
if ( !Q_stricmp( token, "saberType" ) )
{
int saberType;
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saberType = GetIDForString( SaberTable, value );
if ( saberType >= SABER_SINGLE && saberType <= NUM_SABERS )
{
saber->type = (saberType_t)saberType;
}
continue;
}
//saber hilt
if ( !Q_stricmp( token, "saberModel" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
strcpy(saber->model, value);
continue;
}
if ( !Q_stricmp( token, "customSkin" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->skin = trap_R_RegisterSkin(value);
continue;
}
//on sound
if ( !Q_stricmp( token, "soundOn" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->soundOn = BG_SoundIndex( (char *)value );
continue;
}
//loop sound
if ( !Q_stricmp( token, "soundLoop" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->soundLoop = BG_SoundIndex( (char *)value );
continue;
}
//off sound
if ( !Q_stricmp( token, "soundOff" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->soundOff = BG_SoundIndex( (char *)value );
continue;
}
if ( !Q_stricmp( token, "numBlades" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n < 1 || n > MAX_BLADES )
{
Com_Error(ERR_DROP, "WP_SaberParseParms: saber %s has illegal number of blades (%d) max: %d", useSaber, n, MAX_BLADES );
continue;
}
saber->numBlades = n;
continue;
}
// saberColor
if ( !Q_stricmpn( token, "saberColor", 10 ) )
{
if (strlen(token)==10)
{
n = -1;
}
else if (strlen(token)==11)
{
n = atoi(&token[10])-1;
if (n > 7 || n < 1 )
{
Com_Printf( S_COLOR_YELLOW"WARNING: bad saberColor '%s' in %s\n", token, useSaber );
continue;
}
}
else
{
Com_Printf( S_COLOR_YELLOW"WARNING: bad saberColor '%s' in %s\n", token, useSaber );
continue;
}
if ( COM_ParseString( &p, &value ) ) //read the color
{
continue;
}
if (n==-1)
{//NOTE: this fills in the rest of the blades with the same color by default
saber_colors_t color = TranslateSaberColor( value );
for ( n = 0; n < MAX_BLADES; n++ )
{
saber->blade[n].color = color;
}
} else
{
saber->blade[n].color = TranslateSaberColor( value );
}
continue;
}
//saber length
if ( !Q_stricmpn( token, "saberLength", 11 ) )
{
if (strlen(token)==11)
{
n = -1;
}
else if (strlen(token)==12)
{
n = atoi(&token[11])-1;
if (n > 7 || n < 1 )
{
Com_Printf( S_COLOR_YELLOW"WARNING: bad saberLength '%s' in %s\n", token, useSaber );
continue;
}
}
else
{
Com_Printf( S_COLOR_YELLOW"WARNING: bad saberLength '%s' in %s\n", token, useSaber );
continue;
}
if ( COM_ParseFloat( &p, &f ) )
{
SkipRestOfLine( &p );
continue;
}
//cap
if ( f < 4.0f )
{
f = 4.0f;
}
if (n==-1)
{//NOTE: this fills in the rest of the blades with the same length by default
for ( n = 0; n < MAX_BLADES; n++ )
{
saber->blade[n].lengthMax = f;
}
}
else
{
saber->blade[n].lengthMax = f;
}
continue;
}
//blade radius
if ( !Q_stricmpn( token, "saberRadius", 11 ) )
{
if (strlen(token)==11)
{
n = -1;
}
else if (strlen(token)==12)
{
n = atoi(&token[11])-1;
if (n > 7 || n < 1 )
{
Com_Printf( S_COLOR_YELLOW"WARNING: bad saberRadius '%s' in %s\n", token, useSaber );
continue;
}
}
else
{
Com_Printf( S_COLOR_YELLOW"WARNING: bad saberRadius '%s' in %s\n", token, useSaber );
continue;
}
if ( COM_ParseFloat( &p, &f ) )
{
SkipRestOfLine( &p );
continue;
}
//cap
if ( f < 0.25f )
{
f = 0.25f;
}
if (n==-1)
{//NOTE: this fills in the rest of the blades with the same length by default
for ( n = 0; n < MAX_BLADES; n++ )
{
saber->blade[n].radius = f;
}
}
else
{
saber->blade[n].radius = f;
}
continue;
}
//locked saber style
if ( !Q_stricmp( token, "saberStyle" ) )
{
int style, styleNum;
if ( COM_ParseString( &p, &value ) )
{
continue;
}
//OLD WAY: only allowed ONE style
style = TranslateSaberStyle( value );
//learn only this style
saber->stylesLearned = (1<<style);
//forbid all other styles
saber->stylesForbidden = 0;
for ( styleNum = SS_NONE+1; styleNum < SS_NUM_SABER_STYLES; styleNum++ )
{
if ( styleNum != style )
{
saber->stylesForbidden |= (1<<styleNum);
}
}
continue;
}
//learned saber style
if ( !Q_stricmp( token, "saberStyleLearned" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->stylesLearned |= (1<<TranslateSaberStyle( value ));
continue;
}
//forbidden saber style
if ( !Q_stricmp( token, "saberStyleForbidden" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->stylesForbidden |= (1<<TranslateSaberStyle( value ));
continue;
}
//maxChain
if ( !Q_stricmp( token, "maxChain" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
saber->maxChain = n;
continue;
}
//lockable
if ( !Q_stricmp( token, "lockable" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n == 0 )
{
saber->saberFlags |= SFL_NOT_LOCKABLE;
}
continue;
}
//throwable
if ( !Q_stricmp( token, "throwable" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n == 0 )
{
saber->saberFlags |= SFL_NOT_THROWABLE;
}
continue;
}
//disarmable
if ( !Q_stricmp( token, "disarmable" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n == 0 )
{
saber->saberFlags |= SFL_NOT_DISARMABLE;
}
continue;
}
//active blocking
if ( !Q_stricmp( token, "blocking" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n == 0 )
{
saber->saberFlags |= SFL_NOT_ACTIVE_BLOCKING;
}
continue;
}
//twoHanded
if ( !Q_stricmp( token, "twoHanded" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_TWO_HANDED;
}
continue;
}
//force power restrictions
if ( !Q_stricmp( token, "forceRestrict" ) )
{
int fp;
if ( COM_ParseString( &p, &value ) )
{
continue;
}
fp = GetIDForString( FPTable, value );
if ( fp >= FP_FIRST && fp < NUM_FORCE_POWERS )
{
saber->forceRestrictions |= (1<<fp);
}
continue;
}
//lockBonus
if ( !Q_stricmp( token, "lockBonus" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
saber->lockBonus = n;
continue;
}
//parryBonus
if ( !Q_stricmp( token, "parryBonus" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
saber->parryBonus = n;
continue;
}
//breakParryBonus
if ( !Q_stricmp( token, "breakParryBonus" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
saber->breakParryBonus = n;
continue;
}
//breakParryBonus2
if ( !Q_stricmp( token, "breakParryBonus2" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
saber->breakParryBonus2 = n;
continue;
}
//disarmBonus
if ( !Q_stricmp( token, "disarmBonus" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
saber->disarmBonus = n;
continue;
}
//disarmBonus2
if ( !Q_stricmp( token, "disarmBonus2" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
saber->disarmBonus2 = n;
continue;
}
//single blade saber style
if ( !Q_stricmp( token, "singleBladeStyle" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->singleBladeStyle = TranslateSaberStyle( value );
continue;
}
//single blade throwable
if ( !Q_stricmp( token, "singleBladeThrowable" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_SINGLE_BLADE_THROWABLE;
}
continue;
}
//broken replacement saber1 (right hand)
if ( !Q_stricmp( token, "brokenSaber1" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
//saber->brokenSaber1 = G_NewString( value );
continue;
}
//broken replacement saber2 (left hand)
if ( !Q_stricmp( token, "brokenSaber2" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
//saber->brokenSaber2 = G_NewString( value );
continue;
}
//spins and does damage on return from saberthrow
if ( !Q_stricmp( token, "returnDamage" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_RETURN_DAMAGE;
}
continue;
}
//spin sound (when thrown)
if ( !Q_stricmp( token, "spinSound" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->spinSound = BG_SoundIndex( (char *)value );
continue;
}
//swing sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "swingSound1" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->swingSound[0] = BG_SoundIndex( (char *)value );
continue;
}
//swing sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "swingSound2" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->swingSound[1] = BG_SoundIndex( (char *)value );
continue;
}
//swing sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "swingSound3" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->swingSound[2] = BG_SoundIndex( (char *)value );
continue;
}
//you move faster/slower when using this saber
if ( !Q_stricmp( token, "moveSpeedScale" ) )
{
if ( COM_ParseFloat( &p, &f ) )
{
SkipRestOfLine( &p );
continue;
}
saber->moveSpeedScale = f;
continue;
}
//plays normal attack animations faster/slower
if ( !Q_stricmp( token, "animSpeedScale" ) )
{
if ( COM_ParseFloat( &p, &f ) )
{
SkipRestOfLine( &p );
continue;
}
saber->animSpeedScale = f;
continue;
}
//if non-zero, the saber will bounce back when it hits solid architecture (good for real-sword type mods)
if ( !Q_stricmp( token, "bounceOnWalls" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_BOUNCE_ON_WALLS;
}
continue;
}
//if set, saber model is bolted to wrist, not in hand... useful for things like claws & shields, etc.
if ( !Q_stricmp( token, "boltToWrist" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_BOLT_TO_WRIST;
}
continue;
}
//kata move
if ( !Q_stricmp( token, "kataMove" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saberMove = GetIDForString( SaberMoveTable, value );
if ( saberMove >= LS_INVALID && saberMove < LS_MOVE_MAX )
{
saber->kataMove = saberMove; //LS_INVALID - if set, player will execute this move when they press both attack buttons at the same time
}
continue;
}
//lungeAtkMove move
if ( !Q_stricmp( token, "lungeAtkMove" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saberMove = GetIDForString( SaberMoveTable, value );
if ( saberMove >= LS_INVALID && saberMove < LS_MOVE_MAX )
{
saber->lungeAtkMove = saberMove;
}
continue;
}
//jumpAtkUpMove move
if ( !Q_stricmp( token, "jumpAtkUpMove" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saberMove = GetIDForString( SaberMoveTable, value );
if ( saberMove >= LS_INVALID && saberMove < LS_MOVE_MAX )
{
saber->jumpAtkUpMove = saberMove;
}
continue;
}
//jumpAtkFwdMove move
if ( !Q_stricmp( token, "jumpAtkFwdMove" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saberMove = GetIDForString( SaberMoveTable, value );
if ( saberMove >= LS_INVALID && saberMove < LS_MOVE_MAX )
{
saber->jumpAtkFwdMove = saberMove;
}
continue;
}
//jumpAtkBackMove move
if ( !Q_stricmp( token, "jumpAtkBackMove" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saberMove = GetIDForString( SaberMoveTable, value );
if ( saberMove >= LS_INVALID && saberMove < LS_MOVE_MAX )
{
saber->jumpAtkBackMove = saberMove;
}
continue;
}
//jumpAtkRightMove move
if ( !Q_stricmp( token, "jumpAtkRightMove" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saberMove = GetIDForString( SaberMoveTable, value );
if ( saberMove >= LS_INVALID && saberMove < LS_MOVE_MAX )
{
saber->jumpAtkRightMove = saberMove;
}
continue;
}
//jumpAtkLeftMove move
if ( !Q_stricmp( token, "jumpAtkLeftMove" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saberMove = GetIDForString( SaberMoveTable, value );
if ( saberMove >= LS_INVALID && saberMove < LS_MOVE_MAX )
{
saber->jumpAtkLeftMove = saberMove;
}
continue;
}
//readyAnim
if ( !Q_stricmp( token, "readyAnim" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
anim = GetIDForString( animTable, value );
if ( anim >= 0 && anim < MAX_ANIMATIONS )
{
saber->readyAnim = anim;
}
continue;
}
//drawAnim
if ( !Q_stricmp( token, "drawAnim" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
anim = GetIDForString( animTable, value );
if ( anim >= 0 && anim < MAX_ANIMATIONS )
{
saber->drawAnim = anim;
}
continue;
}
//putawayAnim
if ( !Q_stricmp( token, "putawayAnim" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
anim = GetIDForString( animTable, value );
if ( anim >= 0 && anim < MAX_ANIMATIONS )
{
saber->putawayAnim = anim;
}
continue;
}
//tauntAnim
if ( !Q_stricmp( token, "tauntAnim" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
anim = GetIDForString( animTable, value );
if ( anim >= 0 && anim < MAX_ANIMATIONS )
{
saber->tauntAnim = anim;
}
continue;
}
//bowAnim
if ( !Q_stricmp( token, "bowAnim" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
anim = GetIDForString( animTable, value );
if ( anim >= 0 && anim < MAX_ANIMATIONS )
{
saber->bowAnim = anim;
}
continue;
}
//meditateAnim
if ( !Q_stricmp( token, "meditateAnim" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
anim = GetIDForString( animTable, value );
if ( anim >= 0 && anim < MAX_ANIMATIONS )
{
saber->meditateAnim = anim;
}
continue;
}
//flourishAnim
if ( !Q_stricmp( token, "flourishAnim" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
anim = GetIDForString( animTable, value );
if ( anim >= 0 && anim < MAX_ANIMATIONS )
{
saber->flourishAnim = anim;
}
continue;
}
//gloatAnim
if ( !Q_stricmp( token, "gloatAnim" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
anim = GetIDForString( animTable, value );
if ( anim >= 0 && anim < MAX_ANIMATIONS )
{
saber->gloatAnim = anim;
}
continue;
}
//if set, cannot do roll-stab move at end of roll
if ( !Q_stricmp( token, "noRollStab" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_NO_ROLL_STAB;
}
continue;
}
//if set, cannot do pull+attack move (move not available in MP anyway)
if ( !Q_stricmp( token, "noPullAttack" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_NO_PULL_ATTACK;
}
continue;
}
//if set, cannot do back-stab moves
if ( !Q_stricmp( token, "noBackAttack" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_NO_BACK_ATTACK;
}
continue;
}
//if set, cannot do stabdown move (when enemy is on ground)
if ( !Q_stricmp( token, "noStabDown" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_NO_STABDOWN;
}
continue;
}
//if set, cannot side-run or forward-run on walls
if ( !Q_stricmp( token, "noWallRuns" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_NO_WALL_RUNS;
}
continue;
}
//if set, cannot do backflip off wall or side-flips off walls
if ( !Q_stricmp( token, "noWallFlips" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_NO_WALL_FLIPS;
}
continue;
}
//if set, cannot grab wall & jump off
if ( !Q_stricmp( token, "noWallGrab" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_NO_WALL_GRAB;
}
continue;
}
//if set, cannot roll
if ( !Q_stricmp( token, "noRolls" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_NO_ROLLS;
}
continue;
}
//if set, cannot do flips
if ( !Q_stricmp( token, "noFlips" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_NO_FLIPS;
}
continue;
}
//if set, cannot do cartwheels
if ( !Q_stricmp( token, "noCartwheels" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_NO_CARTWHEELS;
}
continue;
}
//if set, cannot do kicks (can't do kicks anyway if using a throwable saber/sword)
if ( !Q_stricmp( token, "noKicks" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_NO_KICKS;
}
continue;
}
//if set, cannot do the simultaneous attack left/right moves (only available in Dual Lightsaber Combat Style)
if ( !Q_stricmp( token, "noMirrorAttacks" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags |= SFL_NO_MIRROR_ATTACKS;
}
continue;
}
//stays on in water
if ( !Q_stricmp( token, "onInWater" ) )
{//ignore in MP
SkipRestOfLine( &p );
continue;
}
if ( !Q_stricmp( token, "notInMP" ) )
{//ignore this
SkipRestOfLine( &p );
continue;
}
//===ABOVE THIS, ALL VALUES ARE GLOBAL TO THE SABER========================================================
//bladeStyle2Start - where to start using the second set of blade data
if ( !Q_stricmp( token, "bladeStyle2Start" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
saber->bladeStyle2Start = n;
continue;
}
//===BLADE-SPECIFIC FIELDS=================================================================================
//===PRIMARY BLADE====================================
//stops the saber from drawing marks on the world (good for real-sword type mods)
if ( !Q_stricmp( token, "noWallMarks" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_NO_WALL_MARKS;
}
continue;
}
//stops the saber from drawing a dynamic light (good for real-sword type mods)
if ( !Q_stricmp( token, "noDlight" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_NO_DLIGHT;
}
continue;
}
//stops the saber from drawing a blade (good for real-sword type mods)
if ( !Q_stricmp( token, "noBlade" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_NO_BLADE;
}
continue;
}
//default (0) is normal, 1 is a motion blur and 2 is no trail at all (good for real-sword type mods)
if ( !Q_stricmp( token, "trailStyle" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
saber->trailStyle = n;
continue;
}
//if set, the game will use this shader for marks on enemies instead of the default "gfx/damage/saberglowmark"
if ( !Q_stricmp( token, "g2MarksShader" ) )
{
if ( COM_ParseString( &p, &value ) )
{
SkipRestOfLine( &p );
continue;
}
#ifdef QAGAME//cgame-only cares about this
SkipRestOfLine(&p);
#elif defined CGAME
saber->g2MarksShader = trap_R_RegisterShader( value );
#else
SkipRestOfLine(&p);
#endif
continue;
}
//if set, the game will use this shader for marks on enemies instead of the default "gfx/damage/saberglowmark"
if ( !Q_stricmp( token, "g2WeaponMarkShader" ) )
{
if ( COM_ParseString( &p, &value ) )
{
SkipRestOfLine( &p );
continue;
}
#ifdef QAGAME//cgame-only cares about this
SkipRestOfLine(&p);
#elif defined CGAME
saber->g2WeaponMarkShader = trap_R_RegisterShader( value );
#else
SkipRestOfLine(&p);
#endif
continue;
}
//if non-zero, uses damage done to calculate an appropriate amount of knockback
if ( !Q_stricmp( token, "knockbackScale" ) )
{
if ( COM_ParseFloat( &p, &f ) )
{
SkipRestOfLine( &p );
continue;
}
saber->knockbackScale = f;
continue;
}
//scale up or down the damage done by the saber
if ( !Q_stricmp( token, "damageScale" ) )
{
if ( COM_ParseFloat( &p, &f ) )
{
SkipRestOfLine( &p );
continue;
}
saber->damageScale = f;
continue;
}
//if non-zero, the saber never does dismemberment (good for pointed/blunt melee weapons)
if ( !Q_stricmp( token, "noDismemberment" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_NO_DISMEMBERMENT;
}
continue;
}
//if non-zero, the saber will not do damage or any effects when it is idle (not in an attack anim). (good for real-sword type mods)
if ( !Q_stricmp( token, "noIdleEffect" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_NO_IDLE_EFFECT;
}
continue;
}
//if set, the blades will always be blocking (good for things like shields that should always block)
if ( !Q_stricmp( token, "alwaysBlock" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_ALWAYS_BLOCK;
}
continue;
}
//if set, the blades cannot manually be toggled on and off
if ( !Q_stricmp( token, "noManualDeactivate" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_NO_MANUAL_DEACTIVATE;
}
continue;
}
//if set, the blade does damage in start, transition and return anims (like strong style does)
if ( !Q_stricmp( token, "transitionDamage" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_TRANSITION_DAMAGE;
}
continue;
}
//splashRadius - radius of splashDamage
if ( !Q_stricmp( token, "splashRadius" ) )
{
if ( COM_ParseFloat( &p, &f ) )
{
SkipRestOfLine( &p );
continue;
}
saber->splashRadius = f;
continue;
}
//splashDamage - amount of splashDamage, 100% at a distance of 0, 0% at a distance = splashRadius
if ( !Q_stricmp( token, "splashDamage" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
saber->splashDamage = n;
continue;
}
//splashKnockback - amount of splashKnockback, 100% at a distance of 0, 0% at a distance = splashRadius
if ( !Q_stricmp( token, "splashKnockback" ) )
{
if ( COM_ParseFloat( &p, &f ) )
{
SkipRestOfLine( &p );
continue;
}
saber->splashKnockback = f;
continue;
}
//hit sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "hitSound1" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->hitSound[0] = BG_SoundIndex( (char *)value );
continue;
}
//hit sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "hitSound2" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->hitSound[1] = BG_SoundIndex( (char *)value );
continue;
}
//hit sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "hitSound3" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->hitSound[2] = BG_SoundIndex( (char *)value );
continue;
}
//block sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "blockSound1" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->blockSound[0] = BG_SoundIndex( (char *)value );
continue;
}
//block sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "blockSound2" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->blockSound[1] = BG_SoundIndex( (char *)value );
continue;
}
//block sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "blockSound3" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->blockSound[2] = BG_SoundIndex( (char *)value );
continue;
}
//bounce sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "bounceSound1" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->bounceSound[0] = BG_SoundIndex( (char *)value );
continue;
}
//bounce sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "bounceSound2" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->bounceSound[1] = BG_SoundIndex( (char *)value );
continue;
}
//bounce sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "bounceSound3" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->bounceSound[2] = BG_SoundIndex( (char *)value );
continue;
}
//block effect - when saber/sword hits another saber/sword
if ( !Q_stricmp( token, "blockEffect" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
#ifdef QAGAME//cgame-only cares about this
SkipRestOfLine(&p);
#elif defined CGAME
saber->blockEffect = trap_FX_RegisterEffect( (char *)value );
#else
SkipRestOfLine(&p);
#endif
continue;
}
//hit person effect - when saber/sword hits a person
if ( !Q_stricmp( token, "hitPersonEffect" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
#ifdef QAGAME//cgame-only cares about this
SkipRestOfLine(&p);
#elif defined CGAME
saber->hitPersonEffect = trap_FX_RegisterEffect( (char *)value );
#else
SkipRestOfLine(&p);
#endif
continue;
}
//hit other effect - when saber/sword hits sopmething else damagable
if ( !Q_stricmp( token, "hitOtherEffect" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
#ifdef QAGAME//cgame-only cares about this
SkipRestOfLine(&p);
#elif defined CGAME
saber->hitOtherEffect = trap_FX_RegisterEffect( (char *)value );
#else
SkipRestOfLine(&p);
#endif
continue;
}
//blade effect
if ( !Q_stricmp( token, "bladeEffect" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
#ifdef QAGAME//cgame-only cares about this
SkipRestOfLine(&p);
#elif defined CGAME
saber->bladeEffect = trap_FX_RegisterEffect( (char *)value );
#else
SkipRestOfLine(&p);
#endif
continue;
}
//if non-zero, the saber will not do the big, white clash flare with other sabers
if ( !Q_stricmp( token, "noClashFlare" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_NO_CLASH_FLARE;
}
continue;
}
//===SECONDARY BLADE====================================
//stops the saber from drawing marks on the world (good for real-sword type mods)
if ( !Q_stricmp( token, "noWallMarks2" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_NO_WALL_MARKS2;
}
continue;
}
//stops the saber from drawing a dynamic light (good for real-sword type mods)
if ( !Q_stricmp( token, "noDlight2" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_NO_DLIGHT2;
}
continue;
}
//stops the saber from drawing a blade (good for real-sword type mods)
if ( !Q_stricmp( token, "noBlade2" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_NO_BLADE2;
}
continue;
}
//default (0) is normal, 1 is a motion blur and 2 is no trail at all (good for real-sword type mods)
if ( !Q_stricmp( token, "trailStyle2" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
saber->trailStyle2 = n;
continue;
}
//if set, the game will use this shader for marks on enemies instead of the default "gfx/damage/saberglowmark"
if ( !Q_stricmp( token, "g2MarksShader2" ) )
{
if ( COM_ParseString( &p, &value ) )
{
SkipRestOfLine( &p );
continue;
}
#ifdef QAGAME//cgame-only cares about this
SkipRestOfLine(&p);
#elif defined CGAME
saber->g2MarksShader2 = trap_R_RegisterShader( value );
#else
SkipRestOfLine(&p);
#endif
continue;
}
//if set, the game will use this shader for marks on enemies instead of the default "gfx/damage/saberglowmark"
if ( !Q_stricmp( token, "g2WeaponMarkShader2" ) )
{
if ( COM_ParseString( &p, &value ) )
{
SkipRestOfLine( &p );
continue;
}
#ifdef QAGAME//cgame-only cares about this
SkipRestOfLine(&p);
#elif defined CGAME
saber->g2WeaponMarkShader2 = trap_R_RegisterShader( value );
#else
SkipRestOfLine(&p);
#endif
continue;
}
//if non-zero, uses damage done to calculate an appropriate amount of knockback
if ( !Q_stricmp( token, "knockbackScale2" ) )
{
if ( COM_ParseFloat( &p, &f ) )
{
SkipRestOfLine( &p );
continue;
}
saber->knockbackScale2 = f;
continue;
}
//scale up or down the damage done by the saber
if ( !Q_stricmp( token, "damageScale2" ) )
{
if ( COM_ParseFloat( &p, &f ) )
{
SkipRestOfLine( &p );
continue;
}
saber->damageScale2 = f;
continue;
}
//if non-zero, the saber never does dismemberment (good for pointed/blunt melee weapons)
if ( !Q_stricmp( token, "noDismemberment2" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_NO_DISMEMBERMENT2;
}
continue;
}
//if non-zero, the saber will not do damage or any effects when it is idle (not in an attack anim). (good for real-sword type mods)
if ( !Q_stricmp( token, "noIdleEffect2" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_NO_IDLE_EFFECT2;
}
continue;
}
//if set, the blades will always be blocking (good for things like shields that should always block)
if ( !Q_stricmp( token, "alwaysBlock2" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_ALWAYS_BLOCK2;
}
continue;
}
//if set, the blades cannot manually be toggled on and off
if ( !Q_stricmp( token, "noManualDeactivate2" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_NO_MANUAL_DEACTIVATE2;
}
continue;
}
//if set, the blade does damage in start, transition and return anims (like strong style does)
if ( !Q_stricmp( token, "transitionDamage2" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_TRANSITION_DAMAGE2;
}
continue;
}
//splashRadius - radius of splashDamage
if ( !Q_stricmp( token, "splashRadius2" ) )
{
if ( COM_ParseFloat( &p, &f ) )
{
SkipRestOfLine( &p );
continue;
}
saber->splashRadius2 = f;
continue;
}
//splashDamage - amount of splashDamage, 100% at a distance of 0, 0% at a distance = splashRadius
if ( !Q_stricmp( token, "splashDamage2" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
saber->splashDamage2 = n;
continue;
}
//splashKnockback - amount of splashKnockback, 100% at a distance of 0, 0% at a distance = splashRadius
if ( !Q_stricmp( token, "splashKnockback2" ) )
{
if ( COM_ParseFloat( &p, &f ) )
{
SkipRestOfLine( &p );
continue;
}
saber->splashKnockback2 = f;
continue;
}
//hit sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "hit2Sound1" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->hit2Sound[0] = BG_SoundIndex( (char *)value );
continue;
}
//hit sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "hit2Sound2" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->hit2Sound[1] = BG_SoundIndex( (char *)value );
continue;
}
//hit sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "hit2Sound3" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->hit2Sound[2] = BG_SoundIndex( (char *)value );
continue;
}
//block sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "block2Sound1" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->block2Sound[0] = BG_SoundIndex( (char *)value );
continue;
}
//block sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "block2Sound2" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->block2Sound[1] = BG_SoundIndex( (char *)value );
continue;
}
//block sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "block2Sound3" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->block2Sound[2] = BG_SoundIndex( (char *)value );
continue;
}
//bounce sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "bounce2Sound1" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->bounce2Sound[0] = BG_SoundIndex( (char *)value );
continue;
}
//bounce sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "bounce2Sound2" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->bounce2Sound[1] = BG_SoundIndex( (char *)value );
continue;
}
//bounce sound - NOTE: must provide all 3!!!
if ( !Q_stricmp( token, "bounce2Sound3" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
saber->bounce2Sound[2] = BG_SoundIndex( (char *)value );
continue;
}
//block effect - when saber/sword hits another saber/sword
if ( !Q_stricmp( token, "blockEffect2" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
#ifdef QAGAME//cgame-only cares about this
SkipRestOfLine(&p);
#elif defined CGAME
saber->blockEffect2 = trap_FX_RegisterEffect( (char *)value );
#else
SkipRestOfLine(&p);
#endif
continue;
}
//hit person effect - when saber/sword hits a person
if ( !Q_stricmp( token, "hitPersonEffect2" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
#ifdef QAGAME//cgame-only cares about this
SkipRestOfLine(&p);
#elif defined CGAME
saber->hitPersonEffect2 = trap_FX_RegisterEffect( (char *)value );
#else
SkipRestOfLine(&p);
#endif
continue;
}
//hit other effect - when saber/sword hits sopmething else damagable
if ( !Q_stricmp( token, "hitOtherEffect2" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
#ifdef QAGAME//cgame-only cares about this
SkipRestOfLine(&p);
#elif defined CGAME
saber->hitOtherEffect2 = trap_FX_RegisterEffect( (char *)value );
#else
SkipRestOfLine(&p);
#endif
continue;
}
//blade effect
if ( !Q_stricmp( token, "bladeEffect2" ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
#ifdef QAGAME//cgame-only cares about this
SkipRestOfLine(&p);
#elif defined CGAME
saber->bladeEffect2 = trap_FX_RegisterEffect( (char *)value );
#else
SkipRestOfLine(&p);
#endif
continue;
}
//if non-zero, the saber will not do the big, white clash flare with other sabers
if ( !Q_stricmp( token, "noClashFlare2" ) )
{
if ( COM_ParseInt( &p, &n ) )
{
SkipRestOfLine( &p );
continue;
}
if ( n )
{
saber->saberFlags2 |= SFL2_NO_CLASH_FLARE2;
}
continue;
}
//===END BLADE-SPECIFIC FIELDS=============================================================================
//FIXME: saber sounds (on, off, loop)
#ifdef _DEBUG
Com_Printf( "WARNING: unknown keyword '%s' while parsing '%s'\n", token, useSaber );
#endif
SkipRestOfLine( &p );
}
//FIXME: precache the saberModel(s)?
return qtrue;
}
qboolean WP_SaberParseParm( const char *saberName, const char *parmname, char *saberData )
{
const char *token;
const char *value;
const char *p;
if ( !saberName || !saberName[0] )
{
return qfalse;
}
//try to parse it out
p = SaberParms;
COM_BeginParseSession("saberinfo");
// look for the right saber
while ( p )
{
token = COM_ParseExt( &p, qtrue );
if ( token[0] == 0 )
{
return qfalse;
}
if ( !Q_stricmp( token, saberName ) )
{
break;
}
SkipBracedSection( &p );
}
if ( !p )
{
return qfalse;
}
if ( BG_ParseLiteral( &p, "{" ) )
{
return qfalse;
}
// parse the saber info block
while ( 1 )
{
token = COM_ParseExt( &p, qtrue );
if ( !token[0] )
{
Com_Printf( S_COLOR_RED"ERROR: unexpected EOF while parsing '%s'\n", saberName );
return qfalse;
}
if ( !Q_stricmp( token, "}" ) )
{
break;
}
if ( !Q_stricmp( token, parmname ) )
{
if ( COM_ParseString( &p, &value ) )
{
continue;
}
strcpy( saberData, value );
return qtrue;
}
SkipRestOfLine( &p );
continue;
}
return qfalse;
}
qboolean WP_SaberValidForPlayerInMP( const char *saberName )
{
char allowed [8]={0};
if ( !WP_SaberParseParm( saberName, "notInMP", allowed ) )
{//not defined, default is yes
return qtrue;
}
if ( !allowed[0] )
{//not defined, default is yes
return qtrue;
}
else
{//return value
return ((qboolean)(atoi(allowed)==0));
}
}
void WP_RemoveSaber( saberInfo_t *sabers, int saberNum )
{
if ( !sabers )
{
return;
}
//reset everything for this saber just in case
WP_SaberSetDefaults( &sabers[saberNum] );
strcpy(sabers[saberNum].name, "none");
sabers[saberNum].model[0] = 0;
//ent->client->ps.dualSabers = qfalse;
BG_SI_Deactivate(&sabers[saberNum]);
BG_SI_SetLength(&sabers[saberNum], 0.0f);
// if ( ent->weaponModel[saberNum] > 0 )
// {
// gi.G2API_RemoveGhoul2Model( ent->ghoul2, ent->weaponModel[saberNum] );
// ent->weaponModel[saberNum] = -1;
// }
// if ( saberNum == 1 )
// {
// ent->client->ps.dualSabers = qfalse;
// }
}
void WP_SetSaber( int entNum, saberInfo_t *sabers, int saberNum, const char *saberName )
{
if ( !sabers )
{
return;
}
if ( Q_stricmp( "none", saberName ) == 0 || Q_stricmp( "remove", saberName ) == 0 )
{
if (saberNum != 0)
{ //can't remove saber 0 ever
WP_RemoveSaber( sabers, saberNum );
}
return;
}
if ( entNum < MAX_CLIENTS &&
!WP_SaberValidForPlayerInMP( saberName ) )
{
WP_SaberParseParms( "Kyle", &sabers[saberNum] );//get saber info
}
else
{
WP_SaberParseParms( saberName, &sabers[saberNum] );//get saber info
}
if ((sabers[1].saberFlags&SFL_TWO_HANDED))
{//not allowed to use a 2-handed saber as second saber
WP_RemoveSaber( sabers, 1 );
return;
}
else if ((sabers[0].saberFlags&SFL_TWO_HANDED) &&
sabers[1].model[0])
{ //you can't use a two-handed saber with a second saber, so remove saber 2
WP_RemoveSaber( sabers, 1 );
return;
}
}
void WP_SaberSetColor( saberInfo_t *sabers, int saberNum, int bladeNum, char *colorName )
{
if ( !sabers )
{
return;
}
sabers[saberNum].blade[bladeNum].color = TranslateSaberColor( colorName );
}
static char bgSaberParseTBuffer[MAX_SABER_DATA_SIZE];
void WP_SaberLoadParms( void )
{
int len, totallen, saberExtFNLen, mainBlockLen, fileCnt, i;
//const char *filename = "ext_data/sabers.cfg";
char *holdChar, *marker;
char saberExtensionListBuf[2048]; // The list of file names read in
fileHandle_t f;
len = 0;
//remember where to store the next one
totallen = mainBlockLen = len;
marker = SaberParms+totallen;
*marker = 0;
//now load in the extra .sab extensions
fileCnt = trap_FS_GetFileList("ext_data/sabers", ".sab", saberExtensionListBuf, sizeof(saberExtensionListBuf) );
holdChar = saberExtensionListBuf;
for ( i = 0; i < fileCnt; i++, holdChar += saberExtFNLen + 1 )
{
saberExtFNLen = strlen( holdChar );
len = trap_FS_FOpenFile(va( "ext_data/sabers/%s", holdChar), &f, FS_READ);
if ( len == -1 )
{
Com_Printf( "error reading file\n" );
}
else
{
if ( (totallen + len + 1/*for the endline*/) >= MAX_SABER_DATA_SIZE ) {
Com_Error(ERR_DROP, "Saber extensions (*.sab) are too large" );
}
trap_FS_Read(bgSaberParseTBuffer, len, f);
bgSaberParseTBuffer[len] = 0;
len = COM_Compress( bgSaberParseTBuffer );
Q_strcat( marker, MAX_SABER_DATA_SIZE-totallen, bgSaberParseTBuffer );
trap_FS_FCloseFile(f);
//get around the stupid problem of not having an endline at the bottom
//of a sab file -rww
Q_strcat(marker, MAX_SABER_DATA_SIZE-totallen, "\n");
len++;
totallen += len;
marker = SaberParms+totallen;
}
}
}
/*
rww -
The following were struct functions in SP. Of course
we can't have that in this codebase so I'm having to
externalize them. Which is why this probably seems
structured a bit oddly. But it's to make porting stuff
easier on myself. SI indicates it was under saberinfo,
and BLADE indicates it was under bladeinfo.
*/
//---------------------------------------
void BG_BLADE_ActivateTrail ( bladeInfo_t *blade, float duration )
{
blade->trail.inAction = qtrue;
blade->trail.duration = duration;
}
void BG_BLADE_DeactivateTrail ( bladeInfo_t *blade, float duration )
{
blade->trail.inAction = qfalse;
blade->trail.duration = duration;
}
//---------------------------------------
void BG_SI_Activate( saberInfo_t *saber )
{
int i;
for ( i = 0; i < saber->numBlades; i++ )
{
saber->blade[i].active = qtrue;
}
}
void BG_SI_Deactivate( saberInfo_t *saber )
{
int i;
for ( i = 0; i < saber->numBlades; i++ )
{
saber->blade[i].active = qfalse;
}
}
// Description: Activate a specific Blade of this Saber.
// Created: 10/03/02 by Aurelio Reis, Modified: 10/03/02 by Aurelio Reis.
// [in] int iBlade Which Blade to activate.
// [in] bool bActive Whether to activate it (default true), or deactivate it (false).
// [return] void
void BG_SI_BladeActivate( saberInfo_t *saber, int iBlade, qboolean bActive )
{
// Validate blade ID/Index.
if ( iBlade < 0 || iBlade >= saber->numBlades )
return;
saber->blade[iBlade].active = bActive;
}
qboolean BG_SI_Active(saberInfo_t *saber)
{
int i;
for ( i = 0; i < saber->numBlades; i++ )
{
if ( saber->blade[i].active )
{
return qtrue;
}
}
return qfalse;
}
void BG_SI_SetLength( saberInfo_t *saber, float length )
{
int i;
for ( i = 0; i < saber->numBlades; i++ )
{
saber->blade[i].length = length;
}
}
//not in sp, added it for my own convenience
void BG_SI_SetDesiredLength(saberInfo_t *saber, float len, int bladeNum )
{
int i, startBlade = 0, maxBlades = saber->numBlades;
if ( bladeNum >= 0 && bladeNum < saber->numBlades)
{//doing this on a specific blade
startBlade = bladeNum;
maxBlades = bladeNum+1;
}
for (i = startBlade; i < maxBlades; i++)
{
saber->blade[i].desiredLength = len;
}
}
//also not in sp, added it for my own convenience
void BG_SI_SetLengthGradual(saberInfo_t *saber, int time)
{
int i;
float amt, dLen;
for (i = 0; i < saber->numBlades; i++)
{
dLen = saber->blade[i].desiredLength;
if (dLen == -1)
{ //assume we want max blade len
dLen = saber->blade[i].lengthMax;
}
if (saber->blade[i].length == dLen)
{
continue;
}
if (saber->blade[i].length == saber->blade[i].lengthMax ||
saber->blade[i].length == 0)
{
saber->blade[i].extendDebounce = time;
if (saber->blade[i].length == 0)
{
saber->blade[i].length++;
}
else
{
saber->blade[i].length--;
}
}
amt = (time - saber->blade[i].extendDebounce)*0.01;
if (amt < 0.2f)
{
amt = 0.2f;
}
if (saber->blade[i].length < dLen)
{
saber->blade[i].length += amt;
if (saber->blade[i].length > dLen)
{
saber->blade[i].length = dLen;
}
if (saber->blade[i].length > saber->blade[i].lengthMax)
{
saber->blade[i].length = saber->blade[i].lengthMax;
}
}
else if (saber->blade[i].length > dLen)
{
saber->blade[i].length -= amt;
if (saber->blade[i].length < dLen)
{
saber->blade[i].length = dLen;
}
if (saber->blade[i].length < 0)
{
saber->blade[i].length = 0;
}
}
}
}
float BG_SI_Length(saberInfo_t *saber)
{//return largest length
int len1 = 0;
int i;
for ( i = 0; i < saber->numBlades; i++ )
{
if ( saber->blade[i].length > len1 )
{
len1 = saber->blade[i].length;
}
}
return len1;
}
float BG_SI_LengthMax(saberInfo_t *saber)
{
int len1 = 0;
int i;
for ( i = 0; i < saber->numBlades; i++ )
{
if ( saber->blade[i].lengthMax > len1 )
{
len1 = saber->blade[i].lengthMax;
}
}
return len1;
}
void BG_SI_ActivateTrail ( saberInfo_t *saber, float duration )
{
int i;
for ( i = 0; i < saber->numBlades; i++ )
{
//saber->blade[i].ActivateTrail( duration );
BG_BLADE_ActivateTrail(&saber->blade[i], duration);
}
}
void BG_SI_DeactivateTrail ( saberInfo_t *saber, float duration )
{
int i;
for ( i = 0; i < saber->numBlades; i++ )
{
//saber->blade[i].DeactivateTrail( duration );
BG_BLADE_DeactivateTrail(&saber->blade[i], duration);
}
}
#include "../namespace_end.h"