/* ================= UpdateClientData Data sent to current client only engine sets cd to 0 before calling. ================= */ void UpdateClientData ( const struct edict_s *ent, int sendweapons, struct clientdata_s *cd ) { cd->flags = ent->v.flags; cd->health = ent->v.health; cd->viewmodel = MODEL_INDEX( STRING( ent->v.viewmodel ) ); cd->waterlevel = ent->v.waterlevel; cd->watertype = ent->v.watertype; cd->weapons = ent->v.weapons; // Vectors cd->origin = ent->v.origin; cd->velocity = ent->v.velocity; cd->view_ofs = ent->v.view_ofs; cd->punchangle = ent->v.punchangle; cd->bInDuck = ent->v.bInDuck; cd->flTimeStepSound = ent->v.flTimeStepSound; cd->flDuckTime = ent->v.flDuckTime; cd->flSwimTime = ent->v.flSwimTime; cd->waterjumptime = ent->v.teleport_time; strcpy( cd->physinfo, ENGINE_GETPHYSINFO( ent ) ); cd->maxspeed = ent->v.maxspeed; cd->fov = ent->v.fov; cd->weaponanim = ent->v.weaponanim; cd->pushmsec = ent->v.pushmsec; // Spectator cd->iuser1 = ent->v.iuser1; cd->iuser2 = ent->v.iuser2; if ( sendweapons ) { entvars_t *pev = (entvars_t *)&ent->v; CBasePlayer *pl = ( CBasePlayer *) CBasePlayer::Instance( pev ); if ( pl ) { cd->m_flNextAttack = pl->m_flNextAttack; if ( pl->m_pActiveItem ) { CBasePlayerWeapon *gun; gun = (CBasePlayerWeapon *)pl->m_pActiveItem->GetWeaponPtr(); if ( gun && gun->UseDecrement() ) { ItemInfo II; memset( &II, 0, sizeof( II ) ); gun->GetItemInfo( &II ); cd->m_iId = II.iId; } } } } }
int GetWeaponData( struct edict_s *player, struct weapon_data_s *info ) { #if defined( CLIENT_WEAPONS ) int i; weapon_data_t *item; entvars_t *pev = &player->v; CBasePlayer *pl = ( CBasePlayer *) CBasePlayer::Instance( pev ); CBasePlayerWeapon *gun; ItemInfo II; memset( info, 0, 32 * sizeof( weapon_data_t ) ); if ( !pl ) return 1; // go through all of the weapons and make a list of the ones to pack for ( i = 0 ; i < MAX_ITEM_TYPES ; i++ ) { if ( pl->m_rgpPlayerItems[ i ] ) { // there's a weapon here. Should I pack it? CBasePlayerItem *pPlayerItem = pl->m_rgpPlayerItems[ i ]; while ( pPlayerItem ) { gun = (CBasePlayerWeapon *)pPlayerItem->GetWeaponPtr(); if ( gun && gun->UseDecrement() ) { // Get The ID. memset( &II, 0, sizeof( II ) ); gun->GetItemInfo( &II ); if ( II.iId >= 0 && II.iId < 32 ) { item = &info[ II.iId ]; item->m_iId = II.iId; item->m_iClip = gun->m_iClip; item->m_flTimeWeaponIdle = max( gun->m_flTimeWeaponIdle, -0.001 ); item->m_flNextPrimaryAttack = max( gun->m_flNextPrimaryAttack, -0.001 ); item->m_flNextSecondaryAttack = max( gun->m_flNextSecondaryAttack, -0.001 ); item->m_fInReload = gun->m_fInReload; } } pPlayerItem = pPlayerItem->m_pNext; } } } #else memset( info, 0, 32 * sizeof( weapon_data_t ) ); #endif return 1; }
// // Think: // Used for selection of weapon menu item. // void CHudAmmo::Think() { if( m_bNeedsLocalUpdate ) { m_bNeedsLocalUpdate = false; if( m_pWeapon ) UpdateWeaponHUD( m_pWeapon, m_bOnTarget ); } if ( gHUD.m_bPlayerDead ) return; CBasePlayer* pPlayer = g_Prediction.GetLocalPlayer(); if ( gHUD.m_iWeaponBits != pPlayer->pev->weapons ) { pPlayer->pev->weapons = gHUD.m_iWeaponBits; for (int i = MAX_WEAPONS-1; i > 0; i-- ) { CBasePlayerWeapon *p = g_Prediction.GetWeapon(i); if ( p && p->GetWeaponInfo() ) { if ( gHUD.m_iWeaponBits & ( 1 << p->GetWeaponInfo()->GetID() ) ) pPlayer->AddPlayerItem( p ); else pPlayer->RemovePlayerItem( p ); } } } if( !m_pActiveSel ) return; // has the player selected one? if (gHUD.m_iKeyBits & IN_ATTACK) { if ( m_pActiveSel != (CBasePlayerWeapon *)1) { ServerCmd( m_pActiveSel->GetWeaponInfo()->GetWeaponName()); g_weaponselect = m_pActiveSel->GetWeaponInfo()->GetID(); } m_pLastSel = m_pActiveSel; m_pActiveSel = nullptr; gHUD.m_iKeyBits &= ~IN_ATTACK; PlaySound("common/wpn_select.wav", 1); } }
void CWeaponBox::Touch( CBaseEntity *pOther ) { if ( !(pev->flags & FL_ONGROUND ) ) return; if ( !pOther->IsPlayer() ) return; if ( !pOther->IsAlive() ) return; CBasePlayer *pPlayer = (CBasePlayer *)pOther; int i; // dole out ammo for ( i = 0 ; i < MAX_AMMO_SLOTS ; i++ ) { if ( !FStringNull( m_rgiszAmmo[ i ] ) ) { // there's some ammo of this type. pPlayer->GiveAmmo( m_rgAmmo[ i ], (char *)STRING( m_rgiszAmmo[ i ] ), MaxAmmoCarry( m_rgiszAmmo[ i ] ) ); // now empty the ammo from the weaponbox since we just gave it to the player m_rgiszAmmo[ i ] = iStringNull; m_rgAmmo[ i ] = 0; } } // go through my weapons and try to give the usable ones to the player. // it's important the the player be given ammo first, so the weapons code doesn't refuse // to deploy a better weapon that the player may pick up because he has no ammo for it. for ( i = 0 ; i < MAX_ITEM_TYPES ; i++ ) { if ( m_rgpPlayerItems[ i ] ) { CBasePlayerWeapon *pItem; // have at least one weapon in this slot while ( m_rgpPlayerItems[i] ) { pItem = m_rgpPlayerItems[i]; m_rgpPlayerItems[i] = m_rgpPlayerItems[i]->m_pNext; // unlink this weapon from the box if( pPlayer->AddPlayerItem( pItem )) pItem->AttachToPlayer( pPlayer ); } } } EMIT_SOUND( pOther->edict(), CHAN_BODY, "items/gunpickup2.wav", 1, ATTN_NORM ); SetTouch( NULL ); UTIL_Remove( this ); }
bool HUD_GetWeaponEnabled(int inID) { ASSERT(inID >= 0); ASSERT(inID < 32); // puzl: 497 - use the enabled state in the associated WEAPON instead of the CBasePlayerWeapon's iuser3 bool theWeaponEnabled = false; CBasePlayerWeapon* theWeapon = g_pWpns[inID]; if(theWeapon) { ItemInfo theItemInfo; theWeapon->GetItemInfo(&theItemInfo); WEAPON *pWeapon = gWR.GetWeapon( theItemInfo.iId ); if ( pWeapon != 0 ) { theWeaponEnabled = (pWeapon->iEnabled == 1); } } return theWeaponEnabled; }
void CWeaponBox::Kill( void ) { CBasePlayerWeapon *pWeapon; int i; // destroy the weapons for ( i = 0 ; i < MAX_ITEM_TYPES ; i++ ) { pWeapon = m_rgpPlayerItems[ i ]; while ( pWeapon ) { pWeapon->SetThink( Remove ); pWeapon->SetNextThink( 0.1 ); pWeapon = pWeapon->m_pNext; } } // remove the box UTIL_Remove( this ); }
/* ===================== HUD_WeaponsPostThink Run Weapon firing code on client ===================== */ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cmd, double time, unsigned int random_seed ) { int i; int buttonsChanged; CBasePlayerWeapon *pWeapon = NULL; CBasePlayerWeapon *pCurrent; weapon_data_t nulldata, *pfrom, *pto; static int lasthealth; memset( &nulldata, 0, sizeof( nulldata ) ); HUD_InitClientWeapons(); // Get current clock gpGlobals->time = time; // Fill in data based on selected weapon // FIXME, make this a method in each weapon? where you pass in an entity_state_t *? switch ( from->client.m_iId ) { case WEAPON_DISC: pWeapon = &g_Disc; break; } // We are not predicting the current weapon, just bow out here. if ( !pWeapon ) return; for ( i = 0; i < 32; i++ ) { pCurrent = g_pWpns[ i ]; if ( !pCurrent ) { continue; } pfrom = &from->weapondata[ i ]; pCurrent->m_fInReload = pfrom->m_fInReload; pCurrent->m_iClip = pfrom->m_iClip; pCurrent->m_flNextPrimaryAttack = pfrom->m_flNextPrimaryAttack; pCurrent->m_flNextSecondaryAttack = pfrom->m_flNextSecondaryAttack; pCurrent->m_flTimeWeaponIdle = pfrom->m_flTimeWeaponIdle; // Ricochet uses m_iClip to transmit current/primary ammo to client if ( pWeapon == pCurrent ) { player.m_rgAmmo[pCurrent->m_iPrimaryAmmoType] = pfrom->m_iClip; } } // For random weapon events, use this seed to seed random # generator player.random_seed = random_seed; // Get old buttons from previous state. player.m_afButtonLast = from->playerstate.oldbuttons; // Which buttsons chave changed buttonsChanged = (player.m_afButtonLast ^ cmd->buttons); // These buttons have changed this frame // Debounced button codes for pressed/released // The changed ones still down are "pressed" player.m_afButtonPressed = buttonsChanged & cmd->buttons; // The ones not down are "released" player.m_afButtonReleased = buttonsChanged & (~cmd->buttons); // Set player variables that weapons code might check/alter player.pev->button = cmd->buttons; player.pev->velocity = from->client.velocity; player.pev->flags = from->client.flags; player.pev->deadflag = from->client.deadflag; player.pev->waterlevel = from->client.waterlevel; player.pev->maxspeed = from->client.maxspeed; player.pev->fov = from->client.fov; player.pev->weaponanim = from->client.weaponanim; player.pev->viewmodel = from->client.viewmodel; player.m_flNextAttack = from->client.m_flNextAttack; player.m_flBackupTime = from->client.fuser1; player.m_Activity = (Activity)(int)from->client.fuser2; player.m_flThrowTime = from->client.fuser3; player.m_vecOldVelocity = from->client.vuser1; player.pev->sequence = from->playerstate.sequence; player.pev->gaitsequence = from->playerstate.gaitsequence; player.pev->angles = from->playerstate.angles; // Point to current weapon object if ( from->client.m_iId ) { player.m_pActiveItem = g_pWpns[ from->client.m_iId ]; } // Store pointer to our destination entity_state_t so we can get our origin, etc. from it // for setting up events on the client g_finalstate = to; // Don't go firing anything if we have died. // Or if we don't have a weapon model deployed if ( ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) && !CL_IsDead() && player.pev->viewmodel ) { if ( player.m_flNextAttack <= 0 ) { pWeapon->ItemPostFrame(); } } // If we are running events/etc. go ahead and see if we // managed to die between last frame and this one // If so, run the appropriate player killed or spawn function if ( g_runfuncs ) { if ( to->client.health <= 0 && lasthealth > 0 ) { player.Killed( NULL, 0 ); } else if ( to->client.health > 0 && lasthealth <= 0 ) { player.Spawn(); } lasthealth = to->client.health; } // Fix up animations, etc. player.PostThink(); // Assume that we are not going to switch weapons to->client.m_iId = from->client.m_iId; // Now see if we issued a changeweapon command ( and we're not dead ) if ( cmd->weaponselect && ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) ) { // Switched to a different weapon? if ( from->weapondata[ cmd->weaponselect ].m_iId == cmd->weaponselect ) { CBasePlayerWeapon *pNew = g_pWpns[ cmd->weaponselect ]; if ( pNew && ( pNew != pWeapon ) ) { // Put away old weapon if (player.m_pActiveItem) player.m_pActiveItem->Holster( ); player.m_pLastItem = player.m_pActiveItem; player.m_pActiveItem = pNew; // Deploy new weapon if (player.m_pActiveItem) { player.m_pActiveItem->Deploy( ); } // Update weapon id so we can predict things correctly. to->client.m_iId = cmd->weaponselect; } } } // Copy in results of predcition code to->client.viewmodel = player.pev->viewmodel; to->client.fov = player.pev->fov; to->client.weaponanim = player.pev->weaponanim; to->client.m_flNextAttack = player.m_flNextAttack; to->client.maxspeed = player.pev->maxspeed; to->client.fuser1 = player.m_flBackupTime; to->client.fuser2 = (float)(int)player.m_Activity; to->client.fuser3 = player.m_flThrowTime; to->client.vuser1 = player.m_vecOldVelocity; to->playerstate.sequence = player.pev->sequence; to->playerstate.gaitsequence = player.pev->gaitsequence; // Make sure that weapon animation matches what the game .dll is telling us // over the wire ( fixes some animation glitches ) if ( g_runfuncs && ( HUD_GetWeaponAnim() != to->client.weaponanim ) ) { int body = 2; // Force a fixed anim down to viewmodel HUD_SendWeaponAnim( to->client.weaponanim, body, 1 ); } for ( i = 0; i < 32; i++ ) { pCurrent = g_pWpns[ i ]; pto = &to->weapondata[ i ]; if ( !pCurrent ) { memset( pto, 0, sizeof( weapon_data_t ) ); continue; } pto->m_fInReload = pCurrent->m_fInReload; pto->m_iClip = pCurrent->m_iClip; pto->m_flNextPrimaryAttack = pCurrent->m_flNextPrimaryAttack; pto->m_flNextSecondaryAttack = pCurrent->m_flNextSecondaryAttack; pto->m_flTimeWeaponIdle = pCurrent->m_flTimeWeaponIdle; // Decrement weapon counters, server does this at same time ( during post think, after doing everything else ) pto->m_flNextReload -= cmd->msec / 1000.0; pto->m_fNextAimBonus -= cmd->msec / 1000.0; pto->m_flNextPrimaryAttack -= cmd->msec / 1000.0; pto->m_flNextSecondaryAttack -= cmd->msec / 1000.0; pto->m_flTimeWeaponIdle -= cmd->msec / 1000.0; if ( pto->m_flPumpTime != -9999 ) { pto->m_flPumpTime -= cmd->msec / 1000.0; if ( pto->m_flPumpTime < -0.001 ) pto->m_flPumpTime = -0.001; } if ( pto->m_fNextAimBonus < -1.0 ) { pto->m_fNextAimBonus = -1.0; } if ( pto->m_flNextPrimaryAttack < -1.0 ) { pto->m_flNextPrimaryAttack = -1.0; } if ( pto->m_flNextSecondaryAttack < -0.001 ) { pto->m_flNextSecondaryAttack = -0.001; } if ( pto->m_flTimeWeaponIdle < -0.001 ) { pto->m_flTimeWeaponIdle = -0.001; } if ( pto->m_flNextReload < -0.001 ) { pto->m_flNextReload = -0.001; } } // m_flNextAttack is now part of the weapons, but is part of the player instead to->client.m_flNextAttack -= cmd->msec / 1000.0; if ( to->client.m_flNextAttack < -0.001 ) { to->client.m_flNextAttack = -0.001; } to->client.fuser1 -= cmd->msec / 1000.0; if ( to->client.fuser1 < -0.001 ) { to->client.fuser1 = -0.001; } to->client.fuser3 -= cmd->msec / 1000.0; if ( to->client.fuser3 < -0.001 ) { to->client.fuser3 = -0.001; } // Wipe it so we can't use it after this frame g_finalstate = NULL; }
// // Draw Weapon Menu // int CHudAmmo::DrawWList(float flTime) { int r,g,b,x,y,a,i; if ( !m_pActiveSel ) return 0; int iActiveSlot; if ( m_pActiveSel == ( CBasePlayerWeapon *)1 ) iActiveSlot = -1; // current slot has no weapons else iActiveSlot = m_pActiveSel->GetWeaponInfo()->GetBucket(); x = 10; //!!! y = 10; //!!! CBasePlayer* pPlayer = g_Prediction.GetLocalPlayer(); // Ensure that there are available choices in the active slot if ( iActiveSlot > 0 ) { if ( !pPlayer->GetFirstPos( iActiveSlot ) ) { m_pActiveSel = ( CBasePlayerWeapon *)1; iActiveSlot = -1; } } // Shepard : determine how many buckets we should draw int iBucketsToDraw = 0; for ( i = 0; i < MAX_WEAPON_SLOTS; i++ ) { for ( int j = 0; j < MAX_WEAPONS; j++ ) { CBasePlayerWeapon *pWeapon = pPlayer->GetWeapon( i, j ); if ( pWeapon && pWeapon->GetWeaponInfo() && pWeapon->GetWeaponInfo()->GetBucket() > iBucketsToDraw ) iBucketsToDraw = pWeapon->GetWeaponInfo()->GetBucket(); } } iBucketsToDraw++; // Draw top line for ( i = 0; i < iBucketsToDraw; i++ ) { int iWidth; gHUD.GetPrimaryColor().UnpackRGB(r,g,b); if ( iActiveSlot == i ) a = 255; else a = 192; ScaleColors(r, g, b, 255); SPR_Set(gHUD.GetSprite(m_HUD_bucket0 + i), r, g, b ); // make active slot wide enough to accomodate gun pictures if ( i == iActiveSlot ) { CBasePlayerWeapon *p = pPlayer->GetFirstPos(iActiveSlot); if ( p ) iWidth = p->GetWeaponInfo()->GetHUDInfo()->GetActive().rect.right - p->GetWeaponInfo()->GetHUDInfo()->GetActive().rect.left; else iWidth = m_iBucketWidth; } else iWidth = m_iBucketWidth; SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_bucket0 + i)); x += iWidth + 5; } a = 128; //!!! x = 10; // Draw all of the buckets for (i = 0; i < iBucketsToDraw; i++) { y = m_iBucketHeight + 10; // If this is the active slot, draw the bigger pictures, // otherwise just draw boxes if ( i == iActiveSlot ) { CBasePlayerWeapon *p = pPlayer->GetFirstPos( i ); int iWidth = m_iBucketWidth; if ( p ) iWidth = p->GetWeaponInfo()->GetHUDInfo()->GetActive().rect.right - p->GetWeaponInfo()->GetHUDInfo()->GetActive().rect.left; for ( int iPos = 0; iPos < MAX_WEAPONS; iPos++ ) { p = pPlayer->GetWeapon( i, iPos ); if ( !p || !p->GetWeaponInfo() ) continue; auto pHUDInfo = p->GetWeaponInfo()->GetHUDInfo(); gHUD.GetPrimaryColor().UnpackRGB( r,g,b ); // if active, then we must have ammo. if ( m_pActiveSel == p ) { SPR_Set( pHUDInfo->GetActive().hSprite, r, g, b ); SPR_DrawAdditive(0, x, y, &pHUDInfo->GetActive().rect ); SPR_Set(gHUD.GetSprite(m_HUD_selection), r, g, b ); SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_selection)); } else { // Draw Weapon if Red if no ammo if ( pPlayer->HasAmmo(p) ) ScaleColors(r, g, b, 192); else { gHUD.GetEmptyItemColor().UnpackRGB(r,g,b); ScaleColors(r, g, b, 128); } SPR_Set( pHUDInfo->GetInactive().hSprite, r, g, b ); SPR_DrawAdditive( 0, x, y, &pHUDInfo->GetInactive().rect ); } // Draw Ammo Bar DrawAmmoBar(p, x + m_iABWidth/2, y, m_iABWidth, m_iABHeight); y += pHUDInfo->GetActive().rect.bottom - pHUDInfo->GetActive().rect.top + 5; } x += iWidth + 5; } else { // Draw Row of weapons. gHUD.GetPrimaryColor().UnpackRGB(r,g,b); for ( int iPos = 0; iPos < MAX_WEAPONS; iPos++ ) { CBasePlayerWeapon *p = pPlayer->GetWeapon( i, iPos ); if ( !p || !p->GetWeaponInfo() ) continue; if ( pPlayer->HasAmmo(p) ) { gHUD.GetPrimaryColor().UnpackRGB(r,g,b); a = 128; } else { gHUD.GetEmptyItemColor().UnpackRGB(r,g,b); a = 96; } FillRGBA( x, y, m_iBucketWidth, m_iBucketHeight, r, g, b, a ); y += m_iBucketHeight + 5; } x += m_iBucketWidth + 5; } } return 1; }
bool CHudAmmo::Draw(float flTime) { int a, x, y, r, g, b; int AmmoWidth; if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) )) return true; if ( (gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )) ) return true; // Draw Weapon Menu DrawWList(flTime); // Draw ammo pickup history gHR.DrawAmmoHistory( flTime ); if (!(m_iFlags & HUD_ACTIVE)) return false; if (!m_pWeapon) return false; if( m_pCrosshair->value != 0 && m_hCrosshair != INVALID_HSPRITE ) { float flScale; switch( static_cast<int>( m_pCrosshairMode->value ) ) { default: case CROSS_NATIVESCALE: flScale = 1; break; case CROSS_RESSCALE: flScale = max( ( ScreenWidth / 640.0 ) * 0.75, 1.0 ); break; case CROSS_USERSCALE: flScale = abs( m_pCrosshairScale->value ); break; } class CCrosshairTriCallback : public ITriCoordFallback { public: void Calculate( HSPRITE hSprite, const int frame, const wrect_t& rect, const float flScale, int& x, int& y ) override { x = ( ScreenWidth - ( ( rect.right - rect.left ) ) ) / 2; y = ( ScreenHeight - ( ( rect.bottom - rect.top ) ) ) / 2; } }; CCrosshairTriCallback callback; Tri_DrawScaledSprite( m_hCrosshair, 0, m_iR, m_iG, m_iB, 255, kRenderTransTexture, flScale, callback, &m_CrosshairRC ); } CBasePlayerWeapon *pw = m_pWeapon; // shorthand // SPR_Draw Ammo if( !pw->GetWeaponInfo()->GetPrimaryAmmo() && !pw->GetWeaponInfo()->GetSecondaryAmmo() ) return false; int iFlags = DHN_DRAWZERO; // draw 0 values AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left; a = (int) max( static_cast<float>( MIN_ALPHA ), m_fFade ); if (m_fFade > 0) m_fFade -= (gHUD.m_flTimeDelta * 20); gHUD.GetPrimaryColor().UnpackRGB(r,g,b); ScaleColors(r, g, b, a ); // Does this weapon have a clip? y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight/2; CBasePlayer* pPlayer = g_Prediction.GetLocalPlayer(); // Does weapon have any ammo at all? if ( auto pAmmo = pw->GetWeaponInfo()->GetPrimaryAmmo() ) { const auto& ammo = m_pWeapon->GetWeaponInfo()->GetHUDInfo()->GetPrimaryAmmo(); int iIconWidth = ammo.rect.right - ammo.rect.left; if (pw->m_iClientClip >= 0) { // room for the number and the '|' and the current ammo x = ScreenWidth - (8 * AmmoWidth) - iIconWidth; x = gHUD.DrawHudNumber(x, y, iFlags | DHN_3DIGITS, pw->m_iClientClip, r, g, b); wrect_t rc; rc.top = 0; rc.left = 0; rc.right = AmmoWidth; rc.bottom = 100; int iBarWidth = AmmoWidth/10; x += AmmoWidth/2; gHUD.GetPrimaryColor().UnpackRGB(r,g,b); // draw the | bar FillRGBA(x, y, iBarWidth, gHUD.m_iFontHeight, r, g, b, a); x += iBarWidth + AmmoWidth/2;; // GL Seems to need this ScaleColors(r, g, b, a ); x = gHUD.DrawHudNumber(x, y, iFlags | DHN_3DIGITS, pPlayer->CountAmmo( pAmmo->GetID() ), r, g, b); } else { // SPR_Draw a bullets only line x = ScreenWidth - 4 * AmmoWidth - iIconWidth; x = gHUD.DrawHudNumber(x, y, iFlags | DHN_3DIGITS, pPlayer->CountAmmo( pAmmo->GetID() ), r, g, b); } // Draw the ammo Icon int iOffset = ( ammo.rect.bottom - ammo.rect.top)/8; SPR_Set( ammo.hSprite, r, g, b); SPR_DrawAdditive(0, x, y - iOffset, &ammo.rect ); } // Does weapon have seconday ammo? if ( auto pAmmo = pw->GetWeaponInfo()->GetSecondaryAmmo() ) { const auto& ammo2 = m_pWeapon->GetWeaponInfo()->GetHUDInfo()->GetSecondaryAmmo(); int iIconWidth = ammo2.rect.right - ammo2.rect.left; // Do we have secondary ammo? if ( pPlayer->CountAmmo( pAmmo->GetID() ) > 0 ) { y -= gHUD.m_iFontHeight + gHUD.m_iFontHeight/4; x = ScreenWidth - 4 * AmmoWidth - iIconWidth; x = gHUD.DrawHudNumber(x, y, iFlags|DHN_3DIGITS, pPlayer->CountAmmo( pAmmo->GetID() ), r, g, b); // Draw the ammo Icon SPR_Set( ammo2.hSprite, r, g, b); int iOffset = ( ammo2.rect.bottom - ammo2.rect.top)/8; SPR_DrawAdditive(0, x, y - iOffset, &ammo2.rect ); } } return true; }
void CHudAmmo::SelectSlot( int iSlot, const bool fAdvance, int iDirection ) { if ( gHUD.m_Menu.m_fMenuDisplayed && !fAdvance && (iDirection == 1) ) { // menu is overriding slot use commands gHUD.m_Menu.SelectMenuItem( iSlot + 1 ); // slots are one off the key numbers return; } if ( iSlot > MAX_WEAPON_SLOTS ) return; if ( gHUD.m_bPlayerDead || gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL ) ) return; if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) )) return; if ( ! ( gHUD.m_iWeaponBits & ~(1<<(WEAPON_SUIT)) )) return; CBasePlayerWeapon *p = NULL; bool fastSwitch = CVAR_GET_FLOAT( "hud_fastswitch" ) != 0; CBasePlayer* pPlayer = g_Prediction.GetLocalPlayer(); if ( ( m_pActiveSel == NULL) || ( m_pActiveSel == ( CBasePlayerWeapon *)1) || (iSlot != m_pActiveSel->GetWeaponInfo()->GetBucket()) ) { PlaySound( "common/wpn_hudon.wav", 1 ); p = pPlayer->GetFirstPos( iSlot ); if ( p && fastSwitch ) // check for fast weapon switch mode { // if fast weapon switch is on, then weapons can be selected in a single keypress // but only if there is only one item in the bucket CBasePlayerWeapon *p2 = pPlayer->GetNextActivePos( p->GetWeaponInfo()->GetBucket(), p->GetWeaponInfo()->GetPosition() ); if ( !p2 ) { // only one active item in bucket, so change directly to weapon ServerCmd( p->GetWeaponInfo()->GetWeaponName() ); g_weaponselect = p->GetWeaponInfo()->GetID(); return; } } } else { PlaySound("common/wpn_moveselect.wav", 1); if ( m_pActiveSel ) p = pPlayer->GetNextActivePos( m_pActiveSel->GetWeaponInfo()->GetBucket(), m_pActiveSel->GetWeaponInfo()->GetPosition() ); if ( !p ) p = pPlayer->GetFirstPos( iSlot ); } if ( !p ) // no selection found { // just display the weapon list, unless fastswitch is on just ignore it if ( !fastSwitch ) m_pActiveSel = ( CBasePlayerWeapon *)1; else m_pActiveSel = nullptr; } else m_pActiveSel = p; }
/* ===================== HUD_WeaponsPostThink Run Weapon firing code on client ===================== */ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cmd, double time, unsigned int random_seed ) { int i; int buttonsChanged; CBasePlayerWeapon* pCurrent = NULL; weapon_data_t nulldata, *pfrom, *pto; static int lasthealth; memset( &nulldata, 0, sizeof( nulldata ) ); HUD_InitClientWeapons(); // Get current clock gpGlobals->time = time; // Fill in data based on selected weapon // FIXME, make this a method in each weapon? where you pass in an entity_state_t *? // Store pointer to our destination entity_state_t so we can get our origin, etc. from it CBasePlayerWeapon* pWeapon = HUD_GetWeaponForID(from->client.m_iId); // for setting up events on the client g_finalstate = to; // If we are running events/etc. go ahead and see if we // managed to die between last frame and this one // If so, run the appropriate player killed or spawn function if ( g_runfuncs ) { if ( to->client.health <= 0 && lasthealth > 0 ) { player.Killed( NULL, 0 ); } else if ( to->client.health > 0 && lasthealth <= 0 ) { player.Spawn(); } lasthealth = to->client.health; } // We are not predicting the current weapon, just bow out here. if ( !pWeapon ) return; for ( i = 0; i < 32; i++ ) { pCurrent = g_pWpns[ i ]; if ( !pCurrent ) { continue; } pfrom = &from->weapondata[ i ]; pCurrent->m_fInReload = pfrom->m_fInReload; pCurrent->m_fInSpecialReload = pfrom->m_fInSpecialReload; // pCurrent->m_flPumpTime = pfrom->m_flPumpTime; pCurrent->m_iClip = pfrom->m_iClip; pCurrent->m_flNextPrimaryAttack = pfrom->m_flNextPrimaryAttack; pCurrent->m_flNextSecondaryAttack = pfrom->m_flNextSecondaryAttack; pCurrent->m_flTimeWeaponIdle = pfrom->m_flTimeWeaponIdle; if(pWeapon && (pWeapon->m_iId == pfrom->m_iId)) { // Predict clip gHUD.m_Ammo.SetCurrentClip(pfrom->m_iClip); AvHBasePlayerWeapon* theWeapon = dynamic_cast<AvHBasePlayerWeapon*>(pWeapon); if(theWeapon) { gHUD.SetCurrentWeaponData(pWeapon->m_iId, theWeapon->GetEnabledState()); } //gHUD.SetClientDebugCSP(pfrom, from->client.m_flNextAttack); } // Tell HUD what energy level is needed to use weapon, so alien HUD can indicate this float theEnergyLevel = 0.0f; AvHMUGetEnergyCost((AvHWeaponID)(pWeapon->m_iId), theEnergyLevel); gHUD.SetCurrentUseableEnergyLevel(theEnergyLevel); // New SDK stuff...needed? // pCurrent->pev->fuser1 = pfrom->fuser1; pCurrent->m_flStartThrow = pfrom->fuser2; pCurrent->m_flReleaseThrow = pfrom->fuser3; // pCurrent->m_chargeReady = pfrom->iuser1; // pCurrent->m_fInAttack = pfrom->iuser2; pCurrent->pev->iuser3 = pfrom->iuser3; // pCurrent->m_iSecondaryAmmoType = (int)from->client.vuser3[2]; pCurrent->m_iPrimaryAmmoType = (int)from->client.vuser4[0]; // player.m_rgAmmo[ pCurrent->m_iPrimaryAmmoType ] = (int)from->client.vuser4[1]; // player.m_rgAmmo[ pCurrent->m_iSecondaryAmmoType ] = (int)from->client.vuser4[2]; } // For random weapon events, use this seed to seed random # generator player.random_seed = random_seed; // Get old buttons from previous state. player.m_afButtonLast = from->playerstate.oldbuttons; // Which buttsons chave changed buttonsChanged = (player.m_afButtonLast ^ cmd->buttons); // These buttons have changed this frame // Debounced button codes for pressed/released // The changed ones still down are "pressed" player.m_afButtonPressed = buttonsChanged & cmd->buttons; // The ones not down are "released" player.m_afButtonReleased = buttonsChanged & (~cmd->buttons); // Set player variables that weapons code might check/alter player.pev->button = cmd->buttons; player.pev->velocity = from->client.velocity; player.pev->flags = from->client.flags; player.pev->deadflag = from->client.deadflag; player.pev->waterlevel = from->client.waterlevel; player.pev->maxspeed = from->client.maxspeed; player.pev->fov = from->client.fov; player.pev->weaponanim = from->client.weaponanim; player.pev->viewmodel = from->client.viewmodel; player.m_flNextAttack = from->client.m_flNextAttack; //player.m_flNextAmmoBurn = from->client.fuser2; //player.m_flAmmoStartCharge = from->client.fuser3; // Removed this because NS uses vuser1 and vuser2 (and the HL weapons aren't used) ////Stores all our ammo info, so the client side weapons can use them. //player.ammo_9mm = (int)from->client.vuser1[0]; //player.ammo_357 = (int)from->client.vuser1[1]; //player.ammo_argrens = (int)from->client.vuser1[2]; //player.ammo_bolts = (int)from->client.ammo_nails; //is an int anyways... //player.ammo_buckshot = (int)from->client.ammo_shells; //player.ammo_uranium = (int)from->client.ammo_cells; //player.ammo_hornets = (int)from->client.vuser2[0]; //player.ammo_rockets = (int)from->client.ammo_rockets; // Point to current weapon object if ( from->client.m_iId ) { player.m_pActiveItem = g_pWpns[ from->client.m_iId ]; } if ( player.m_pActiveItem->m_iId == WEAPON_RPG ) { ( ( CRpg * )player.m_pActiveItem)->m_fSpotActive = (int)from->client.vuser2[ 1 ]; ( ( CRpg * )player.m_pActiveItem)->m_cActiveRockets = (int)from->client.vuser2[ 2 ]; } // Don't go firing anything if we have died. // Or if we don't have a weapon model deployed if ( ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) && !CL_IsDead() && player.pev->viewmodel && !g_iUser1 ) { if ( player.m_flNextAttack <= 0 ) { pWeapon->ItemPostFrame(); } // if ( g_runfuncs ) // { // pWeapon->PrintState(); // } } // Assume that we are not going to switch weapons to->client.m_iId = from->client.m_iId; // Now see if we issued a changeweapon command ( and we're not dead ) if ( cmd->weaponselect && ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) ) { // Switched to a different weapon? if ( from->weapondata[ cmd->weaponselect ].m_iId == cmd->weaponselect ) { ASSERT(cmd->weaponselect >= 0); ASSERT(cmd->weaponselect < 32); CBasePlayerWeapon *pNew = g_pWpns[ cmd->weaponselect ]; if ( pNew && ( pNew != pWeapon ) && player.m_pActiveItem && player.m_pActiveItem->CanHolster()) { // Put away old weapon if (player.m_pActiveItem) player.m_pActiveItem->Holster( ); player.m_pLastItem = player.m_pActiveItem; player.m_pActiveItem = pNew; // Deploy new weapon if (player.m_pActiveItem) { player.m_pActiveItem->Deploy( ); } // Update weapon id so we can predict things correctly. to->client.m_iId = cmd->weaponselect; } } } // Copy in results of prediction code to->client.viewmodel = player.pev->viewmodel; to->client.fov = player.pev->fov; to->client.weaponanim = player.pev->weaponanim; to->client.m_flNextAttack = player.m_flNextAttack; //to->client.fuser2 = player.m_flNextAmmoBurn; //to->client.fuser3 = player.m_flAmmoStartCharge; to->client.maxspeed = player.pev->maxspeed; // Removed this because NS uses vuser1 and vuser2 (and the HL weapons aren't used) // //HL Weapons // to->client.vuser1[0] = player.ammo_9mm; // to->client.vuser1[1] = player.ammo_357; // to->client.vuser1[2] = player.ammo_argrens; // // to->client.ammo_nails = player.ammo_bolts; // to->client.ammo_shells = player.ammo_buckshot; // to->client.ammo_cells = player.ammo_uranium; // to->client.vuser2[0] = player.ammo_hornets; // to->client.ammo_rockets = player.ammo_rockets; if ( player.m_pActiveItem->m_iId == WEAPON_RPG ) { from->client.vuser2[ 1 ] = ( ( CRpg * )player.m_pActiveItem)->m_fSpotActive; from->client.vuser2[ 2 ] = ( ( CRpg * )player.m_pActiveItem)->m_cActiveRockets; } // Make sure that weapon animation matches what the game .dll is telling us // over the wire ( fixes some animation glitches ) if ( g_runfuncs && ( HUD_GetWeaponAnim() != to->client.weaponanim ) ) { int body = 2; //Pop the model to body 0. //if ( pWeapon == &g_Tripmine ) // body = 0; // Force a fixed anim down to viewmodel HUD_SendWeaponAnim( to->client.weaponanim, body, 1 ); } for ( i = 0; i < 32; i++ ) { pCurrent = g_pWpns[ i ]; pto = &to->weapondata[ i ]; if ( !pCurrent ) { memset( pto, 0, sizeof( weapon_data_t ) ); continue; } pto->m_fInReload = pCurrent->m_fInReload; pto->m_fInSpecialReload = pCurrent->m_fInSpecialReload; // pto->m_flPumpTime = pCurrent->m_flPumpTime; pto->m_iClip = pCurrent->m_iClip; pto->m_flNextPrimaryAttack = pCurrent->m_flNextPrimaryAttack; pto->m_flNextSecondaryAttack = pCurrent->m_flNextSecondaryAttack; pto->m_flTimeWeaponIdle = pCurrent->m_flTimeWeaponIdle; // pto->fuser1 = pCurrent->pev->fuser1; // pto->fuser2 = pCurrent->m_flStartThrow; // pto->fuser3 = pCurrent->m_flReleaseThrow; // pto->iuser1 = pCurrent->m_chargeReady; // pto->iuser2 = pCurrent->m_fInAttack; pto->iuser3 = pCurrent->pev->iuser3; // Decrement weapon counters, server does this at same time ( during post think, after doing everything else ) pto->m_flNextReload -= cmd->msec / 1000.0; pto->m_fNextAimBonus -= cmd->msec / 1000.0; pto->m_flNextPrimaryAttack -= cmd->msec / 1000.0; pto->m_flNextSecondaryAttack -= cmd->msec / 1000.0; pto->m_flTimeWeaponIdle -= cmd->msec / 1000.0; pto->fuser1 -= cmd->msec / 1000.0; to->client.vuser3[2] = pCurrent->m_iSecondaryAmmoType; to->client.vuser4 = pCurrent->pev->vuser4; // to->client.vuser4[0] = pCurrent->m_iPrimaryAmmoType; // to->client.vuser4[1] = player.m_rgAmmo[ pCurrent->m_iPrimaryAmmoType ]; // to->client.vuser4[2] = player.m_rgAmmo[ pCurrent->m_iSecondaryAmmoType ]; /* if ( pto->m_flPumpTime != -9999 ) { pto->m_flPumpTime -= cmd->msec / 1000.0; if ( pto->m_flPumpTime < -0.001 ) pto->m_flPumpTime = -0.001; }*/ if ( pto->m_fNextAimBonus < -1.0 ) { pto->m_fNextAimBonus = -1.0; } if ( pto->m_flNextPrimaryAttack < -1.0 ) { pto->m_flNextPrimaryAttack = -1.0; } if ( pto->m_flNextSecondaryAttack < -0.001 ) { pto->m_flNextSecondaryAttack = -0.001; } if ( pto->m_flTimeWeaponIdle < -0.001 ) { pto->m_flTimeWeaponIdle = -0.001; } if ( pto->m_flNextReload < -0.001 ) { pto->m_flNextReload = -0.001; } if ( pto->fuser1 < -0.001 ) { pto->fuser1 = -0.001; } } // m_flNextAttack is now part of the weapons, but is part of the player instead to->client.m_flNextAttack -= cmd->msec / 1000.0; if ( to->client.m_flNextAttack < -0.001 ) { to->client.m_flNextAttack = -0.001; } to->client.fuser2 -= cmd->msec / 1000.0; if ( to->client.fuser2 < -0.001 ) { to->client.fuser2 = -0.001; } to->client.fuser3 -= cmd->msec / 1000.0; if ( to->client.fuser3 < -0.001 ) { to->client.fuser3 = -0.001; } // Store off the last position from the predicted state. HUD_SetLastOrg(); // Wipe it so we can't use it after this frame g_finalstate = NULL; }
/* ===================== HUD_WeaponsPostThink Run Weapon firing code on client ===================== */ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cmd, double time, unsigned int random_seed ) { int i; int buttonsChanged; CBasePlayerWeapon *pWeapon = NULL; CBasePlayerWeapon *pCurrent; weapon_data_t nulldata, *pfrom, *pto; static int lasthealth; memset( &nulldata, 0, sizeof( nulldata ) ); HUD_InitClientWeapons(); // Get current clock gpGlobals->time = time; // Fill in data based on selected weapon // FIXME, make this a method in each weapon? where you pass in an entity_state_t *? switch ( from->client.m_iId ) { case WEAPON_GLOCK: pWeapon = &g_QuakeGun; break; } // Store pointer to our destination entity_state_t so we can get our origin, etc. from it // for setting up events on the client g_finalstate = to; // If we are running events/etc. go ahead and see if we // managed to die between last frame and this one // If so, run the appropriate player killed or spawn function if ( g_runfuncs ) { if ( to->client.health <= 0 && lasthealth > 0 ) { player.Killed( NULL, 0 ); } else if ( to->client.health > 0 && lasthealth <= 0 ) { player.Spawn(); } lasthealth = to->client.health; } // We are not predicting the current weapon, just bow out here. if ( !pWeapon ) return; gpGlobals->deathmatch = from->client.iuser4; for ( i = 0; i < 32; i++ ) { pCurrent = g_pWpns[ i ]; if ( !pCurrent ) { continue; } pfrom = &from->weapondata[ i ]; pCurrent->m_fInReload = pfrom->m_fInReload; pCurrent->m_iClip = pfrom->m_iClip; pCurrent->m_flNextPrimaryAttack = pfrom->m_flNextPrimaryAttack; pCurrent->m_flNextSecondaryAttack = pfrom->m_flNextSecondaryAttack; pCurrent->m_flTimeWeaponIdle = pfrom->m_flTimeWeaponIdle; } // For random weapon events, use this seed to seed random # generator player.random_seed = random_seed; // Get old buttons from previous state. player.m_afButtonLast = from->playerstate.oldbuttons; // Which buttsons chave changed buttonsChanged = (player.m_afButtonLast ^ cmd->buttons); // These buttons have changed this frame // Debounced button codes for pressed/released // The changed ones still down are "pressed" player.m_afButtonPressed = buttonsChanged & cmd->buttons; // The ones not down are "released" player.m_afButtonReleased = buttonsChanged & (~cmd->buttons); // Set player variables that weapons code might check/alter player.pev->button = cmd->buttons; player.pev->velocity = from->client.velocity; player.pev->flags = from->client.flags; player.pev->deadflag = from->client.deadflag; g_iWaterLevel = player.pev->waterlevel = from->client.waterlevel; player.pev->maxspeed = from->client.maxspeed; player.pev->fov = from->client.fov; player.pev->weaponanim = from->client.weaponanim; player.pev->viewmodel = from->client.viewmodel; player.m_flNextAttack = from->client.m_flNextAttack; player.m_iQuakeWeapon = (int)from->client.fuser1; iCarriedWeapons = player.m_iQuakeItems = from->client.iuser3; player.m_iAmmoShells = from->client.ammo_shells; player.m_iAmmoCells = from->client.ammo_cells; player.m_iAmmoRockets = from->client.ammo_rockets; player.m_iAmmoNails = from->client.ammo_nails; player.m_iNailOffset = (int)from->client.fuser2 != 0.0 ? 4.0 : -4.0; // REally useful for debugging prediction /* if ( player.m_iQuakeWeapon > 0 ) { gEngfuncs.Con_NPrintf( 9, "got qw %i", player.m_iQuakeWeapon ); char items[33]; for ( int i = 0; i < 32; i++ ) { if ( player.m_iQuakeItems & (1<<i) ) { items[i] = '1'; } else { items[i] = '0'; } } items[32] = 0; gEngfuncs.Con_NPrintf( 10, "got qi %s", items ); gEngfuncs.Con_NPrintf( 11, "shells %i", player.m_iAmmoShells ); gEngfuncs.Con_NPrintf( 12, "cells %i", player.m_iAmmoCells ); gEngfuncs.Con_NPrintf( 13, "rockets %i", player.m_iAmmoRockets ); gEngfuncs.Con_NPrintf( 14, "nails %i", player.m_iAmmoNails ); gEngfuncs.Con_NPrintf( 15, "viewmodel %i", player.pev->viewmodel ); gEngfuncs.Con_NPrintf( 16, "dm == %i", gpGlobals->deathmatch ); }*/ // Point to current weapon object if ( from->client.m_iId ) { player.m_pActiveItem = g_pWpns[ from->client.m_iId ]; } // Set ammo, but don't change anim player.W_SetCurrentAmmo( 0 ); // Don't go firing anything if we have died. // Or if we don't have a weapon model deployed if ( ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) && !CL_IsDead() ) // && player.pev->viewmodel ) { if ( player.m_flNextAttack <= 0 ) { pWeapon->ItemPostFrame(); } } // Assume that we are not going to switch weapons to->client.m_iId = from->client.m_iId; // Now see if we issued a changeweapon command ( and we're not dead ) if ( cmd->weaponselect && ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) ) { // Switched to a different weapon? if ( Quake_NumForWeaponItem( player.m_iQuakeWeapon ) != cmd->weaponselect ) { player.W_ChangeWeapon( cmd->weaponselect ); } } if ( player.m_iQuakeWeapon != IT_LIGHTNING && pBeam != NULL ) { pBeam->die = 0.0; pBeam = NULL; } // Copy in results of predcition code to->client.viewmodel = player.pev->viewmodel; to->client.fov = player.pev->fov; to->client.weaponanim = player.pev->weaponanim; to->client.m_flNextAttack = player.m_flNextAttack; to->client.maxspeed = player.pev->maxspeed; to->client.iuser3 = player.m_iQuakeItems; to->client.fuser1 = (float)player.m_iQuakeWeapon; to->client.fuser2 = (float)player.m_iNailOffset > 0.0 ? 1.0 : 0.0; to->client.ammo_shells = player.m_iAmmoShells; to->client.ammo_cells = player.m_iAmmoCells; to->client.ammo_rockets = player.m_iAmmoRockets; to->client.ammo_nails = player.m_iAmmoNails; // Make sure that weapon animation matches what the game .dll is telling us // over the wire ( fixes some animation glitches ) if ( g_runfuncs && ( HUD_GetWeaponAnim() != to->client.weaponanim ) ) { int body = 2; // Force a fixed anim down to viewmodel HUD_SendWeaponAnim( to->client.weaponanim, body, 1 ); } for ( i = 0; i < 32; i++ ) { pCurrent = g_pWpns[ i ]; pto = &to->weapondata[ i ]; if ( !pCurrent ) { memset( pto, 0, sizeof( weapon_data_t ) ); continue; } pto->m_fInReload = pCurrent->m_fInReload; pto->m_iClip = pCurrent->m_iClip; pto->m_flNextPrimaryAttack = pCurrent->m_flNextPrimaryAttack; pto->m_flNextSecondaryAttack = pCurrent->m_flNextSecondaryAttack; pto->m_flTimeWeaponIdle = pCurrent->m_flTimeWeaponIdle; // Decrement weapon counters, server does this at same time ( during post think, after doing everything else ) pto->m_flNextReload -= cmd->msec / 1000.0; pto->m_fNextAimBonus -= cmd->msec / 1000.0; pto->m_flNextPrimaryAttack -= cmd->msec / 1000.0; pto->m_flNextSecondaryAttack -= cmd->msec / 1000.0; pto->m_flTimeWeaponIdle -= cmd->msec / 1000.0; if ( pto->m_flPumpTime != -9999 ) { pto->m_flPumpTime -= cmd->msec / 1000.0; if ( pto->m_flPumpTime < -0.001 ) pto->m_flPumpTime = -0.001; } if ( pto->m_fNextAimBonus < -1.0 ) { pto->m_fNextAimBonus = -1.0; } if ( pto->m_flNextPrimaryAttack < -1.0 ) { pto->m_flNextPrimaryAttack = -1.0; } if ( pto->m_flNextSecondaryAttack < -0.001 ) { pto->m_flNextSecondaryAttack = -0.001; } if ( pto->m_flTimeWeaponIdle < -0.001 ) { pto->m_flTimeWeaponIdle = -0.001; } if ( pto->m_flNextReload < -0.001 ) { pto->m_flNextReload = -0.001; } } // m_flNextAttack is now part of the weapons, but is part of the player instead to->client.m_flNextAttack -= cmd->msec / 1000.0; if ( to->client.m_flNextAttack < -0.001 ) { to->client.m_flNextAttack = -0.001; } // Store off the last position from the predicted state. HUD_SetLastOrg(); // Wipe it so we can't use it after this frame g_finalstate = NULL; }
/* ===================== HUD_WeaponsPostThink Run Weapon firing code on client ===================== */ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cmd, double time, unsigned int random_seed ) { int i; int buttonsChanged; CBasePlayerWeapon *pWeapon = NULL; static int lasthealth; int flags; HUD_InitClientWeapons(); // Get current clock gpGlobals->time = time; // Fill in data based on selected weapon switch ( from->client.m_iId ) { case WEAPON_P228: pWeapon = &g_P228; break; case WEAPON_SCOUT: pWeapon = &g_SCOUT; break; case WEAPON_HEGRENADE: pWeapon = &g_HEGrenade; break; case WEAPON_XM1014: pWeapon = &g_XM1014; break; case WEAPON_C4: pWeapon = &g_C4; break; case WEAPON_MAC10: pWeapon = &g_MAC10; break; case WEAPON_AUG: pWeapon = &g_AUG; break; case WEAPON_SMOKEGRENADE: pWeapon = &g_SmokeGrenade; break; case WEAPON_ELITE: pWeapon = &g_ELITE; break; case WEAPON_FIVESEVEN: pWeapon = &g_FiveSeven; break; case WEAPON_UMP45: pWeapon = &g_UMP45; break; case WEAPON_SG550: pWeapon = &g_SG550; break; case WEAPON_GALIL: pWeapon = &g_Galil; break; case WEAPON_FAMAS: pWeapon = &g_Famas; break; case WEAPON_USP: pWeapon = &g_USP; break; case WEAPON_GLOCK18: pWeapon = &g_GLOCK18; break; case WEAPON_AWP: pWeapon = &g_AWP; break; case WEAPON_MP5N: pWeapon = &g_MP5N; break; case WEAPON_M249: pWeapon = &g_M249; break; case WEAPON_M3: pWeapon = &g_M3; break; case WEAPON_M4A1: pWeapon = &g_M4A1; break; case WEAPON_TMP: pWeapon = &g_TMP; break; case WEAPON_G3SG1: pWeapon = &g_G3SG1; break; case WEAPON_FLASHBANG: pWeapon = &g_Flashbang; break; case WEAPON_DEAGLE: pWeapon = &g_DEAGLE; break; case WEAPON_SG552: pWeapon = &g_SG552; break; case WEAPON_AK47: pWeapon = &g_AK47; break; case WEAPON_KNIFE: pWeapon = &g_Knife; break; case WEAPON_P90: pWeapon = &g_P90; break; /*case WEAPON_NONE: break; case WEAPON_GLOCK: default: gEngfuncs.Con_Printf("VALVEWHY: Unknown Weapon %i is active.\n", from->client.m_iId ); break;*/ } // Store pointer to our destination entity_state_t so we can get our origin, etc. from it // for setting up events on the client g_finalstate = to; // If we are running events/etc. go ahead and see if we // managed to die between last frame and this one // If so, run the appropriate player killed or spawn function if ( g_runfuncs ) { if ( to->client.health <= 0 && lasthealth > 0 ) { player.Killed( NULL, 0 ); } else if ( to->client.health > 0 && lasthealth <= 0 ) { player.Spawn(); } lasthealth = to->client.health; } // We are not predicting the current weapon, just bow out here. if ( !pWeapon ) return; for ( i = 0; i < MAX_WEAPONS; i++ ) { CBasePlayerWeapon *pCurrent = g_pWpns[ i ]; if ( !pCurrent ) { continue; } weapon_data_t *pfrom = from->weapondata + i; pCurrent->m_fInReload = pfrom->m_fInReload; pCurrent->m_fInSpecialReload = pfrom->m_fInSpecialReload; pCurrent->m_iClip = pfrom->m_iClip; pCurrent->m_flNextPrimaryAttack = pfrom->m_flNextPrimaryAttack; pCurrent->m_flNextSecondaryAttack = pfrom->m_flNextSecondaryAttack; pCurrent->m_flTimeWeaponIdle = pfrom->m_flTimeWeaponIdle; pCurrent->m_flStartThrow = pfrom->fuser2; pCurrent->m_flReleaseThrow = pfrom->fuser3; pCurrent->m_iSwing = pfrom->iuser1; pCurrent->m_iWeaponState = pfrom->m_iWeaponState; pCurrent->m_flLastFire = pfrom->m_fAimedDamage; pCurrent->m_iShotsFired = pfrom->m_fInZoom; } if( from->client.vuser4.x < 0 || from->client.vuser4.x > MAX_AMMO_TYPES ) { pWeapon->m_iPrimaryAmmoType = 0; } else { pWeapon->m_iPrimaryAmmoType = (int)from->client.vuser4.x; player.m_rgAmmo[ pWeapon->m_iPrimaryAmmoType ] = (int)from->client.vuser4.y; } g_iWeaponFlags = pWeapon->m_iWeaponState; // For random weapon events, use this seed to seed random # generator player.random_seed = random_seed; // Get old buttons from previous state. player.m_afButtonLast = from->playerstate.oldbuttons; // Which buttsons chave changed buttonsChanged = (player.m_afButtonLast ^ cmd->buttons); // These buttons have changed this frame // Debounced button codes for pressed/released // The changed ones still down are "pressed" player.m_afButtonPressed = buttonsChanged & cmd->buttons; // The ones not down are "released" player.m_afButtonReleased = buttonsChanged & (~cmd->buttons); // Set player variables that weapons code might check/alter player.pev->button = cmd->buttons; player.pev->velocity = from->client.velocity; g_iPlayerFlags = player.pev->flags = from->client.flags; player.pev->deadflag = from->client.deadflag; player.pev->waterlevel = from->client.waterlevel; player.pev->maxspeed = from->client.maxspeed; player.pev->punchangle = from->client.punchangle; player.pev->fov = from->client.fov; player.pev->weaponanim = from->client.weaponanim; player.pev->viewmodel = from->client.viewmodel; player.m_flNextAttack = from->client.m_flNextAttack; g_vPlayerVelocity = from->client.velocity; g_flPlayerSpeed = from->client.velocity.Length(); //Stores all our ammo info, so the client side weapons can use them. player.ammo_9mm = (int)from->client.ammo_nails; player.ammo_556nato = (int)from->client.ammo_cells; player.ammo_buckshot = (int)from->client.ammo_shells; player.ammo_556natobox = (int)from->client.ammo_rockets; player.ammo_762nato = (int)from->client.vuser2.x; player.ammo_45acp = (int)from->client.vuser2.y; player.ammo_50ae = (int)from->client.vuser2.z; player.ammo_338mag = (int)from->client.vuser3.x; player.ammo_57mm = (int)from->client.vuser3.y; player.ammo_357sig = (int)from->client.vuser3.z; cl_entity_t *pplayer = gEngfuncs.GetLocalPlayer(); if( pplayer ) { player.pev->origin = from->client.origin; player.pev->angles = pplayer->angles; player.pev->v_angle = v_angles; } flags = from->client.iuser3; g_bHoldingKnife = pWeapon->m_iId == WEAPON_KNIFE; player.m_bCanShoot = (flags & PLAYER_CAN_SHOOT) != 0; g_iFreezeTimeOver = !(flags & PLAYER_FREEZE_TIME_OVER); g_bInBombZone = (flags & PLAYER_IN_BOMB_ZONE) != 0; g_bHoldingShield = (flags & PLAYER_HOLDING_SHIELD) != 0; // Point to current weapon object if ( from->client.m_iId ) { player.m_pActiveItem = pWeapon; } // Don't go firing anything if we have died. // Or if we don't have a weapon model deployed if ( ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) && !CL_IsDead() && player.pev->viewmodel && !g_iUser1 ) { if( g_bHoldingKnife && pWeapon->m_iClientWeaponState && player.pev->button & IN_FORWARD ) player.m_flNextAttack = 0; else if( player.m_flNextAttack <= 0 ) { pWeapon->ItemPostFrame(); } } // Assume that we are not going to switch weapons to->client.m_iId = from->client.m_iId; // Now see if we issued a changeweapon command ( and we're not dead ) if ( cmd->weaponselect && ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) ) { // Switched to a different weapon? if ( from->weapondata[ cmd->weaponselect ].m_iId == cmd->weaponselect ) { CBasePlayerWeapon *pNew = g_pWpns[ cmd->weaponselect ]; if ( pNew && ( pNew != pWeapon ) ) { // Put away old weapon if (player.m_pActiveItem) player.m_pActiveItem->Holster( ); player.m_pLastItem = player.m_pActiveItem; player.m_pActiveItem = pNew; // Deploy new weapon if (player.m_pActiveItem) { player.m_pActiveItem->Deploy( ); } // Update weapon id so we can predict things correctly. to->client.m_iId = cmd->weaponselect; } } } // Copy in results of prediction code to->client.viewmodel = player.pev->viewmodel; to->client.fov = player.pev->fov; to->client.weaponanim = player.pev->weaponanim; to->client.m_flNextAttack = player.m_flNextAttack; to->client.maxspeed = player.pev->maxspeed; to->client.punchangle = player.pev->punchangle; to->client.ammo_nails = player.ammo_9mm; to->client.ammo_cells = player.ammo_556nato; to->client.ammo_shells = player.ammo_buckshot; to->client.ammo_rockets = player.ammo_556natobox; to->client.vuser2.x = player.ammo_762nato; to->client.vuser2.y = player.ammo_45acp; to->client.vuser2.z = player.ammo_50ae; to->client.vuser3.x = player.ammo_338mag; to->client.vuser3.y = player.ammo_57mm; to->client.vuser3.z = player.ammo_357sig; to->client.iuser3 = flags; // Make sure that weapon animation matches what the game .dll is telling us // over the wire ( fixes some animation glitches ) if ( g_runfuncs && ( HUD_GetWeaponAnim() != to->client.weaponanim ) ) // Force a fixed anim down to viewmodel HUD_SendWeaponAnim( to->client.weaponanim, to->client.m_iId, 2, 1 ); if (pWeapon->m_iPrimaryAmmoType < MAX_AMMO_TYPES) { to->client.vuser4.x = pWeapon->m_iPrimaryAmmoType; to->client.vuser4.y = player.m_rgAmmo[ pWeapon->m_iPrimaryAmmoType ]; } else { to->client.vuser4.x = -1.0; to->client.vuser4.y = 0; } for ( i = 0; i < MAX_WEAPONS; i++ ) { CBasePlayerWeapon *pCurrent = g_pWpns[ i ]; weapon_data_t *pto = to->weapondata + i; if ( !pCurrent ) { memset( pto, 0, sizeof( weapon_data_t ) ); continue; } pto->m_fInReload = pCurrent->m_fInReload; pto->m_fInSpecialReload = pCurrent->m_fInSpecialReload; pto->m_iClip = pCurrent->m_iClip; pto->m_flNextPrimaryAttack = pCurrent->m_flNextPrimaryAttack; pto->m_flNextSecondaryAttack = pCurrent->m_flNextSecondaryAttack; pto->m_flTimeWeaponIdle = pCurrent->m_flTimeWeaponIdle; pto->m_flNextReload = pCurrent->m_flNextReload; pto->fuser2 = pCurrent->m_flStartThrow; pto->fuser3 = pCurrent->m_flReleaseThrow; pto->iuser1 = pCurrent->m_iSwing; pto->m_iWeaponState = pCurrent->m_iWeaponState; pto->m_fInZoom = pCurrent->m_iShotsFired; pto->m_fAimedDamage = pCurrent->m_flLastFire; // Decrement weapon counters, server does this at same time ( during post think, after doing everything else ) pto->m_flNextReload -= cmd->msec / 1000.0f; pto->m_fNextAimBonus -= cmd->msec / 1000.0f; pto->m_flNextPrimaryAttack -= cmd->msec / 1000.0f; pto->m_flNextSecondaryAttack -= cmd->msec / 1000.0f; pto->m_flTimeWeaponIdle -= cmd->msec / 1000.0f; if( pto->m_flPumpTime != -9999.0f ) { pto->m_flPumpTime -= cmd->msec / 1000.0f; if( pto->m_flPumpTime < -1.0f ) pto->m_flPumpTime = 1.0f; } if ( pto->m_fNextAimBonus < -1.0 ) { pto->m_fNextAimBonus = -1.0; } if ( pto->m_flNextPrimaryAttack < -1.0 ) { pto->m_flNextPrimaryAttack = -1.0; } if ( pto->m_flNextSecondaryAttack < -0.001 ) { pto->m_flNextSecondaryAttack = -0.001; } if ( pto->m_flTimeWeaponIdle < -0.001 ) { pto->m_flTimeWeaponIdle = -0.001; } if ( pto->m_flNextReload < -0.001 ) { pto->m_flNextReload = -0.001; } /*if ( pto->fuser1 < -0.001 ) { pto->fuser1 = -0.001; }*/ } // m_flNextAttack is now part of the weapons, but is part of the player instead to->client.m_flNextAttack -= cmd->msec / 1000.0f; if ( to->client.m_flNextAttack < -0.001 ) { to->client.m_flNextAttack = -0.001; } // Wipe it so we can't use it after this frame g_finalstate = NULL; }
/* ===================== HUD_WeaponsPostThink Run Weapon firing code on client ===================== */ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cmd, double time, unsigned int random_seed ) { int i; int buttonsChanged; CBasePlayerWeapon *pWeapon = NULL; CBasePlayerWeapon *pCurrent; weapon_data_t nulldata, *pfrom, *pto; static int lasthealth; memset( &nulldata, 0, sizeof( nulldata ) ); HUD_InitClientWeapons(); // Get current clock gpGlobals->time = time; // Fill in data based on selected weapon // FIXME, make this a method in each weapon? where you pass in an entity_state_t *? switch ( from->client.m_iId ) { case WEAPON_CROWBAR: pWeapon = &g_Crowbar; break; case WEAPON_GLOCK: pWeapon = &g_Glock; break; case WEAPON_PYTHON: pWeapon = &g_Python; break; case WEAPON_MP5: pWeapon = &g_Mp5; break; case WEAPON_CROSSBOW: pWeapon = &g_Crossbow; break; case WEAPON_SHOTGUN: pWeapon = &g_Shotgun; break; case WEAPON_RPG: pWeapon = &g_Rpg; break; case WEAPON_GAUSS: pWeapon = &g_Gauss; break; case WEAPON_EGON: pWeapon = &g_Egon; break; case WEAPON_HORNETGUN: pWeapon = &g_HGun; break; case WEAPON_HANDGRENADE: pWeapon = &g_HandGren; break; case WEAPON_SATCHEL: pWeapon = &g_Satchel; break; case WEAPON_TRIPMINE: pWeapon = &g_Tripmine; break; case WEAPON_SNARK: pWeapon = &g_Snark; break; } // Store pointer to our destination entity_state_t so we can get our origin, etc. from it // for setting up events on the client g_finalstate = to; // If we are running events/etc. go ahead and see if we // managed to die between last frame and this one // If so, run the appropriate player killed or spawn function if ( g_runfuncs ) { if ( to->client.health <= 0 && lasthealth > 0 ) { player.Killed( NULL, 0 ); } else if ( to->client.health > 0 && lasthealth <= 0 ) { player.Spawn(); } lasthealth = to->client.health; } // We are not predicting the current weapon, just bow out here. if ( !pWeapon ) return; for ( i = 0; i < 32; i++ ) { pCurrent = g_pWpns[ i ]; if ( !pCurrent ) { continue; } pfrom = &from->weapondata[ i ]; pCurrent->m_fInReload = pfrom->m_fInReload; pCurrent->m_fInSpecialReload = pfrom->m_fInSpecialReload; // pCurrent->m_flPumpTime = pfrom->m_flPumpTime; pCurrent->m_iClip = pfrom->m_iClip; pCurrent->m_flNextPrimaryAttack = pfrom->m_flNextPrimaryAttack; pCurrent->m_flNextSecondaryAttack = pfrom->m_flNextSecondaryAttack; pCurrent->m_flTimeWeaponIdle = pfrom->m_flTimeWeaponIdle; pCurrent->pev->fuser1 = pfrom->fuser1; pCurrent->m_flStartThrow = pfrom->fuser2; pCurrent->m_flReleaseThrow = pfrom->fuser3; pCurrent->m_chargeReady = pfrom->iuser1; pCurrent->m_fInAttack = pfrom->iuser2; pCurrent->m_fireState = pfrom->iuser3; pCurrent->m_iSecondaryAmmoType = (int)from->client.vuser3[ 2 ]; pCurrent->m_iPrimaryAmmoType = (int)from->client.vuser4[ 0 ]; player.m_rgAmmo[ pCurrent->m_iPrimaryAmmoType ] = (int)from->client.vuser4[ 1 ]; player.m_rgAmmo[ pCurrent->m_iSecondaryAmmoType ] = (int)from->client.vuser4[ 2 ]; } // For random weapon events, use this seed to seed random # generator player.random_seed = random_seed; // Get old buttons from previous state. player.m_afButtonLast = from->playerstate.oldbuttons; // Which buttsons chave changed buttonsChanged = (player.m_afButtonLast ^ cmd->buttons); // These buttons have changed this frame // Debounced button codes for pressed/released // The changed ones still down are "pressed" player.m_afButtonPressed = buttonsChanged & cmd->buttons; // The ones not down are "released" player.m_afButtonReleased = buttonsChanged & (~cmd->buttons); // Set player variables that weapons code might check/alter player.pev->button = cmd->buttons; player.pev->velocity = from->client.velocity; player.pev->flags = from->client.flags; player.pev->deadflag = from->client.deadflag; player.pev->waterlevel = from->client.waterlevel; player.pev->maxspeed = from->client.maxspeed; player.pev->fov = from->client.fov; player.pev->weaponanim = from->client.weaponanim; player.pev->viewmodel = from->client.viewmodel; player.m_flNextAttack = from->client.m_flNextAttack; player.m_flNextAmmoBurn = from->client.fuser2; player.m_flAmmoStartCharge = from->client.fuser3; //Stores all our ammo info, so the client side weapons can use them. player.ammo_9mm = (int)from->client.vuser1[0]; player.ammo_357 = (int)from->client.vuser1[1]; player.ammo_argrens = (int)from->client.vuser1[2]; player.ammo_bolts = (int)from->client.ammo_nails; //is an int anyways... player.ammo_buckshot = (int)from->client.ammo_shells; player.ammo_uranium = (int)from->client.ammo_cells; player.ammo_hornets = (int)from->client.vuser2[0]; player.ammo_rockets = (int)from->client.ammo_rockets; // Point to current weapon object if ( from->client.m_iId ) { player.m_pActiveItem = g_pWpns[ from->client.m_iId ]; } if ( player.m_pActiveItem->m_iId == WEAPON_RPG ) { ( ( CRpg * )player.m_pActiveItem)->m_fSpotActive = (int)from->client.vuser2[ 1 ]; ( ( CRpg * )player.m_pActiveItem)->m_cActiveRockets = (int)from->client.vuser2[ 2 ]; } // Don't go firing anything if we have died or are spectating // Or if we don't have a weapon model deployed if ( ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) && !CL_IsDead() && player.pev->viewmodel && !g_iUser1 ) { if ( player.m_flNextAttack <= 0 ) { pWeapon->ItemPostFrame(); } } // Assume that we are not going to switch weapons to->client.m_iId = from->client.m_iId; // Now see if we issued a changeweapon command ( and we're not dead ) if ( cmd->weaponselect && ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) ) { // Switched to a different weapon? if ( from->weapondata[ cmd->weaponselect ].m_iId == cmd->weaponselect ) { CBasePlayerWeapon *pNew = g_pWpns[ cmd->weaponselect ]; if ( pNew && ( pNew != pWeapon ) ) { // Put away old weapon if (player.m_pActiveItem) player.m_pActiveItem->Holster( ); player.m_pLastItem = player.m_pActiveItem; player.m_pActiveItem = pNew; // Deploy new weapon if (player.m_pActiveItem) { player.m_pActiveItem->Deploy( ); } // Update weapon id so we can predict things correctly. to->client.m_iId = cmd->weaponselect; } } } // Copy in results of prediction code to->client.viewmodel = player.pev->viewmodel; to->client.fov = player.pev->fov; to->client.weaponanim = player.pev->weaponanim; to->client.m_flNextAttack = player.m_flNextAttack; to->client.fuser2 = player.m_flNextAmmoBurn; to->client.fuser3 = player.m_flAmmoStartCharge; to->client.maxspeed = player.pev->maxspeed; //HL Weapons to->client.vuser1[0] = player.ammo_9mm; to->client.vuser1[1] = player.ammo_357; to->client.vuser1[2] = player.ammo_argrens; to->client.ammo_nails = player.ammo_bolts; to->client.ammo_shells = player.ammo_buckshot; to->client.ammo_cells = player.ammo_uranium; to->client.vuser2[0] = player.ammo_hornets; to->client.ammo_rockets = player.ammo_rockets; if ( player.m_pActiveItem->m_iId == WEAPON_RPG ) { from->client.vuser2[ 1 ] = ( ( CRpg * )player.m_pActiveItem)->m_fSpotActive; from->client.vuser2[ 2 ] = ( ( CRpg * )player.m_pActiveItem)->m_cActiveRockets; } // Make sure that weapon animation matches what the game .dll is telling us // over the wire ( fixes some animation glitches ) if ( g_runfuncs && ( HUD_GetWeaponAnim() != to->client.weaponanim ) ) { int body = 2; //Pop the model to body 0. if ( pWeapon == &g_Tripmine ) body = 0; //Show laser sight/scope combo if ( pWeapon == &g_Python && bIsMultiplayer() ) body = 1; // Force a fixed anim down to viewmodel HUD_SendWeaponAnim( to->client.weaponanim, body, 1 ); } for ( i = 0; i < 32; i++ ) { pCurrent = g_pWpns[ i ]; pto = &to->weapondata[ i ]; if ( !pCurrent ) { memset( pto, 0, sizeof( weapon_data_t ) ); continue; } pto->m_fInReload = pCurrent->m_fInReload; pto->m_fInSpecialReload = pCurrent->m_fInSpecialReload; // pto->m_flPumpTime = pCurrent->m_flPumpTime; pto->m_iClip = pCurrent->m_iClip; pto->m_flNextPrimaryAttack = pCurrent->m_flNextPrimaryAttack; pto->m_flNextSecondaryAttack = pCurrent->m_flNextSecondaryAttack; pto->m_flTimeWeaponIdle = pCurrent->m_flTimeWeaponIdle; pto->fuser1 = pCurrent->pev->fuser1; pto->fuser2 = pCurrent->m_flStartThrow; pto->fuser3 = pCurrent->m_flReleaseThrow; pto->iuser1 = pCurrent->m_chargeReady; pto->iuser2 = pCurrent->m_fInAttack; pto->iuser3 = pCurrent->m_fireState; // Decrement weapon counters, server does this at same time ( during post think, after doing everything else ) pto->m_flNextReload -= cmd->msec / 1000.0; pto->m_fNextAimBonus -= cmd->msec / 1000.0; pto->m_flNextPrimaryAttack -= cmd->msec / 1000.0; pto->m_flNextSecondaryAttack -= cmd->msec / 1000.0; pto->m_flTimeWeaponIdle -= cmd->msec / 1000.0; pto->fuser1 -= cmd->msec / 1000.0; to->client.vuser3[2] = pCurrent->m_iSecondaryAmmoType; to->client.vuser4[0] = pCurrent->m_iPrimaryAmmoType; to->client.vuser4[1] = player.m_rgAmmo[ pCurrent->m_iPrimaryAmmoType ]; to->client.vuser4[2] = player.m_rgAmmo[ pCurrent->m_iSecondaryAmmoType ]; /* if ( pto->m_flPumpTime != -9999 ) { pto->m_flPumpTime -= cmd->msec / 1000.0; if ( pto->m_flPumpTime < -0.001 ) pto->m_flPumpTime = -0.001; }*/ if ( pto->m_fNextAimBonus < -1.0 ) { pto->m_fNextAimBonus = -1.0; } if ( pto->m_flNextPrimaryAttack < -1.0 ) { pto->m_flNextPrimaryAttack = -1.0; } if ( pto->m_flNextSecondaryAttack < -0.001 ) { pto->m_flNextSecondaryAttack = -0.001; } if ( pto->m_flTimeWeaponIdle < -0.001 ) { pto->m_flTimeWeaponIdle = -0.001; } if ( pto->m_flNextReload < -0.001 ) { pto->m_flNextReload = -0.001; } if ( pto->fuser1 < -0.001 ) { pto->fuser1 = -0.001; } } // m_flNextAttack is now part of the weapons, but is part of the player instead to->client.m_flNextAttack -= cmd->msec / 1000.0; if ( to->client.m_flNextAttack < -0.001 ) { to->client.m_flNextAttack = -0.001; } to->client.fuser2 -= cmd->msec / 1000.0; if ( to->client.fuser2 < -0.001 ) { to->client.fuser2 = -0.001; } to->client.fuser3 -= cmd->msec / 1000.0; if ( to->client.fuser3 < -0.001 ) { to->client.fuser3 = -0.001; } // Store off the last position from the predicted state. HUD_SetLastOrg(); // Wipe it so we can't use it after this frame g_finalstate = NULL; }
/* <18b4aa> ../cstrike/dlls/training_gamerules.cpp:52 */ void CHalfLifeTraining::__MAKE_VHOOK(PlayerThink)(CBasePlayer *pPlayer) { if (pPlayer->pev->radsuit_finished && gpGlobals->time > pPlayer->pev->radsuit_finished) { SERVER_COMMAND("reload\n"); } if (!pPlayer->m_iAccount) { if (pPlayer->pev->scale) { pPlayer->m_iAccount = (int)pPlayer->pev->scale; } } if (pPlayer->m_iTeam == UNASSIGNED) { pPlayer->SetProgressBarTime(0); pPlayer->m_bHasDefuser = pPlayer->pev->ideal_yaw != 0; } m_iHostagesRescued = 0; m_iRoundTimeSecs = (int)(gpGlobals->time + 1.0f); m_bFreezePeriod = FALSE; g_fGameOver = FALSE; pPlayer->m_iTeam = CT; pPlayer->m_bCanShoot = true; pPlayer->m_fLastMovement = gpGlobals->time; if (pPlayer->m_pActiveItem) pPlayer->m_iHideHUD &= ~HIDEHUD_WEAPONS; else pPlayer->m_iHideHUD |= HIDEHUD_WEAPONS; if (pPlayer->HasNamedPlayerItem("weapon_c4")) { if (pPlayer->m_rgAmmo[ pPlayer->GetAmmoIndex("C4") ] <= 0) { pPlayer->m_bHasC4 = false; CBasePlayerWeapon *pWeapon = (CBasePlayerWeapon *)pPlayer->m_pActiveItem; if (FClassnameIs(pWeapon->pev, "weapon_c4")) { pPlayer->pev->weapons &= ~(1 << pWeapon->m_iId); pPlayer->RemovePlayerItem(pWeapon); pWeapon->Drop(); } } else pPlayer->m_bHasC4 = true; } if (!pPlayer->m_bVGUIMenus) { if (fVGUIMenus) { pPlayer->m_bVGUIMenus = fVGUIMenus; } } CGrenade *pBomb = NULL; while ((pBomb = (CGrenade *)UTIL_FindEntityByClassname(pBomb, "grenade")) != NULL) { if (pBomb->m_pentCurBombTarget != NULL) pBomb->m_bStartDefuse = true; } if (pPlayer->m_signals.GetState() & SIGNAL_BUY) { if (!fInBuyArea) { FillAccountTime = 1; if (!fVisitedBuyArea) { MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, NULL, pPlayer->pev); WRITE_BYTE(STATUSICON_FLASH); WRITE_STRING("buyzone"); WRITE_BYTE(0); WRITE_BYTE(160); WRITE_BYTE(0); MESSAGE_END(); } } fInBuyArea = TRUE; if (pPlayer->m_iAccount < 16000 && FillAccountTime == 0.0f) FillAccountTime = gpGlobals->time + 5; if (FillAccountTime != 0.0f && gpGlobals->time > FillAccountTime) { if (!fVisitedBuyArea) { MESSAGE_BEGIN(MSG_ONE, gmsgBlinkAcct, NULL, pPlayer->pev); WRITE_BYTE(3); MESSAGE_END(); MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, NULL, pPlayer->pev); WRITE_BYTE(STATUSICON_SHOW); WRITE_STRING("buyzone"); WRITE_BYTE(0); WRITE_BYTE(160); WRITE_BYTE(0); MESSAGE_END(); fVisitedBuyArea = TRUE; } pPlayer->AddAccount(16000 - pPlayer->m_iAccount); FillAccountTime = 0; } } else if (fInBuyArea && fVisitedBuyArea) { fInBuyArea = FALSE; } pPlayer->pev->scale = pPlayer->m_iAccount; pPlayer->pev->ideal_yaw = pPlayer->m_bHasDefuser; if (TheBots != NULL) { TheBots->OnEvent(EVENT_PLAYER_CHANGED_TEAM, pPlayer); } }
/* ================= UpdateClientData Data sent to current client only engine sets cd to 0 before calling. ================= */ void UpdateClientData ( const struct edict_s *ent, int sendweapons, struct clientdata_s *cd ) { cd->flags = ent->v.flags; cd->health = ent->v.health; cd->viewmodel = MODEL_INDEX( STRING( ent->v.viewmodel ) ); cd->waterlevel = ent->v.waterlevel; cd->watertype = ent->v.watertype; cd->weapons = ent->v.weapons; // Vectors cd->origin = ent->v.origin; cd->velocity = ent->v.velocity; cd->view_ofs = ent->v.view_ofs; cd->punchangle = ent->v.punchangle; cd->bInDuck = ent->v.bInDuck; cd->flTimeStepSound = ent->v.flTimeStepSound; cd->flDuckTime = ent->v.flDuckTime; cd->flSwimTime = ent->v.flSwimTime; cd->waterjumptime = ent->v.teleport_time; strcpy( cd->physinfo, ENGINE_GETPHYSINFO( ent ) ); cd->maxspeed = ent->v.maxspeed; cd->fov = ent->v.fov; cd->weaponanim = ent->v.weaponanim; cd->pushmsec = ent->v.pushmsec; #if defined( CLIENT_WEAPONS ) if ( sendweapons ) { entvars_t *pev = (entvars_t *)&ent->v; CBasePlayer *pl = ( CBasePlayer *) CBasePlayer::Instance( pev ); if ( pl ) { cd->m_flNextAttack = pl->m_flNextAttack; cd->fuser2 = pl->m_flNextAmmoBurn; cd->fuser3 = pl->m_flAmmoStartCharge; cd->vuser1.x = pl->ammo_9mm; cd->vuser1.y = pl->ammo_357; cd->vuser1.z = pl->ammo_argrens; cd->ammo_nails = pl->ammo_bolts; cd->ammo_shells = pl->ammo_buckshot; cd->ammo_rockets = pl->ammo_rockets; cd->ammo_cells = pl->ammo_uranium; cd->vuser2.x = pl->ammo_hornets; if ( pl->m_pActiveItem ) { CBasePlayerWeapon *gun; gun = (CBasePlayerWeapon *)pl->m_pActiveItem->GetWeaponPtr(); if ( gun && gun->UseDecrement() ) { ItemInfo II; memset( &II, 0, sizeof( II ) ); gun->GetItemInfo( &II ); cd->m_iId = II.iId; cd->vuser3.z = gun->m_iSecondaryAmmoType; cd->vuser4.x = gun->m_iPrimaryAmmoType; cd->vuser4.y = pl->m_rgAmmo[gun->m_iPrimaryAmmoType]; cd->vuser4.z = pl->m_rgAmmo[gun->m_iSecondaryAmmoType]; if ( pl->m_pActiveItem->m_iId == WEAPON_RPG ) { cd->vuser2.y = ( ( CRpg * )pl->m_pActiveItem)->m_fSpotActive; cd->vuser2.z = ( ( CRpg * )pl->m_pActiveItem)->m_cActiveRockets; } } } } } #endif }
void CBasePlayer::PostThink() { if( g_fGameOver ) goto pt_end; // intermission or finale if( !IsAlive() ) goto pt_end; // Handle Tank controlling if( m_pTank != NULL ) { // if they've moved too far from the gun, or selected a weapon, unuse the gun if( m_pTank->OnControls( this ) && !HasWeaponModelName() ) { m_pTank->Use( this, this, USE_SET, 2 ); // try fire the gun } else { // they've moved off the platform m_pTank->Use( this, this, USE_OFF, 0 ); m_pTank = NULL; } } // do weapon stuff ItemPostFrame(); // check to see if player landed hard enough to make a sound // falling farther than half of the maximum safe distance, but not as far a max safe distance will // play a bootscrape sound, and no damage will be inflicted. Fallling a distance shorter than half // of maximum safe distance will make no sound. Falling farther than max safe distance will play a // fallpain sound, and damage will be inflicted based on how far the player fell if( GetFlags().Any( FL_ONGROUND ) && ( GetHealth() > 0 ) && m_flFallVelocity >= PLAYER_FALL_PUNCH_THRESHHOLD ) { // ALERT ( at_console, "%f\n", m_flFallVelocity ); if( GetWaterType() == CONTENTS_WATER ) { // Did he hit the world or a non-moving entity? // BUG - this happens all the time in water, especially when // BUG - water has current force //CBaseEntity* pEntity = GetGroundEntity(); //if ( !pEntity || pEntity->GetAbsVelocity().z == 0 ) // EMIT_SOUND( this, CHAN_BODY, "player/pl_wade1.wav", 1, ATTN_NORM); } else if( m_flFallVelocity > PLAYER_MAX_SAFE_FALL_SPEED ) { // after this point, we start doing damage float flFallDamage = g_pGameRules->FlPlayerFallDamage( this ); if( flFallDamage > GetHealth() ) {//splat // note: play on item channel because we play footstep landing on body channel EMIT_SOUND( this, CHAN_ITEM, "common/bodysplat.wav", 1, ATTN_NORM ); } if( flFallDamage > 0 ) { TakeDamage( CWorld::GetInstance(), CWorld::GetInstance(), flFallDamage, DMG_FALL ); Vector vecPunchAngle = GetPunchAngle(); vecPunchAngle.x = 0; SetPunchAngle( vecPunchAngle ); } } if( IsAlive() ) { SetAnimation( PLAYER_WALK ); } } if( GetFlags().Any( FL_ONGROUND ) ) { if( m_flFallVelocity > 64 && !g_pGameRules->IsMultiplayer() ) { CSoundEnt::InsertSound( bits_SOUND_PLAYER, GetAbsOrigin(), m_flFallVelocity, 0.2 ); // ALERT( at_console, "fall %f\n", m_flFallVelocity ); } m_flFallVelocity = 0; } // select the proper animation for the player character if( IsAlive() ) { if( !GetAbsVelocity().x && !GetAbsVelocity().y ) SetAnimation( PLAYER_IDLE ); else if( ( GetAbsVelocity().x || GetAbsVelocity().y ) && ( GetFlags().Any( FL_ONGROUND ) ) ) SetAnimation( PLAYER_WALK ); else if( GetWaterLevel() > WATERLEVEL_FEET ) SetAnimation( PLAYER_WALK ); } StudioFrameAdvance(); CheckPowerups( this ); UpdatePlayerSound(); pt_end: #if defined( CLIENT_WEAPONS ) // Decay timers on weapons // go through all of the weapons and make a list of the ones to pack for( int i = 0; i < MAX_WEAPON_SLOTS; i++ ) { if( m_rgpPlayerItems[ i ] ) { CBasePlayerWeapon *pPlayerItem = m_rgpPlayerItems[ i ]; while( pPlayerItem ) { if( pPlayerItem->IsPredicted() ) { pPlayerItem->m_flNextPrimaryAttack = max( pPlayerItem->m_flNextPrimaryAttack - gpGlobals->frametime, -1.0f ); pPlayerItem->m_flNextSecondaryAttack = max( pPlayerItem->m_flNextSecondaryAttack - gpGlobals->frametime, -0.001f ); if( pPlayerItem->m_flTimeWeaponIdle != 1000 ) { pPlayerItem->m_flTimeWeaponIdle = max( pPlayerItem->m_flTimeWeaponIdle - gpGlobals->frametime, -0.001f ); } if( pPlayerItem->pev->fuser1 != 1000 ) { pPlayerItem->pev->fuser1 = max( pPlayerItem->pev->fuser1 - gpGlobals->frametime, -0.001f ); } pPlayerItem->DecrementTimers( gpGlobals->frametime ); // Only decrement if not flagged as NO_DECREMENT // if ( gun->m_flPumpTime != 1000 ) // { // gun->m_flPumpTime = max( gun->m_flPumpTime - gpGlobals->frametime, -0.001 ); // } } pPlayerItem = pPlayerItem->m_pNext; } } } m_flNextAttack -= gpGlobals->frametime; if( m_flNextAttack < -0.001 ) m_flNextAttack = -0.001; if( m_flNextAmmoBurn != 1000 ) { m_flNextAmmoBurn -= gpGlobals->frametime; if( m_flNextAmmoBurn < -0.001 ) m_flNextAmmoBurn = -0.001; } if( m_flAmmoStartCharge != 1000 ) { m_flAmmoStartCharge -= gpGlobals->frametime; if( m_flAmmoStartCharge < -0.001 ) m_flAmmoStartCharge = -0.001; } #endif // Track button info so we can detect 'pressed' and 'released' buttons next frame m_afButtonLast = GetButtons().Get(); }