IMPLEMENT_RMI(CGameRules, ClEnteredGame) { if(!gEnv->bServer && m_pGameFramework->GetClientActor()) { CActor* pActor = GetActorByChannelId(m_pGameFramework->GetClientActor()->GetChannelId()); if(pActor) { int status[2]; status[0] = GetTeam(pActor->GetEntityId()); status[1] = pActor->GetSpectatorMode(); m_pGameplayRecorder->Event(pActor->GetEntity(), GameplayEvent(eGE_Connected, 0, 0, (void*)status)); } } return true; }
//------------------------------------------------------------------------ int CScriptBind_Actor::Fall(IFunctionHandler *pH, Vec3 hitPos) { CActor *pActor = GetActor(pH); if (!pActor) return pH->EndFunction(); // [Mikko] 11.10.2007 - Moved the check here, since it was causing too much trouble in CActor.Fall(). // The point of this filtering is to mostly mask out self-induced collision damage on friendly NPCs // which are playing special animations. if(!g_pGameCVars->g_enableFriendlyFallAndPlay) { if (IAnimatedCharacter* pAC = pActor->GetAnimatedCharacter()) { if ((pAC->GetPhysicalColliderMode() == eColliderMode_NonPushable) || (pAC->GetPhysicalColliderMode() == eColliderMode_PushesPlayersOnly)) { // Only mask for player friendly NPCs. if (pActor->GetEntity() && pActor->GetEntity()->GetAI()) { IAIObject* pAI = pActor->GetEntity()->GetAI(); IAIObject* playerAI = 0; if (IActor* pPlayerActor = m_pGameFW->GetClientActor()) playerAI = pPlayerActor->GetEntity()->GetAI(); if (playerAI && gEnv->pAISystem->GetFactionMap().GetReaction(playerAI->GetFactionID(), pAI->GetFactionID()) > IFactionMap::eRT_Hostile) return pH->EndFunction(); } } } } pActor->Fall(hitPos); return pH->EndFunction(); }
void CFists::RaiseWeapon(bool raise, bool faster /*= false*/) { //Only when colliding something while running if(raise && (GetCurrentAnimState()==eFAS_RUNNING || GetCurrentAnimState()==eFAS_JUMPING) && !IsWeaponRaised()) { if((m_fm && m_fm->IsFiring())||(m_melee && m_melee->IsFiring())) return; PlayAction(g_pItemStrings->raise); SetDefaultIdleAnimation( eIGS_FirstPerson,g_pItemStrings->idle_relaxed); SetWeaponRaised(true); //Also give the player some impulse into the opposite direction CActor *pPlayer = GetOwnerActor(); Vec3 pos; if(pPlayer) { IPhysicalEntity* playerPhysics = pPlayer->GetEntity()->GetPhysics(); if(playerPhysics) { IMovementController *pMC = pPlayer->GetMovementController(); if(pMC) { SMovementState state; pMC->GetMovementState(state); pe_action_impulse impulse; impulse.iApplyTime = 1; impulse.impulse = -state.eyeDirection*600.0f; playerPhysics->Action(&impulse); pos = state.eyePosition + state.eyeDirection*0.5f; } } } GetScheduler()->TimerAction(GetCurrentAnimationTime(eIGS_FirstPerson), CSchedulerAction<EndRaiseWeaponAction>::Create(EndRaiseWeaponAction(this)), true); //Sound and FX feedback CollisionFeeback(pos,m_currentAnimState); } else if(!raise) SetWeaponRaised(false); }
void CMelee::OnFailedHit() { const SCollisionTestParams& collisionParams = m_collisionHelper.GetCollisionTestParams(); bool collided = PerformCylinderTest(collisionParams.m_pos, collisionParams.m_dir, collisionParams.m_remote); CActor* pOwner = m_pWeapon->GetOwnerActor(); if(pOwner && pOwner->IsClient()) { if(!collided && s_meleeSnapTargetId) { Vec3 ownerpos = pOwner->GetEntity()->GetWorldPos(); IEntity* pTarget = gEnv->pEntitySystem->GetEntity(s_meleeSnapTargetId); if(pTarget && ownerpos.GetSquaredDistance(pTarget->GetWorldPos()) < cry_sqr(GetRange() * m_pMeleeParams->meleeparams.target_range_mult)) { collided = m_collisionHelper.PerformMeleeOnAutoTarget(s_meleeSnapTargetId); } } s_meleeSnapTargetId = 0; CHANGED_NETWORK_STATE(pOwner, CPlayer::ASPECT_SNAP_TARGET); if(g_pGameCVars->pl_melee.mp_melee_system_camera_lock_and_turn) { pOwner->GetActorParams().viewLimits.ClearViewLimit(SViewLimitParams::eVLS_Item); } } if(m_pMeleeAction) { if(pOwner) { m_pMeleeAction->OnHitResult(pOwner, collided); } else { //Owner has dropped weapon (Likely from being killed) so we can stop and release the action m_pMeleeAction->ForceFinish(); SAFE_RELEASE(m_pMeleeAction); } } ApplyMeleeEffects(collided); }
//------------------------------------------------------------------------ int CScriptBind_Actor::AttachVulnerabilityEffect(IFunctionHandler *pH, int characterSlot, int partid, Vec3 hitPos, float radius, const char* effect, const char* attachmentIdentifier) { CActor *pActor = GetActor(pH); if (!pActor) return pH->EndFunction(); IEntity* pEntity = pActor->GetEntity(); ICharacterInstance* pChar = pEntity->GetCharacter(characterSlot); if (!pChar || !effect) return pH->EndFunction(); //fallback: use nearest attachment float minDiff = radius*radius; IAttachment* pClosestAtt = 0; IAttachmentManager* pMan = pChar->GetIAttachmentManager(); for (int i=0; i<pMan->GetAttachmentCount(); ++i) { IAttachment* pAtt = pMan->GetInterfaceByIndex(i); float diff = (hitPos - pAtt->GetAttWorldAbsolute().t).len2(); if (diff < minDiff) { // only use specified attachments if (attachmentIdentifier[0] && !strstr(pAtt->GetName(), attachmentIdentifier)) continue; minDiff = diff; pClosestAtt = pAtt; } //CryLog("diff: %.2f, att: %s", diff, attName.c_str()); } if (!pClosestAtt) return pH->EndFunction(); //CryLog("AttachVulnerabilityEffect: closest att %s, attaching effect %s", pClosestAtt->GetName(), effect); CEffectAttachment *pEffectAttachment = new CEffectAttachment(effect, Vec3(ZERO), Vec3(0,1,0), 1.f); pClosestAtt->AddBinding(pEffectAttachment); pClosestAtt->HideAttachment(0); return pH->EndFunction(pClosestAtt->GetName()); }
void CAutoAimManager::RegisterCharacterTargetInfo(const CActor& targetActor, const SAutoaimTargetRegisterParams& registerParams) { SAutoaimTarget aimTarget; aimTarget.entityId = targetActor.GetEntityId(); aimTarget.pActorWeak = targetActor.GetWeakPtr(); aimTarget.fallbackOffset = registerParams.fallbackOffset; aimTarget.primaryBoneId = registerParams.primaryBoneId; aimTarget.physicsBoneId = registerParams.physicsBoneId; aimTarget.secondaryBoneId = registerParams.secondaryBoneId; aimTarget.innerRadius = registerParams.innerRadius; aimTarget.outerRadius = registerParams.outerRadius; aimTarget.snapRadius = registerParams.snapRadius; aimTarget.snapRadiusTagged = registerParams.snapRadiusTagged; if (!gEnv->bMultiplayer) { IEntity* pTargetEntity = targetActor.GetEntity(); aimTarget.aiFaction = IFactionMap::InvalidFactionID; //Instance properties, other stuff could be added here easily (grab enemy, sliding hit, etc) SmartScriptTable props; SmartScriptTable propsPlayerInteractions; IScriptTable* pScriptTable = pTargetEntity->GetScriptTable(); if (pScriptTable && pScriptTable->GetValue("Properties", props)) { if (props->GetValue("PlayerInteractions", propsPlayerInteractions)) { int stealhKill = 0; if (propsPlayerInteractions->GetValue("bStealthKill", stealhKill) && (stealhKill != 0)) { aimTarget.SetFlag(eAATF_StealthKillable); } int canBeGrabbed = 0; if (propsPlayerInteractions->GetValue("bCanBeGrabbed", canBeGrabbed) && (canBeGrabbed != 0)) { aimTarget.SetFlag(eAATF_CanBeGrabbed); } } } } m_autoaimTargets.push_back(aimTarget); }
//------------------------------------------------------------------------ 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); } } 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((!IsSilencerAttached()) && fDist2<sqr(SAFE_GAMEAUDIO_BATTLESTATUS_FUNC_RET(GetBattleRange()))) SAFE_GAMEAUDIO_BATTLESTATUS_FUNC(TickBattleStatus(1.0f)); } } }
//------------------------------------------------------------------------ int CScriptBind_Actor::IsFlying(IFunctionHandler *pH) { CActor *pActor = GetActor(pH); if (!pActor) return pH->EndFunction(); if (pActor) { pe_status_living livStat; IPhysicalEntity *pPhysEnt = pActor->GetEntity()->GetPhysics(); if (!pPhysEnt) return pH->EndFunction(); if(pPhysEnt->GetStatus(&livStat)) return pH->EndFunction(livStat.bFlying!=0); } return pH->EndFunction(); }
//------------------------------------------------------------------------ int CScriptBind_Actor::ResetVulnerabilityEffects(IFunctionHandler *pH, int characterSlot) { CActor *pActor = GetActor(pH); if (!pActor) return pH->EndFunction(); IEntity* pEntity = pActor->GetEntity(); ICharacterInstance* pChar = pEntity->GetCharacter(characterSlot); if (pChar) { IAttachmentManager* pMan = pChar->GetIAttachmentManager(); for (int i=0; i<pMan->GetAttachmentCount(); ++i) { IAttachment* pAtt = pMan->GetInterfaceByIndex(i); if (strstr(pAtt->GetName(), "vulnerable")) pAtt->ClearBinding(); } } return pH->EndFunction(); }
//------------------------------------------------------------------------ void SSleepEffect::Activate(EntityId targetId, EntityId ownerId, EntityId weaponId, const char *effect, const char *defaultEffect) { CActor *pActor = (CActor *)gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(targetId); if (pActor) { IAISystem *pAISystem=gEnv->pAISystem; if (pAISystem) { if(IEntity* pEntity=pActor->GetEntity()) { if(IAIObject* pAIObj=pEntity->GetAI()) { IAISignalExtraData *pEData = pAISystem->CreateSignalExtraData(); // no leak - this will be deleted inside SendAnonymousSignal // try to retrieve the shooter position if (IEntity* pOwnerEntity = gEnv->pEntitySystem->GetEntity(ownerId)) pEData->point = pOwnerEntity->GetWorldPos(); else pEData->point = pEntity->GetWorldPos(); IAIActor* pAIActor = pAIObj->CastToIAIActor(); if(pAIActor) pAIActor->SetSignal(1,"TRANQUILIZED",0,pEData); } } } pActor->CreateScriptEvent("sleep", 0); pActor->GetGameObject()->SetPhysicalizationProfile(eAP_Sleep); // no dropping weapons for AI if(pActor->IsPlayer()) pActor->DropItem(pActor->GetCurrentItemId(), 1.0f, false); pActor->SetSleepTimer(12.5f); } }
// returns true if firing is allowed bool CPlant::GetPlantingParameters(Vec3& pos, Vec3& dir, Vec3& vel) const { CActor *pActor = m_pWeapon->GetOwnerActor(); IMovementController *pMC = pActor?pActor->GetMovementController():0; SMovementState info; if (pMC) pMC->GetMovementState(info); if (m_pWeapon->GetStats().fp) pos = m_pWeapon->GetSlotHelperPos( eIGS_FirstPerson, m_plantparams.helper.c_str(), true); else if (pMC) pos = info.eyePosition+info.eyeDirection*0.25f; else pos = pActor->GetEntity()->GetWorldPos(); if (pMC) dir = info.eyeDirection; else dir = pActor->GetEntity()->GetWorldRotation().GetColumn1(); if (IPhysicalEntity *pPE=pActor->GetEntity()->GetPhysics()) { pe_status_dynamics sv; if (pPE->GetStatus(&sv)) { if (sv.v.len2()>0.01f) { float dot=sv.v.GetNormalized().Dot(dir); if (dot<0.0f) dot=0.0f; vel=sv.v*dot; } } } // if the ammo should be placed (claymore/mine) rather than thrown forward (c4), check if we can do so... if(m_plantparams.place_on_ground) { ray_hit hit; static const int objTypes = ent_static | ent_terrain; static const unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any; static IPhysicalEntity* pSkipEnts[10]; int nskip = CSingle::GetSkipEntities(m_pWeapon, pSkipEnts, 10); int res = gEnv->pPhysicalWorld->RayWorldIntersection(pos, 2.0f * dir, objTypes, flags, &hit, 1, pSkipEnts, nskip); if(!res) return false; else { // check surface normal - must be close to up if(hit.n.z < 0.8f) return false; // special case to stop stacking of claymores/mines (they are static so are hit by the ray) if(hit.pCollider && hit.pCollider->GetiForeignData() == PHYS_FOREIGN_ID_ENTITY) { IEntity * pEntity = (IEntity*)hit.pCollider->GetForeignData(PHYS_FOREIGN_ID_ENTITY); if(pEntity) { if(!m_pClaymoreClass) m_pClaymoreClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("claymoreexplosive"); if(!m_pAVMineClass) m_pAVMineClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("avexplosive"); if(pEntity->GetClass() == m_pClaymoreClass || pEntity->GetClass() == m_pAVMineClass) return false; } } // second check to see if there is another object in the way float hitDist = hit.dist; int res = gEnv->pPhysicalWorld->RayWorldIntersection(pos, 2.0f * dir, ent_all, flags, &hit, 1, pSkipEnts, nskip); if(res && hit.dist < hitDist-0.1f) { return false; } pos = hit.pt; } } return true; }
//------------------------------------------------------------------------ void CMelee::Hit(const Vec3 &pt, const Vec3 &dir, const Vec3 &normal, IPhysicalEntity *pCollider, int partId, int ipart, int surfaceIdx, float damageScale, bool remote) { // generate the damage IEntity *pTarget = gEnv->pEntitySystem->GetEntityFromPhysics(pCollider); // Report punch to AI system. // The AI notification must come before the game rules are // called so that the death handler in AIsystem understands that the hit // came from the player. bool ok = true; if(pTarget) { CActor *pActor = m_pWeapon->GetOwnerActor(); if(!gEnv->bMultiplayer && pActor && pActor->IsPlayer()) { if (IActor *pAITarget = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pTarget->GetId())) { if (IAIObject *pAITargetObject = pTarget->GetAI()) { if (pAITargetObject->IsFriendly(pActor->GetEntity()->GetAI(), false)) { ok = false; m_noImpulse = true; } } } } if(ok) { CGameRules *pGameRules = g_pGame->GetGameRules(); HitInfo info(m_pWeapon->GetOwnerId(), pTarget->GetId(), m_pWeapon->GetEntityId(), m_pShared->meleeparams.damage * damageScale * m_meleeScale, 0.0f, pGameRules->GetHitMaterialIdFromSurfaceId(surfaceIdx), partId, pGameRules->GetHitTypeId(m_pShared->meleeparams.hit_type.c_str()), pt, dir, normal); info.remote = remote; pGameRules->ClientHit(info); } } // play effects if(ok) { if(IMaterialEffects *pMaterialEffects = gEnv->pGame->GetIGameFramework()->GetIMaterialEffects()) { TMFXEffectId effectId = pMaterialEffects->GetEffectId("melee", surfaceIdx); if (effectId != InvalidEffectId) { SMFXRunTimeEffectParams params; params.pos = pt; params.normal = -dir; params.playflags = MFX_PLAY_ALL | MFX_DISABLE_DELAY; params.soundSemantic = eSoundSemantic_Player_Foley; pMaterialEffects->ExecuteEffect(effectId, params); } } } ApplyCameraShake(true); m_pWeapon->PlayAction(m_pShared->meleeactions.hit.c_str()); }
//------------------------------------------------------------------------ // returns true if entity is killed, false if it is not bool CGameRulesMPDamageHandling::SvOnHit( const HitInfo &hitInfo ) { const HitTypeInfo * pHitTypeInfo = m_pGameRules->GetHitTypeInfo(hitInfo.type); #if !defined(_RELEASE) if(!pHitTypeInfo) CryFatalError("By ::SvOnHit() all hit info should have a hit type that is valid and registered in the GameRules. This isn't true of type %d!", hitInfo.type); #endif SDamageHandling damageHandling(&hitInfo, 1.0f); float damage = hitInfo.damage; IActorSystem* pActorSystem = g_pGame->GetIGameFramework()->GetIActorSystem(); CActor *pTargetActor = static_cast<CActor*>(pActorSystem->GetActor(hitInfo.targetId)); CActor *pShooterActor = static_cast<CActor*>(pActorSystem->GetActor(hitInfo.shooterId)); CPlayer* pShooterPlayer = (pShooterActor && pShooterActor->IsPlayer()) ? static_cast<CPlayer*>(pShooterActor) : NULL ; bool isPlayer = pTargetActor != NULL && pTargetActor->IsPlayer(); #ifndef _RELEASE //--- Fix to allow the damage handling to work for these entity classes in the same way as for Players static IEntityClass* sDamEntClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("DamageTestEnt"); isPlayer |= pTargetActor != NULL && pTargetActor->GetEntity()->GetClass() == sDamEntClass; #endif CPlayer* pPlayer = isPlayer ? static_cast<CPlayer*>(pTargetActor) : NULL; const bool isMelee = ((pHitTypeInfo->m_flags & CGameRules::EHitTypeFlag::IsMeleeAttack) != 0); const bool checkHeadshots = ((pHitTypeInfo->m_flags & CGameRules::EHitTypeFlag::IgnoreHeadshots) == 0); bool bIsHeadShot = false; if(pPlayer && hitInfo.partId >= 0 && checkHeadshots) { bIsHeadShot = pPlayer->IsHeadShot(hitInfo); if (!bIsHeadShot && g_pGameCVars->g_mpHeadshotsOnly) { damage = 0.f; } } //If the player has died more than kTimeToAllowKillsAfterDeath seconds ago, we disallow any damage they apply, unless the hit type is flagged as allowing it. static const float kTimeToAllowKillsAfterDeath = 0.05f; if(pTargetActor && pShooterPlayer && !hitInfo.hitViaProxy && ((pHitTypeInfo->m_flags & CGameRules::EHitTypeFlag::AllowPostDeathDamage) == 0) && pShooterActor->IsDead() && (gEnv->pTimer->GetFrameStartTime().GetSeconds() - pShooterPlayer->GetDeathTime()) > kTimeToAllowKillsAfterDeath) { damage = 0.0f; } IGameRulesStateModule *stateModule = m_pGameRules->GetStateModule(); IGameRulesRoundsModule* pRoundsModule = m_pGameRules->GetRoundsModule(); if ( (stateModule != NULL && (stateModule->GetGameState() == IGameRulesStateModule::EGRS_PostGame)) || (pRoundsModule!= NULL && !pRoundsModule->IsInProgress() )) { // No damage allowed once the game has ended, except in cases where it would cause graphical glitches if (hitInfo.type != CGameRules::EHitType::PunishFall) { damage = 0.0f; } } IEntity *pTarget = gEnv->pEntitySystem->GetEntity(hitInfo.targetId); #if defined(SERVER_CHECKS) if(damage != 0.0f) { int nNewCheckCounter = m_checkCounter + 1; if (CItem *pItem = static_cast<CItem *>(g_pGame->GetIGameFramework()->GetIItemSystem()->GetItem(hitInfo.weaponId))) { if(CWeapon * pWeapon = static_cast<CWeapon*>(pItem->GetIWeapon())) { int nFireModeFromShotId = GetFireModeFromShotId(hitInfo.shotId); static const int kCheckFreq = 7; if(pShooterActor && nNewCheckCounter == kCheckFreq) { float fDamageAtXMeters = 0.0f; float fDistance2D, fDistanceMax, fNetLagSeconds; CServerCheatMonitor::GetHitValidationInfo(*pShooterActor, hitInfo, fDistance2D, fDistanceMax, fNetLagSeconds); bool bDoDamageValidation = false; if(isMelee) { if(CMelee * pMelee = pWeapon->GetMelee()) { //This check can't be used for everything because the default firemode returns '0.f' for range and only CMelee extends it // the horizontal player speed is x 2.0f as the players could have potentially immediately turned and run away from each other float fMeleeRangeError = fDistance2D - (pMelee->GetRange() + (CServerCheatMonitor::kMaxHorizontalPlayerSpeed * fNetLagSeconds * 2.0f)); if(fMeleeRangeError > 0.1f) { g_pGame->GetAntiCheatManager()->FlagActivity(eCT_MeleeRange, pShooterActor->GetChannelId(), fMeleeRangeError); } fDamageAtXMeters = pMelee->GetDamageAmountAtXMeters(fDistance2D); bDoDamageValidation = true; } } else { ////////////////////////////////////////////////////////////////////// // Verify that the hit is from a valid shot DoShotValidation(hitInfo, pHitTypeInfo, pShooterActor); ////////////////////////////////////////////////////////////////////// CFireMode * pFireMode = static_cast<CFireMode*>(pWeapon->GetFireMode(nFireModeFromShotId)); if(pFireMode) { const SFireModeParams * pParams = pFireMode->GetShared(); char projectileClassName[128]; g_pGame->GetIGameFramework()->GetNetworkSafeClassName(projectileClassName, sizeof(projectileClassName), hitInfo.projectileClassId); IEntityClass * pProjectileClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(projectileClassName); if((pProjectileClass && (pProjectileClass == pParams->fireparams.ammo_type_class || pProjectileClass == pParams->plantparams.ammo_type_class))) { float fBulletSpeed = 100.f; const SAmmoParams * pAmmoParams = g_pGame->GetWeaponSystem()->GetAmmoParams(pFireMode->GetAmmoType()); if(pAmmoParams) { fBulletSpeed = pAmmoParams->speed; } //Might have been closer when the shot was fired const float fMaxTimeSinceShot = ((fDistanceMax / fBulletSpeed) * 2.0f) + fNetLagSeconds; //Should be less than this. Laaaaarge fudge factor float fDistance_Conservative = fDistance2D - (fMaxTimeSinceShot * CServerCheatMonitor::kMaxHorizontalPlayerSpeed); fDamageAtXMeters = pFireMode->GetDamageAmountAtXMeters(fDistance_Conservative); } } else if(pHitTypeInfo->m_flags & CGameRules::EHitTypeFlag::ValidationRequired) { CryStackStringT<char, 256> invalidFireModeMessage; invalidFireModeMessage.Format("Invalid fire mode, weapon: '%s', firemode: %d", pWeapon->GetEntity()->GetName(), nFireModeFromShotId); g_pGame->GetAntiCheatManager()->FlagActivity(eCT_ValidHitInfo, pShooterActor->GetChannelId(), invalidFireModeMessage.c_str()); } } float fDamageFromWeapon = hitInfo.damage; if(fDamageFromWeapon > fDamageAtXMeters && fDamageAtXMeters > 0.0f) { //Log the ratio of actual damage to expected damage, e.g. 1.2 x expected CryStackStringT<char, 256> excessiveDamageMessage; excessiveDamageMessage.Format("Weapon '%s', firemode %d", pWeapon->GetEntity()->GetName(), nFireModeFromShotId); g_pGame->GetAntiCheatManager()->FlagActivity(eCT_WeaponDamage, pShooterActor->GetChannelId(), fDamageFromWeapon / fDamageAtXMeters, excessiveDamageMessage.c_str()); } if(pTargetActor) { CServerCheatMonitor::ValidateTargetActorPositionAgainstHit(*pTargetActor, hitInfo, fNetLagSeconds); } nNewCheckCounter = 0; } else { nNewCheckCounter = kCheckFreq - 1; } } } m_checkCounter = nNewCheckCounter; } // Update the shotcounter for tracking headshots and traversal times if(pShooterPlayer && (pHitTypeInfo->m_flags & CGameRules::EHitTypeFlag::ValidationRequired)) { char netName[128]; g_pGame->GetIGameFramework()->GetNetworkSafeClassName(netName, sizeof(netName), hitInfo.projectileClassId); IEntityClass * pProjectileClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(netName); if (pProjectileClass) { CShotCounter* pShotCounter = pShooterPlayer->GetShotCounter(); pShotCounter->RecordHit(hitInfo, bIsHeadShot); } } #endif // SERVER_CHECKS IEntityClass* pTargetClass = pTarget ? pTarget->GetClass() : NULL; // Check for friendly fire if( bool bCheckFriendlyFire = ((hitInfo.targetId!=hitInfo.shooterId) && (hitInfo.type!=CGameRules::EHitType::EventDamage)) ) { if(IVehicle* pTargetVehicle = g_pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(hitInfo.targetId)) { if(IActor* pDriverTargetVehicle = pTargetVehicle->GetDriver()) { // Vehicle driver shot own vehicle (same as shooting yourself), don't do friendly fire. bCheckFriendlyFire = pDriverTargetVehicle->GetEntityId()!=hitInfo.shooterId; } } if(bCheckFriendlyFire) { if (m_pGameRules->GetTeamCount() > 1) { int shooterTeamId = m_pGameRules->GetTeam(hitInfo.shooterId); int targetTeamId = m_pGameRules->GetTeam(hitInfo.targetId); if (shooterTeamId && (shooterTeamId == targetTeamId)) { damage = GetFriendlyFireDamage(damage, hitInfo, pTargetActor); } } } } if (damage <= 0.f) { // If the hit isn't doing anything bail, this means any hit that gets past here has damage associated with it and thus wants to // display a hit indicator return false; } if (pPlayer) { if(hitInfo.partId >= 0 && !isMelee) { damageHandling.damageMultiplier *= pPlayer->GetBodyDamageMultiplier(hitInfo); } if (isMelee) { damageHandling.damageMultiplier *= g_pGameCVars->pl_melee.damage_multiplier_mp; } } damage *= damageHandling.damageMultiplier; HitInfo hitInfoWithDamage = hitInfo; hitInfoWithDamage.damage = damage; if(pPlayer) { SActorStats* pStats = pPlayer->GetActorStats(); float actorHealth = pPlayer->GetHealth(); if(pStats) { #ifndef _RELEASE if (g_pGameCVars->g_LogDamage) { char weaponClassName[64], projectileClassName[64]; CryLog ("[DAMAGE] %s '%s' took %.3f '%s' damage (%.3f x %.3f) weapon=%s projectile=%s", pPlayer->GetEntity()->GetClass()->GetName(), pPlayer->GetEntity()->GetName(), damage, m_pGameRules->GetHitType(hitInfo.type), hitInfo.damage, damageHandling.damageMultiplier, g_pGame->GetIGameFramework()->GetNetworkSafeClassName(weaponClassName, sizeof(weaponClassName), hitInfo.weaponClassId) ? weaponClassName : "none", g_pGame->GetIGameFramework()->GetNetworkSafeClassName(projectileClassName, sizeof(projectileClassName), hitInfo.projectileClassId) ? projectileClassName : "none"); } #endif if(pStats->bStealthKilling && actorHealth <= damage) { if(pPlayer->GetStealthKill().GetTargetId() != hitInfoWithDamage.shooterId) { pPlayer->StoreDelayedKillingHitInfo(hitInfoWithDamage); } hitInfoWithDamage.damage = 0; } else if (pStats->bStealthKilled && hitInfoWithDamage.type != CGameRules::EHitType::StealthKill) { hitInfoWithDamage.damage = 0; } } } bool bKilled = SvOnHitScaled(hitInfoWithDamage); return bKilled; }
void CAIAwarenessToPlayerHelper::RecalculateAwareness() { int highestAlertnessInGameRightNow = 0; float distanceToTheClosestHostileAgentSq = FLT_MAX; Vec3 playerPosition(ZERO); const IFactionMap& factionMap = gEnv->pAISystem->GetFactionMap(); uint8 playerFactionID = factionMap.GetFactionID("Players"); IAIObject* playerAiObject = NULL; CActor* playerActor = static_cast<CActor*>(gEnv->pGame->GetIGameFramework()->GetClientActor()); if (playerActor) { if (IEntity* playerEntity = playerActor->GetEntity()) { playerPosition = playerEntity->GetWorldPos(); playerAiObject = playerEntity->GetAI(); } } IF_UNLIKELY ((playerActor == NULL) || (playerAiObject == NULL)) return; const bool playerIsCloaked = playerActor ? playerActor->IsCloaked() : true; const bool applyProximityToHostileAgentIncrement = m_actualAwareness < kAIAwarenessToPlayerAware && !playerPosition.IsZero(); // Go through actors IActorIteratorPtr actorIt = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->CreateActorIterator(); if (actorIt) { while (IActor* actor = actorIt->Next()) { const IAIObject* ai = actor->GetEntity()->GetAI(); const IAIActor* aiActor = ai ? ai->CastToIAIActor() : NULL; if (aiActor && aiActor->IsActive()) { const int alertness = GetAlertnessAffectedByVisibility(*aiActor, *playerAiObject, playerIsCloaked); highestAlertnessInGameRightNow = std::max(alertness, highestAlertnessInGameRightNow); if (applyProximityToHostileAgentIncrement && factionMap.GetReaction(playerFactionID, ai->GetFactionID()) == IFactionMap::Hostile) { float distanceSq = playerPosition.GetSquaredDistance(ai->GetPos()); if (distanceToTheClosestHostileAgentSq > distanceSq) { distanceToTheClosestHostileAgentSq = distanceSq; } } } } } // Go through non Actors { SAwarenessEntitiesVector::iterator it = m_awarenessEntities.begin(); SAwarenessEntitiesVector::iterator end = m_awarenessEntities.end(); for (; it != end; ++it) { const IAwarenessEntity* pAwarenessEntity = *it; const int awareness = pAwarenessEntity->GetAwarenessToActor( playerAiObject, playerActor ); highestAlertnessInGameRightNow = std::max(awareness, highestAlertnessInGameRightNow); } } /// assert(highestAlertnessInGameRightNow >= 0 && highestAlertnessInGameRightNow <= 2); switch (highestAlertnessInGameRightNow) { default: { const float thresholdDistanceSq = square(g_pGameCVars->ai_ProximityToHostileAlertnessIncrementThresholdDistance); if (applyProximityToHostileAgentIncrement && distanceToTheClosestHostileAgentSq < thresholdDistanceSq) { m_actualAwareness = kAIAwarenessToPlayerAware * (1 - (distanceToTheClosestHostileAgentSq / thresholdDistanceSq)); } else { m_actualAwareness = 0.0f; } } break; case 1: m_actualAwareness = kAIAwarenessToPlayerAware; break; case 2: m_actualAwareness = kAIAwarenessToPlayerAlerted; break; } }
void CHandGrenades::UpdateStowedWeapons() { CActor *pOwnerActor = GetOwnerActor(); if (!pOwnerActor) return; ICharacterInstance *pOwnerCharacter = pOwnerActor->GetEntity()->GetCharacter(0); if (!pOwnerCharacter) return; IStatObj *pTPObj = GetEntity()->GetStatObj(eIGS_ThirdPerson); if (!pTPObj) return; int ammoCount = m_fm ? pOwnerActor->GetInventory()->GetAmmoCount(m_fm->GetAmmoType()) : 0; if (IsSelected() && (ammoCount > 0)) { ammoCount--; } if (!pOwnerActor->IsThirdPerson()) { ammoCount = 0; } int numGrenDiff = ammoCount - m_numStowedCopies; if(numGrenDiff != 0) { if (m_stowSlot < 0) { m_stowSlot = PickStowSlot(pOwnerCharacter->GetIAttachmentManager(), m_sharedparams->params.bone_attachment_01.c_str(), m_sharedparams->params.bone_attachment_02.c_str()); } if (m_stowSlot >= 0) { bool attach = numGrenDiff > 0; int tot = abs(numGrenDiff); IAttachmentManager *pAttachmentManager = pOwnerCharacter->GetIAttachmentManager(); IAttachment *pAttachment = NULL; for (int i=0; i<tot; i++) { //--- Generate the secondary slot from the first by adding one to the attachment name, is all we need at present... const char *attach1 = (m_stowSlot == 0) ? m_sharedparams->params.bone_attachment_01.c_str() : m_sharedparams->params.bone_attachment_02.c_str(); int lenAttachName = strlen(attach1); stack_string attach2(attach1, lenAttachName-1); attach2 += (attach1[lenAttachName-1]+1); if (attach) { pAttachment = pAttachmentManager->GetInterfaceByName(attach1); if(pAttachment && pAttachment->GetIAttachmentObject()) { pAttachment = pAttachmentManager->GetInterfaceByName(attach2); } if (pAttachment && !pAttachment->GetIAttachmentObject()) { CCGFAttachment *pCGFAttachment = new CCGFAttachment(); pCGFAttachment->pObj = pTPObj; pAttachment->AddBinding(pCGFAttachment); pAttachment->HideAttachment(0); pAttachment->HideInShadow(0); m_numStowedCopies++; } } else { pAttachment = pAttachmentManager->GetInterfaceByName(attach2); if(!pAttachment || !pAttachment->GetIAttachmentObject()) { pAttachment = pAttachmentManager->GetInterfaceByName(attach1); } if (pAttachment && pAttachment->GetIAttachmentObject()) { pAttachment->ClearBinding(); m_numStowedCopies--; } } } } } }
void CGameStateRecorder::OnGameplayEvent(IEntity *pEntity, const GameplayEvent &event) { EntityId id; if(!pEntity || !(id = pEntity->GetId())) { GameWarning("TimeDemo:GameState::OnGamePlayEvent: Entity not found"); return; } CActor *pActor = (CActor*)(gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(id)); if(!pActor) { GameWarning("TimeDemo:GameState::OnGamePlayEvent: Entity %s has no actor", pEntity->GetName()); return; } GameplayEvent event2 = event; event2.extra = 0;// event2 is the forwarded event, extra either will be not used by the listener or re-set as a string uint8 eType = event.event; bool bPlayer = (pActor->IsPlayer() && m_mode); if(bPlayer || m_mode==GPM_AllActors) { //items switch(eType) { case eGE_ItemPickedUp: { CheckInventory(pActor,0);//,*m_pRecordGameEventFtor); } break; case eGE_ItemDropped: { TItemName itemName = GetItemName(EntityId(event.extra)); if(!itemName ) //if(itemIdx < 0) break; event2.description = itemName; SendGamePlayEvent(pEntity,event2); IEntity* pItemEntity = gEnv->pEntitySystem->FindEntityByName(itemName); if(!pItemEntity) break; IItem* pItem = g_pGame->GetIGameFramework()->GetIItemSystem()->GetItem(pItemEntity->GetId()); if(!pItem) break; IEntityClass* pItemClass = pItem->GetEntity()->GetClass(); if(pItemClass && !strcmpi(pItemClass->GetName(),"SOCOM")) { IItem* pCurrentItem = pActor->GetCurrentItem(); if(pCurrentItem) { IEntityClass* pCurrentItemClass = pCurrentItem->GetEntity()->GetClass(); if(pCurrentItemClass && !strcmpi(pCurrentItemClass->GetName(),"SOCOM")) { GameplayEvent event3; event3.event = eGE_ItemSelected; TItemName itemName = GetItemName(pCurrentItem->GetEntity()->GetId()); if(!itemName) break; event3.value = 0; event3.description = (const char*)itemName; SendGamePlayEvent(pEntity,event3); } } } } break; case eGE_WeaponFireModeChanged: { TItemName itemIdx = GetItemName(EntityId(event.extra)); if(!itemIdx)//if(itemIdx < 0) break; event2.description = (const char*)itemIdx; SendGamePlayEvent(pEntity,event2); } break; case eGE_ItemSelected: { EntityId itemId = EntityId(event.extra); TItemName itemIdx = GetItemName(itemId); if(itemId && !itemIdx) break; event2.value = 0; event2.description = (const char*)itemIdx; SendGamePlayEvent(pEntity,event2); } break; case eGE_AttachedAccessory: { if(!IsGrenade(event.description)) // NOT OffHandGrenade SendGamePlayEvent(pEntity,event2); } break; case eGE_AmmoCount: { const char* itemIdx = event.description; if(!itemIdx) break; TGameStates::iterator itGS; /*if(pActor->IsPlayer()) itGS = m_itSingleActorGameState; else */if(pActor->GetEntity()) itGS = m_GameStates.find(pActor->GetEntity()->GetId()); else break; if(itGS == m_GameStates.end()) break; SActorGameState& gstate = itGS->second; IEntity* pItemEntity = gEnv->pEntitySystem->FindEntityByName(itemIdx); if(!pItemEntity) break; IItem* pItem = g_pGame->GetIGameFramework()->GetIItemSystem()->GetItem(pItemEntity->GetId()); if(!pItem) break; CWeapon* pWeapon = (CWeapon*)(pItem->GetIWeapon()); if(pWeapon && pWeapon->GetEntity()) { TItemContainer::iterator it = gstate.Items.find(itemIdx); if(it==gstate.Items.end()) break; SItemProperties& recItem = it->second; SWeaponAmmo weaponAmmo = pWeapon->GetFirstAmmo(); bool bGrenade = false; if(!weaponAmmo.pAmmoClass) { // special case for grenades if(IsAmmoGrenade((const char*)(event.extra))) { weaponAmmo.pAmmoClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass((const char*)event.extra); weaponAmmo.count = (int)event.value; bGrenade = true; } } for(; weaponAmmo.pAmmoClass ; weaponAmmo = pWeapon->GetNextAmmo()) { int ammoCount = weaponAmmo.count; const char* ammoClass; if(weaponAmmo.pAmmoClass && (ammoClass = weaponAmmo.pAmmoClass->GetName())) { TAmmoContainer& recAmmo = bGrenade? gstate.AmmoMags : recItem.Ammo; if(recAmmo.find(ammoClass) == recAmmo.end()) recAmmo.insert(std::make_pair(ammoClass,0)); if(ammoCount != recAmmo[ammoClass]) { event2.event = eGE_AmmoCount; event2.value = (float)ammoCount; if(event2.value < 0) event2.value = 0; event2.extra = (void*)ammoClass; event2.description = (const char*)itemIdx; SendGamePlayEvent(pEntity,event2); } } } } } break; case eGE_EntityGrabbed: { EntityId entityId = EntityId(event.extra); IEntity * pGrabbedEntity = gEnv->pEntitySystem->GetEntity(entityId); if(pGrabbedEntity) { event2.description = pGrabbedEntity->GetName(); SendGamePlayEvent(pEntity,event2); } } break; case eGE_WeaponReload: case eGE_ZoomedIn: case eGE_ZoomedOut: case eGE_HealthChanged: case eGE_ItemExchanged: SendGamePlayEvent(pEntity,event2); break; default: break; } } }
//------------------------------------------------------------------------ int CScriptBind_Actor::SetNanoSuitMode(IFunctionHandler *pH, int mode) { CActor *pActor = GetActor(pH); if (!pActor) return pH->EndFunction(); if(mode<0 || mode>=NANOMODE_LAST) return pH->EndFunction(); if(pActor->GetActorClass() != CPlayer::GetActorClassType()) return pH->EndFunction(); if(CNanoSuit *pSuit = ((CPlayer*)pActor)->GetNanoSuit()) pSuit->SetMode((ENanoMode)mode); else GameWarning("Lua tried to set NanoMode on not activated/existing Nanosuit of Player %s!", pActor->GetEntity()->GetName()); return pH->EndFunction(); }
void CFlashLight::EnableLight(bool enable) { CWeapon* pWeapon = GetWeapon(); if (!pWeapon || !m_sharedparams->pFlashLightParams || (m_lightEnabled && enable) || (!m_lightEnabled && !enable)) { return; } CActor* pOwner = pWeapon->GetOwnerActor(); bool ownerIsFP = pWeapon->IsOwnerFP(); int slot = ownerIsFP ? eIGS_FirstPerson : eIGS_ThirdPerson; if (enable) { const char* attachHelper = "light_term"; const Vec3 direction = Vec3(-1.0f, 0.0f, 0.0f); IRenderNode* pCasterException = NULL; if (pOwner) { IComponentRender* pRenderProxy = static_cast<IComponentRender*>(pOwner->GetEntity()->GetComponent<IComponentRender>().get()); if (pRenderProxy) { pCasterException = pRenderProxy->GetRenderNode(); } } EntityEffects::SLightAttachParams lightParams; lightParams.pCasterException = pCasterException; lightParams.color = m_sharedparams->pFlashLightParams->color * m_sharedparams->pFlashLightParams->diffuseMult; lightParams.direction = direction; lightParams.radius = m_sharedparams->pFlashLightParams->distance; lightParams.specularMultiplier = m_sharedparams->pFlashLightParams->specularMult; lightParams.projectFov = m_sharedparams->pFlashLightParams->fov; lightParams.hdrDynamic = m_sharedparams->pFlashLightParams->HDRDynamic; lightParams.projectTexture = m_sharedparams->pFlashLightParams->lightCookie.c_str(); lightParams.style = m_sharedparams->pFlashLightParams->style; lightParams.animSpeed = m_sharedparams->pFlashLightParams->animSpeed; lightParams.castShadows = g_pGameCVars->i_flashlight_has_shadows != 0; lightParams.firstSafeSlot = eIGS_Last; m_lightId = pWeapon->AttachLight(slot, attachHelper, lightParams); EnableFogVolume(pWeapon, slot, true); } else { if (m_lightId) { pWeapon->DetachEffect(m_lightId); } m_lightId = 0; EnableFogVolume(pWeapon, slot, false); } m_lightEnabled = enable; }
void CPlayerView::ViewSpectatorTarget(SViewParams &viewParams) { CActor* pTarget = (CActor*)g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_in.stats_spectatorTarget); if(!pTarget) return; IVehicle* pVehicle = pTarget->GetLinkedVehicle(); static float defaultOffset = 0.3f; static float viewHeight = 1.8f; Matrix34 worldTM = pTarget->GetEntity()->GetWorldTM(); Vec3 worldPos = worldTM.GetTranslation(); if(!pVehicle) { const SStanceInfo* stanceInfo = pTarget->GetStanceInfo(pTarget->GetStance()); if(stanceInfo) { Interpolate(viewHeight, stanceInfo->viewOffset.z, 5.0f, viewParams.frameTime); worldPos.z += viewHeight + defaultOffset; } else { worldPos.z += 1.8f; } } else { // use vehicle pos/ori worldTM = pVehicle->GetEntity()->GetWorldTM(); worldPos = pVehicle->GetEntity()->GetWorldPos(); worldPos.z += 1.5f; } Ang3 worldAngles = Ang3::GetAnglesXYZ(Matrix33(worldTM)); float distance = 3; // if freelook allowed, get orientation and distance from player entity if(g_pGameCVars->g_spectate_FixedOrientation == 0) { CPlayer* pThisPlayer = static_cast<CPlayer*>(g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_in.entityId)); if(!pThisPlayer) return; Matrix34 ownOrientation = pThisPlayer->GetEntity()->GetWorldTM(); worldAngles += Ang3::GetAnglesXYZ(Matrix33(ownOrientation)); distance = pThisPlayer->GetSpectatorZoom(); } if(pVehicle) { distance *= 4.0f; // air vehicles need bigger distance if(pVehicle->GetMovement() && pVehicle->GetMovement()->GetMovementType() == IVehicleMovement::eVMT_Air) distance *= 2.0f; } Vec3 goal; goal.x = distance * cos(worldAngles.z + gf_PI*1.5f) + worldPos.x; goal.y = distance * sin(worldAngles.z - gf_PI/2.0f) + worldPos.y; AABB targetBounds; pTarget->GetEntity()->GetLocalBounds(targetBounds); goal.z = targetBounds.max.z; float offset = defaultOffset; if(pVehicle) { if(pVehicle->GetMovement() && pVehicle->GetMovement()->GetMovementType() == IVehicleMovement::eVMT_Air) offset = 3.0f; else offset = 1.0f; } goal.z += pTarget->GetEntity()->GetWorldPos().z + offset; // store / interpolate the offset, not the world pos (reduces percieved jitter in vehicles) static Vec3 viewOffset(goal-worldPos); static Vec3 camPos(goal); static Vec3 entPos(worldPos); static EntityId lastSpectatorTarget(m_in.stats_spectatorTarget); // do a ray cast to check for camera intersection static ray_hit hit; IPhysicalEntity* pSkipEntities[10]; int nSkip = 0; if(pVehicle) { // vehicle drivers don't seem to have current items, so need to add the vehicle itself here nSkip = pVehicle->GetSkipEntities(pSkipEntities, 10); } else { IItem* pItem = pTarget->GetCurrentItem(); if (pItem) { CWeapon* pWeapon = (CWeapon*)pItem->GetIWeapon(); if (pWeapon) nSkip = CSingle::GetSkipEntities(pWeapon, pSkipEntities, 10); } } static float minDist = 0.4f; // how close we're allowed to get to the target static float wallSafeDistance = 0.3f; // how far to keep camera from walls Vec3 dir = goal - worldPos; primitives::sphere sphere; sphere.center = worldPos; sphere.r = wallSafeDistance; geom_contact *pContact = 0; float hitDist = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(sphere.type, &sphere, dir, ent_static|ent_terrain|ent_rigid|ent_sleeping_rigid, &pContact, 0, (geom_colltype_player<<rwi_colltype_bit) | rwi_stop_at_pierceable, 0, 0, 0, pSkipEntities, nSkip); // even when we have contact, keep the camera the same height above the target float minHeightDiff = dir.z; if(hitDist > 0 && pContact) { goal = worldPos + (hitDist * dir.GetNormalizedSafe()); if(goal.z - worldPos.z < minHeightDiff) { // can't move the camera far enough away from the player in this direction. Try moving it directly up a bit int numHits = 0; sphere.center = goal; // (move back just slightly to avoid colliding with the wall we've already found...) sphere.center -= dir.GetNormalizedSafe() * 0.05f; float newHitDist = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(sphere.type, &sphere, Vec3(0,0,minHeightDiff), ent_static|ent_terrain|ent_rigid|ent_sleeping_rigid, &pContact, 0, (geom_colltype_player<<rwi_colltype_bit) | rwi_stop_at_pierceable, 0, 0, 0, pSkipEntities, nSkip); float raiseDist = minHeightDiff - (goal.z - worldPos.z) - wallSafeDistance; if(newHitDist != 0) { raiseDist = MIN(minHeightDiff, newHitDist); } raiseDist = MAX(0.0f, raiseDist); goal.z += raiseDist; worldPos.z += raiseDist*0.8f; } } int thisFrameId = gEnv->pRenderer->GetFrameID(); static int frameNo(thisFrameId); if(thisFrameId - frameNo > 5) { // reset positions viewOffset = goal - worldPos; entPos = worldPos; camPos = goal; } if(lastSpectatorTarget != m_in.stats_spectatorTarget) { viewOffset = goal - worldPos; entPos = worldPos; camPos = goal; lastSpectatorTarget = m_in.stats_spectatorTarget; } frameNo = thisFrameId; static float interpSpeed = 5.0f; static float interpSpeed2 = 5.0f; static float interpSpeed3 = 8.0f; if(pVehicle) { Interpolate(viewOffset, goal-worldPos, interpSpeed, viewParams.frameTime); entPos = worldPos; viewParams.position = worldPos + viewOffset; camPos = viewParams.position; } else { Vec3 camPosChange = goal - camPos; Vec3 entPosChange = worldPos - entPos; if(camPosChange.GetLengthSquared() > 100.0f) camPos = goal; if(entPosChange.GetLengthSquared() > 100.0f) entPos = worldPos; Interpolate(camPos, goal, interpSpeed2, viewParams.frameTime); Interpolate(entPos, worldPos, interpSpeed3, viewParams.frameTime); viewParams.position = camPos; } Matrix33 rotation = Matrix33::CreateRotationVDir((entPos - viewParams.position).GetNormalizedSafe()); viewParams.rotation = GetQuatFromMat33(rotation); m_io.bUsePivot = true; m_io.stats_bobCycle = 0.0; }
void CPlayerView::ViewDeathCamTarget(SViewParams &viewParams) { CActor* pTarget = (CActor*)g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_in.stats_spectatorTarget); if(!pTarget) return; Matrix34 targetWorldTM = pTarget->GetEntity()->GetWorldTM(); Vec3 camPos = viewParams.position; static float offset = 1.5f; camPos.z += offset; float heightOffset = 1.5f; const SStanceInfo* pSI = pTarget->GetStanceInfo(pTarget->GetStance()); if(pSI) { heightOffset = pSI->viewOffset.z; } Vec3 targetPos = targetWorldTM.GetTranslation(); targetPos.z += heightOffset; int thisFrameId = gEnv->pRenderer->GetFrameID(); static int frameNo(thisFrameId); static Vec3 oldCamPos(camPos); static Vec3 oldTargetPos(targetPos); static EntityId lastSpectatorTarget(m_in.stats_spectatorTarget); static float oldFOVScale(1.0f); // if more than a few frames have passed since our last update, invalidate the positions if(thisFrameId - frameNo > 5) { oldCamPos = viewParams.position; // interpolate from current camera pos oldTargetPos = targetPos; oldFOVScale = 1.0f; } // if target changed, reset positions if(lastSpectatorTarget != m_in.stats_spectatorTarget) { oldCamPos = camPos; oldTargetPos = targetPos; lastSpectatorTarget = m_in.stats_spectatorTarget; oldFOVScale = 1.0f; } frameNo = thisFrameId; // slight zoom after 2s float timeNow = gEnv->pTimer->GetCurrTime(); float distSq = (targetPos - camPos).GetLengthSquared(); float scale = 1.0f; if(timeNow - m_in.deathTime > 1.0f && distSq > 2500.0f) { // 1.0f at 50m, 0.3f at 100m+ scale = 1.0f - (distSq - 2500.0f)/25000.0f; scale = CLAMP(scale, 0.3f, 1.0f); } Interpolate(oldCamPos, camPos, 5.0f, viewParams.frameTime); Interpolate(oldTargetPos, targetPos, 5.0f, viewParams.frameTime); Interpolate(oldFOVScale, scale, 0.5f, viewParams.frameTime); viewParams.position = oldCamPos; Vec3 dir = (oldTargetPos - oldCamPos).GetNormalizedSafe(); Matrix33 rotation = Matrix33::CreateRotationVDir(dir); dir.z = 0.0f; // quick ray check to make sure there's not a wall in the way... IActor* pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_in.entityId); if (pActor) { static ray_hit hit; IPhysicalEntity* pSkipEntities[10]; int nSkip = 0; IItem* pItem = pActor->GetCurrentItem(); if (pItem) { CWeapon* pWeapon = (CWeapon*)pItem->GetIWeapon(); if (pWeapon) nSkip = CSingle::GetSkipEntities(pWeapon, pSkipEntities, 10); } if (gEnv->pPhysicalWorld->RayWorldIntersection(viewParams.position, -dir, ent_static|ent_terrain|ent_rigid, rwi_ignore_noncolliding | rwi_stop_at_pierceable, &hit, 1, pSkipEntities, nSkip)) { dir.zero(); } } viewParams.position -= dir; viewParams.fov = m_in.defaultFov*oldFOVScale*(gf_PI/180.0f);; viewParams.rotation = GetQuatFromMat33(rotation); m_io.bUsePivot = true; m_io.stats_bobCycle = 0.0; }
void CPlayerView::ViewSpectatorTarget(SViewParams &viewParams) { CActor *pTarget = (CActor *)g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_in.stats_spectatorTarget); if(!pTarget) { return; } Matrix34 worldTM = pTarget->GetEntity()->GetWorldTM(); Vec3 worldPos = worldTM.GetTranslation(); worldPos.z += 1.5f; Ang3 worldAngles = Ang3::GetAnglesXYZ(Matrix33(worldTM)); float rot = worldAngles.z;// + m_rot; float distance = 3;//(m_defaultDistance != 0) ? m_defaultDistance : m_distance; if(IVehicle *pVehicle = pTarget->GetLinkedVehicle()) { AABB vehicleBox; pVehicle->GetEntity()->GetLocalBounds(vehicleBox); distance = 2.0f * vehicleBox.GetRadius(); } Vec3 goal; float zoom = 1.0f; goal.x = distance * zoom * cosf(rot + gf_PI * 1.5f) + worldPos.x; goal.y = distance * zoom * sinf(rot - gf_PI / 2.0f) + worldPos.y; AABB targetBounds; pTarget->GetEntity()->GetLocalBounds(targetBounds); goal.z = targetBounds.max.z; static float defaultOffset = 0.75f; float offset = defaultOffset; if(pTarget->GetLinkedVehicle()) { offset = 2.0f; } goal.z += pTarget->GetEntity()->GetWorldPos().z + offset; // store / interpolate the offset, not the world pos (reduces percieved jitter in vehicles) static Vec3 viewOffset(goal - worldPos); static Vec3 position(goal); static Vec3 entPos(worldPos); static EntityId lastSpectatorTarget(m_in.stats_spectatorTarget); // do a ray cast to check for camera intersection static ray_hit hit; IPhysicalEntity *pSkipEntities[10]; int nSkip = 0; IItem *pItem = pTarget->GetCurrentItem(); if (pItem) { CWeapon *pWeapon = (CWeapon *)pItem->GetIWeapon(); if (pWeapon) { nSkip = CSingle::GetSkipEntities(pWeapon, pSkipEntities, 10); } } else if(IVehicle *pVehicle = pTarget->GetLinkedVehicle()) { // vehicle drivers don't seem to have current items, so need to add the vehicle itself here nSkip = pVehicle->GetSkipEntities(pSkipEntities, 10); } const float wallSafeDistance = 0.2f; // how far to keep camera from walls Vec3 dir = goal - worldPos; primitives::sphere sphere; sphere.center = worldPos; sphere.r = wallSafeDistance; geom_contact *pContact = 0; float hitDist = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(sphere.type, &sphere, dir, ent_static | ent_terrain | ent_rigid | ent_sleeping_rigid, &pContact, 0, geom_colltype_player, 0, 0, 0, pSkipEntities, nSkip); // even when we have contact, keep the camera the same height above the target float minHeightDiff = dir.z; if(hitDist > 0 && pContact) { goal = worldPos + (hitDist * dir.GetNormalizedSafe()); if(goal.z - worldPos.z < minHeightDiff) { // can't move the camera far enough away from the player in this direction. Try moving it directly up a bit sphere.center = goal; // (move back just slightly to avoid colliding with the wall we've already found...) sphere.center -= dir.GetNormalizedSafe() * 0.05f; float newHitDist = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(sphere.type, &sphere, Vec3(0, 0, minHeightDiff), ent_static | ent_terrain | ent_rigid | ent_sleeping_rigid, &pContact, 0, geom_colltype_player, 0, 0, 0, pSkipEntities, nSkip); float raiseDist = minHeightDiff - (goal.z - worldPos.z) - wallSafeDistance; if(newHitDist != 0) { raiseDist = MIN(minHeightDiff, newHitDist); } raiseDist = MAX(0.0f, raiseDist); goal.z += raiseDist; worldPos.z += raiseDist * 0.8f; } } int thisFrameId = gEnv->pRenderer->GetFrameID(); static int frameNo(thisFrameId); if(thisFrameId - frameNo > 5) { // reset positions viewOffset = goal - worldPos; entPos = worldPos; position = goal; } if(lastSpectatorTarget != m_in.stats_spectatorTarget) { viewOffset = goal - worldPos; entPos = worldPos; position = goal; lastSpectatorTarget = m_in.stats_spectatorTarget; } frameNo = thisFrameId; if(pTarget->GetLinkedVehicle()) { Interpolate(viewOffset, goal - worldPos, 5.0f, viewParams.frameTime); entPos = worldPos; viewParams.position = worldPos + viewOffset; position = viewParams.position; } else { Vec3 camPosChange = goal - position; Vec3 entPosChange = worldPos - entPos; if(camPosChange.GetLengthSquared() > 100.0f) { position = goal; } if(entPosChange.GetLengthSquared() > 100.0f) { entPos = worldPos; } Interpolate(position, goal, 5.0f, viewParams.frameTime); Interpolate(entPos, worldPos, 5.0f, viewParams.frameTime); viewParams.position = position; } Matrix33 rotation = Matrix33::CreateRotationVDir((entPos - viewParams.position).GetNormalizedSafe()); viewParams.rotation = Quat(rotation); m_io.bUsePivot = true; m_io.stats_bobCycle = 0.0; }
bool CShotgun::Shoot(bool resetAnimation, bool autoreload/* =true */, bool noSound /* =false */) { IEntityClass *ammo = m_pShared->fireparams.ammo_type_class; int ammoCount = m_pWeapon->GetAmmoCount(ammo); if(m_pShared->fireparams.clip_size==0) ammoCount = m_pWeapon->GetInventoryAmmoCount(ammo); CActor *pActor = m_pWeapon->GetOwnerActor(); bool playerIsShooter = pActor?pActor->IsPlayer():false; if(!CanFire(true)) { if((ammoCount <= 0) && (!m_reloading)) { m_pWeapon->PlayAction(m_pShared->actions.empty_clip); //Auto reload m_pWeapon->Reload(); } return false; } else if(m_pWeapon->IsWeaponLowered()) { m_pWeapon->PlayAction(m_pShared->actions.null_fire); return false; } if(m_reloading) { if(m_pWeapon->IsBusy()) m_pWeapon->SetBusy(false); if(CanFire(true) && !m_break_reload) { m_break_reload = true; m_pWeapon->RequestCancelReload(); } return false; } // Aim assistance m_pWeapon->AssistAiming(); const char *action = m_pShared->actions.fire_cock.c_str(); if(ammoCount == 1 || (m_pShared->fireparams.no_cock && m_pWeapon->IsZoomed())) action = m_pShared->actions.fire.c_str(); m_pWeapon->PlayAction(action, 0, false, CItem::eIPAF_Default|CItem::eIPAF_RestartAnimation|CItem::eIPAF_CleanBlending); Vec3 hit = GetProbableHit(WEAPON_HIT_RANGE); Vec3 pos = GetFiringPos(hit); Vec3 fdir = ApplySpread(GetFiringDir(hit, pos), GetSpread()); Vec3 vel = GetFiringVelocity(fdir); Vec3 dir; CheckNearMisses(hit, pos, fdir, WEAPON_HIT_RANGE, m_pShared->shotgunparams.spread); bool serverSpawn = m_pWeapon->IsServerSpawn(ammo); // SHOT HERE for(int i = 0; i < m_pShared->shotgunparams.pellets; i++) { CProjectile *pAmmo = m_pWeapon->SpawnAmmo(ammo, false); if(pAmmo) { dir = ApplySpread(fdir, m_pShared->shotgunparams.spread); int hitTypeId = g_pGame->GetGameRules()->GetHitTypeId(m_pShared->fireparams.hit_type.c_str()); pAmmo->SetParams(m_pWeapon->GetOwnerId(), m_pWeapon->GetHostId(), m_pWeapon->GetEntityId(), m_pShared->shotgunparams.pelletdamage, hitTypeId, playerIsShooter?m_pShared->fireparams.damage_drop_per_meter:0.0f, m_pShared->fireparams.damage_drop_min_distance); pAmmo->SetDestination(m_pWeapon->GetDestination()); pAmmo->Launch(pos, dir, vel); if((!m_pShared->tracerparams.geometry.empty() || !m_pShared->tracerparams.effect.empty()) && (ammoCount==GetClipSize() || (ammoCount%m_pShared->tracerparams.frequency==0))) { EmitTracer(pos,hit,false); } m_projectileId = pAmmo->GetEntity()->GetId(); } } m_pWeapon->OnShoot(m_pWeapon->GetOwnerId(), 0, ammo, pos, dir, vel); if(m_pWeapon->IsServer()) { const char *ammoName = ammo != NULL ? ammo->GetName() : NULL; g_pGame->GetIGameFramework()->GetIGameplayRecorder()->Event(m_pWeapon->GetOwner(), GameplayEvent(eGE_WeaponShot, ammoName, m_pShared->shotgunparams.pellets, (void *)m_pWeapon->GetEntityId())); } MuzzleFlashEffect(true); RejectEffect(); m_fired = true; m_next_shot += m_next_shot_dt; m_zoomtimeout = m_next_shot + 0.5f; ammoCount--; if(playerIsShooter) { if(pActor->InZeroG()) { IEntityPhysicalProxy *pPhysicsProxy = (IEntityPhysicalProxy *)pActor->GetEntity()->GetProxy(ENTITY_PROXY_PHYSICS); SMovementState ms; pActor->GetMovementController()->GetMovementState(ms); CPlayer *plr = (CPlayer *)pActor; if(m_recoilparams.back_impulse > 0.0f) { Vec3 impulseDir = ms.aimDirection * -1.0f; Vec3 impulsePos = ms.pos; float impulse = m_recoilparams.back_impulse; pPhysicsProxy->AddImpulse(-1, impulsePos, impulseDir * impulse * 100.0f, true, 1.0f); } if(m_recoilparams.angular_impulse > 0.0f) { float impulse = m_recoilparams.angular_impulse; pActor->AddAngularImpulse(Ang3(0,impulse,0), 1.0f); } } if(pActor->IsClient()) if(gEnv->pInput) gEnv->pInput->ForceFeedbackEvent(SFFOutputEvent(eDI_XI, eFF_Rumble_Basic, 0.15f, 0.0f, fabsf(m_recoilparams.back_impulse)*3.0f)); } if(m_pShared->fireparams.clip_size != -1) { if(m_pShared->fireparams.clip_size!=0) m_pWeapon->SetAmmoCount(ammo, ammoCount); else m_pWeapon->SetInventoryAmmoCount(ammo, ammoCount); } if((ammoCount<1) && !m_pShared->fireparams.slider_layer.empty()) { const char *slider_back_layer = m_pShared->fireparams.slider_layer.c_str(); m_pWeapon->PlayLayer(slider_back_layer, CItem::eIPAF_Default|CItem::eIPAF_NoBlend); } if(OutOfAmmo()) { m_pWeapon->OnOutOfAmmo(ammo); if(autoreload) { m_pWeapon->GetScheduler()->TimerAction(m_pWeapon->GetCurrentAnimationTime(eIGS_FirstPerson), CSchedulerAction<ScheduleReload>::Create(m_pWeapon), false); } } m_pWeapon->RequestShoot(ammo, pos, dir, vel, hit, 1.0f, 0, false); return true; }
//------------------------------------------------------------------------ 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)); } } }
//------------------------------------------------------------------------ int CScriptBind_Actor::GetCloseColliderParts(IFunctionHandler *pH, int characterSlot, Vec3 hitPos, float radius) { // find nearest physic. parts to explosion center // for now we just return the closest part (using the AABB) CActor *pActor = GetActor(pH); if (!pActor) return pH->EndFunction(); IEntity* pEntity = pActor->GetEntity(); ICharacterInstance* pChar = pEntity->GetCharacter(characterSlot); if (pChar && pChar->GetISkeletonPose()->GetCharacterPhysics()) { IPhysicalEntity* pPhysics = pChar->GetISkeletonPose()->GetCharacterPhysics(); pe_status_nparts nparts; int numParts = pPhysics->GetStatus(&nparts); float minLenSq = radius*radius + 0.1f; int minLenPart = -1; pe_status_pos status; for (int i=0; i<numParts; ++i) { status.ipart = i; if (pPhysics->GetStatus(&status)) { AABB box(status.pos+status.BBox[0], status.pos+status.BBox[1]); // if hitpos inside AABB, return if (box.IsContainPoint(hitPos)) { minLenPart = i; break; } // else find closest distance float lenSq = Distance::Point_AABBSq(hitPos, box); if (lenSq < minLenSq) { minLenSq = lenSq; minLenPart = i; } } } // get material from selected part static ISurfaceTypeManager* pSurfaceMan = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeManager(); if (minLenPart != -1) { pe_params_part params; params.ipart = minLenPart; if (pPhysics->GetParams(¶ms)) { phys_geometry* pGeom = params.pPhysGeomProxy ? params.pPhysGeomProxy : params.pPhysGeom; if (pGeom->surface_idx > 0 && pGeom->surface_idx < params.nMats) { if (ISurfaceType *pSurfaceType=pSurfaceMan->GetSurfaceType(pGeom->pMatMapping[pGeom->surface_idx])) return pH->EndFunction(params.partid, pSurfaceType->GetName(), pSurfaceType->GetType()); } } return pH->EndFunction(params.partid); } } return pH->EndFunction(); }
//------------------------------------------------------------------------ void CItem::UpdateMounted(float frameTime) { IRenderAuxGeom* pAuxGeom = gEnv->pRenderer->GetIRenderAuxGeom(); if (!m_ownerId || !m_stats.mounted) return; CActor *pActor = GetOwnerActor(); if (!pActor) return; CheckViewChange(); if (true) { if (IsClient()) { ICharacterInstance *pCharacter = GetEntity()->GetCharacter(eIGS_FirstPerson); if (pCharacter && !m_idleAnimation[eIGS_FirstPerson].empty() && pCharacter->GetISkeletonAnim()->GetNumAnimsInFIFO(0)<1) PlayAction(m_idleAnimation[eIGS_FirstPerson], 0, true); } // need to explicitly update characters at this point // cause the entity system update occered earlier, with the last position for (int i=0; i<eIGS_Last; i++) { if (GetEntity()->GetSlotFlags(i)&ENTITY_SLOT_RENDER) { ICharacterInstance *pCharacter = GetEntity()->GetCharacter(i); if (pCharacter) { Matrix34 mloc = GetEntity()->GetSlotLocalTM(i,false); Matrix34 m34 = GetEntity()->GetWorldTM()*mloc; QuatT renderLocation = QuatT(m34); pCharacter->GetISkeletonPose()->SetForceSkeletonUpdate(9); pCharacter->SkeletonPreProcess(renderLocation, renderLocation, GetISystem()->GetViewCamera(),0x55 ); pCharacter->SetPostProcessParameter(renderLocation, renderLocation, 0, 0.0f, 0x55 ); } } } // f32 fColor[4] = {1,1,0,1}; // f32 g_YLine=60.0f; // gEnv->pRenderer->Draw2dLabel( 1,g_YLine, 1.3f, fColor, false, "Mounted Gun Code" ); //adjust the orientation of the gun based on the aim-direction SMovementState info; IMovementController* pMC = pActor->GetMovementController(); pMC->GetMovementState(info); Vec3 dir = info.aimDirection.GetNormalized(); Matrix34 tm = Matrix33::CreateRotationVDir(dir); Vec3 vGunXAxis=tm.GetColumn0(); if (pActor->GetLinkedVehicle()==0) { if (pMC) { if(!pActor->IsPlayer()) { // prevent snapping direction Vec3 currentDir = GetEntity()->GetWorldRotation().GetColumn1(); float dot = currentDir.Dot(dir); dot = CLAMP(dot,-1,1); float reqAngle = cry_acosf(dot); const float maxRotSpeed = 2.0f; float maxAngle = frameTime * maxRotSpeed; if(fabs(reqAngle) > maxAngle) { Vec3 axis = currentDir.Cross(dir); if(axis.GetLengthSquared()>0.001f) // current dir and new dir are enough different dir = currentDir.GetRotated(axis.GetNormalized(),sgn(reqAngle)*maxAngle); } } //adjust the orientation of the gun based on the aim-direction tm = Matrix33::CreateRotationVDir(dir); Vec3 vWPos=GetEntity()->GetWorldPos(); tm.SetTranslation(vWPos); GetEntity()->SetWorldTM(tm); //set the new orientation of the mounted gun vGunXAxis=tm.GetColumn0(); Vec3 vInitialAimDirection = m_stats.mount_dir; Matrix33 vInitialPlayerOrientation = Matrix33::CreateRotationVDir(vInitialAimDirection); assert( vInitialAimDirection.IsUnit() ); Vec3 newp; if (pActor->IsThirdPerson()) { //third person f32 dist = m_mountparams.body_distance*1.3f; Vec3 oldp = pActor->GetEntity()->GetWorldPos(); newp = GetEntity()->GetWorldPos()-vInitialAimDirection*dist; //mounted gun newp.z = oldp.z; } else { //first person f32 fMoveBack = (1.0f+(dir.z*dir.z*dir.z*dir.z*4.0f))*0.75f; f32 dist = m_mountparams.eye_distance*fMoveBack; Vec3 oldp = pActor->GetEntity()->GetWorldPos(); newp = GetEntity()->GetWorldPos()-dir*dist; //mounted gun //newp.z -= 0.75f; newp.z = oldp.z; } Matrix34 actortm(pActor->GetEntity()->GetWorldTM()); //if (pActor->IsThirdPerson()) actortm=vInitialPlayerOrientation; actortm.SetTranslation(newp); pActor->GetEntity()->SetWorldTM(actortm, ENTITY_XFORM_USER); pActor->GetAnimationGraphState()->SetInput("Action","gunnerMounted"); //f32 g_YLine=80.0f; //gEnv->pRenderer->Draw2dLabel( 1,g_YLine, 1.3f, fColor, false, "Mounted Gun Active for FP and AI" ); if (ICharacterInstance *pCharacter = pActor->GetEntity()->GetCharacter(0)) { ISkeletonAnim *pSkeletonAnim = pCharacter->GetISkeletonAnim(); assert(pSkeletonAnim); uint32 numAnimsLayer = pSkeletonAnim->GetNumAnimsInFIFO(0); for(uint32 i=0; i<numAnimsLayer; i++) { CAnimation &animation = pSkeletonAnim->GetAnimFromFIFO(0, i); if (animation.m_AnimParams.m_nFlags & CA_MANUAL_UPDATE) { f32 aimrad = Ang3::CreateRadZ(Vec2(vInitialAimDirection),Vec2(dir)); animation.m_fAnimTime = clamp_tpl(aimrad/gf_PI,-1.0f,+1.0f)*0.5f+0.5f; //if (pActor->IsThirdPerson()==0) //animation.m_fAnimTime=0.6f; //Ivo & Benito: high advanced future code. don't ask what it is //Benito - Not needed any more ;) //f32 g_YLine=100.0f; //gEnv->pRenderer->Draw2dLabel( 1,g_YLine, 1.3f, fColor, false, "AnimTime: %f MyAimAngle: %f deg:% distance:%f", animation.m_fAnimTime, aimrad, RAD2DEG(aimrad),m_mountparams.body_distance ); } } } m_stats.mount_last_aimdir = dir; } } if (ICharacterInstance* pCharInstance = pActor->GetEntity()->GetCharacter(0)) { if (ISkeletonAnim* pSkeletonAnim = pCharInstance->GetISkeletonAnim()) { OldBlendSpace ap; if (GetAimBlending(ap)) { pSkeletonAnim->SetBlendSpaceOverride(eMotionParamID_TurnSpeed, 0.5f + 0.5f * ap.m_turn, true); } } } UpdateIKMounted(pActor, vGunXAxis*0.1f); RequireUpdate(eIUS_General); } }
void CHUD::UpdateMissionObjectiveIcon(EntityId objective, int friendly, FlashOnScreenIcon iconType, bool forceNoOffset, Vec3 rotationTarget) { IEntity *pObjectiveEntity = GetISystem()->GetIEntitySystem()->GetEntity(objective); if(!pObjectiveEntity) return; AABB box; pObjectiveEntity->GetWorldBounds(box); Vec3 vWorldPos = Vec3(0,0,0); SEntitySlotInfo info; int slotCount = pObjectiveEntity->GetSlotCount(); for(int i=0; i<slotCount; ++i) { if (pObjectiveEntity->GetSlotInfo(i, info)) { if (info.pCharacter) { int16 id = info.pCharacter->GetISkeletonPose()->GetJointIDByName("objectiveicon"); if (id >= 0) { //vPos = pCharacter->GetISkeleton()->GetHelperPos(helper); vWorldPos = info.pCharacter->GetISkeletonPose()->GetAbsJointByID(id).t; if (!vWorldPos.IsZero()) { vWorldPos = pObjectiveEntity->GetSlotWorldTM(i).TransformPoint(vWorldPos); break; } } } } } if(vWorldPos == Vec3(0,0,0)) vWorldPos = pObjectiveEntity->GetWorldPos(); if(!forceNoOffset) vWorldPos.z += 2.0f; Vec3 vEntityScreenSpace; m_pRenderer->ProjectToScreen( vWorldPos.x, vWorldPos.y, vWorldPos.z, &vEntityScreenSpace.x, &vEntityScreenSpace.y, &vEntityScreenSpace.z); Vec3 vEntityTargetSpace; bool useTarget = false; if(!rotationTarget.IsZero()) { m_pRenderer->ProjectToScreen( rotationTarget.x, rotationTarget.y, rotationTarget.z, &vEntityTargetSpace.x, &vEntityTargetSpace.y, &vEntityTargetSpace.z); useTarget = true; } CActor *pActor = (CActor*)(gEnv->pGame->GetIGameFramework()->GetClientActor()); bool bBack = false; if (IMovementController *pMV = pActor->GetMovementController()) { SMovementState state; pMV->GetMovementState(state); Vec3 vLook = state.eyeDirection; Vec3 vDir = vWorldPos - pActor->GetEntity()->GetWorldPos(); float fDot = vLook.Dot(vDir); if(fDot<0.0f) bBack = true; } bool bLeft(false), bRight(false), bTop(false), bBottom(false); if(vEntityScreenSpace.z > 1.0f && bBack) { Vec2 vCenter(50.0f, 50.0f); Vec2 vTarget(-vEntityScreenSpace.x, -vEntityScreenSpace.y); Vec2 vScreenDir = vTarget - vCenter; vScreenDir = vCenter + (100.0f * vScreenDir.NormalizeSafe()); vEntityScreenSpace.y = vScreenDir.y; vEntityScreenSpace.x = vScreenDir.x; useTarget = false; } if(vEntityScreenSpace.x < 2.0f) { bLeft = true; vEntityScreenSpace.x = 2.0f; useTarget = false; } if(vEntityScreenSpace.x > 98.0f) { bRight = true; vEntityScreenSpace.x = 98.0f; useTarget = false; } if(vEntityScreenSpace.y < 2.01f) { bTop = true; vEntityScreenSpace.y = 2.0f; useTarget = false; } if(vEntityScreenSpace.y > 97.99f) { bBottom = true; vEntityScreenSpace.y = 98.0f; useTarget = false; } float fScaleX = 0.0f; float fScaleY = 0.0f; float fHalfUselessSize = 0.0f; GetProjectionScale(&m_animMissionObjective,&fScaleX,&fScaleY,&fHalfUselessSize); if(bLeft && bTop) { iconType = eOS_TopLeft; } else if(bLeft && bBottom) { iconType = eOS_BottomLeft; } else if(bRight && bTop) { iconType = eOS_TopRight; } else if(bRight && bBottom) { iconType = eOS_BottomRight; } else if(bLeft) { iconType = eOS_Left; } else if(bRight) { iconType = eOS_Right; } else if(bTop) { iconType = eOS_Top; } else if(bBottom) { iconType = eOS_Bottom; } float rotation = 0.0f; if(useTarget) { float diffX = (vEntityScreenSpace.x*fScaleX+fHalfUselessSize+16.0f) - (vEntityTargetSpace.x*fScaleX+fHalfUselessSize+16.0f); float diffY = (vEntityScreenSpace.y*fScaleY) - (vEntityTargetSpace.y*fScaleY); Vec2 dir(diffX, diffY); dir.NormalizeSafe(); float fAngle; if(dir.y < 0) { fAngle = RAD2DEG(acos_tpl(dir.x)); } else { fAngle = RAD2DEG(gf_PI2-acos_tpl(dir.x)); } rotation = fAngle - 90.0f; } int iMinDist = g_pGameCVars->hud_onScreenNearDistance; int iMaxDist = g_pGameCVars->hud_onScreenFarDistance; float fMinSize = g_pGameCVars->hud_onScreenNearSize; float fMaxSize = g_pGameCVars->hud_onScreenFarSize; CActor *pPlayerActor = static_cast<CActor *>(gEnv->pGame->GetIGameFramework()->GetClientActor()); float fDist = (vWorldPos-pPlayerActor->GetEntity()->GetWorldPos()).len(); float fSize = 1.0; if(fDist<=iMinDist) { fSize = fMinSize; } else if(fDist>=iMaxDist) { fSize = fMaxSize; } else if(iMaxDist>iMinDist) { float fA = ((float)iMaxDist - fDist); float fB = (float)(iMaxDist - iMinDist); float fC = (fMinSize - fMaxSize); fSize = ((fA / fB) * fC) + fMaxSize; } float centerX = 50.0; float centerY = 50.0; m_missionObjectiveNumEntries += FillUpMOArray(&m_missionObjectiveValues, objective, vEntityScreenSpace.x*fScaleX+fHalfUselessSize+16.0f, vEntityScreenSpace.y*fScaleY, iconType, friendly, (int)fDist, fSize*fSize, -rotation); bool nearCenter = (pow(centerX-vEntityScreenSpace.x+1.5f,2.0f)+pow(centerY-vEntityScreenSpace.y+2.5f,2.0f))<16.0f; if(nearCenter && (gEnv->bMultiplayer || m_pHUDScopes->IsBinocularsShown())) { m_objectiveNearCenter = objective; } }
float CGameStateRecorder::RenderInfo(float y, bool bRecording) { float retY = 0; IRenderer *pRenderer = gEnv->pRenderer; if (bRecording) { float fColor[4] = {1,0,0,1}; pRenderer->Draw2dLabel( 1,y+retY, 1.3f, fColor,false," Recording game state"); retY +=15; } else { const float xp = 300; const float xr = 400; const float xri = 600; float fColor[4] = {0,1,0,1}; float fColorWarning[4] = {1,1,0,1}; const char* actorName = m_demo_actorInfo->GetString(); CActor *pActor = GetActorOfName(actorName); if(pActor) { pRenderer->Draw2dLabel( 1,y+retY, 1.3f, fColor,false," Game state - Actor: %s --------------------------------------------------",pActor->GetEntity()? pActor->GetEntity()->GetName(): "(no entity)"); retY +=15; if(m_itSingleActorGameState != m_GameStates.end() && pActor->GetEntity() && m_itSingleActorGameState->first == pActor->GetEntity()->GetId()) { ICVar *pVar = gEnv->pConsole->GetCVar( "demo_force_game_state" ); if(pVar) { int demo_forceGameState = pVar->GetIVal(); if(demo_forceGameState) { pRenderer->Draw2dLabel( 1,y+retY, 1.3f, fColor,false,demo_forceGameState==1 ? " Override mode = (health, suit energy)" : " Override mode = (all)"); retY +=15; } } pRenderer->Draw2dLabel( xp,y+retY, 1.3f, fColor,false,"Current"); pRenderer->Draw2dLabel( xr,y+retY, 1.3f, fColor,false,"Recorded"); retY +=15; SActorGameState& gstate = m_itSingleActorGameState->second; float recordedHealth = (float)gstate.health; float health = (float)pActor->GetHealth(); bool bError = CHECK_MISMATCH(health, recordedHealth,10); pRenderer->Draw2dLabel( 1,y+retY, 1.3f, fColor,false," Health:"); pRenderer->Draw2dLabel( xp,y+retY, 1.3f, bError? fColorWarning : fColor, false,"%d",(int)health); pRenderer->Draw2dLabel( xr,y+retY, 1.3f, bError? fColorWarning : fColor, false,"%d",(int)recordedHealth); retY +=15; // items pRenderer->Draw2dLabel( 1,y+retY, 1.3f, fColor,false," Inventory ---------------------------------------------------------------------------------------"); retY +=15; pRenderer->Draw2dLabel( xp,y+retY, 1.3f, fColor,false,"Current"); pRenderer->Draw2dLabel( xri,y+retY, 1.3f, fColor,false,"Recorded"); retY +=15; CInventory *pInventory = (CInventory*)(pActor->GetInventory()); if(pInventory) { int nInvItems = pInventory->GetCount(); TItemContainer& Items = gstate.Items; int nRecItems = Items.size(); int maxItems = max(nRecItems,nInvItems); int i=0; EntityId curSelectedId = pActor->GetCurrentItemId(); TItemName curSelClass = GetItemName(curSelectedId); bool bSelectedError = !equal_strings(gstate.itemSelected,curSelClass); for(; i< nInvItems; i++) { IItem *pItem = g_pGame->GetIGameFramework()->GetIItemSystem()->GetItem(pInventory->GetItem(i)); if(pItem) { TItemName szItemName = GetItemName(pItem->GetEntityId()); TItemContainer::iterator it = Items.find(szItemName); bError = it==Items.end(); pRenderer->Draw2dLabel( 1,y+retY, 1.3f, fColor,false," %2d)",i+1); EntityId curId = pItem->GetEntityId(); TItemName curClass = GetItemName(curId); if(equal_strings(curClass,curSelClass) ) pRenderer->Draw2dLabel( xp-16,y+retY, 1.3f,bSelectedError ? fColorWarning:fColor, false, "[]"); if(equal_strings(szItemName, gstate.itemSelected)) pRenderer->Draw2dLabel( xri-16,y+retY, 1.3f,bSelectedError ? fColorWarning:fColor, false, "[]"); char itemName[32]; const char* originalItemName = pItem->GetEntity() ? pItem->GetEntity()->GetName():"(null)"; int length = strlen(originalItemName); length = min(length,31); strncpy(itemName,originalItemName,length); itemName[length]=0; pRenderer->Draw2dLabel( 1,y+retY, 1.3f, bError? fColorWarning : fColor, false," %s",itemName); if(bError) pRenderer->Draw2dLabel( xp,y+retY, 1.3f, fColorWarning, false, "Missing"); else { SItemProperties& recItem = it->second; CWeapon *pWeapon = (CWeapon*)(pItem->GetIWeapon()); IEntityClass* pItemClass = pItem->GetEntity()->GetClass(); if(pItemClass && !strcmpi(pItemClass->GetName(),"binoculars")) pWeapon = NULL; // no fire mode or ammo recorded for binocular (which is a weapon) if(pWeapon) { int idx = 0; // ammo float xa = 0; for(SWeaponAmmo weaponAmmo = pWeapon->GetFirstAmmo(); weaponAmmo.pAmmoClass ; weaponAmmo = pWeapon->GetNextAmmo()) { int ammoCount = weaponAmmo.count; const char* ammoClass; if(weaponAmmo.pAmmoClass && (ammoClass = weaponAmmo.pAmmoClass->GetName())) { TAmmoContainer::iterator it = recItem.Ammo.find(ammoClass); if(it!=recItem.Ammo.end()) { int recAmmoCount = recItem.Ammo[ammoClass]; bool bError2 = ammoCount!=recAmmoCount; pRenderer->Draw2dLabel( xp+xa,y+retY, 1.3f, bError2? fColorWarning : fColor, false,"Am%d:%d",idx,ammoCount); pRenderer->Draw2dLabel( xri+xa,y+retY, 1.3f, bError2? fColorWarning : fColor, false,"Am%d:%d",idx,recAmmoCount); xa += 50; ++idx; if(idx%5 ==0) { xa=0; retY+=15; } } } } // current fire mode int curFireModeIdx = pWeapon->GetCurrentFireMode(); int recFireModeIdx = recItem.fireMode; bool bError3 = curFireModeIdx!= recFireModeIdx; pRenderer->Draw2dLabel( xp+xa,y+retY, 1.3f, bError3? fColorWarning : fColor, false,"FMode:%d",curFireModeIdx); pRenderer->Draw2dLabel( xri+xa,y+retY, 1.3f, bError3? fColorWarning : fColor, false,"FMode:%d",recFireModeIdx); } else { pRenderer->Draw2dLabel( xp,y+retY, 1.3f, fColor, false, "Ok"); } } } retY +=15; } /// Accessories int nInvAccessories = pInventory->GetAccessoryCount(); TAccessoryContainer& Accessories = gstate.Accessories; int nRecAccessories = Accessories.size(); if(nRecAccessories) { pRenderer->Draw2dLabel( 1,y+retY, 1.3f, bError? fColorWarning : fColor, false," Accessories"); retY +=15; } for(int j=0 ; j< nInvAccessories; j++,i++) { const char* accessory = pInventory->GetAccessory(j); if(accessory && strlen(accessory)) { IEntityClass* pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(accessory); if(pClass) { TItemName szItemName = pClass->GetName(); TAccessoryContainer::iterator it = Accessories.find(szItemName); bError = it==Accessories.end(); pRenderer->Draw2dLabel( 1,y+retY, 1.3f, fColor,false," %2d)",i+1); char itemName[32]; int length = strlen(accessory); length = min(length,31); strncpy(itemName,accessory,length); itemName[length]=0; pRenderer->Draw2dLabel( 1,y+retY, 1.3f, bError? fColorWarning : fColor, false," %s",itemName); if(bError) pRenderer->Draw2dLabel( xp,y+retY, 1.3f, fColorWarning, false, "Missing"); else pRenderer->Draw2dLabel( xp,y+retY, 1.3f, fColor, false, "Ok"); retY +=15; } } } /// Ammo Mags TAmmoContainer& Ammo = gstate.AmmoMags; int nRecAmmo = Ammo.size(); int nInvAmmo = pInventory->GetAmmoPackCount(); if(nInvAmmo) { pRenderer->Draw2dLabel( 1,y+retY, 1.3f, bError? fColorWarning : fColor, false," Ammo Packs"); retY +=15; } pInventory->AmmoIteratorFirst(); for(int j=0 ; !pInventory->AmmoIteratorEnd(); j++, pInventory->AmmoIteratorNext()) { TAmmoContainer& Mags = gstate.AmmoMags; const IEntityClass* pAmmoClass = pInventory->AmmoIteratorGetClass(); if(pAmmoClass) { int invAmmoCount = pInventory->AmmoIteratorGetCount(); const char* ammoClassName = pAmmoClass->GetName(); bool bNotFound = Mags.find(ammoClassName) == Mags.end(); int recAmmoCount = bNotFound ? 0 :Mags[ammoClassName]; bool bError = bNotFound || invAmmoCount!= recAmmoCount; pRenderer->Draw2dLabel( 1,y+retY, 1.3f, bError? fColorWarning : fColor, false," %s:",ammoClassName); pRenderer->Draw2dLabel( xp,y+retY, 1.3f, bError? fColorWarning : fColor, false,"%d",invAmmoCount); if(bNotFound) pRenderer->Draw2dLabel( xr,y+retY, 1.3f, fColorWarning, false,"NotRecd"); else pRenderer->Draw2dLabel( xr,y+retY, 1.3f, bError? fColorWarning : fColor, false,"%d",recAmmoCount); retY +=15; } } } } else // m_itSingleActorGameState != m_GameStates.end() { pRenderer->Draw2dLabel( 1,y+retY, 1.3f, fColor,false, "<<Not Recorded>>"); retY +=15; } } else // pActor { pRenderer->Draw2dLabel( 1,y+retY, 1.3f, fColor,false, "<<Actor %s not in the map>>",actorName ? actorName:"(no name)"); retY +=15; } } return retY; }
void CAnimatedGrabHandler::UpdatePosVelRot(float frameTime) { IEntity *pGrab = gEnv->pEntitySystem->GetEntity(m_grabStats.grabId); if ( !pGrab) return; IEntity *pEnt = m_pActor->GetEntity(); if (m_grabStats.grabDelay<0.001f) { Vec3 grabWPos (GetGrabBoneWorldTM ().t); // NOTE Aug 3, 2007: <pvl> the second part of this test means don't enable // the correction if animation/ik wasn't used for grabbing in the first place if (m_grabStats.readIkInaccuracyCorrection && m_grabStats.grabAnimGraphSignal[0]) { // NOTE Aug 2, 2007: <pvl> executed the first time this function is called // for a particular grabbing action m_grabStats.ikInaccuracyCorrection = grabWPos - (pGrab->GetWorldTM().GetTranslation() + m_grabStats.entityGrabSpot); m_grabStats.readIkInaccuracyCorrection = false; // FIXME Sep 13, 2007: <pvl> only putting it here because it's called just // once, at the instant when the object is grabbed - rename readIkInaccuracyCorrection // to make this clearer, or put this somewhere else DisableGrabbedAnimatedCharacter (true); } else { // NOTE Aug 2, 2007: <pvl> phase it out gradually m_grabStats.ikInaccuracyCorrection *= 0.9f; if (m_grabStats.ikInaccuracyCorrection.len2 () < 0.01f) m_grabStats.ikInaccuracyCorrection = Vec3 (0.0f, 0.0f, 0.0f); } // NOTE Sep 13, 2007: <pvl> this should prevent us from calling SetWPos() // later so that the IK "release" phase can take over m_grabStats.IKActive = false; Matrix34 tm(pGrab->GetWorldTM()); tm.SetTranslation(grabWPos - (m_grabStats.ikInaccuracyCorrection + pGrab->GetRotation() * m_grabStats.entityGrabSpot)); pGrab->SetWorldTM(tm,ENTITY_XFORM_USER); } //update IK for (int i=0;i<m_grabStats.limbNum;++i) { SIKLimb *pLimb = m_pActor->GetIKLimb(m_grabStats.limbId[i]); // NOTE Dez 14, 2006: <pvl> this class is always supposed to have // m_grabStats.usingAnimation == true if (m_grabStats.usingAnimation && m_grabStats.releaseIKTime>0.001f && m_grabStats.IKActive) { // NOTE Dez 15, 2006: <pvl> use IK to constantly offset the // animation so that the difference between where the animation // expects the object to be and where the object really is is taken // into account. Vec3 animPos = pEnt->GetSlotWorldTM(0) * pLimb->lAnimPos; Vec3 assumedGrabPos = pEnt->GetSlotWorldTM(0) * m_grabStats.grabbedObjOfs; Vec3 actualGrabPos = pGrab->GetWorldPos() + m_grabStats.entityGrabSpot; Vec3 adjustment = actualGrabPos - assumedGrabPos; pLimb->SetWPos(pEnt,animPos + adjustment,ZERO,0.5f,2.0f,1000); //gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(pGrab->GetWorldPos() + m_grabStats.entityGrabSpot, 0.5f, ColorB(0,255,0,100)); } //if there are multiple limbs, only the first one sets the rotation of the object. if (m_grabStats.useIKRotation && i == 0 && m_grabStats.grabDelay<0.001f) { // NOTE Aug 8, 2007: <pvl> the idea here is to store current world // rotations of both the object being grabbed and the end bone of // a grabbing limb. Then track how the end bone rotates with respect // to the stored original rotation and rotate the grabbed object // the same way. That way, the grabbed object rotates the same as // the limb and appears to be "stabbed" by it. QuatT endBoneWorldRot = GetGrabBoneWorldTM (); endBoneWorldRot.q.Normalize(); // may not be necessary - just to be safe if ( ! m_grabStats.origRotationsValid) { m_grabStats.origRotation = pGrab->GetRotation(); m_grabStats.origRotation.Normalize(); // may not be necessary - just to be safe m_grabStats.origEndBoneWorldRot = endBoneWorldRot; m_grabStats.origRotationsValid = true; } Quat grabQuat( (endBoneWorldRot*m_grabStats.origEndBoneWorldRot.GetInverted()).q * m_grabStats.origRotation); grabQuat.Normalize(); // NOTE Dez 14, 2006: <pvl> this code sets up and look vectors for the grabbed // entity in case it's an Actor (the player, mostly) so that the player always // looks roughly at the grabber. The grabber is supposed to be the Hunter here // so this code is somewhat Hunter-specific. // UPDATE Aug 7, 2007: <pvl> do the above for the player only // UPDATE Sep 13, 2007: <pvl> don't do it for anybody ATM, it doesn't seem useful CActor *pGrabbedActor = (CActor *)g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(m_grabStats.grabId); if (false && pGrabbedActor && pGrabbedActor->IsClient() && pGrabbedActor->GetActorStats()) { Vec3 upVec(Quat(endBoneWorldRot.q * m_grabStats.additionalRotation).GetColumn2()); upVec.z = fabs_tpl(upVec.z) * 2.0f; upVec.NormalizeSafe(Vec3(0,0,1)); SActorStats *pAS = pGrabbedActor->GetActorStats(); if (pAS) { pAS->forceUpVector = upVec; pAS->forceLookVector = (pEnt->GetSlotWorldTM(0) * m_pActor->GetLocalEyePos(0)) - pGrabbedActor->GetEntity()->GetWorldPos(); float lookLen(pAS->forceLookVector.len()); pAS->forceLookVector *= (1.0f/lookLen)*0.33f; //pAS->forceLookVector = -Quat(boneRot * m_grabStats.additionalRotation).GetColumn1();//boneRot.GetColumn2(); } } else { pGrab->SetRotation(grabQuat,ENTITY_XFORM_USER); } } } if (m_grabStats.grabDelay<0.001f) { // NOTE Sep 16, 2007: <pvl> now that grabbed entity rotation coming from // a grabbing bone (if any) is computed, bone-space offset can be applied Matrix34 tm(pGrab->GetWorldTM()); tm.AddTranslation(GetGrabBoneWorldTM().q * m_grabStats.boneGrabOffset); pGrab->SetWorldTM(tm,ENTITY_XFORM_USER); /* { // debug draw for the grab bone QuatT grabBoneWorldTM = GetGrabBoneWorldTM(); Vec3 start = grabBoneWorldTM.t; Vec3 end = start + grabBoneWorldTM.q * Vec3 (1,0,0) * 3; gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine (start, ColorB (255,0,0), end, ColorB (0,0,255), 6.0f); gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere (start, 0.5f, ColorB (255,128,0)); } */ /* { // draw complete coord systems for both the end bone and the grabbed thing QuatT grabBoneWorldTM = GetGrabBoneWorldTM(); Vec3 start = grabBoneWorldTM.t; Vec3 end = start + grabBoneWorldTM.q * Vec3 (1,0,0) * 3; gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine (start, ColorB (128,0,0), end, ColorB (128,0,0), 6.0f); end = start + grabBoneWorldTM.q * Vec3 (0,1,0) * 3; gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine (start, ColorB (0,128,0), end, ColorB (0,128,0), 6.0f); end = start + grabBoneWorldTM.q * Vec3 (0,0,1) * 3; gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine (start, ColorB (0,0,128), end, ColorB (0,0,128), 6.0f); gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere (start, 0.2f, ColorB (255,255,255)); start = pGrab->GetWorldTM().GetTranslation(); end = start + pGrab->GetRotation() * Vec3 (1,0,0) * 3; gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine (start, ColorB (128,0,0), end, ColorB (128,0,0), 6.0f); end = start + pGrab->GetRotation() * Vec3 (0,1,0) * 3; gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine (start, ColorB (0,128,0), end, ColorB (0,128,0), 6.0f); end = start + pGrab->GetRotation() * Vec3 (0,0,1) * 3; gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine (start, ColorB (0,0,128), end, ColorB (0,0,128), 6.0f); gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere (start, 0.2f, ColorB (64,64,64)); } */ } /* { // debug draw for the grabbed object Vec3 start = pGrab->GetWorldTM().GetTranslation(); Vec3 end = start + pGrab->GetRotation() * Vec3 (0,0,1) * 3; gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine (start, ColorB (255,0,0), end, ColorB (0,0,255), 6.0f); gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere (start, 0.2f, ColorB (255,128,0)); } */ }
//------------------------------------------------------------------------ void CGameRules::ProcessServerHit(const HitInfo &hitInfo) { bool ok=true; // check if shooter is alive CActor *pShooter = GetActorByEntityId(hitInfo.shooterId); CActor *pTarget = GetActorByEntityId(hitInfo.targetId); if (hitInfo.shooterId) { if (pShooter && pShooter->GetHealth()<=0) ok=false; } if (hitInfo.targetId) { if (pTarget && pTarget->GetSpectatorMode()) ok=false; } if (ok) { float fTargetHealthBeforeHit = 0.0f; if(pTarget) { fTargetHealthBeforeHit = pTarget->GetHealth(); } CreateScriptHitInfo(m_scriptHitInfo, hitInfo); CallScript(m_serverStateScript, "OnHit", m_scriptHitInfo); if(pTarget && !pTarget->IsDead()) { const float fCausedDamage = fTargetHealthBeforeHit - pTarget->GetHealth(); ProcessLocalHit(hitInfo, fCausedDamage); } // call hit listeners if any if (m_hitListeners.empty() == false) { for (size_t i = 0; i < m_hitListeners.size(); ) { size_t count = m_hitListeners.size(); m_hitListeners[i]->OnHit(hitInfo); if (count == m_hitListeners.size()) i++; else continue; } } if (pShooter && hitInfo.shooterId!=hitInfo.targetId && hitInfo.weaponId!=hitInfo.shooterId && hitInfo.weaponId!=hitInfo.targetId && hitInfo.damage>=0) { EntityId params[2]; params[0] = hitInfo.weaponId; params[1] = hitInfo.targetId; m_pGameplayRecorder->Event(pShooter->GetEntity(), GameplayEvent(eGE_WeaponHit, 0, 0, (void *)params)); } if (pShooter) m_pGameplayRecorder->Event(pShooter->GetEntity(), GameplayEvent(eGE_Hit, 0, 0, (void *)hitInfo.weaponId)); if (pShooter) m_pGameplayRecorder->Event(pShooter->GetEntity(), GameplayEvent(eGE_Damage, 0, hitInfo.damage, (void *)hitInfo.weaponId)); } }
//------------------------------------------------------------------------ void CMelee::Hit(const Vec3 &pt, const Vec3 &dir, const Vec3 &normal, IPhysicalEntity *pCollider, int partId, int ipart, int surfaceIdx, float damageScale, bool remote) { // generate the damage IEntity *pTarget = gEnv->pEntitySystem->GetEntityFromPhysics(pCollider); // Report punch to AI system. // The AI notification must come before the game rules are // called so that the death handler in AIsystem understands that the hit // came from the player. CActor *pActor = m_pWeapon->GetOwnerActor(); if (pActor && pActor->GetActorClass() == CPlayer::GetActorClassType()) { CPlayer *pPlayer = (CPlayer *)pActor; if (pPlayer && pPlayer->GetNanoSuit()) { if (pPlayer->GetEntity() && pPlayer->GetEntity()->GetAI()) { SAIEVENT AIevent; AIevent.targetId = pTarget ? pTarget->GetId() : 0; // pPlayer->GetNanoSuit()->GetMode() == NANOMODE_STRENGTH pPlayer->GetEntity()->GetAI()->Event(AIEVENT_PLAYER_STUNT_PUNCH, &AIevent); } } } bool ok = true; if(pTarget) { if(!gEnv->bMultiplayer && pActor && pActor->IsPlayer()) { IActor* pAITarget = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pTarget->GetId()); if(pAITarget && pTarget->GetAI() && !pTarget->GetAI()->IsHostile(pActor->GetEntity()->GetAI(),false)) { ok = false; m_noImpulse = true; } } if(ok) { CGameRules *pGameRules = g_pGame->GetGameRules(); HitInfo info(m_pWeapon->GetOwnerId(), pTarget->GetId(), m_pWeapon->GetEntityId(), m_meleeparams.damage*damageScale*m_meleeScale, 0.0f, pGameRules->GetHitMaterialIdFromSurfaceId(surfaceIdx), partId, pGameRules->GetHitTypeId(m_meleeparams.hit_type.c_str()), pt, dir, normal); info.remote = remote; if (m_pWeapon->GetForcedHitMaterial() != -1) info.material=pGameRules->GetHitMaterialIdFromSurfaceId(m_pWeapon->GetForcedHitMaterial()); pGameRules->ClientHit(info); } } // play effects if(ok) { IMaterialEffects* pMaterialEffects = gEnv->pGame->GetIGameFramework()->GetIMaterialEffects(); TMFXEffectId effectId = pMaterialEffects->GetEffectId("melee", surfaceIdx); if (effectId != InvalidEffectId) { SMFXRunTimeEffectParams params; params.pos = pt; params.playflags = MFX_PLAY_ALL | MFX_DISABLE_DELAY; params.soundSemantic = eSoundSemantic_Player_Foley; pMaterialEffects->ExecuteEffect(effectId, params); } } ApplyCameraShake(true); m_pWeapon->PlayAction(m_meleeactions.hit.c_str()); }