void WP_SetSaber( gentity_t *ent, int saberNum, 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].style ) { ent->client->ps.saberStylesKnown |= (1<<ent->client->ps.saber[saberNum].style); } if ( saberNum == 1 && ent->client->ps.saber[1].twoHanded ) {//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 ); //int boltNum = ent->handRBolt; if ( saberNum == 1 ) { ent->client->ps.dualSabers = qtrue; //boltNum = ent->handLBolt; } WP_SaberAddG2SaberModels( ent, saberNum ); ent->client->ps.saber[saberNum].SetLength( 0.0f ); ent->client->ps.saber[saberNum].Activate(); if ( ent->client->ps.saber[saberNum].style != SS_NONE ) {//change to the style we're supposed to be using ent->client->ps.saberAnimLevel = ent->client->ps.saber[saberNum].style; ent->client->ps.saberStylesKnown |= (1<<ent->client->ps.saberAnimLevel); if ( ent->s.number < MAX_CLIENTS ) { cg.saberAnimLevelPending = ent->client->ps.saberAnimLevel; } } }
static void Svcmd_Saber_f() { const char *saber = gi.argv(1); const char *saber2 = gi.argv(2); char name[MAX_CVAR_VALUE_STRING] = {0}; if ( gi.argc() < 2 ) { gi.Printf( "Usage: saber <saber1> <saber2>\n" ); gi.Cvar_VariableStringBuffer( "g_saber", name, sizeof(name) ); gi.Printf("g_saber is set to %s\n", name); gi.Cvar_VariableStringBuffer( "g_saber2", name, sizeof(name) ); if ( name[0] ) gi.Printf("g_saber2 is set to %s\n", name); return; } if ( !g_entities[0].client || !saber || !saber[0] ) { return; } gi.cvar_set( "g_saber", saber ); WP_SetSaber( &g_entities[0], 0, saber ); if ( saber2 && saber2[0] && !(g_entities[0].client->ps.saber[0].saberFlags&SFL_TWO_HANDED) ) {//want to use a second saber and first one is not twoHanded gi.cvar_set( "g_saber2", saber2 ); WP_SetSaber( &g_entities[0], 1, saber2 ); } else { gi.cvar_set( "g_saber2", "" ); WP_RemoveSaber( &g_entities[0], 1 ); } }
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].twoHanded) {//not allowed to use a 2-handed saber as second saber WP_RemoveSaber( sabers, 1 ); return; } else if (sabers[0].twoHanded && 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 Pickup_Saber( gentity_t *self, qboolean hadSaber, qboolean saberSolo, char *saberType, char *saberColor ) { //G_RemoveWeaponModels( ent );//??? if ( Q_stricmp( "player", saberType ) == 0 ) {//"player" means use cvar info G_SetSabersFromCVars( self ); } else { saberInfo_t newSaber={0}; if ( WP_SaberParseParms( saberType, &newSaber ) ) {//successfully found a saber .sab entry to use //FIXME: what about dual sabers? int saberNum = 0; if ( saberSolo//only supposed to use this one saber when grab this pickup || newSaber.twoHanded //new saber is two-handed || (hadSaber && self->client->ps.saber[0].twoHanded) )//old saber is two-handed {//replace the old right-hand saber and remove the left hand one WP_RemoveSaber( self, 1 ); } else {//add it as a second saber saberNum = 1; } WP_SetSaber( self, saberNum, saberType ); WP_SaberInitBladeData( self ); if ( self->client->ps.saber[saberNum].style ) { self->client->ps.saberStylesKnown |= (1<<self->client->ps.saber[saberNum].style); } if ( saberColor != NULL ) {//NPC_targetname = saberColor saber_colors_t saber_color = TranslateSaberColor( saberColor ); for ( int bladeNum = 0; bladeNum < MAX_BLADES; bladeNum++ ) { self->client->ps.saber[saberNum].blade[bladeNum].color = saber_color; } } } WP_SaberFreeStrings(newSaber); } }
static void Svcmd_Saber_f() { char *saber = gi.argv(1); char *saber2 = gi.argv(2); if ( !g_entities[0].client || !saber || !saber[0] ) { return; } gi.cvar_set( "g_saber", saber ); WP_SetSaber( &g_entities[0], 0, saber ); if ( saber2 && saber2[0] && !(g_entities[0].client->ps.saber[0].saberFlags&SFL_TWO_HANDED) ) {//want to use a second saber and first one is not twoHanded gi.cvar_set( "g_saber2", saber2 ); WP_SetSaber( &g_entities[0], 1, saber2 ); } else { gi.cvar_set( "g_saber2", "" ); WP_RemoveSaber( &g_entities[0], 1 ); } }
void Cmd_SaberDrop_f( gentity_t *ent, int saberNum ) { if ( saberNum < 0 ) { return; } if ( saberNum > 1 ) { return; } if ( !ent || !ent->client ) { return; } if ( ent->weaponModel[saberNum] <= 0 ) { return; } if ( ent->client->ps.weapon != WP_SABER ) { return; } if ( ent->client->ps.weaponTime > 0 ) { return; } if ( ent->client->ps.saberMove != LS_READY && ent->client->ps.saberMove != LS_PUTAWAY && ent->client->ps.saberMove != LS_DRAW && ent->client->ps.saberMove != LS_NONE ) { return; } if ( !g_saberPickuppableDroppedSabers->integer ) { return; } if ( !ent->client->ps.saber[saberNum].name || !ent->client->ps.saber[saberNum].name[0] ) { return; } //have a valid string to use for saberType //turn it into a pick-uppable item! if ( G_DropSaberItem( ent->client->ps.saber[saberNum].name, ent->client->ps.saber[saberNum].blade[0].color, (saberNum==0?ent->client->renderInfo.handRPoint:ent->client->renderInfo.handLPoint), ent->client->ps.velocity, ent->currentAngles ) != NULL ) {//dropped it WP_RemoveSaber( ent, saberNum ); } if ( ent->weaponModel[0] <= 0 && ent->weaponModel[1] <= 0 ) {//no sabers left! //remove saber from inventory ent->client->ps.stats[STAT_WEAPONS] &= ~(1<<WP_SABER); //change weapons if ( ent->s.number < MAX_CLIENTS ) {//player CG_ChangeWeapon( WP_NONE ); } else { ChangeWeapon( ent, WP_NONE ); } ent->client->ps.weapon = WP_NONE; } }
qboolean Pickup_Saber( gentity_t *self, qboolean hadSaber, gentity_t *pickUpSaber ) { //NOTE: loopAnim = saberSolo, alt_fire = saberLeftHand, NPC_type = saberType, NPC_targetname = saberColor qboolean foundIt = qfalse; if ( !pickUpSaber || !self || !self->client ) { return qfalse; } //G_RemoveWeaponModels( ent );//??? if ( Q_stricmp( "player", pickUpSaber->NPC_type ) == 0 ) {//"player" means use cvar info G_SetSabersFromCVars( self ); foundIt = qtrue; } else { saberInfo_t newSaber={0}; qboolean swapSabers = qfalse; if ( self->client->ps.weapon == WP_SABER && self->client->ps.weaponTime > 0 ) {//can't pick up a new saber while the old one is busy (also helps to work as a debouncer so you don't swap out sabers rapidly when touching more than one at a time) return qfalse; } if ( pickUpSaber->count == 1 && g_saberPickuppableDroppedSabers->integer ) { swapSabers = qtrue; } if ( WP_SaberParseParms( pickUpSaber->NPC_type, &newSaber ) ) {//successfully found a saber .sab entry to use int saberNum = 0; qboolean removeLeftSaber = qfalse; if ( pickUpSaber->alt_fire ) {//always go in the left hand if ( !hadSaber ) {//can't have a saber only in your left hand! return qfalse; } saberNum = 1; //just in case... removeLeftSaber = qtrue; } else if ( !hadSaber ) {//don't have a saber at all yet, put it in our right hand saberNum = 0; //just in case... removeLeftSaber = qtrue; } else if ( pickUpSaber->loopAnim//only supposed to use this one saber when grab this pickup || (newSaber.saberFlags&SFL_TWO_HANDED) //new saber is two-handed || (hadSaber && (self->client->ps.saber[0].saberFlags&SFL_TWO_HANDED)) )//old saber is two-handed {//replace the old right-hand saber and remove the left hand one saberNum = 0; removeLeftSaber = qtrue; } else {//have, at least, a saber in our right hand and the new one could go in either left or right hand if ( self->client->ps.dualSabers ) {//I already have 2 sabers vec3_t dir2Saber, rightDir; //to determine which one to replace, see which side of me it's on VectorSubtract( pickUpSaber->currentOrigin, self->currentOrigin, dir2Saber ); dir2Saber[2] = 0; AngleVectors( self->currentAngles, NULL, rightDir, NULL ); rightDir[2] = 0; if ( DotProduct( rightDir, dir2Saber ) > 0 ) { saberNum = 0; } else { saberNum = 1; //just in case... removeLeftSaber = qtrue; } } else {//just add it as a second saber saberNum = 1; //just in case... removeLeftSaber = qtrue; } } if ( saberNum == 0 ) {//want to reach out with right hand if ( self->client->ps.torsoAnim == BOTH_BUTTON_HOLD ) {//but only if already playing the pickup with left hand anim... NPC_SetAnim( self, SETANIM_TORSO, BOTH_SABERPULL, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD ); } if ( swapSabers ) {//drop first one where the one we're picking up is G_DropSaberItem( self->client->ps.saber[saberNum].name, self->client->ps.saber[saberNum].blade[0].color, pickUpSaber->currentOrigin, (float *)vec3_origin, pickUpSaber->currentAngles, pickUpSaber ); if ( removeLeftSaber ) {//drop other one at my origin G_DropSaberItem( self->client->ps.saber[1].name, self->client->ps.saber[1].blade[0].color, self->currentOrigin, (float *)vec3_origin, self->currentAngles, pickUpSaber ); } } } else { if ( swapSabers ) { G_DropSaberItem( self->client->ps.saber[saberNum].name, self->client->ps.saber[saberNum].blade[0].color, pickUpSaber->currentOrigin, (float *)vec3_origin, pickUpSaber->currentAngles, pickUpSaber ); } } if ( removeLeftSaber ) { WP_RemoveSaber( self, 1 ); } WP_SetSaber( self, saberNum, pickUpSaber->NPC_type ); WP_SaberInitBladeData( self ); if ( self->client->ps.saber[saberNum].stylesLearned ) { self->client->ps.saberStylesKnown |= self->client->ps.saber[saberNum].stylesLearned; } if ( self->client->ps.saber[saberNum].singleBladeStyle ) { self->client->ps.saberStylesKnown |= self->client->ps.saber[saberNum].singleBladeStyle; } if ( pickUpSaber->NPC_targetname != NULL ) {//NPC_targetname = saberColor saber_colors_t saber_color = TranslateSaberColor( pickUpSaber->NPC_targetname ); for ( int bladeNum = 0; bladeNum < MAX_BLADES; bladeNum++ ) { self->client->ps.saber[saberNum].blade[bladeNum].color = saber_color; } } if ( self->client->ps.torsoAnim == BOTH_BUTTON_HOLD || self->client->ps.torsoAnim == BOTH_SABERPULL ) {//don't let them attack right away, force them to finish the anim self->client->ps.weaponTime = self->client->ps.torsoAnimTimer; } foundIt = qtrue; } WP_SaberFreeStrings(newSaber); } return foundIt; }
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, 6 ) //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; }