/* =========================================================================== Copyright (C) 2000 - 2013, Raven Software, Inc. Copyright (C) 2001 - 2013, Activision, Inc. Copyright (C) 2013 - 2015, OpenJK contributors This file is part of the OpenJK source code. OpenJK is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . =========================================================================== */ //wp_saberLoad.cpp #include "../qcommon/q_shared.h" #include "g_local.h" #include "wp_saber.h" #include "../cgame/cg_local.h" extern qboolean G_ParseLiteral( const char **data, const char *string ); extern saber_colors_t TranslateSaberColor( const char *name ); extern qboolean PM_SaberInStart( int move ); extern qboolean PM_SaberInTransition( int move ); extern qboolean PM_SaberInAttack( int move ); extern stringID_table_t FPTable[]; #define MAX_SABER_DATA_SIZE (1024*1024) // 1mb, was 512kb char SaberParms[MAX_SABER_DATA_SIZE]; void Saber_SithSwordPrecache( void ) {//*SIGH* special sounds used by the sith sword int i; for ( i = 1; i < 5; i++ ) { G_SoundIndex( va( "sound/weapons/sword/stab%d.wav", i ) ); } for ( i = 1; i < 5; i++ ) { G_SoundIndex( va( "sound/weapons/sword/swing%d.wav", i ) ); } for ( i = 1; i < 7; i++ ) { G_SoundIndex( va( "sound/weapons/sword/fall%d.wav", i ) ); } /* for ( i = 1; i < 4; i++ ) { G_SoundIndex( va( "sound/weapons/sword/spin%d.wav", i ) ); } */ } 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), ENUM2STRING(SABER_SITH_SWORD), { "", -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 } }; 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; } void WP_SaberFreeStrings( saberInfo_t &saber ) { if ( saber.name && gi.bIsFromZone( saber.name, TAG_G_ALLOC ) ) { gi.Free( saber.name ); saber.name = NULL; } if ( saber.fullName && gi.bIsFromZone( saber.fullName, TAG_G_ALLOC ) ) { gi.Free( saber.fullName ); saber.fullName = NULL; } if ( saber.model && gi.bIsFromZone( saber.model, TAG_G_ALLOC ) ) { gi.Free( saber.model ); saber.model = NULL; } if ( saber.skin && gi.bIsFromZone( saber.skin, TAG_G_ALLOC ) ) { gi.Free( saber.skin ); saber.skin = NULL; } if ( saber.brokenSaber1 && gi.bIsFromZone( saber.brokenSaber1, TAG_G_ALLOC ) ) { gi.Free( saber.brokenSaber1 ); saber.brokenSaber1 = NULL; } if ( saber.brokenSaber2 && gi.bIsFromZone( saber.brokenSaber2, TAG_G_ALLOC ) ) { gi.Free( saber.brokenSaber2 ); saber.brokenSaber2 = NULL; } } qboolean WP_SaberBladeUseSecondBladeStyle( saberInfo_t *saber, int bladeNum ) { if ( saber && saber->bladeStyle2Start > 0 && bladeNum >= saber->bladeStyle2Start ) return qtrue; return qfalse; } qboolean WP_SaberBladeDoTransitionDamage( saberInfo_t *saber, int bladeNum ) { //use first blade style for this blade if ( !WP_SaberBladeUseSecondBladeStyle( saber, bladeNum ) && (saber->saberFlags2 & SFL2_TRANSITION_DAMAGE) ) return qtrue; //use second blade style for this blade else if ( WP_SaberBladeUseSecondBladeStyle( saber, bladeNum ) && (saber->saberFlags2 & SFL2_TRANSITION_DAMAGE2) ) return qtrue; return qfalse; } qboolean WP_UseFirstValidSaberStyle( gentity_t *ent, int *saberAnimLevel ) { if ( ent && ent->client ) { qboolean styleInvalid = qfalse; int validStyles = 0, styleNum; //initially, all styles are valid for ( styleNum = SS_NONE+1; styleNum < SS_NUM_SABER_STYLES; styleNum++ ) { validStyles |= (1<client->ps.saber[0].Active() && ent->client->ps.saber[0].stylesForbidden ) { if ( (ent->client->ps.saber[0].stylesForbidden&(1<<*saberAnimLevel)) ) {//not a valid style for first saber! styleInvalid = qtrue; validStyles &= ~ent->client->ps.saber[0].stylesForbidden; } } if ( ent->client->ps.dualSabers ) {//check second saber, too if ( ent->client->ps.saber[1].Active() && ent->client->ps.saber[1].stylesForbidden ) { if ( (ent->client->ps.saber[1].stylesForbidden&(1<<*saberAnimLevel)) ) {//not a valid style for second saber! styleInvalid = qtrue; //only the ones both sabers allow is valid validStyles &= ~ent->client->ps.saber[1].stylesForbidden; } } else {//can't use dual style if not using 2 sabers validStyles &= ~(1<client ) { if ( ent->client->ps.saber[0].Active() && ent->client->ps.saber[0].stylesForbidden ) { if ( (ent->client->ps.saber[0].stylesForbidden&(1<client->ps.dualSabers ) {//check second saber, too if ( ent->client->ps.saber[1].Active() ) { if ( ent->client->ps.saber[1].stylesForbidden ) { if ( (ent->client->ps.saber[1].stylesForbidden&(1<client->ps.saber[0].Active() && (ent->client->ps.saber[0].stylesLearned&(1<client->ps.saber[1].stylesLearned&(1<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, qboolean setColors = qtrue ) { //Set defaults so that, if it fails, there's at least something there saber->name = NULL; saber->fullName = NULL; for ( int i = 0; i < MAX_BLADES; i++ ) { if ( setColors ) { saber->blade[i].color = SABER_RED; } saber->blade[i].radius = SABER_RADIUS_STANDARD; saber->blade[i].lengthMax = 32; } saber->model = "models/weapons2/saber_reborn/saber_w.glm"; saber->skin = NULL; saber->soundOn = G_SoundIndex( "sound/weapons/saber/enemy_saber_on.wav" ); saber->soundLoop = G_SoundIndex( "sound/weapons/saber/saberhum3.wav" ); saber->soundOff = G_SoundIndex( "sound/weapons/saber/enemy_saber_off.wav" ); saber->numBlades = 1; saber->type = SABER_SINGLE; saber->stylesLearned = 0; saber->stylesForbidden = 0; 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======================================================================================== //these values are global to the saber, like all of the ones above 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!!! saber->fallSound[0] = 0; //none - if set, plays one of these 3 sounds when weapon falls to the ground - NOTE: must provide all 3!!! saber->fallSound[1] = 0; //none - if set, plays one of these 3 sounds when weapon falls to the ground - NOTE: must provide all 3!!! saber->fallSound[2] = 0; //none - if set, plays one of these 3 sounds when weapon falls to the ground - 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]=0; //none - if set, the game will use this shader for marks on enemies instead of the default "gfx/damage/saberglowmark" saber->g2WeaponMarkShader[0]=0; //none - if set, the game will ry to project this shader onto the weapon when it damages a person (good for a blood splatter on the weapon) //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]=0; //none - if set, the game will use this shader for marks on enemies instead of the default "gfx/damage/saberglowmark" saber->g2WeaponMarkShader2[0]=0; //none - if set, the game will ry to project this shader onto the weapon when it damages a person (good for a blood splatter on the weapon) //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 //========================================================================================================================================= } static void Saber_ParseName( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->fullName = G_NewString( value ); } static void Saber_ParseSaberType( saberInfo_t *saber, const char **p ) { const char *value; int saberType; if ( COM_ParseString( p, &value ) ) return; saberType = GetIDForString( SaberTable, value ); if ( saberType >= SABER_SINGLE && saberType <= NUM_SABERS ) saber->type = (saberType_t)saberType; } static void Saber_ParseSaberModel( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->model = G_NewString( value ); } static void Saber_ParseCustomSkin( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->skin = G_NewString( value ); } static void Saber_ParseSoundOn( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->soundOn = G_SoundIndex( value ); } static void Saber_ParseSoundLoop( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->soundLoop = G_SoundIndex( value ); } static void Saber_ParseSoundOff( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->soundOff = G_SoundIndex( value ); } static void Saber_ParseNumBlades( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n < 1 || n > MAX_BLADES ) { Com_Error( ERR_DROP, "WP_SaberParseParms: saber %s has illegal number of blades (%d) max: %d", saber->name, n, MAX_BLADES ); return; } saber->numBlades = n; } qboolean Saber_SetColor = qtrue; static void Saber_ParseSaberColor( saberInfo_t *saber, const char **p ) { const char *value; int i=0; saber_colors_t color; if ( COM_ParseString( p, &value ) ) return; // don't actually want to set the colors // read the color out anyway just to advance the *p pointer if ( !Saber_SetColor ) return; color = TranslateSaberColor( value ); for ( i=0; iblade[i].color = color; } static void Saber_ParseSaberColor2( saberInfo_t *saber, const char **p ) { const char *value; saber_colors_t color; if ( COM_ParseString( p, &value ) ) return; // don't actually want to set the colors // read the color out anyway just to advance the *p pointer if ( !Saber_SetColor ) return; color = TranslateSaberColor( value ); saber->blade[1].color = color; } static void Saber_ParseSaberColor3( saberInfo_t *saber, const char **p ) { const char *value; saber_colors_t color; if ( COM_ParseString( p, &value ) ) return; // don't actually want to set the colors // read the color out anyway just to advance the *p pointer if ( !Saber_SetColor ) return; color = TranslateSaberColor( value ); saber->blade[2].color = color; } static void Saber_ParseSaberColor4( saberInfo_t *saber, const char **p ) { const char *value; saber_colors_t color; if ( COM_ParseString( p, &value ) ) return; // don't actually want to set the colors // read the color out anyway just to advance the *p pointer if ( !Saber_SetColor ) return; color = TranslateSaberColor( value ); saber->blade[3].color = color; } static void Saber_ParseSaberColor5( saberInfo_t *saber, const char **p ) { const char *value; saber_colors_t color; if ( COM_ParseString( p, &value ) ) return; // don't actually want to set the colors // read the color out anyway just to advance the *p pointer if ( !Saber_SetColor ) return; color = TranslateSaberColor( value ); saber->blade[4].color = color; } static void Saber_ParseSaberColor6( saberInfo_t *saber, const char **p ) { const char *value; saber_colors_t color; if ( COM_ParseString( p, &value ) ) return; // don't actually want to set the colors // read the color out anyway just to advance the *p pointer if ( !Saber_SetColor ) return; color = TranslateSaberColor( value ); saber->blade[5].color = color; } static void Saber_ParseSaberColor7( saberInfo_t *saber, const char **p ) { const char *value; saber_colors_t color; if ( COM_ParseString( p, &value ) ) return; // don't actually want to set the colors // read the color out anyway just to advance the *p pointer if ( !Saber_SetColor ) return; color = TranslateSaberColor( value ); saber->blade[6].color = color; } static void Saber_ParseSaberLength( saberInfo_t *saber, const char **p ) { int i=0; float f; if ( COM_ParseFloat( p, &f ) ) return; if ( f < 4.0f ) f = 4.0f; for ( i=0; iblade[i].lengthMax = f; } static void Saber_ParseSaberLength2( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) return; if ( f < 4.0f ) f = 4.0f; saber->blade[1].lengthMax = f; } static void Saber_ParseSaberLength3( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) return; if ( f < 4.0f ) f = 4.0f; saber->blade[2].lengthMax = f; } static void Saber_ParseSaberLength4( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) return; if ( f < 4.0f ) f = 4.0f; saber->blade[3].lengthMax = f; } static void Saber_ParseSaberLength5( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) return; if ( f < 4.0f ) f = 4.0f; saber->blade[4].lengthMax = f; } static void Saber_ParseSaberLength6( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) return; if ( f < 4.0f ) f = 4.0f; saber->blade[5].lengthMax = f; } static void Saber_ParseSaberLength7( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) return; if ( f < 4.0f ) f = 4.0f; saber->blade[6].lengthMax = f; } static void Saber_ParseSaberRadius( saberInfo_t *saber, const char **p ) { int i=0; float f; if ( COM_ParseFloat( p, &f ) ) return; if ( f < 0.25f ) f = 0.25f; for ( i=0; iblade[i].radius = f; } static void Saber_ParseSaberRadius2( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) return; if ( f < 0.25f ) f = 0.25f; saber->blade[1].radius = f; } static void Saber_ParseSaberRadius3( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) return; if ( f < 0.25f ) f = 0.25f; saber->blade[2].radius = f; } static void Saber_ParseSaberRadius4( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) return; if ( f < 0.25f ) f = 0.25f; saber->blade[3].radius = f; } static void Saber_ParseSaberRadius5( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) return; if ( f < 0.25f ) f = 0.25f; saber->blade[4].radius = f; } static void Saber_ParseSaberRadius6( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) return; if ( f < 0.25f ) f = 0.25f; saber->blade[5].radius = f; } static void Saber_ParseSaberRadius7( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) return; if ( f < 0.25f ) f = 0.25f; saber->blade[6].radius = f; } static void Saber_ParseSaberStyle( saberInfo_t *saber, const char **p ) { const char *value; int style, styleNum; if ( COM_ParseString( p, &value ) ) return; //OLD WAY: only allowed ONE style style = TranslateSaberStyle( value ); //learn only this style saber->stylesLearned = (1<stylesForbidden = 0; for ( styleNum=SS_NONE+1; styleNumstylesForbidden |= (1<stylesLearned |= (1<stylesForbidden |= (1<maxChain = n; } static void Saber_ParseLockable( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n == 0 ) saber->saberFlags |= SFL_NOT_LOCKABLE; } static void Saber_ParseThrowable( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n == 0 ) saber->saberFlags |= SFL_NOT_THROWABLE; } static void Saber_ParseDisarmable( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n == 0 ) saber->saberFlags |= SFL_NOT_DISARMABLE; } static void Saber_ParseBlocking( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n == 0 ) saber->saberFlags |= SFL_NOT_ACTIVE_BLOCKING; } static void Saber_ParseTwoHanded( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_TWO_HANDED; } static void Saber_ParseForceRestrict( saberInfo_t *saber, const char **p ) { const char *value; int fp; if ( COM_ParseString( p, &value ) ) return; fp = GetIDForString( FPTable, value ); if ( fp >= FP_FIRST && fp < NUM_FORCE_POWERS ) saber->forceRestrictions |= (1<lockBonus = n; } static void Saber_ParseParryBonus( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } saber->parryBonus = n; } static void Saber_ParseBreakParryBonus( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } saber->breakParryBonus = n; } static void Saber_ParseBreakParryBonus2( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } saber->breakParryBonus2 = n; } static void Saber_ParseDisarmBonus( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } saber->disarmBonus = n; } static void Saber_ParseDisarmBonus2( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } saber->disarmBonus2 = n; } static void Saber_ParseSingleBladeStyle( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->singleBladeStyle = TranslateSaberStyle( value ); } static void Saber_ParseSingleBladeThrowable( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_SINGLE_BLADE_THROWABLE; } static void Saber_ParseBrokenSaber1( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->brokenSaber1 = G_NewString( value ); } static void Saber_ParseBrokenSaber2( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->brokenSaber2 = G_NewString( value ); } static void Saber_ParseReturnDamage( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_RETURN_DAMAGE; } static void Saber_ParseSpinSound( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->spinSound = G_SoundIndex( value ); } static void Saber_ParseSwingSound1( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->swingSound[0] = G_SoundIndex( value ); } static void Saber_ParseSwingSound2( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->swingSound[1] = G_SoundIndex( value ); } static void Saber_ParseSwingSound3( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->swingSound[2] = G_SoundIndex( value ); } static void Saber_ParseFallSound1( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->fallSound[0] = G_SoundIndex( value ); } static void Saber_ParseFallSound2( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->fallSound[1] = G_SoundIndex( value ); } static void Saber_ParseFallSound3( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->fallSound[2] = G_SoundIndex( value ); } static void Saber_ParseMoveSpeedScale( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) { SkipRestOfLine( p ); return; } saber->moveSpeedScale = f; } static void Saber_ParseAnimSpeedScale( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) { SkipRestOfLine( p ); return; } saber->animSpeedScale = f; } static void Saber_ParseOnInWater( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_ON_IN_WATER; } static void Saber_ParseBounceOnWalls( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_BOUNCE_ON_WALLS; } static void Saber_ParseBoltToWrist( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_BOLT_TO_WRIST; } static void Saber_ParseKataMove( saberInfo_t *saber, const char **p ) { const char *value; int saberMove = LS_INVALID; if ( COM_ParseString( p, &value ) ) return; 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 } static void Saber_ParseLungeAtkMove( saberInfo_t *saber, const char **p ) { const char *value; int saberMove = LS_INVALID; if ( COM_ParseString( p, &value ) ) return; saberMove = GetIDForString( SaberMoveTable, value ); if ( saberMove >= LS_INVALID && saberMove < LS_MOVE_MAX ) saber->lungeAtkMove = saberMove; } static void Saber_ParseJumpAtkUpMove( saberInfo_t *saber, const char **p ) { const char *value; int saberMove = LS_INVALID; if ( COM_ParseString( p, &value ) ) return; saberMove = GetIDForString( SaberMoveTable, value ); if ( saberMove >= LS_INVALID && saberMove < LS_MOVE_MAX ) saber->jumpAtkUpMove = saberMove; } static void Saber_ParseJumpAtkFwdMove( saberInfo_t *saber, const char **p ) { const char *value; int saberMove = LS_INVALID; if ( COM_ParseString( p, &value ) ) return; saberMove = GetIDForString( SaberMoveTable, value ); if ( saberMove >= LS_INVALID && saberMove < LS_MOVE_MAX ) saber->jumpAtkFwdMove = saberMove; } static void Saber_ParseJumpAtkBackMove( saberInfo_t *saber, const char **p ) { const char *value; int saberMove = LS_INVALID; if ( COM_ParseString( p, &value ) ) return; saberMove = GetIDForString( SaberMoveTable, value ); if ( saberMove >= LS_INVALID && saberMove < LS_MOVE_MAX ) saber->jumpAtkBackMove = saberMove; } static void Saber_ParseJumpAtkRightMove( saberInfo_t *saber, const char **p ) { const char *value; int saberMove = LS_INVALID; if ( COM_ParseString( p, &value ) ) return; saberMove = GetIDForString( SaberMoveTable, value ); if ( saberMove >= LS_INVALID && saberMove < LS_MOVE_MAX ) saber->jumpAtkRightMove = saberMove; } static void Saber_ParseJumpAtkLeftMove( saberInfo_t *saber, const char **p ) { const char *value; int saberMove = LS_INVALID; if ( COM_ParseString( p, &value ) ) return; saberMove = GetIDForString( SaberMoveTable, value ); if ( saberMove >= LS_INVALID && saberMove < LS_MOVE_MAX ) saber->jumpAtkLeftMove = saberMove; } static void Saber_ParseReadyAnim( saberInfo_t *saber, const char **p ) { const char *value; int anim = -1; if ( COM_ParseString( p, &value ) ) return; anim = GetIDForString( animTable, value ); if ( anim >= 0 && anim < MAX_ANIMATIONS ) saber->readyAnim = anim; } static void Saber_ParseDrawAnim( saberInfo_t *saber, const char **p ) { const char *value; int anim = -1; if ( COM_ParseString( p, &value ) ) return; anim = GetIDForString( animTable, value ); if ( anim >= 0 && anim < MAX_ANIMATIONS ) saber->drawAnim = anim; } static void Saber_ParsePutawayAnim( saberInfo_t *saber, const char **p ) { const char *value; int anim = -1; if ( COM_ParseString( p, &value ) ) return; anim = GetIDForString( animTable, value ); if ( anim >= 0 && anim < MAX_ANIMATIONS ) saber->putawayAnim = anim; } static void Saber_ParseTauntAnim( saberInfo_t *saber, const char **p ) { const char *value; int anim = -1; if ( COM_ParseString( p, &value ) ) return; anim = GetIDForString( animTable, value ); if ( anim >= 0 && anim < MAX_ANIMATIONS ) saber->tauntAnim = anim; } static void Saber_ParseBowAnim( saberInfo_t *saber, const char **p ) { const char *value; int anim = -1; if ( COM_ParseString( p, &value ) ) return; anim = GetIDForString( animTable, value ); if ( anim >= 0 && anim < MAX_ANIMATIONS ) saber->bowAnim = anim; } static void Saber_ParseMeditateAnim( saberInfo_t *saber, const char **p ) { const char *value; int anim = -1; if ( COM_ParseString( p, &value ) ) return; anim = GetIDForString( animTable, value ); if ( anim >= 0 && anim < MAX_ANIMATIONS ) saber->meditateAnim = anim; } static void Saber_ParseFlourishAnim( saberInfo_t *saber, const char **p ) { const char *value; int anim = -1; if ( COM_ParseString( p, &value ) ) return; anim = GetIDForString( animTable, value ); if ( anim >= 0 && anim < MAX_ANIMATIONS ) saber->flourishAnim = anim; } static void Saber_ParseGloatAnim( saberInfo_t *saber, const char **p ) { const char *value; int anim = -1; if ( COM_ParseString( p, &value ) ) return; anim = GetIDForString( animTable, value ); if ( anim >= 0 && anim < MAX_ANIMATIONS ) saber->gloatAnim = anim; } static void Saber_ParseNoRollStab( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_NO_ROLL_STAB; } static void Saber_ParseNoPullAttack( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_NO_PULL_ATTACK; } static void Saber_ParseNoBackAttack( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_NO_BACK_ATTACK; } static void Saber_ParseNoStabDown( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_NO_STABDOWN; } static void Saber_ParseNoWallRuns( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_NO_WALL_RUNS; } static void Saber_ParseNoWallFlips( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_NO_WALL_FLIPS; } static void Saber_ParseNoWallGrab( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_NO_WALL_GRAB; } static void Saber_ParseNoRolls( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_NO_ROLLS; } static void Saber_ParseNoFlips( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_NO_FLIPS; } static void Saber_ParseNoCartwheels( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_NO_CARTWHEELS; } static void Saber_ParseNoKicks( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_NO_KICKS; } static void Saber_ParseNoMirrorAttacks( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags |= SFL_NO_MIRROR_ATTACKS; } static void Saber_ParseNotInMP( saberInfo_t *saber, const char **p ) { SkipRestOfLine( p ); } static void Saber_ParseBladeStyle2Start( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } saber->bladeStyle2Start = n; } static void Saber_ParseNoWallMarks( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_NO_WALL_MARKS; } static void Saber_ParseNoDLight( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_NO_DLIGHT; } static void Saber_ParseNoBlade( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_NO_BLADE; } static void Saber_ParseTrailStyle( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } saber->trailStyle = n; } static void Saber_ParseG2MarksShader( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) { SkipRestOfLine( p ); return; } Q_strncpyz( saber->g2MarksShader, value, sizeof( saber->g2MarksShader ) ); //NOTE: registers this on cgame side where it registers all client assets } static void Saber_ParseG2WeaponMarkShader( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) { SkipRestOfLine( p ); return; } Q_strncpyz( saber->g2WeaponMarkShader, value, sizeof( saber->g2WeaponMarkShader ) ); //NOTE: registers this on cgame side where it registers all client assets } static void Saber_ParseKnockbackScale( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) { SkipRestOfLine( p ); return; } saber->knockbackScale = f; } static void Saber_ParseDamageScale( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) { SkipRestOfLine( p ); return; } saber->damageScale = f; } static void Saber_ParseNoDismemberment( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_NO_DISMEMBERMENT; } static void Saber_ParseNoIdleEffect( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_NO_IDLE_EFFECT; } static void Saber_ParseAlwaysBlock( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_ALWAYS_BLOCK; } static void Saber_ParseNoManualDeactivate( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_NO_MANUAL_DEACTIVATE; } static void Saber_ParseTransitionDamage( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_TRANSITION_DAMAGE; } static void Saber_ParseSplashRadius( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) { SkipRestOfLine( p ); return; } saber->splashRadius = f; } static void Saber_ParseSplashDamage( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } saber->splashDamage = n; } static void Saber_ParseSplashKnockback( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) { SkipRestOfLine( p ); return; } saber->splashKnockback = f; } static void Saber_ParseHitSound1( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->hitSound[0] = G_SoundIndex( value ); } static void Saber_ParseHitSound2( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->hitSound[1] = G_SoundIndex( value ); } static void Saber_ParseHitSound3( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->hitSound[2] = G_SoundIndex( value ); } static void Saber_ParseBlockSound1( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->blockSound[0] = G_SoundIndex( value ); } static void Saber_ParseBlockSound2( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->blockSound[1] = G_SoundIndex( value ); } static void Saber_ParseBlockSound3( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->blockSound[2] = G_SoundIndex( value ); } static void Saber_ParseBounceSound1( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->bounceSound[0] = G_SoundIndex( value ); } static void Saber_ParseBounceSound2( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->bounceSound[1] = G_SoundIndex( value ); } static void Saber_ParseBounceSound3( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->bounceSound[2] = G_SoundIndex( value ); } static void Saber_ParseBlockEffect( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->blockEffect = G_EffectIndex( value ); } static void Saber_ParseHitPersonEffect( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->hitPersonEffect = G_EffectIndex( value ); } static void Saber_ParseHitOtherEffect( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->hitOtherEffect = G_EffectIndex( value ); } static void Saber_ParseBladeEffect( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->bladeEffect = G_EffectIndex( value ); } static void Saber_ParseNoClashFlare( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_NO_CLASH_FLARE; } static void Saber_ParseNoWallMarks2( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_NO_WALL_MARKS2; } static void Saber_ParseNoDLight2( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_NO_DLIGHT2; } static void Saber_ParseNoBlade2( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_NO_BLADE2; } static void Saber_ParseTrailStyle2( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } saber->trailStyle2 = n; } static void Saber_ParseG2MarksShader2( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) { SkipRestOfLine( p ); return; } Q_strncpyz( saber->g2MarksShader2, value, sizeof(saber->g2MarksShader2) ); //NOTE: registers this on cgame side where it registers all client assets } static void Saber_ParseG2WeaponMarkShader2( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) { SkipRestOfLine( p ); return; } Q_strncpyz( saber->g2WeaponMarkShader2, value, sizeof(saber->g2WeaponMarkShader2) ); //NOTE: registers this on cgame side where it registers all client assets } static void Saber_ParseKnockbackScale2( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) { SkipRestOfLine( p ); return; } saber->knockbackScale2 = f; } static void Saber_ParseDamageScale2( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) { SkipRestOfLine( p ); return; } saber->damageScale2 = f; } static void Saber_ParseNoDismemberment2( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_NO_DISMEMBERMENT2; } static void Saber_ParseNoIdleEffect2( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_NO_IDLE_EFFECT2; } static void Saber_ParseAlwaysBlock2( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_ALWAYS_BLOCK2; } static void Saber_ParseNoManualDeactivate2( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_NO_MANUAL_DEACTIVATE2; } static void Saber_ParseTransitionDamage2( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_TRANSITION_DAMAGE2; } static void Saber_ParseSplashRadius2( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) { SkipRestOfLine( p ); return; } saber->splashRadius2 = f; } static void Saber_ParseSplashDamage2( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } saber->splashDamage2 = n; } static void Saber_ParseSplashKnockback2( saberInfo_t *saber, const char **p ) { float f; if ( COM_ParseFloat( p, &f ) ) { SkipRestOfLine( p ); return; } saber->splashKnockback2 = f; } static void Saber_ParseHit2Sound1( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->hit2Sound[0] = G_SoundIndex( value ); } static void Saber_ParseHit2Sound2( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->hit2Sound[1] = G_SoundIndex( value ); } static void Saber_ParseHit2Sound3( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->hit2Sound[2] = G_SoundIndex( value ); } static void Saber_ParseBlock2Sound1( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->block2Sound[0] = G_SoundIndex( value ); } static void Saber_ParseBlock2Sound2( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->block2Sound[1] = G_SoundIndex( value ); } static void Saber_ParseBlock2Sound3( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->block2Sound[2] = G_SoundIndex( value ); } static void Saber_ParseBounce2Sound1( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->bounce2Sound[0] = G_SoundIndex( value ); } static void Saber_ParseBounce2Sound2( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->bounce2Sound[1] = G_SoundIndex( value ); } static void Saber_ParseBounce2Sound3( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->bounce2Sound[2] = G_SoundIndex( value ); } static void Saber_ParseBlockEffect2( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->blockEffect2 = G_EffectIndex( value ); } static void Saber_ParseHitPersonEffect2( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->hitPersonEffect2 = G_EffectIndex( value ); } static void Saber_ParseHitOtherEffect2( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->hitOtherEffect2 = G_EffectIndex( value ); } static void Saber_ParseBladeEffect2( saberInfo_t *saber, const char **p ) { const char *value; if ( COM_ParseString( p, &value ) ) return; saber->bladeEffect2 = G_EffectIndex( (char *)value ); } static void Saber_ParseNoClashFlare2( saberInfo_t *saber, const char **p ) { int n; if ( COM_ParseInt( p, &n ) ) { SkipRestOfLine( p ); return; } if ( n ) saber->saberFlags2 |= SFL2_NO_CLASH_FLARE2; } /* =============== Keyword Hash =============== */ #define KEYWORDHASH_SIZE (512) typedef struct keywordHash_s { char *keyword; void (*func)(saberInfo_t *saber, const char **p); struct keywordHash_s *next; } keywordHash_t; static int KeywordHash_Key( const char *keyword ) { int hash, i; hash = 0; for ( i=0; keyword[i]; i++ ) { if ( keyword[i] >= 'A' && keyword[i] <= 'Z' ) hash += (keyword[i] + ('a'-'A')) * (119 + i); else hash += keyword[i] * (119 + i); } hash = (hash ^ (hash >> 10) ^ (hash >> 20)) & (KEYWORDHASH_SIZE-1); return hash; } static void KeywordHash_Add( keywordHash_t *table[], keywordHash_t *key ) { int hash = KeywordHash_Key( key->keyword ); key->next = table[hash]; table[hash] = key; } static keywordHash_t *KeywordHash_Find( keywordHash_t *table[], const char *keyword ) { keywordHash_t *key; int hash = KeywordHash_Key(keyword); for ( key=table[hash]; key; key=key->next ) { if ( !Q_stricmp( key->keyword, keyword ) ) return key; } return NULL; } static keywordHash_t saberParseKeywords[] = { { "name", Saber_ParseName, NULL }, { "saberType", Saber_ParseSaberType, NULL }, { "saberModel", Saber_ParseSaberModel, NULL }, { "customSkin", Saber_ParseCustomSkin, NULL }, { "soundOn", Saber_ParseSoundOn, NULL }, { "soundLoop", Saber_ParseSoundLoop, NULL }, { "soundOff", Saber_ParseSoundOff, NULL }, { "numBlades", Saber_ParseNumBlades, NULL }, { "saberColor", Saber_ParseSaberColor, NULL }, { "saberColor2", Saber_ParseSaberColor2, NULL }, { "saberColor3", Saber_ParseSaberColor3, NULL }, { "saberColor4", Saber_ParseSaberColor4, NULL }, { "saberColor5", Saber_ParseSaberColor5, NULL }, { "saberColor6", Saber_ParseSaberColor6, NULL }, { "saberColor7", Saber_ParseSaberColor7, NULL }, { "saberLength", Saber_ParseSaberLength, NULL }, { "saberLength2", Saber_ParseSaberLength2, NULL }, { "saberLength3", Saber_ParseSaberLength3, NULL }, { "saberLength4", Saber_ParseSaberLength4, NULL }, { "saberLength5", Saber_ParseSaberLength5, NULL }, { "saberLength6", Saber_ParseSaberLength6, NULL }, { "saberLength7", Saber_ParseSaberLength7, NULL }, { "saberRadius", Saber_ParseSaberRadius, NULL }, { "saberRadius2", Saber_ParseSaberRadius2, NULL }, { "saberRadius3", Saber_ParseSaberRadius3, NULL }, { "saberRadius4", Saber_ParseSaberRadius4, NULL }, { "saberRadius5", Saber_ParseSaberRadius5, NULL }, { "saberRadius6", Saber_ParseSaberRadius6, NULL }, { "saberRadius7", Saber_ParseSaberRadius7, NULL }, { "saberStyle", Saber_ParseSaberStyle, NULL }, { "saberStyleLearned", Saber_ParseSaberStyleLearned, NULL }, { "saberStyleForbidden", Saber_ParseSaberStyleForbidden, NULL }, { "maxChain", Saber_ParseMaxChain, NULL }, { "lockable", Saber_ParseLockable, NULL }, { "throwable", Saber_ParseThrowable, NULL }, { "disarmable", Saber_ParseDisarmable, NULL }, { "blocking", Saber_ParseBlocking, NULL }, { "twoHanded", Saber_ParseTwoHanded, NULL }, { "forceRestrict", Saber_ParseForceRestrict, NULL }, { "lockBonus", Saber_ParseLockBonus, NULL }, { "parryBonus", Saber_ParseParryBonus, NULL }, { "breakParryBonus", Saber_ParseBreakParryBonus, NULL }, { "breakParryBonus2", Saber_ParseBreakParryBonus2, NULL }, { "disarmBonus", Saber_ParseDisarmBonus, NULL }, { "disarmBonus2", Saber_ParseDisarmBonus2, NULL }, { "singleBladeStyle", Saber_ParseSingleBladeStyle, NULL }, { "singleBladeThrowable", Saber_ParseSingleBladeThrowable,NULL }, { "brokenSaber1", Saber_ParseBrokenSaber1, NULL }, { "brokenSaber2", Saber_ParseBrokenSaber2, NULL }, { "returnDamage", Saber_ParseReturnDamage, NULL }, { "spinSound", Saber_ParseSpinSound, NULL }, { "swingSound1", Saber_ParseSwingSound1, NULL }, { "swingSound2", Saber_ParseSwingSound2, NULL }, { "swingSound3", Saber_ParseSwingSound3, NULL }, { "fallSound1", Saber_ParseFallSound1, NULL }, { "fallSound2", Saber_ParseFallSound2, NULL }, { "fallSound3", Saber_ParseFallSound3, NULL }, { "moveSpeedScale", Saber_ParseMoveSpeedScale, NULL }, { "animSpeedScale", Saber_ParseAnimSpeedScale, NULL }, { "onInWater", Saber_ParseOnInWater, NULL }, { "bounceOnWalls", Saber_ParseBounceOnWalls, NULL }, { "boltToWrist", Saber_ParseBoltToWrist, NULL }, { "kataMove", Saber_ParseKataMove, NULL }, { "lungeAtkMove", Saber_ParseLungeAtkMove, NULL }, { "jumpAtkUpMove", Saber_ParseJumpAtkUpMove, NULL }, { "jumpAtkFwdMove", Saber_ParseJumpAtkFwdMove, NULL }, { "jumpAtkBackMove", Saber_ParseJumpAtkBackMove, NULL }, { "jumpAtkRightMove", Saber_ParseJumpAtkRightMove, NULL }, { "jumpAtkLeftMove", Saber_ParseJumpAtkLeftMove, NULL }, { "readyAnim", Saber_ParseReadyAnim, NULL }, { "drawAnim", Saber_ParseDrawAnim, NULL }, { "putawayAnim", Saber_ParsePutawayAnim, NULL }, { "tauntAnim", Saber_ParseTauntAnim, NULL }, { "bowAnim", Saber_ParseBowAnim, NULL }, { "meditateAnim", Saber_ParseMeditateAnim, NULL }, { "flourishAnim", Saber_ParseFlourishAnim, NULL }, { "gloatAnim", Saber_ParseGloatAnim, NULL }, { "noRollStab", Saber_ParseNoRollStab, NULL }, { "noPullAttack", Saber_ParseNoPullAttack, NULL }, { "noBackAttack", Saber_ParseNoBackAttack, NULL }, { "noStabDown", Saber_ParseNoStabDown, NULL }, { "noWallRuns", Saber_ParseNoWallRuns, NULL }, { "noWallFlips", Saber_ParseNoWallFlips, NULL }, { "noWallGrab", Saber_ParseNoWallGrab, NULL }, { "noRolls", Saber_ParseNoRolls, NULL }, { "noFlips", Saber_ParseNoFlips, NULL }, { "noCartwheels", Saber_ParseNoCartwheels, NULL }, { "noKicks", Saber_ParseNoKicks, NULL }, { "noMirrorAttacks", Saber_ParseNoMirrorAttacks, NULL }, { "notInMP", Saber_ParseNotInMP, NULL }, { "bladeStyle2Start", Saber_ParseBladeStyle2Start, NULL }, { "noWallMarks", Saber_ParseNoWallMarks, NULL }, { "noWallMarks2", Saber_ParseNoWallMarks2, NULL }, { "noDlight", Saber_ParseNoDLight, NULL }, { "noDlight2", Saber_ParseNoDLight2, NULL }, { "noBlade", Saber_ParseNoBlade, NULL }, { "noBlade2", Saber_ParseNoBlade2, NULL }, { "trailStyle", Saber_ParseTrailStyle, NULL }, { "trailStyle2", Saber_ParseTrailStyle2, NULL }, { "g2MarksShader", Saber_ParseG2MarksShader, NULL }, { "g2MarksShader2", Saber_ParseG2MarksShader2, NULL }, { "g2WeaponMarkShader", Saber_ParseG2WeaponMarkShader, NULL }, { "g2WeaponMarkShader2", Saber_ParseG2WeaponMarkShader2, NULL }, { "knockbackScale", Saber_ParseKnockbackScale, NULL }, { "knockbackScale2", Saber_ParseKnockbackScale2, NULL }, { "damageScale", Saber_ParseDamageScale, NULL }, { "damageScale2", Saber_ParseDamageScale2, NULL }, { "noDismemberment", Saber_ParseNoDismemberment, NULL }, { "noDismemberment2", Saber_ParseNoDismemberment2, NULL }, { "noIdleEffect", Saber_ParseNoIdleEffect, NULL }, { "noIdleEffect2", Saber_ParseNoIdleEffect2, NULL }, { "alwaysBlock", Saber_ParseAlwaysBlock, NULL }, { "alwaysBlock2", Saber_ParseAlwaysBlock2, NULL }, { "noManualDeactivate", Saber_ParseNoManualDeactivate, NULL }, { "noManualDeactivate2", Saber_ParseNoManualDeactivate2, NULL }, { "transitionDamage", Saber_ParseTransitionDamage, NULL }, { "transitionDamage2", Saber_ParseTransitionDamage2, NULL }, { "splashRadius", Saber_ParseSplashRadius, NULL }, { "splashRadius2", Saber_ParseSplashRadius2, NULL }, { "splashDamage", Saber_ParseSplashDamage, NULL }, { "splashDamage2", Saber_ParseSplashDamage2, NULL }, { "splashKnockback", Saber_ParseSplashKnockback, NULL }, { "splashKnockback2", Saber_ParseSplashKnockback2, NULL }, { "hitSound1", Saber_ParseHitSound1, NULL }, { "hit2Sound1", Saber_ParseHit2Sound1, NULL }, { "hitSound2", Saber_ParseHitSound2, NULL }, { "hit2Sound2", Saber_ParseHit2Sound2, NULL }, { "hitSound3", Saber_ParseHitSound3, NULL }, { "hit2Sound3", Saber_ParseHit2Sound3, NULL }, { "blockSound1", Saber_ParseBlockSound1, NULL }, { "block2Sound1", Saber_ParseBlock2Sound1, NULL }, { "blockSound2", Saber_ParseBlockSound2, NULL }, { "block2Sound2", Saber_ParseBlock2Sound2, NULL }, { "blockSound3", Saber_ParseBlockSound3, NULL }, { "block2Sound3", Saber_ParseBlock2Sound3, NULL }, { "bounceSound1", Saber_ParseBounceSound1, NULL }, { "bounce2Sound1", Saber_ParseBounce2Sound1, NULL }, { "bounceSound2", Saber_ParseBounceSound2, NULL }, { "bounce2Sound2", Saber_ParseBounce2Sound2, NULL }, { "bounceSound3", Saber_ParseBounceSound3, NULL }, { "bounce2Sound3", Saber_ParseBounce2Sound3, NULL }, { "blockEffect", Saber_ParseBlockEffect, NULL }, { "blockEffect2", Saber_ParseBlockEffect2, NULL }, { "hitPersonEffect", Saber_ParseHitPersonEffect, NULL }, { "hitPersonEffect2", Saber_ParseHitPersonEffect2, NULL }, { "hitOtherEffect", Saber_ParseHitOtherEffect, NULL }, { "hitOtherEffect2", Saber_ParseHitOtherEffect2, NULL }, { "bladeEffect", Saber_ParseBladeEffect, NULL }, { "bladeEffect2", Saber_ParseBladeEffect2, NULL }, { "noClashFlare", Saber_ParseNoClashFlare, NULL }, { "noClashFlare2", Saber_ParseNoClashFlare2, NULL }, { NULL, NULL, NULL } }; static keywordHash_t *saberParseKeywordHash[KEYWORDHASH_SIZE]; static qboolean hashSetup = qfalse; static void WP_SaberSetupKeywordHash( void ) { int i; memset( saberParseKeywordHash, 0, sizeof( saberParseKeywordHash ) ); for ( i=0; saberParseKeywords[i].keyword; i++ ) KeywordHash_Add( saberParseKeywordHash, &saberParseKeywords[i] ); hashSetup = qtrue; } qboolean WP_SaberParseParms( const char *SaberName, saberInfo_t *saber, qboolean setColors ) { const char *token; const char *p; keywordHash_t *key; // make sure the hash table has been setup if ( !hashSetup ) WP_SaberSetupKeywordHash(); if ( !saber ) return qfalse; //Set defaults so that, if it fails, there's at least something there WP_SaberSetDefaults( saber, setColors ); if ( !VALIDSTRING( SaberName ) ) return qfalse; //check if we want to set the sabercolors or not (for if we're loading a savegame) Saber_SetColor = setColors; //try to parse it out p = SaberParms; COM_ParseSession ps; // look for the right saber while ( p ) { token = COM_ParseExt( &p, qtrue ); if ( !token[0] ) return qfalse; if ( !Q_stricmp( token, SaberName ) ) break; SkipBracedSection( &p ); } if ( !p ) return qfalse; saber->name = G_NewString( SaberName ); if ( G_ParseLiteral( &p, "{" ) ) return qfalse; // parse the saber info block while ( 1 ) { token = COM_ParseExt( &p, qtrue ); if ( !token[0] ) { gi.Printf( S_COLOR_RED"ERROR: unexpected EOF while parsing '%s' (WP_SaberParseParms)\n", SaberName ); return qfalse; } if ( !Q_stricmp( token, "}" ) ) break; key = KeywordHash_Find( saberParseKeywordHash, token ); if ( key ) { key->func( saber, &p ); continue; } gi.Printf( "WARNING: unknown keyword '%s' while parsing '%s'\n", token, SaberName ); SkipRestOfLine( &p ); } //FIXME: precache the saberModel(s)? if ( saber->type == SABER_SITH_SWORD ) {//precache all the sith sword sounds Saber_SithSwordPrecache(); } return qtrue; } void WP_RemoveSaber( gentity_t *ent, int saberNum ) { if ( !ent || !ent->client ) { return; } //reset everything for this saber just in case WP_SaberSetDefaults( &ent->client->ps.saber[saberNum] ); ent->client->ps.dualSabers = qfalse; ent->client->ps.saber[saberNum].Deactivate(); ent->client->ps.saber[saberNum].SetLength( 0.0f ); if ( ent->weaponModel[saberNum] > 0 ) { gi.G2API_SetSkin( &ent->ghoul2[ent->weaponModel[saberNum]], -1, 0 ); gi.G2API_RemoveGhoul2Model( ent->ghoul2, ent->weaponModel[saberNum] ); ent->weaponModel[saberNum] = -1; } if ( ent->client->ps.saberAnimLevel == SS_DUAL || ent->client->ps.saberAnimLevel == SS_STAFF ) {//change to the style to the default for ( int i = SS_NONE+1; i < SS_NUM_SABER_STYLES; i++ ) { if ( (ent->client->ps.saberStylesKnown&(1<client->ps.saberAnimLevel = i; if ( ent->s.number < MAX_CLIENTS ) { cg.saberAnimLevelPending = ent->client->ps.saberAnimLevel; } break; } } } } void WP_SetSaber( gentity_t *ent, int saberNum, const char *saberName ) { if ( !ent || !ent->client ) { return; } if ( Q_stricmp( "none", saberName ) == 0 || Q_stricmp( "remove", saberName ) == 0 ) { WP_RemoveSaber( ent, saberNum ); return; } if ( ent->weaponModel[saberNum] > 0 ) { gi.G2API_RemoveGhoul2Model(ent->ghoul2, ent->weaponModel[saberNum]); ent->weaponModel[saberNum] = -1; } WP_SaberParseParms( saberName, &ent->client->ps.saber[saberNum] );//get saber info if ( ent->client->ps.saber[saberNum].stylesLearned ) { ent->client->ps.saberStylesKnown |= ent->client->ps.saber[saberNum].stylesLearned; } if ( ent->client->ps.saber[saberNum].singleBladeStyle ) { ent->client->ps.saberStylesKnown |= ent->client->ps.saber[saberNum].singleBladeStyle; } if ( saberNum == 1 && (ent->client->ps.saber[1].saberFlags&SFL_TWO_HANDED) ) {//not allowed to use a 2-handed saber as second saber WP_RemoveSaber( ent, saberNum ); return; } G_ModelIndex( ent->client->ps.saber[saberNum].model ); WP_SaberInitBladeData( ent ); if ( saberNum == 1 ) {//now have 2 sabers ent->client->ps.dualSabers = qtrue; } /* else if ( saberNum == 0 ) { if ( ent->weaponModel[1] == -1 ) {//don't have 2 sabers ent->client->ps.dualSabers = qfalse; } } */ WP_SaberAddG2SaberModels( ent, saberNum ); ent->client->ps.saber[saberNum].SetLength( 0.0f ); ent->client->ps.saber[saberNum].Activate(); if ( ent->client->ps.saber[saberNum].stylesLearned ) {//change to the style we're supposed to be using ent->client->ps.saberStylesKnown |= ent->client->ps.saber[saberNum].stylesLearned; } if ( ent->client->ps.saber[saberNum].singleBladeStyle ) { ent->client->ps.saberStylesKnown |= ent->client->ps.saber[saberNum].singleBladeStyle; } WP_UseFirstValidSaberStyle( ent, &ent->client->ps.saberAnimLevel ); if ( ent->s.number < MAX_CLIENTS ) { cg.saberAnimLevelPending = ent->client->ps.saberAnimLevel; } } void WP_SaberSetColor( gentity_t *ent, int saberNum, int bladeNum, char *colorName ) { if ( !ent || !ent->client ) { return; } ent->client->ps.saber[saberNum].blade[bladeNum].color = TranslateSaberColor( colorName ); } extern void WP_SetSaberEntModelSkin( gentity_t *ent, gentity_t *saberent ); qboolean WP_BreakSaber( gentity_t *ent, const char *surfName, saberType_t saberType ) {//Make sure there *is* one specified and not using dualSabers if ( ent == NULL || ent->client == NULL ) {//invalid ent or client return qfalse; } if ( ent->s.number < MAX_CLIENTS ) {//player //if ( g_spskill->integer < 3 ) {//only on the hardest level? //FIXME: add a cvar? return qfalse; } } if ( ent->health <= 0 ) {//not if they're dead return qfalse; } if ( ent->client->ps.weapon != WP_SABER ) {//not holding saber return qfalse; } if ( ent->client->ps.dualSabers ) {//FIXME: handle this? return qfalse; } if ( !ent->client->ps.saber[0].brokenSaber1 ) {//not breakable into another type of saber return qfalse; } if ( PM_SaberInStart( ent->client->ps.saberMove ) //in a start || PM_SaberInTransition( ent->client->ps.saberMove ) //in a transition || PM_SaberInAttack( ent->client->ps.saberMove ) )//in an attack {//don't break when in the middle of an attack return qfalse; } if ( Q_stricmpn( "w_", surfName, 2 ) && Q_stricmpn( "saber", surfName, 5 ) //hack because using mod-community made saber && Q_stricmp( "cylinder01", surfName ) )//hack because using mod-community made saber {//didn't hit my weapon return qfalse; } //Sith Sword should ALWAYS do this if ( saberType != SABER_SITH_SWORD && Q_irand( 0, 50 ) )//&& Q_irand( 0, 10 ) ) {//10% chance - FIXME: extern this, too? return qfalse; } //break it char *replacementSaber1 = G_NewString( ent->client->ps.saber[0].brokenSaber1 ); char *replacementSaber2 = G_NewString( ent->client->ps.saber[0].brokenSaber2 ); int i, originalNumBlades = ent->client->ps.saber[0].numBlades; qboolean broken = qfalse; saber_colors_t colors[MAX_BLADES]; //store the colors for ( i = 0; i < MAX_BLADES; i++ ) { colors[i] = ent->client->ps.saber[0].blade[i].color; } //FIXME: chance of dropping the right-hand one? Based on damage, or...? //FIXME: sound & effect when this happens, and send them into a broken parry? //remove saber[0], replace with replacementSaber1 if ( replacementSaber1 ) { WP_RemoveSaber( ent, 0 ); WP_SetSaber( ent, 0, replacementSaber1 ); for ( i = 0; i < ent->client->ps.saber[0].numBlades; i++ ) { ent->client->ps.saber[0].blade[i].color = colors[i]; } broken = qtrue; //change my saberent's model and skin to match my new right-hand saber WP_SetSaberEntModelSkin( ent, &g_entities[ent->client->ps.saberEntityNum] ); } if ( originalNumBlades <= 1 ) {//nothing to split off //FIXME: handle this? } else { //remove saber[1], replace with replacementSaber2 if ( replacementSaber2 ) {//FIXME: 25% chance that it just breaks - just spawn the second saber piece and toss it away immediately, can't be picked up. //shouldn't be one in this hand, but just in case, remove it WP_RemoveSaber( ent, 1 ); WP_SetSaber( ent, 1, replacementSaber2 ); //put the remainder of the original saber's blade colors onto this saber's blade(s) for ( i = ent->client->ps.saber[0].numBlades; i < MAX_BLADES; i++ ) { ent->client->ps.saber[1].blade[i-ent->client->ps.saber[0].numBlades].color = colors[i]; } broken = qtrue; } } return broken; } void WP_SaberLoadParms( void ) { int len, totallen, saberExtFNLen, fileCnt, i; char *buffer, *holdChar, *marker; char saberExtensionListBuf[2048]; // The list of file names read in //gi.Printf( "Parsing *.sab saber definitions\n" ); //set where to store the first one totallen = 0; marker = SaberParms; marker[0] = '\0'; //now load in the .sab definitions fileCnt = gi.FS_GetFileList("ext_data/sabers", ".sab", saberExtensionListBuf, sizeof(saberExtensionListBuf) ); holdChar = saberExtensionListBuf; for ( i = 0; i < fileCnt; i++, holdChar += saberExtFNLen + 1 ) { saberExtFNLen = strlen( holdChar ); len = gi.FS_ReadFile( va( "ext_data/sabers/%s", holdChar), (void **) &buffer ); if ( len == -1 ) { gi.Printf( "WP_SaberLoadParms: error reading %s\n", holdChar ); } else { if ( totallen && *(marker-1) == '}' ) {//don't let it end on a } because that should be a stand-alone token strcat( marker, " " ); totallen++; marker++; } len = COM_Compress( buffer ); if ( totallen + len >= MAX_SABER_DATA_SIZE ) { G_Error( "WP_SaberLoadParms: ran out of space before reading %s\n(you must make the .sab files smaller)", holdChar ); } strcat( marker, buffer ); gi.FS_FreeFile( buffer ); totallen += len; marker += len; } } }