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; }