//------------------------------------------------------------------------ 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(); IAIActor* pAIActor = pAI->CastToIAIActor(); if (pAIActor && pAIActor->GetParameters().m_nSpecies == 0) { return pH->EndFunction(); } } } } } pActor->Fall(hitPos); return pH->EndFunction(); }
bool CDialogActorContext::DoLookAt(IEntity *pEntity, IEntity *pLookAtEntity, bool& bReachedTarget) { bReachedTarget = false; IAIObject* pAI = pEntity->GetAI(); if (pAI == 0) return false; IAIActor* pAIActor = pAI->CastToIAIActor(); if (!pAIActor) { return false; } if (pLookAtEntity == 0) { pAIActor->ResetLookAt(); bReachedTarget = true; m_bLookAtNeedsReset = false; } else { IAIObject* pTargetAI = pLookAtEntity->GetAI(); Vec3 pos = pTargetAI ? pTargetAI->GetPos() : pLookAtEntity->GetWorldPos(); bReachedTarget = pAIActor->SetLookAtPointPos(pos, true); m_bLookAtNeedsReset = true; } return true; }
bool CCannonBall::FilterFriendlyAIHit(IEntity* pHitTarget) { bool bResult = false; if (!gEnv->bMultiplayer && pHitTarget) { const bool bIsClient = (m_ownerId == g_pGame->GetIGameFramework()->GetClientActorId()); IEntity* pOwnerEntity = gEnv->pEntitySystem->GetEntity(m_ownerId); //Filter client hits against friendly AI if (pOwnerEntity && bIsClient) { IAIObject *pOwnerAI = pOwnerEntity->GetAI(); IAIObject *pTargetAI = pHitTarget->GetAI(); if (pOwnerAI && pTargetAI && !pTargetAI->IsHostile(pOwnerAI)) { const bool bEnableFriendlyHit = g_pGameCVars->g_enableFriendlyPlayerHits != 0; if (!bEnableFriendlyHit) { g_pGame->GetGameRules()->SetEntityToIgnore(pHitTarget->GetId()); bResult = true; } } } } return bResult; }
bool CDialogActorContext::ExecuteAI(int& goalPipeID, const char* signalText, IAISignalExtraData* pExtraData, bool bRegisterAsListener) { IEntitySystem* pSystem = gEnv->pEntitySystem; IEntity* pEntity = pSystem->GetEntity(m_entityID); if (pEntity == 0) return false; IAIObject* pAI = pEntity->GetAI(); if (pAI == 0) return false; unsigned short nType=pAI->GetAIType(); if ( nType != AIOBJECT_ACTOR ) { if ( nType == AIOBJECT_PLAYER ) { goalPipeID = -1; // not needed for player // pAI->SetSignal( 10, signalText, pEntity, NULL ); // 10 means this signal must be sent (but sent[!], not set) // even if the same signal is already present in the queue return true; } // invalid AIObject type return false; } IPipeUser* pPipeUser = pAI->CastToIPipeUser(); if (pPipeUser) { if (goalPipeID > 0) { pPipeUser->RemoveSubPipe(goalPipeID, true); pPipeUser->UnRegisterGoalPipeListener( this, goalPipeID ); goalPipeID = 0; } } goalPipeID = gEnv->pAISystem->AllocGoalPipeId(); if (pExtraData == 0) pExtraData = gEnv->pAISystem->CreateSignalExtraData(); pExtraData->iValue = goalPipeID; if (pPipeUser && bRegisterAsListener) { pPipeUser->RegisterGoalPipeListener( this, goalPipeID, "CDialogActorContext::ExecuteAI"); } IAIActor* pAIActor = CastToIAIActorSafe(pAI); if(pAIActor) pAIActor->SetSignal( 10, signalText, pEntity, pExtraData ); // 10 means this signal must be sent (but sent[!], not set) // even if the same signal is already present in the queue return true; }
void CGameStateRecorder::StartSession() { m_GameStates.clear(); m_itSingleActorGameState = m_GameStates.end(); m_IgnoredEvents.clear(); const char* filterName = m_demo_actorFilter->GetString(); // send game events to record the initial game state /* if(m_mode) { CActor *pActor = static_cast<CActor *>(gEnv->pGame->GetIGameFramework()->GetClientActor()); */ m_pSingleActor = GetActorOfName(filterName); if(m_pSingleActor)// && !pActor->GetSpectatorMode() && pActor->IsPlayer()) { m_mode = GPM_SingleActor; AddActorToStats(m_pSingleActor); m_itSingleActorGameState = m_GameStates.begin();// position of requested actor's id (player by default) } // } else if (!strcmpi(filterName,"all")) { IAIObjectManager* pAIObjMgr = gEnv->pAISystem->GetAIObjectManager(); m_mode = GPM_AllActors; { AutoAIObjectIter it(pAIObjMgr->GetFirstAIObject(OBJFILTER_TYPE, AIOBJECT_ACTOR)); for(; it->GetObject(); it->Next()) { IAIObject* pObject = it->GetObject(); if(pObject) { CActor* pActor = static_cast<CActor *>(gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pObject->GetEntityID())); if(pActor) AddActorToStats(pActor); } } } { AutoAIObjectIter it(pAIObjMgr->GetFirstAIObject(OBJFILTER_TYPE, AIOBJECT_VEHICLE)); for(; it->GetObject(); it->Next()) { IAIObject* pObject = it->GetObject(); if(pObject) { CActor* pActor = static_cast<CActor *>(gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pObject->GetEntityID())); if(pActor) AddActorToStats(pActor); } } } } }
//------------------------------------------------------------------------ int CScriptBind_Action::SetAimQueryMode(IFunctionHandler* pH, ScriptHandle entityId, int mode) { IEntity* entity = gEnv->pEntitySystem->GetEntity(static_cast<EntityId>(entityId.n)); IAIObject* ai = entity ? entity->GetAI() : NULL; CAIProxy* proxy = ai ? static_cast<CAIProxy*>(ai->GetProxy()) : NULL; if (proxy) proxy->SetAimQueryMode(static_cast<CAIProxy::AimQueryMode>(mode)); return pH->EndFunction(); }
IAIObject* CTacticalPointLanguageExtender::GetBattleFrontObject() const { IAIObjectManager* pAIObjMgr = gEnv->pAISystem->GetAIObjectManager(); IAIObject *pObj = pAIObjMgr->GetAIObject(m_battlefrontAIObject); if (!pObj) { // Not created or has been removed (by reset, etc), so create one ITacticalPointSystem& tacticalPointSystem = *gEnv->pAISystem->GetTacticalPointSystem(); pObj = tacticalPointSystem.CreateExtenderDummyObject("Game_BattleFront"); assert(pObj); m_battlefrontAIObject = pObj ? pObj->GetAIObjectID() : 0; } return pObj; }
bool CDialogActorContext::DoAnimActionEP(IEntity* pEntity, const char* sAction) { IAIObject* pAI = pEntity->GetAI(); if (pAI == 0) return false; IPipeUser* pPipeUser = pAI->CastToIPipeUser(); if (!pPipeUser) { return false; } Vec3 pos = pEntity->GetWorldPos(); Vec3 dir = pAI->GetMoveDir(); // EP Direction is either lookat direction or forward direction CDialogScript::TActorID lookAt = m_pCurLine->m_lookatActor; if (lookAt != CDialogScript::NO_ACTOR_ID) { IEntity* pLookAtEntity = m_pSession->GetActorEntity(lookAt); if (pLookAtEntity != 0) { dir = pLookAtEntity->GetWorldPos(); dir -= pos; dir.z = 0; dir.NormalizeSafe(pAI->GetMoveDir()); } } pPipeUser->SetRefPointPos(pos, dir); static const Vec3 startRadius (0.1f,0.1f,0.1f); static const float dirTolerance = 5.f; static const float targetRadius = 0.05f; IAISignalExtraData* pData = gEnv->pAISystem->CreateSignalExtraData(); pData->iValue2 = m_bAnimUseAGSignal ? 1 : 0; pData->SetObjectName(sAction); pData->point = startRadius; pData->fValue = dirTolerance; pData->point2.x = targetRadius; const bool ok = ExecuteAI(m_exPosAnimPipeID, "ACT_ANIMEX", pData); return ok; }
// Description: // // Arguments: // // Return: // void CPersonalSignalTimer::SetListener(bool bAdd) { IEntity *pEntity = GetEntity();; if (pEntity) { IAIObject *pAIObject = pEntity->GetAI(); if (pAIObject) { CAIProxy* pAIProxy = (CAIProxy*)pAIObject->GetProxy(); if (pAIProxy) { if (bAdd) pAIProxy->AddListener(this); else pAIProxy->RemoveListener(this); } } } }
//------------------------------------------------------------------------ void CProjectile::SetParams(EntityId ownerId, EntityId hostId, EntityId weaponId, int damage, int hitTypeId, float damageDrop /*= 0.0f*/, float damageDropMinR /*=0.0f*/) { m_ownerId = ownerId; m_weaponId = weaponId; m_hostId = hostId; m_damage = damage; m_hitTypeId = hitTypeId; m_damageDropPerMeter = damageDrop; m_damageDropMinDisSqr = damageDropMinR*damageDropMinR; if(m_hostId || m_ownerId) { IEntity *pSelfEntity = GetEntity(); if(pSelfEntity) pSelfEntity->AddEntityLink("Shooter", m_ownerId); IEntity *pEntity = gEnv->pEntitySystem->GetEntity(m_hostId?m_hostId:m_ownerId); if(pEntity) { if(pSelfEntity) { //need to set AI species to the shooter - not to be scared of it's own rockets IAIObject *projectileAI = pSelfEntity->GetAI(); IAIObject *shooterAI = pEntity->GetAI(); if(projectileAI && shooterAI) projectileAI->SetFactionID(shooterAI->GetFactionID()); } if(m_pPhysicalEntity && m_pPhysicalEntity->GetType()==PE_PARTICLE) { pe_params_particle pparams; pparams.pColliderToIgnore = pEntity->GetPhysics(); m_pPhysicalEntity->SetParams(&pparams); } } } }
void StalkerModule::UpdateInstance(StalkerInstance& instance, float frameTime) { Agent stalker(instance.GetEntityID()); IAIObject* liveTarget = (stalker.IsValid() ? stalker.GetLiveTarget() : NULL); if (liveTarget) { if (instance.asyncState == AsyncReady) { instance.asyncState = AsyncInProgress; QueueLineOfSightRay(stalker, liveTarget, instance); } bool inTargetFov = liveTarget->IsPointInFOV(stalker.GetPos()) == IAIObject::eFOV_Primary; if (instance.lastInTargetFov != inTargetFov) { instance.lastInTargetFov = inTargetFov; instance.SendSignal(inTargetFov ? "OnInTargetFov" : "OnNotInTargetFov"); } } }
uint8 CAutoAimManager::GetLocalPlayerFaction() const { if (m_localPlayerFaction != IFactionMap::InvalidFactionID) { return m_localPlayerFaction; } else { IEntity* pLocalPlayerEntity = gEnv->pEntitySystem->GetEntity(g_pGame->GetIGameFramework()->GetClientActorId()); if (pLocalPlayerEntity) { IAIObject* pAIObject = pLocalPlayerEntity->GetAI(); if (pAIObject) { m_localPlayerFaction = pAIObject->GetFactionID(); } } } return m_localPlayerFaction; }
CAIAwarenessToPlayerHelper::VisorIconColor CAIAwarenessToPlayerHelper::GetMarkerColorForAgent(const EntityId entityId) const { CAIAwarenessToPlayerHelper::VisorIconColor defaultColor = Green; IEntity* entity = gEnv->pEntitySystem->GetEntity(entityId); const IAIObject* ai = entity ? entity->GetAI() : NULL; const IAIActor* aiActor = ai ? ai->CastToIAIActor() : NULL; IAIObject* playerAiObject = NULL; CActor* playerActor = static_cast<CActor*>(gEnv->pGame->GetIGameFramework()->GetClientActor()); if (playerActor) { if (IEntity* playerEntity = playerActor->GetEntity()) { playerAiObject = playerEntity->GetAI(); } } if (!playerActor || !playerAiObject) return defaultColor; const bool playerIsCloaked = playerActor->IsCloaked(); if (aiActor) { const int alertness = GetAlertnessAffectedByVisibility(*aiActor, *playerAiObject, playerIsCloaked); if (alertness == 0) return Green; else if (alertness == 1) return Orange; else return Red; } else { // Turrets are not AI actors so they are treated a bit differently // TODO: extend this to generic IAwarenessEntity. for now in C3 is fine as we dont want Towers to be show here. if (CTurret* turret = TurretHelpers::FindTurret(entityId)) { if (IEntity* turretEntity = turret->GetEntity()) { if (IAIObject* turretAI = turretEntity->GetAI()) { const bool turretIsDeployed = (turret->GetStateId() == eTurretBehaviorState_Deployed); if (!playerIsCloaked && turretIsDeployed && turretAI->IsHostile(playerAiObject) && turret->IsVisionIdInVisionRange(playerAiObject->GetVisionID())) return Red; else return Green; } } } } return defaultColor; }
int CAIAwarenessToPlayerHelper::GetAlertnessAffectedByVisibility(const IAIActor& aiActor, const IAIObject& playerAiObject, const bool playerIsCloaked) const { int alertness = aiActor.GetProxy()->GetAlertnessState(); // Clamp the alertness to orange (1) if the player is cloaked or // if he's not currently seen by this ai actor. if (playerIsCloaked || !aiActor.CanSee(playerAiObject.GetVisionID())) { alertness = std::min(alertness, 1); } return alertness; }
bool CTacticalPointLanguageExtender::GetObject(TObjectParameters& parameters) const { CAIBattleFrontGroup* battleFrontGroup = gGameAIEnv.battleFrontModule ->GetGroupForEntity(parameters.pOwner.actorEntityId); assert(battleFrontGroup); if (!battleFrontGroup) { gEnv->pLog->LogError("CTacticalPointLanguageExtender::GetObject: Couldn't get battlefront group for entity %d", parameters.pOwner.actorEntityId); return false; } IAIObject * pBattleFrontAIObject = GetBattleFrontObject(); assert(pBattleFrontAIObject); if (!pBattleFrontAIObject) return false; pBattleFrontAIObject->SetPos(battleFrontGroup->GetBattleFrontPosition()); // Return the result // (MATT) The interface is poor for this - it shouldn't need a pointer {2009/12/01} parameters.result = pBattleFrontAIObject; return true; }
uint8 CAutoAimManager::GetTargetFaction( IEntity& targetEntity ) const { IAIObject* pAIObject = targetEntity.GetAI(); return pAIObject ? pAIObject->GetFactionID() : IFactionMap::InvalidFactionID; }
void CGameAIRecorder::AddRecordBookmark(EntityId requesterId) { assert(requesterId > 0); assert(gEnv->bServer); if (m_bIsRecording) { if (!gEnv->bServer) { CryLogAlways("[AI] Recorder bookmark requested on Client. Only the Server can do this!"); return; } IEntity *pEntity = gEnv->pEntitySystem->GetEntity(requesterId); IAIObject *pAI = pEntity ? pEntity->GetAI() : NULL; if (!pAI) { CryLogAlways("[AI] Attempting to add recorder bookmark, but the requester does not have an AI!"); return; } static int g_iBookmarkCounter = 0; int iBookmark = ++g_iBookmarkCounter; // (Kevin) We need to unify the timestamp for this, which should be set when the Recorder itself starts. // This way, all screenshots will match up with the recorder per date/time/build. Then we need to // move these into subfolders that contain the date/time/build as the name. (10/08/2009) time_t ltime; time(<ime); tm *pTm = localtime(<ime); char szDate[128]; strftime(szDate, 128, "Date(%d %b %Y) Time(%H %M %S)", pTm); // Get current version line const SFileVersion& fileVersion = gEnv->pSystem->GetFileVersion(); const bool bTakeScreenshot = (requesterId == g_pGame->GetIGameFramework()->GetClientActorId()); // Output to log CryLogAlways("[AI] --- RECORDER BOOKMARK ADDED ---"); CryLogAlways("[AI] Id: %d", iBookmark); CryLogAlways("[AI] %s", szDate); CryLogAlways("[AI] By: %s", pEntity->GetName()); if (!bTakeScreenshot) { CryLogAlways("[AI] No Screenshot was made for this bookmark, because requester is not the server!"); } else { string sScreenShotFile; sScreenShotFile.Format("Recorder_Bookmark(%d) Build(%d) %s", iBookmark, fileVersion[0], szDate); const string sScreenShotPath = PathUtil::Make("Recordings", sScreenShotFile.c_str(), "jpg"); // Take screenshot CryLogAlways("[AI] Screenshot: \'%s\'", sScreenShotPath.c_str()); gEnv->pRenderer->ScreenShot(sScreenShotPath.c_str()); OnAddBookmark(sScreenShotPath); } // Add bookmark to stream IAIRecordable::RecorderEventData data((float)iBookmark); pAI->RecordEvent(IAIRecordable::E_BOOKMARK, &data); } }
//------------------------------------------------------------------------ void CProjectile::Launch(const Vec3 &pos, const Vec3 &dir, const Vec3 &velocity, float speedScale) { Matrix34 worldTM=Matrix34(Matrix33::CreateRotationVDir(dir.GetNormalizedSafe())); worldTM.SetTranslation(pos); GetEntity()->SetWorldTM(worldTM); //Must set velocity after position, if not velocity could be reseted for PE_RIGID SetVelocity(pos, dir, velocity, speedScale); m_initial_pos = pos; m_initial_dir = dir; m_initial_vel = velocity; m_last = pos; // Attach effect when fired (not first update) if (m_trailEffectId<0) TrailEffect(true); IAIObject* pAI = 0; if ((pAI = GetEntity()->GetAI()) != NULL && pAI->GetAIType() == AIOBJECT_GRENADE) { IEntity *pOwnerEntity = gEnv->pEntitySystem->GetEntity(m_ownerId); if (pOwnerEntity && pOwnerEntity->GetAI()) { pe_status_dynamics dyn; pe_status_dynamics dynProj; if (pOwnerEntity->GetAI()->GetProxy() && pOwnerEntity->GetPhysics() && pOwnerEntity->GetPhysics()->GetStatus(&dyn) && GetEntity()->GetPhysics()->GetStatus(&dynProj)) { Vec3 ownerVel( dyn.v); Vec3 grenadeDir(dynProj.v.GetNormalizedSafe()); // Trigger the signal at the predicted landing position. Vec3 predictedPos = pos; float dummySpeed; if (GetWeapon()) GetWeapon()->PredictProjectileHit(pOwnerEntity->GetPhysics(), pos, dir, velocity, speedScale * m_pAmmoParams->speed, predictedPos, dummySpeed); /* bool res = pOwnerEntity->GetAI()->GetProxy()->GetSecWeapon()->PredictProjectileHit( pOwnerEntity->GetPhysics(), GetEntity()->GetPos(), grenadeDir, ownerVel, 1, predictedPos, speed);*/ gEnv->pAISystem->GrenadeEvent(predictedPos, 0.0f, AIGE_GRENADE_THROWN, GetEntity(), pOwnerEntity); // Inform the AI that sees the throw /* IAIObject* pOwnerAI = pOwnerEntity->GetAI(); AutoAIObjectIter it(gEnv->pAISystem->GetFirstAIObjectInRange(IAISystem::OBJFILTER_TYPE, AIOBJECT_PUPPET, predictedPos, 20.0f, false)); for(; it->GetObject(); it->Next()) { IAIObject* pAI = it->GetObject(); if (!pAI->IsEnabled()) continue; if (pOwnerAI && !pOwnerAI->IsHostile(pAI,false)) continue; // Only sense grenades that are on front of the AI and visible when thrown. // Another signal is sent when the grenade hits the ground. Vec3 delta = GetEntity()->GetPos() - pAI->GetPos(); // grenade to AI float dist = delta.NormalizeSafe(); const float thr = cosf(DEG2RAD(160.0f)); if (delta.Dot(pAI->GetViewDir()) > thr) { ray_hit hit; static const int objTypes = ent_static | ent_terrain | ent_rigid | ent_sleeping_rigid; static const unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any; int res = gEnv->pPhysicalWorld->RayWorldIntersection(pAI->GetPos(), delta*dist, objTypes, flags, &hit, 1); if (!res || hit.dist > dist*0.9f) { IAISignalExtraData* pEData = gEnv->pAISystem->CreateSignalExtraData(); // no leak - this will be deleted inside SendAnonymousSignal pEData->point = predictedPos; pEData->nID = pOwnerEntity->GetId(); pEData->iValue = 1; gEnv->pAISystem->SendSignal(SIGNALFILTER_SENDER, 1, "OnGrenadeDanger", pAI, pEData); } } } */ } } } }
void CLocalPlayerComponent::UpdatePlayerLowHealthStatus( const float oldHealth ) { const float healthThrLow = g_pGameCVars->g_playerLowHealthThreshold; const float healthThrMid = g_pGameCVars->g_playerMidHealthThreshold; const float maxHealth = (float)m_rPlayer.GetMaxHealth(); const float minHealth = 0; const float currentHealth = m_rPlayer.m_health.GetHealth(); const bool isDead = m_rPlayer.m_health.IsDead(); CRY_ASSERT( maxHealth > minHealth ); //Extra 'mid-low' health sound hint if ((currentHealth <= healthThrMid) && (oldHealth > healthThrMid)) { m_rPlayer.PlaySound(CPlayer::ESound_EnterMidHealth); m_playedMidHealthSound = true; } else if ((oldHealth <= healthThrMid) && (currentHealth > healthThrMid) && m_playedMidHealthSound) { m_rPlayer.PlaySound(CPlayer::ESound_EnterMidHealth, false); m_rPlayer.PlaySound(CPlayer::ESound_ExitMidHealth); m_playedMidHealthSound = false; } if((currentHealth <= healthThrLow) && (oldHealth > healthThrLow)) { if(!isDead) { m_rPlayer.SetClientSoundmood(CPlayer::ESoundmood_LowHealth); } IAIObject* pAI = m_rPlayer.GetEntity()->GetAI(); if (pAI) { float mercyTimeScale = 1.0f; SAIEVENT aiEvent; aiEvent.fThreat = mercyTimeScale; pAI->Event(AIEVENT_LOWHEALTH, &aiEvent); CGameRules* pGameRules = g_pGame->GetGameRules(); if(pGameRules != NULL) { IGameRulesDamageHandlingModule* pDamageHandling = pGameRules->GetDamageHandlingModule(); if(pDamageHandling != NULL) { pDamageHandling->OnGameEvent(IGameRulesDamageHandlingModule::eGameEvent_LocalPlayerEnteredMercyTime); } } } } else if((currentHealth > healthThrLow) && (oldHealth <= healthThrLow)) { m_rPlayer.SetClientSoundmood(CPlayer::ESoundmood_Alive); } const float k_minDamageForHit = 10.0f; //this is partly to deal with small differences in health over the network if(!isDead && (currentHealth < oldHealth - k_minDamageForHit)) { m_rPlayer.SendMusicLogicEvent(eMUSICLOGICEVENT_PLAYER_WOUNDED); } const float defiantSkillKillLowHealth = maxHealth * g_pGameCVars->g_defiant_lowHealthFraction; if(currentHealth > defiantSkillKillLowHealth) { m_timeEnteredLowHealth = 0.f; } else if(m_timeEnteredLowHealth <= 0.f) { m_timeEnteredLowHealth = gEnv->pTimer->GetFrameStartTime(); } }
//------------------------------------------------------------------------ void CProjectile::HandleEvent(const SGameObjectEvent &event) { if(m_destroying) return; FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); if(event.event == eGFE_OnCollision) { EventPhysCollision *pCollision = (EventPhysCollision *)event.ptr; if(pCollision == NULL) return; const SCollisionParams *pCollisionParams = m_pAmmoParams->pCollision; if(pCollisionParams) { if(pCollisionParams->pParticleEffect) pCollisionParams->pParticleEffect->Spawn(true, IParticleEffect::ParticleLoc(pCollision->pt, pCollision->n, pCollisionParams->scale)); if(pCollisionParams->sound) { _smart_ptr<ISound> pSound = gEnv->pSoundSystem->CreateSound(pCollisionParams->sound, FLAG_SOUND_DEFAULT_3D); if(pSound) { pSound->SetSemantic(eSoundSemantic_Projectile); pSound->SetPosition(pCollision->pt); pSound->Play(); } } } // add battledust for bulletimpact if(gEnv->bServer && g_pGame->GetGameRules()) { if(CBattleDust *pBD = g_pGame->GetGameRules()->GetBattleDust()) { pBD->RecordEvent(eBDET_ShotImpact, pCollision->pt, GetEntity()->GetClass()); } } Ricochet(pCollision); //Update damage if((m_damageDropPerMeter>0.0001f)&& (((pCollision->pt-m_initial_pos).len2()>m_damageDropMinDisSqr)||m_firstDropApplied)) { if(!m_firstDropApplied) { m_firstDropApplied = true; m_initial_pos = m_initial_pos + (m_initial_dir*(sqrt_fast_tpl(m_damageDropMinDisSqr))); } Vec3 vDiff = pCollision->pt - m_initial_pos; float dis = vDiff.len(); m_damage -= (int)(floor_tpl(m_damageDropPerMeter * dis)); //Check m_damage is positive if(m_damage<MIN_DAMAGE) m_damage=MIN_DAMAGE; //Also modify initial position (the projectile could not be destroyed, cause of pirceability) m_initial_pos = pCollision->pt; } // Notify AI system about grenades. if(gEnv->pAISystem) { IAIObject *pAI = 0; if((pAI = GetEntity()->GetAI()) != NULL && pAI->GetAIType() == AIOBJECT_GRENADE) { // Associate event with vehicle if the shooter is in a vehicle (tank cannon shot, etc) EntityId ownerId = m_ownerId; IActor *pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(ownerId); if(pActor && pActor->GetLinkedVehicle() && pActor->GetLinkedVehicle()->GetEntityId()) ownerId = pActor->GetLinkedVehicle()->GetEntityId(); SAIStimulus stim(AISTIM_GRENADE, AIGRENADE_COLLISION, ownerId, GetEntityId(), GetEntity()->GetWorldPos(), ZERO, 12.0f); gEnv->pAISystem->RegisterStimulus(stim); } } } }
//------------------------------------------------------------------------ int CMelee::Hit(const Vec3 &pt, const Vec3 &dir, const Vec3 &normal, IPhysicalEntity *pCollider, EntityId collidedEntityId, int partId, int ipart, int surfaceIdx, bool remote) { MeleeDebugLog ("CMelee<%p> HitPointDirNormal(remote=%s)", this, remote ? "true" : "false"); int hitTypeID = 0; CActor *pOwnerActor = m_pWeapon->GetOwnerActor(); if (pOwnerActor) { IActor* pTargetActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(collidedEntityId); IEntity* pTarget = pTargetActor ? pTargetActor->GetEntity() : gEnv->pEntitySystem->GetEntity(collidedEntityId); IEntity* pOwnerEntity = pOwnerActor->GetEntity(); IAIObject* pOwnerAI = pOwnerEntity->GetAI(); float damageScale = 1.0f; bool silentHit = false; if(pTargetActor) { IAnimatedCharacter* pTargetAC = pTargetActor->GetAnimatedCharacter(); IAnimatedCharacter* pOwnerAC = pOwnerActor->GetAnimatedCharacter(); if(pTargetAC && pOwnerAC) { Vec3 targetFacing(pTargetAC->GetAnimLocation().GetColumn1()); Vec3 ownerFacing(pOwnerAC->GetAnimLocation().GetColumn1()); float ownerFacingDot = ownerFacing.Dot(targetFacing); float fromBehindDot = cos_tpl(DEG2RAD(g_pGameCVars->pl_melee.angle_limit_from_behind)); if(ownerFacingDot > fromBehindDot) { #ifndef _RELEASE if (g_pGameCVars->g_LogDamage) { CryLog ("[DAMAGE] %s '%s' is%s meleeing %s '%s' from behind (because %f > %f)", pOwnerActor->GetEntity()->GetClass()->GetName(), pOwnerActor->GetEntity()->GetName(), silentHit ? " silently" : "", pTargetActor->GetEntity()->GetClass()->GetName(), pTargetActor->GetEntity()->GetName(), ownerFacingDot, fromBehindDot); } #endif damageScale *= g_pGameCVars->pl_melee.damage_multiplier_from_behind; } } } // Send target stimuli if (!gEnv->bMultiplayer) { IAISystem *pAISystem = gEnv->pAISystem; ITargetTrackManager *pTargetTrackManager = pAISystem ? pAISystem->GetTargetTrackManager() : NULL; if (pTargetTrackManager && pOwnerAI) { IAIObject *pTargetAI = pTarget ? pTarget->GetAI() : NULL; if (pTargetAI) { const tAIObjectID aiOwnerId = pOwnerAI->GetAIObjectID(); const tAIObjectID aiTargetId = pTargetAI->GetAIObjectID(); TargetTrackHelpers::SStimulusEvent eventInfo; eventInfo.vPos = pt; eventInfo.eStimulusType = TargetTrackHelpers::eEST_Generic; eventInfo.eTargetThreat = AITHREAT_AGGRESSIVE; pTargetTrackManager->HandleStimulusEventForAgent(aiTargetId, aiOwnerId, "MeleeHit",eventInfo); pTargetTrackManager->HandleStimulusEventInRange(aiOwnerId, "MeleeHitNear", eventInfo, 5.0f); } } } //Check if is a friendly hit, in that case FX and Hit will be skipped bool isFriendlyHit = (pOwnerEntity && pTarget) ? IsFriendlyHit(pOwnerEntity, pTarget) : false; if(!isFriendlyHit) { CPlayer * pAttackerPlayer = pOwnerActor->IsPlayer() ? static_cast<CPlayer*>(pOwnerActor) : NULL; float damage = m_pMeleeParams->meleeparams.damage_ai; if(pOwnerActor->IsPlayer()) { damage = m_slideKick ? m_pMeleeParams->meleeparams.slide_damage : GetMeleeDamage(); } #ifndef _RELEASE if (pTargetActor && g_pGameCVars->g_LogDamage) { CryLog ("[DAMAGE] %s '%s' is%s meleeing %s '%s' applying damage = %.3f x %.3f = %.3f", pOwnerActor->GetEntity()->GetClass()->GetName(), pOwnerActor->GetEntity()->GetName(), silentHit ? " silently" : "", pTargetActor->GetEntity()->GetClass()->GetName(), pTargetActor->GetEntity()->GetName(), damage, damageScale, damage * damageScale); } #endif //Generate Hit if(pTarget) { CGameRules *pGameRules = g_pGame->GetGameRules(); CRY_ASSERT_MESSAGE(pGameRules, "No game rules! Melee can not apply hit damage"); if (pGameRules) { hitTypeID = silentHit ? CGameRules::EHitType::SilentMelee : m_hitTypeID; HitInfo info(m_pWeapon->GetOwnerId(), pTarget->GetId(), m_pWeapon->GetEntityId(), damage * damageScale, 0.0f, surfaceIdx, partId, hitTypeID, pt, dir, normal); if (m_pMeleeParams->meleeparams.knockdown_chance>0 && Random(100) < m_pMeleeParams->meleeparams.knockdown_chance) info.knocksDown = true; info.remote = remote; pGameRules->ClientHit(info); } if (pAttackerPlayer && pAttackerPlayer->IsClient()) { const Vec3 posOffset = (pt - pTarget->GetWorldPos()); SMeleeHitParams params; params.m_boostedMelee = false; params.m_hitNormal = normal; params.m_hitOffset = posOffset; params.m_surfaceIdx = surfaceIdx; params.m_targetId = pTarget->GetId(); pAttackerPlayer->OnMeleeHit(params); } } else { //Play Material FX PlayHitMaterialEffect(pt, normal, false, surfaceIdx); } } if (pTarget) { CActor *pCTargetActor = static_cast<CActor*>(pTargetActor); CPlayer* pTargetPlayer = (pTargetActor && pTargetActor->IsPlayer()) ? static_cast<CPlayer*>(pTargetActor) : NULL; if(pTargetPlayer && pTargetPlayer->IsClient()) { if(m_pMeleeParams->meleeparams.trigger_client_reaction) { pTargetPlayer->TriggerMeleeReaction(); } } } } return hitTypeID; }
//------------------------------------------------------------------------ void CProjectile::Launch(const Vec3 &pos, const Vec3 &dir, const Vec3 &velocity, float speedScale) { m_destroying = false; GetGameObject()->EnablePhysicsEvent(true, eEPE_OnCollisionLogged); // Only for bullets m_hitPoints = m_pAmmoParams->hitPoints; m_hitListener = false; if(m_hitPoints>0) { //Only projectiles with hit points are hit listeners g_pGame->GetGameRules()->AddHitListener(this); m_hitListener = true; m_noBulletHits = m_pAmmoParams->noBulletHits; } Matrix34 worldTM=Matrix34(Matrix33::CreateRotationVDir(dir.GetNormalizedSafe())); worldTM.SetTranslation(pos); GetEntity()->SetWorldTM(worldTM); //Must set velocity after position, if not velocity could be reseted for PE_RIGID SetVelocity(pos, dir, velocity, speedScale); m_initial_pos = pos; m_initial_dir = dir; m_initial_vel = velocity; m_last = pos; // Attach effect when fired (not first update) if(m_trailEffectId<0) TrailEffect(true); IAIObject *pAI = 0; if((pAI = GetEntity()->GetAI()) != NULL && pAI->GetAIType() == AIOBJECT_GRENADE) { IEntity *pOwnerEntity = gEnv->pEntitySystem->GetEntity(m_ownerId); pe_status_dynamics dyn; pe_status_dynamics dynProj; if(pOwnerEntity->GetPhysics() && pOwnerEntity->GetPhysics()->GetStatus(&dyn) && GetEntity()->GetPhysics()->GetStatus(&dynProj)) { // Vec3 ownerVel(dyn.v); Vec3 grenadeDir(dynProj.v.GetNormalizedSafe()); // Trigger the signal at the predicted landing position. Vec3 predictedPos = pos; float dummySpeed; if(GetWeapon()) GetWeapon()->PredictProjectileHit(pOwnerEntity->GetPhysics(), pos, dir, velocity, speedScale * m_pAmmoParams->speed, predictedPos, dummySpeed); // Associate event with vehicle if the shooter is in a vehicle (tank cannon shot, etc) EntityId ownerId = pOwnerEntity->GetId(); IActor *pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(ownerId); if(pActor && pActor->GetLinkedVehicle() && pActor->GetLinkedVehicle()->GetEntityId()) ownerId = pActor->GetLinkedVehicle()->GetEntityId(); SAIStimulus stim(AISTIM_GRENADE, AIGRENADE_THROWN, ownerId, GetEntityId(), predictedPos, ZERO, 20.0f); gEnv->pAISystem->RegisterStimulus(stim); } } }
void CDialogActorContext::CancelCurrent(bool bResetStates) { if (!m_bNeedsCancel) return; assert (m_bInCancel == false); if (m_bInCancel == true) return; m_bInCancel = true; // remove from AG if (m_pAGState != 0) { m_pAGState->RemoveListener(this); if (bResetStates) { ResetAGState(); } m_pAGState = 0; } m_queryID = 0; m_bAnimStarted = false; // reset lookat IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_entityID); if (pEntity) { IAIObject* pAI = pEntity->GetAI(); if (pAI) { IAIActor* pAIActor = pAI->CastToIAIActor(); if (pAIActor) { if (m_bLookAtNeedsReset) { pAIActor->ResetLookAt(); m_bLookAtNeedsReset = false; } IPipeUser* pPipeUser = pAI->CastToIPipeUser(); if (pPipeUser) { if (m_goalPipeID > 0) { if (GetAIBehaviourMode() == CDialogSession::eDIB_InterruptMedium) { int dummyPipe = 0; ExecuteAI(dummyPipe, "ACT_DIALOG_OVER", 0, false); } pPipeUser->UnRegisterGoalPipeListener( this, m_goalPipeID ); pPipeUser->RemoveSubPipe(m_goalPipeID, true); m_goalPipeID = 0; } if (m_exPosAnimPipeID > 0) { pPipeUser->UnRegisterGoalPipeListener( this, m_exPosAnimPipeID ); pPipeUser->CancelSubPipe(m_exPosAnimPipeID); pPipeUser->RemoveSubPipe(m_exPosAnimPipeID, false); m_exPosAnimPipeID = 0; } } } } } // facial expression is always reset // if (bResetStates) { // Reset Facial Expression IEntity* pActorEntity = m_pSession->GetActorEntity(m_actorID); if (pActorEntity) { DoFacialExpression(pActorEntity, "", 1.0f, 0.0f); } } // should we stop the current sound? // we don't stop the sound if the actor aborts and has eDACF_NoAbortSound set. // if actor died (entity destroyed) though, sound is stopped anyway const bool bDontStopSound = (IsAborted() == false && CheckActorFlags(CDialogSession::eDACF_NoAbortSound)) || (IsAborted() && CheckActorFlags(CDialogSession::eDACF_NoAbortSound) && GetAbortReason() != CDialogSession::eAR_ActorDead && GetAbortReason() != CDialogSession::eAR_EntityDestroyed); if (bDontStopSound == false) { // stop sound (this also forces m_soundId to be INVALID_SOUNDID) and markes Context as non-playing! // e.g. IsStillPlaying will then return false // we explicitly stop the sound in the d'tor if we don't take this path here StopSound(); } IEntitySystem* pES = gEnv->pEntitySystem; pES->RemoveEntityEventListener( m_entityID, ENTITY_EVENT_AI_DONE, this ); pES->RemoveEntityEventListener( m_entityID, ENTITY_EVENT_DONE, this ); pES->RemoveEntityEventListener( m_entityID, ENTITY_EVENT_RESET, this ); m_phase = eDAC_Idle; m_bInCancel = false; m_bNeedsCancel = false; }
////////////////////////////////////////////////////////////////////////// // IsMountedWeaponUsableWithTarget // A piece of game-code moved from CryAction when scriptbind_AI moved to the AI system ////////////////////////////////////////////////////////////////////////// int CScriptBind_Game::IsMountedWeaponUsableWithTarget(IFunctionHandler *pH) { int paramCount = pH->GetParamCount(); if(paramCount<2) { GameWarning("%s: too few parameters.", __FUNCTION__); return pH->EndFunction(); } GET_ENTITY(1); if(!pEntity) { GameWarning("%s: wrong entity id in parameter 1.", __FUNCTION__); return pH->EndFunction(); } IAIObject* pAI = pEntity->GetAI(); if (!pAI) { GameWarning("%s: Entity '%s' does not have AI.",__FUNCTION__, pEntity->GetName()); return pH->EndFunction(); } EntityId itemEntityId; ScriptHandle hdl2; if(!pH->GetParam(2,hdl2)) { GameWarning("%s: wrong parameter 2 format.", __FUNCTION__); return pH->EndFunction(); } itemEntityId = (EntityId)hdl2.n; if (!itemEntityId) { GameWarning("%s: wrong entity id in parameter 2.", __FUNCTION__); return pH->EndFunction(); } IGameFramework *pGameFramework = gEnv->pGame->GetIGameFramework(); IItem* pItem = pGameFramework->GetIItemSystem()->GetItem(itemEntityId); if (!pItem) { //gEnv->pAISystem->Warning("<CScriptBind> ", "entity in parameter 2 is not an item/weapon"); GameWarning("%s: entity in parameter 2 is not an item/weapon.", __FUNCTION__); return pH->EndFunction(); } float minDist = 7; bool bSkipTargetCheck = false; Vec3 targetPos(ZERO); if(paramCount > 2) { for(int i=3;i <= paramCount ; i++) { if(pH->GetParamType(i) == svtBool) pH->GetParam(i,bSkipTargetCheck); else if(pH->GetParamType(i) == svtNumber) pH->GetParam(i,minDist); else if(pH->GetParamType(i) == svtObject) pH->GetParam(i,targetPos); } } IAIActor* pAIActor = CastToIAIActorSafe(pAI); if (!pAIActor) { GameWarning("%s: entity '%s' in parameter 1 is not an AI actor.", __FUNCTION__, pEntity->GetName()); return pH->EndFunction(); } IEntity* pItemEntity = pItem->GetEntity(); if(!pItemEntity) return pH->EndFunction(); if(!pItem->GetOwnerId()) { // weapon is not used, check if it is on a vehicle IEntity* pParentEntity = pItemEntity->GetParent(); if(pParentEntity) { IAIObject* pParentAI = pParentEntity->GetAI(); if(pParentAI && pParentAI->GetAIType()==AIOBJECT_VEHICLE) { // (MATT) Feature was cut and code was tricky, hence ignore weapons in vehicles {2008/02/15:11:08:51} return pH->EndFunction(); } } } else if( pItem->GetOwnerId()!= pEntity->GetId()) // item is used by someone else? return pH->EndFunction(false); // check target if(bSkipTargetCheck) return pH->EndFunction(true); IAIObject* pTarget = pAIActor->GetAttentionTarget(); if(targetPos.IsZero()) { if(!pTarget) return pH->EndFunction(); targetPos = pTarget->GetPos(); } Vec3 targetDir(targetPos - pItemEntity->GetWorldPos()); Vec3 targetDirXY(targetDir.x, targetDir.y, 0); float length2D = targetDirXY.GetLength(); if(length2D < minDist || length2D<=0) return pH->EndFunction(); targetDirXY /= length2D;//normalize IWeapon* pWeapon = pItem->GetIWeapon(); bool vehicleGun = pWeapon && pWeapon->GetHostId(); if (!vehicleGun) { Vec3 mountedAngleLimits(pItem->GetMountedAngleLimits()); float yawRange = DEG2RAD(mountedAngleLimits.z); if(yawRange > 0 && yawRange < gf_PI) { float deltaYaw = pItem->GetMountedDir().Dot(targetDirXY); if(deltaYaw < cosf(yawRange)) return pH->EndFunction(false); } float minPitch = DEG2RAD(mountedAngleLimits.x); float maxPitch = DEG2RAD(mountedAngleLimits.y); //maxPitch = (maxPitch - minPitch)/2; //minPitch = -maxPitch; float pitch = atanf(targetDir.z / length2D); if ( pitch < minPitch || pitch > maxPitch ) return pH->EndFunction(false); } if(pTarget) { IEntity* pTargetEntity = pTarget->GetEntity(); if(pTargetEntity) { // check target distance and where he's going IPhysicalEntity *phys = pTargetEntity->GetPhysics(); if(phys) { pe_status_dynamics dyn; phys->GetStatus(&dyn); Vec3 velocity ( dyn.v); velocity.z = 0; float speed = velocity.GetLength2D(); if(speed>0) { //velocity /= speed; if(length2D< minDist * 0.75f && velocity.Dot(targetDirXY)<=0) return pH->EndFunction(false); } } } } return pH->EndFunction(true); }
//--------------------------------------------------------------------------- void CVehicleWeapon::CheckForFriendlyAI(float frameTime) { if (m_pVehicle) { if (CActor* pOwnerActor = GetOwnerActor()) { if (pOwnerActor->IsPlayer() && !gEnv->bMultiplayer) { m_timeToUpdate -= frameTime; if (m_timeToUpdate > 0.f) return; m_timeToUpdate = 0.15f; if (IMovementController* pMC = pOwnerActor->GetMovementController()) { SMovementState info; pMC->GetMovementState(info); LowerWeapon(false); // Try ray hit ray_hit rayhit; IPhysicalEntity* pSkipEnts[10]; int nSkip = CSingle::GetSkipEntities(this, pSkipEnts, 10); int intersect = gEnv->pPhysicalWorld->RayWorldIntersection(info.weaponPosition, info.aimDirection * 150.f, ent_all, rwi_stop_at_pierceable | rwi_colltype_any, &rayhit, 1, pSkipEnts, nSkip); if (intersect && rayhit.pCollider) { if (IEntity* pLookAtEntity = m_pEntitySystem->GetEntityFromPhysics(rayhit.pCollider)) { if (EntityId lookAtEntityId = pLookAtEntity->GetId()) { IAIObject* pLookAtAIObject = pLookAtEntity->GetAI(); IEntity* pOwnerEntity = pOwnerActor->GetEntity(); if (pOwnerEntity && pLookAtAIObject && (lookAtEntityId != GetEntityId())) { if (IVehicle* pVehicle = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(lookAtEntityId)) { if (pVehicle->HasFriendlyPassenger(pOwnerEntity)) { LowerWeapon(true); StopFire(); // Just in case } } else { if (pLookAtAIObject->IsFriendly(pOwnerEntity->GetAI(), false)) { LowerWeapon(true); StopFire(); // Just in case } } } else { // Special case (Animated objects), check for script table value "bNoFriendlyFire" if (IScriptTable* pScriptTable = pLookAtEntity->GetScriptTable()) { SmartScriptTable props; if (pScriptTable->GetValue("Properties", props)) { int isFriendly; if (props->GetValue("bNoFriendlyFire", isFriendly) && (isFriendly != 0)) { LowerWeapon(true); StopFire(); // Just in case } } } } } } } } } } } }