void G_Gametype_GENERIC_ClientRespawn( edict_t *self, int old_team, int new_team ) { int i; gclient_t *client = self->r.client; gs_weapon_definition_t *weapondef; if( G_ISGHOSTING( self ) ) return; //give default items if( self->s.team != TEAM_SPECTATOR ) { if( GS_Instagib() ) { client->ps.inventory[WEAP_INSTAGUN] = 1; client->ps.inventory[AMMO_INSTAS] = 1; client->ps.inventory[AMMO_WEAK_INSTAS] = 1; } else { if( GS_MatchState() <= MATCH_STATE_WARMUP ) { for( i = WEAP_GUNBLADE; i < WEAP_TOTAL; i++ ) { if( i == WEAP_INSTAGUN ) // dont add instagun... continue; weapondef = GS_GetWeaponDef( i ); client->ps.inventory[i] = 1; if( weapondef->firedef_weak.ammo_id ) client->ps.inventory[weapondef->firedef_weak.ammo_id] = weapondef->firedef_weak.ammo_max; if( weapondef->firedef.ammo_id ) client->ps.inventory[weapondef->firedef.ammo_id] = weapondef->firedef.ammo_max; } client->resp.armor = GS_Armor_MaxCountForTag( ARMOR_YA ); } else { weapondef = GS_GetWeaponDef( WEAP_GUNBLADE ); client->ps.inventory[WEAP_GUNBLADE] = 1; client->ps.inventory[AMMO_GUNBLADE] = weapondef->firedef.ammo_max;; client->ps.inventory[AMMO_WEAK_GUNBLADE] = 0; } } } // select rocket launcher if available if( GS_CheckAmmoInWeapon( &client->ps, WEAP_ROCKETLAUNCHER ) ) client->ps.stats[STAT_PENDING_WEAPON] = WEAP_ROCKETLAUNCHER; else client->ps.stats[STAT_PENDING_WEAPON] = GS_SelectBestWeapon( &client->ps ); // add a teleportation effect if( self->r.solid != SOLID_NOT ) G_RespawnEffect( self ); }
//========================================== // BOT_DMClass_ChangeWeapon //========================================== static bool BOT_DMClass_ChangeWeapon( edict_t *self, int weapon ) { if( weapon == self->r.client->ps.stats[STAT_PENDING_WEAPON] ) return false; if( !GS_CheckAmmoInWeapon( &self->r.client->ps , weapon ) ) return false; // Change to this weapon self->r.client->ps.stats[STAT_PENDING_WEAPON] = weapon; self->ai->changeweapon_timeout = level.time + 2000 + ( 4000 * ( 1.0 - self->ai->pers.skillLevel ) ); return true; }
//========================================== // BOT_DMclass_ChooseWeapon // Choose weapon based on range & weights //========================================== static float BOT_DMclass_ChooseWeapon( edict_t *self ) { float dist; int i; float best_weight = 0.0; gsitem_t *weaponItem; int curweapon, weapon_range = 0, best_weapon = WEAP_NONE; curweapon = self->r.client->ps.stats[STAT_PENDING_WEAPON]; // if no enemy, then what are we doing here? if( !self->enemy ) { weapon_range = AIWEAP_MEDIUM_RANGE; if( curweapon == WEAP_GUNBLADE || curweapon == WEAP_NONE ) self->ai->changeweapon_timeout = level.time; } else // Base weapon selection on distance: { dist = DistanceFast( self->s.origin, self->enemy->s.origin ); if( dist < 150 ) weapon_range = AIWEAP_MELEE_RANGE; else if( dist < 500 ) // Medium range limit is Grenade launcher range weapon_range = AIWEAP_SHORT_RANGE; else if( dist < 900 ) weapon_range = AIWEAP_MEDIUM_RANGE; else weapon_range = AIWEAP_LONG_RANGE; } if( self->ai->changeweapon_timeout > level.time ) return AIWeapons[curweapon].RangeWeight[weapon_range]; for( i = WEAP_GUNBLADE; i < WEAP_TOTAL; i++ ) { float rangeWeight; if( ( weaponItem = GS_FindItemByTag( i ) ) == NULL ) continue; if( !GS_CheckAmmoInWeapon( &self->r.client->ps, i ) ) continue; rangeWeight = AIWeapons[i].RangeWeight[weapon_range] * self->ai->pers.cha.weapon_affinity[i - ( WEAP_GUNBLADE - 1 )]; // weigh up if having strong ammo if( self->r.client->ps.inventory[weaponItem->ammo_tag] ) rangeWeight *= 1.25; // add a small random factor (less random the more skill) rangeWeight += brandom( -( 1.0 - self->ai->pers.skillLevel ), 1.0 - self->ai->pers.skillLevel ); // compare range weights if( rangeWeight > best_weight ) { best_weight = rangeWeight; best_weapon = i; } } // do the change (same weapon, or null best_weapon is covered at ChangeWeapon) if( best_weapon != WEAP_NONE ) BOT_DMClass_ChangeWeapon( self, best_weapon ); return AIWeapons[curweapon].RangeWeight[weapon_range]; // return current }
/* * GS_ThinkPlayerWeapon */ int GS_ThinkPlayerWeapon( player_state_t *playerState, int buttons, int msecs, int timeDelta ) { firedef_t *firedef; qboolean refire = qfalse; assert( playerState->stats[STAT_PENDING_WEAPON] >= 0 && playerState->stats[STAT_PENDING_WEAPON] < WEAP_TOTAL ); if( GS_MatchPaused() ) return playerState->stats[STAT_WEAPON]; if( playerState->pmove.pm_type != PM_NORMAL ) { playerState->weaponState = WEAPON_STATE_READY; playerState->stats[STAT_PENDING_WEAPON] = playerState->stats[STAT_WEAPON] = WEAP_NONE; playerState->stats[STAT_WEAPON_TIME] = 0; return playerState->stats[STAT_WEAPON]; } if( playerState->pmove.stats[PM_STAT_NOUSERCONTROL] > 0 ) buttons = 0; if( !msecs ) goto done; if( playerState->stats[STAT_WEAPON_TIME] > 0 ) playerState->stats[STAT_WEAPON_TIME] -= msecs; else playerState->stats[STAT_WEAPON_TIME] = 0; firedef = GS_FiredefForPlayerState( playerState, playerState->stats[STAT_WEAPON] ); // during cool-down time it can shoot again or go into reload time if( playerState->weaponState == WEAPON_STATE_REFIRE || playerState->weaponState == WEAPON_STATE_REFIRESTRONG ) { int last_firemode; if( playerState->stats[STAT_WEAPON_TIME] > 0 ) goto done; last_firemode = ( playerState->weaponState == WEAPON_STATE_REFIRESTRONG ) ? FIRE_MODE_STRONG : FIRE_MODE_WEAK; if( last_firemode == firedef->fire_mode ) refire = qtrue; playerState->weaponState = WEAPON_STATE_READY; } // nothing can be done during reload time if( playerState->weaponState == WEAPON_STATE_RELOADING ) { if( playerState->stats[STAT_WEAPON_TIME] > 0 ) goto done; playerState->weaponState = WEAPON_STATE_READY; } if( playerState->weaponState == WEAPON_STATE_NOAMMOCLICK ) { if( playerState->stats[STAT_WEAPON_TIME] > 0 ) goto done; if( playerState->stats[STAT_WEAPON] != playerState->stats[STAT_PENDING_WEAPON] ) playerState->weaponState = WEAPON_STATE_READY; } // there is a weapon to be changed if( playerState->stats[STAT_WEAPON] != playerState->stats[STAT_PENDING_WEAPON] ) { if( ( playerState->weaponState == WEAPON_STATE_READY ) || ( playerState->weaponState == WEAPON_STATE_DROPPING ) || ( playerState->weaponState == WEAPON_STATE_ACTIVATING ) ) { if( playerState->weaponState != WEAPON_STATE_DROPPING ) { playerState->weaponState = WEAPON_STATE_DROPPING; playerState->stats[STAT_WEAPON_TIME] += firedef->weapondown_time; if( firedef->weapondown_time ) module_PredictedEvent( playerState->POVnum, EV_WEAPONDROP, 0 ); } } } // do the change if( playerState->weaponState == WEAPON_STATE_DROPPING ) { if( playerState->stats[STAT_WEAPON_TIME] > 0 ) goto done; playerState->stats[STAT_WEAPON] = playerState->stats[STAT_PENDING_WEAPON]; // update the firedef firedef = GS_FiredefForPlayerState( playerState, playerState->stats[STAT_WEAPON] ); playerState->weaponState = WEAPON_STATE_ACTIVATING; playerState->stats[STAT_WEAPON_TIME] += firedef->weaponup_time; module_PredictedEvent( playerState->POVnum, EV_WEAPONACTIVATE, playerState->stats[STAT_WEAPON] ); } if( playerState->weaponState == WEAPON_STATE_ACTIVATING ) { if( playerState->stats[STAT_WEAPON_TIME] > 0 ) goto done; playerState->weaponState = WEAPON_STATE_READY; } if( ( playerState->weaponState == WEAPON_STATE_READY ) || ( playerState->weaponState == WEAPON_STATE_NOAMMOCLICK ) ) { if( playerState->stats[STAT_WEAPON_TIME] > 0 ) goto done; if( !GS_ShootingDisabled() ) { if( buttons & BUTTON_ATTACK ) { if( GS_CheckAmmoInWeapon( playerState, playerState->stats[STAT_WEAPON] ) ) { playerState->weaponState = WEAPON_STATE_FIRING; } else { // player has no ammo nor clips if( playerState->weaponState == WEAPON_STATE_NOAMMOCLICK ) { playerState->weaponState = WEAPON_STATE_RELOADING; playerState->stats[STAT_WEAPON_TIME] += NOAMMOCLICK_AUTOSWITCH; if( playerState->stats[STAT_PENDING_WEAPON] == playerState->stats[STAT_WEAPON] ) playerState->stats[STAT_PENDING_WEAPON] = GS_SelectBestWeapon( playerState ); } else { playerState->weaponState = WEAPON_STATE_NOAMMOCLICK; playerState->stats[STAT_WEAPON_TIME] += NOAMMOCLICK_PENALTY; module_PredictedEvent( playerState->POVnum, EV_NOAMMOCLICK, 0 ); goto done; } } } // gunblade auto attack is special else if( playerState->stats[STAT_WEAPON] == WEAP_GUNBLADE && playerState->pmove.stats[PM_STAT_NOUSERCONTROL] <= 0 && playerState->pmove.stats[PM_STAT_NOAUTOATTACK] <= 0 && GS_CheckBladeAutoAttack( playerState, timeDelta ) ) { firedef = &GS_GetWeaponDef( WEAP_GUNBLADE )->firedef_weak; playerState->weaponState = WEAPON_STATE_FIRING; } } } if( playerState->weaponState == WEAPON_STATE_FIRING ) { int parm = playerState->stats[STAT_WEAPON]; if( firedef->fire_mode == FIRE_MODE_STRONG ) parm |= EV_INVERSE; playerState->stats[STAT_WEAPON_TIME] += firedef->reload_time; if( firedef->fire_mode == FIRE_MODE_STRONG ) playerState->weaponState = WEAPON_STATE_REFIRESTRONG; else playerState->weaponState = WEAPON_STATE_REFIRE; if( refire && firedef->smooth_refire ) module_PredictedEvent( playerState->POVnum, EV_SMOOTHREFIREWEAPON, parm ); else module_PredictedEvent( playerState->POVnum, EV_FIREWEAPON, parm ); // waste ammo if( !GS_InfiniteAmmo() ) { if( firedef->ammo_id != AMMO_NONE && firedef->usage_count ) playerState->inventory[firedef->ammo_id] -= firedef->usage_count; } } done: return playerState->stats[STAT_WEAPON]; }