//------------------------------------------------------------------------ bool CC4::CanSelect() const { bool canSelect = (CWeapon::CanSelect() && !OutOfAmmo(false)); //Check for remaining projectiles to detonate if(!canSelect) { CActor *pOwner = GetOwnerActor(); if(!pOwner) return false; EntityId detonatorId = pOwner->GetInventory()?pOwner->GetInventory()->GetItemByClass(CItem::sDetonatorClass):0; //Do not re-select detonator again if(detonatorId && (detonatorId==pOwner->GetCurrentItemId())) return false; IFireMode *pFM = GetFireMode(GetCurrentFireMode()); if(pFM) { //CC4::Select will select the detonator in this case EntityId projectileId = pFM->GetProjectileId(); if(projectileId && g_pGame->GetWeaponSystem()->GetProjectile(projectileId)) return true; } } return canSelect; };
//--------------------------------------------------------------------------------- bool CWeapon::OnActionFiremode(EntityId actorId, const ActionId& actionId, int activationMode, float value) { CActor* pOwner = GetOwnerActor(); CPlayer* pPlayer = pOwner && pOwner->IsPlayer() ? static_cast<CPlayer*>(pOwner) : 0; if (pPlayer && (pPlayer->IsCinematicFlagActive(SPlayerStats::eCinematicFlag_LowerWeapon) || pPlayer->IsCinematicFlagActive(SPlayerStats::eCinematicFlag_LowerWeaponMP)) ) return true; bool incompatibleZommMode = (m_secondaryZmId != 0 && (IsZoomed() || IsZoomingInOrOut())); if (AreAnyItemFlagsSet(eIF_BlockActions) || incompatibleZommMode) { return true; } if (activationMode == eAAM_OnPress) { IFireMode* pNewFiremode = GetFireMode(GetNextFireMode(GetCurrentFireMode())); if (pNewFiremode == m_fm) { if(pPlayer && pPlayer->CanSwitchItems()) { pPlayer->SwitchToWeaponWithAccessoryFireMode(); } } else if (!IsReloading()) { StartChangeFireMode(); } } return true; }
void CWeapon::EndVerificationSample(IActor * pActor, uint32 oldShotId) { if(m_fSampleNumShots > 1.0f) //This check needs to be here as some calls will call this directly { // without calling ShouldEndVerificationSample() const float fSampleStartTime = m_fSampleStartTime; const INetChannel* pNetChannel = gEnv->pGame->GetIGameFramework()->GetNetChannel(pActor->GetChannelId()); const float fNetLag = ((pActor->IsClient() || !pNetChannel) ? 0 : (pNetChannel->GetPing(true))); // GetPing() is the round journey but we're giving some leeway //work out how long the sample covered. //TODO: Work out if we need latency compensation here? const float kServerFrameTime = gEnv->pTimer->GetFrameTime(); const float kAdditionalFudge = (kServerFrameTime * 2.0f) + (fNetLag * 2.0f); //Generously assume that their ping could spike significantly const float fActualSampleLength = (m_fLastSampleTakenTime - fSampleStartTime) + kAdditionalFudge; const float fFireRate = m_fSampleNumShots / fActualSampleLength; const int kCurrentFireModeIdx = (oldShotId & CWeapon::GetShotIdFireModeMask()) >> CWeapon::GetShotIdFireModeOffset(); CFireMode * pFireMode = static_cast<CFireMode*>(GetFireMode(kCurrentFireModeIdx)); if(pFireMode) { //Fire rate is in shots per minute, convert to shots per second float fMaxFireRate = pFireMode->GetFireRate() * ( 1.0f / 60.0f ); if(pActor->IsPlayer()) { fMaxFireRate *= __fres(pFireMode->GetTimeBetweenShotsMultiplier(static_cast<CPlayer*>(pActor))); } if(fFireRate > fMaxFireRate) { g_pGame->GetAntiCheatManager()->FlagActivity(eCT_FireRate, pActor->GetChannelId(), fFireRate / fMaxFireRate, GetEntity()->GetName()); } } } }
void CHeavyMountedWeapon::SetUnMountedConfiguration() { SwitchToRippedOffFireMode(); IFireMode * pMountedFireMode = GetFireMode(0); assert(pMountedFireMode); pMountedFireMode->Enable(false); ExitZoom(true); //Second zoom mode is supposed to be unmounted if(GetZoomMode(1)) { EnableZoomMode(1, true); SetCurrentZoomMode(1); } //Just in case, it was not clear properly CActor* pOwner = GetOwnerActor(); if ((pOwner != NULL) && pOwner->IsClient()) { float defaultFov = 55.0f; gEnv->pRenderer->EF_Query(EFQ_SetDrawNearFov,defaultFov); } }
//------------------------------------------------------------------------ IMPLEMENT_RMI(CC4, ClSetProjectileId) { IFireMode *pFireMode=GetFireMode(params.fmId); if (pFireMode) pFireMode->SetProjectileId(params.id); else return false; return true; }
//------------------------------------------------------------------------ IMPLEMENT_RMI(CWeapon, SvStartedCharging) { CHECK_OWNER_REQUEST(); if(CFireMode* pFireMode = static_cast<CFireMode*>(GetFireMode(GetCurrentFireMode()))) { pFireMode->NetSetCharging(true); CHANGED_NETWORK_STATE(this, ASPECT_CHARGING); } return true; }
//------------------------------------------------------------------------ IMPLEMENT_RMI(CC4, SvRequestTime) { IFireMode *pFireMode=GetFireMode(params.fmId); if (pFireMode && !stricmp(pFireMode->GetType(), "Plant")) { CPlant *pPlant=static_cast<CPlant *>(pFireMode); pPlant->SetTime(params.time); } else return false; return true; }
//------------------------------------------------------------------------ bool CGunTurret::ReadItemParams(const IItemParamsNode *root) { //m_tpgeometry.position.Set(0.f, 0.f, 0.f); //m_aux0geometry.position.Set(0.f, 0.f, 0.f); if(!CWeapon::ReadItemParams(root)) return false; string rocket_fire_mode; const IItemParamsNode *params = root->GetChild("params"); { CItemParamReader reader(params); reader.Read("rocket_firemode", rocket_fire_mode); reader.Read("radar_helper", m_radarHelper); reader.Read("barrel_helper", m_barrelHelper); reader.Read("fire_helper", m_fireHelper); reader.Read("rocket_helper", m_rocketHelper); /*Matrix34 tm = GetEntity()->GetSlotLocalTM(eIGS_Aux0,false); tm.SetTranslation(GetSlotHelperPos(eIGS_Aux0,m_radarHelper.c_str(),false)); GetEntity()->SetSlotLocalTM(eIGS_ThirdPerson,tm); if (GetEntity()->IsSlotValid(eIGS_Aux1)) { tm.SetTranslation(GetSlotHelperPos(eIGS_ThirdPerson,m_barrelHelper.c_str(),false)); GetEntity()->SetSlotLocalTM(eIGS_Aux1,tm); }*/ m_radarHelperPos = GetSlotHelperPos(eIGS_Aux0, m_radarHelper.c_str(), false); m_barrelHelperPos = GetSlotHelperPos(eIGS_ThirdPerson, m_barrelHelper.c_str(), false); m_fireHelperPos = GetSlotHelperPos(eIGS_ThirdPerson, m_fireHelper.c_str(), false); m_rocketHelperPos = GetSlotHelperPos(eIGS_ThirdPerson, m_rocketHelper, false); } if(const IItemParamsNode *turret = root->GetChild("turret")) { if(const IItemParamsNode *search = turret->GetChild("search")) m_searchparams.Reset(search); if(const IItemParamsNode *fire = turret->GetChild("fire")) m_fireparams.Reset(fire); } m_fm2=GetFireMode(rocket_fire_mode.c_str()); if(m_fm2) m_fm2->Activate(true); return true; }
//------------------------------------------------------------------------ void CWeapon::NetShootEx(const Vec3 &pos, const Vec3 &dir, const Vec3 &vel, const Vec3 &hit, float extra, int predictionHandle, int fireModeId) { IFireMode *pFM = GetFireMode(fireModeId); if (pFM) { pFM->NetShootEx(pos, dir, vel, hit, extra, predictionHandle); } else { #ifdef SERVER_CHECKS g_pGame->GetAntiCheatManager()->FlagActivity(eCT_ShootingWithoutFiremode, GetOwnerActor()->GetChannelId()); #endif } }
bool CHeavyMountedWeapon::UpdateAimAnims( SParams_WeaponFPAiming &aimAnimParams) { if (!m_rippedOff && !m_rippingOff) { IFireMode* pFireMode = GetFireMode(GetCurrentFireMode()); aimAnimParams.shoulderLookParams = pFireMode ? &static_cast<CFireMode*>(pFireMode)->GetShared()->aimLookParams : &m_sharedparams->params.aimLookParams; return true; } return BaseClass::UpdateAimAnims(aimAnimParams); }
bool CNoWeapon::UpdateAimAnims(SParams_WeaponFPAiming &aimAnimParams) { if (m_sharedparams->params.hasAimAnims) { IFireMode* pFireMode = GetFireMode(GetCurrentFireMode()); aimAnimParams.shoulderLookParams = pFireMode ? &static_cast<CFireMode*>(pFireMode)->GetShared()->aimLookParams : &m_sharedparams->params.aimLookParams; return true; } return false; }
//----------------------------------------------------------------------- bool CC4::OnActionSelectDetonator(EntityId actorId, const ActionId& actionId, int activationMode, float value) { if(activationMode == eAAM_OnPress) { bool projectile = false; IFireMode* pFM = GetFireMode(GetCurrentFireMode()); if(pFM) { EntityId projectileId = pFM->GetProjectileId(); if(projectileId && g_pGame->GetWeaponSystem()->GetProjectile(projectileId)) projectile = true; } //If there is some projectile we can switch if(projectile) SelectDetonator(); } return true; }
//------------------------------------------------------------------------ void CC4::Select(bool select) { if(select) { bool outOfAmmo = OutOfAmmo(false); bool projectile = false; IFireMode *pFM = GetFireMode(GetCurrentFireMode()); if(pFM) { EntityId projectileId = pFM->GetProjectileId(); if(projectileId && g_pGame->GetWeaponSystem()->GetProjectile(projectileId)) projectile = true; } if(outOfAmmo && projectile) { SelectDetonator(); return; } else if(outOfAmmo) { Select(false); CActor *pOwner=GetOwnerActor(); if(!pOwner) return; EntityId fistsId = pOwner->GetInventory()?pOwner->GetInventory()->GetItemByClass(CItem::sFistsClass):0; if(fistsId) pOwner->SelectItem(fistsId,true); return; } } CWeapon::Select(select); }
//------------------------------------------------------------------------ void CWeapon::OnStartReload(EntityId shooterId, IEntityClass* pAmmoType) { BROADCAST_WEAPON_EVENT(OnStartReload, (this, shooterId, pAmmoType)); if (CActor *pActor = GetOwnerActor()) { if (IAIObject *pAIObject=pActor->GetEntity()->GetAI()) if (gEnv->pAISystem) gEnv->pAISystem->SendSignal( SIGNALFILTER_SENDER, 1, "OnReload", pAIObject); if(pActor->IsClient()) { if (gEnv->bMultiplayer && pActor->IsCloaked()) { CPersistantStats::GetInstance()->IncrementClientStats(EIPS_CloakedReloads); } if(m_weaponsharedparams->bulletBeltParams.numBullets > 0) { const uint32 refillTime = (uint32)(GetCurrentAnimationTime(eIGS_Owner) * m_weaponsharedparams->bulletBeltParams.beltRefillReloadFraction); GetScheduler()->TimerAction(refillTime, CSchedulerAction<RefillBeltAction>::Create(RefillBeltAction(this)), false); } } } IFireMode *pFireMode = GetFireMode(GetCurrentFireMode()); if (pFireMode) { if(GetInventoryAmmoCount(pAmmoType) < pFireMode->GetClipSize()) { BATTLECHATTER(BC_LowAmmo, shooterId); } else { BATTLECHATTER(BC_Reloading, shooterId); } } }
//------------------------------------------------------------------------ void CWeapon::OnShoot(EntityId shooterId, EntityId ammoId, IEntityClass* pAmmoType, const Vec3 &pos, const Vec3 &dir, const Vec3&vel) { BROADCAST_WEAPON_EVENT(OnShoot, (this, shooterId, ammoId, pAmmoType, pos, dir, vel)); //FIXME:quick temporary solution CActor *pActor = static_cast<CActor*> (g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(shooterId)); if (pActor) pActor->HandleEvent(SGameObjectEvent(eCGE_OnShoot,eGOEF_ToExtensions)); IActor *pClientActor=m_pGameFramework->GetClientActor(); if (pActor && pActor->GetActorClass() == CPlayer::GetActorClassType() && IsServer()) { if (pActor == pClientActor) { if (IAIObject *pAIObject=pActor->GetEntity()->GetAI()) gEnv->pAISystem->SendSignal(SIGNALFILTER_LEADER, 1, "OnEnableFire", pAIObject, 0); } CPlayer *pPlayer=static_cast<CPlayer *>(pActor); CNanoSuit *pSuit=pPlayer->GetNanoSuit(); if(m_fm && strcmp(m_fm->GetType(), "Repair")) { if(pSuit) { if (pSuit->GetMode() == NANOMODE_STRENGTH && !IsMounted()) pSuit->SetSuitEnergy(pSuit->GetSuitEnergy()-g_pGameCVars->g_suitRecoilEnergyCost); else if(pSuit->GetMode() == NANOMODE_CLOAK) pSuit->SetSuitEnergy(0.0f); } } if (gEnv->bServer && pSuit && pSuit->IsInvulnerable()) pSuit->SetInvulnerability(false); } if (pClientActor && m_fm && strcmp(m_fm->GetType(), "Thrown")) { // inform the HUDRadar about the sound event Vec3 vPlayerPos=pClientActor->GetEntity()->GetWorldPos(); float fDist2=(vPlayerPos-pos).len2(); if (fDist2<250.0f*250.0f) { //if (pClientActor->GetEntityId() != shooterId) // pHUD->ShowSoundOnRadar(pos); if(gEnv->bMultiplayer) { CGameRules *pGameRules = g_pGame->GetGameRules(); if(pGameRules->GetTeamCount() < 2 || (pGameRules->GetTeam(shooterId) != pGameRules->GetTeam(pClientActor->GetEntityId()))) { //Small workaround for patch2... IFireMode* pFM = GetFireMode(GetCurrentFireMode()); bool grenade = pFM?(pFM->GetAmmoType()==CItem::sScarGrenadeClass):false; //~... if (!IsSilencerAttached() || grenade) { SAFE_HUD_FUNC(GetRadar()->AddEntityTemporarily(shooterId, 5.0f)); } else if(fDist2<5.0f*5.0f) { //Silencer attached SAFE_HUD_FUNC(GetRadar()->AddEntityTemporarily(shooterId, 5.0f)); } } } if ((!IsSilencerAttached()) && fDist2<sqr(SAFE_HUD_FUNC_RET(GetBattleRange()))) SAFE_HUD_FUNC(TickBattleStatus(1.0f)); } } }
//------------------------------------------------------------------------ Vec3 CGunTurret::PredictTargetPos(IEntity *pTarget, bool sec)//sec - weapon to use { pTarget = ResolveTarget(pTarget); Vec3 tpos = GetTargetPos(pTarget); if(m_turretparams.search_only || m_turretparams.prediction == 0.f) return tpos; IPhysicalEntity *pe = pTarget->GetPhysics(); pe_status_dynamics dyn; if(!pe || !pe->GetStatus(&dyn)) return tpos; Vec3 vel = dyn.v; Vec3 acc = dyn.a; float a = acc.len(); if(a < 0.01f) a = 0.f; else acc /= a; Vec3 vpos = GetWeaponPos(); Vec3 dist = tpos-vpos; float d = dist.len(); if(d < 0.01f) return tpos; dist /= d; float d_speed = vel*dist; float speed = 800.0f; const SAmmoParams *ammo = g_pGame->GetWeaponSystem()->GetAmmoParams(GetFireMode(0)->GetAmmoType()); if(!ammo) return tpos; if(ammo->physicalizationType == ePT_None) return tpos; speed = ammo->speed; float time_to = d/max(1.f, speed-d_speed); // MR: clamped acc prediction to reduce jerkyness when targetting objects that are able // to do near-instant velocity changes (like players) a = min(a, 25.f); Vec3 delta = vel*(time_to) + 0.5f*a*acc*time_to*time_to; delta *= m_turretparams.prediction; if(g_pGameCVars->i_debug_turrets == eGTD_Prediction) { IPersistantDebug *pDebug = gEnv->pGame->GetIGameFramework()->GetIPersistantDebug(); pDebug->Begin("CGunTurret::PredictTargetPos", false); pDebug->AddSphere(tpos+delta, 0.2f, ColorF(1,0,0,1), 1.f); gEnv->pRenderer->DrawLabel(vpos, 1.4f, "Predict %s: speed %.1f (dspeed %.1f), acc %.1f, time %.1f", pTarget->GetName(), vel.len(), d_speed, a, time_to); } return tpos+delta; }
//------------------------------------------------------------------------ IMPLEMENT_RMI(CWeapon, SvRequestShootEx) { CHECK_OWNER_REQUEST(); bool ok=true; CActor *pActor=GetActorByNetChannel(pNetChannel); if (!pActor || pActor->IsDead()) { ok=false; } #ifdef SERVER_CHECKS CAntiCheatManager * pAntiCheatManager = static_cast<CAntiCheatManager*>(g_pGame->GetAntiCheatManager()); bool validatePrediction = pAntiCheatManager ? pAntiCheatManager->GetAntiCheatVar(eAV_IP_UseTest_ValidatePredicatedSpawn, 1) != 0 : false; if(ok && validatePrediction && params.predictionHandle) { CFireMode *pFireMode = (CFireMode*)GetFireMode(params.fireModeId); if (pFireMode) { const SFireModeParams *pFireModeParams = pFireMode->GetShared(); if(pFireModeParams) { IEntityClass *pAmmoClass = pFireModeParams->fireparams.ammo_type_class; if(pAmmoClass) { int totalAmmoCount = GetAmmoCount(pAmmoClass) + GetInventoryAmmoCount(pAmmoClass); if(totalAmmoCount <= 0) { CryLog("actor %s does not have enough ammo for predicted spawn of %s, not spawning...", pActor->GetEntity()->GetName(), pAmmoClass->GetName()); ok = false; } } } } } #endif if (ok) { m_fireCounter++; m_expended_ammo++; IActor *pLocalActor=m_pGameFramework->GetClientActor(); bool isLocal = pLocalActor && (pLocalActor->GetChannelId() == pActor->GetChannelId()); if (!isLocal) { NetShootEx(params.pos, params.dir, params.vel, params.hit, params.extra, params.predictionHandle, params.fireModeId); } CHANGED_NETWORK_STATE(this, ASPECT_STREAM); } else { if(params.predictionHandle) { CGameRules::SPredictionParams predictionParams(params.predictionHandle); g_pGame->GetGameRules()->GetGameObject()->InvokeRMI(CGameRules::ClPredictionFailed(), predictionParams, eRMI_ToClientChannel, m_pGameFramework->GetGameChannelId(pNetChannel)); } } return true; }