//------------------------------------------------------------------------ void CVehicleActionDeployRope::OnVehicleEvent(EVehicleEvent event, const SVehicleEventParams& params) { if (event == eVE_PassengerExit && params.iParam == m_seatId) { IActorSystem* pActorSystem = gEnv->pGame->GetIGameFramework()->GetIActorSystem(); assert(pActorSystem); IActor* pActor = pActorSystem->GetActor(params.entityId); if (!pActor) { assert(pActor); return; } m_actorId = pActor->GetEntityId(); DeployRope(); AttachOnRope(pActor->GetEntity()); } else if (event == eVE_Destroyed) { if (m_ropeUpperId) { gEnv->pEntitySystem->RemoveEntity(m_ropeUpperId); m_ropeUpperId = 0; } if (m_ropeLowerId) { gEnv->pEntitySystem->RemoveEntity(m_ropeLowerId); m_ropeLowerId = 0; } } }
virtual void ProcessEvent( EFlowEvent event, SActivationInfo *pActInfo ) { switch (event) { case eFE_Initialize: case eFE_Activate: { IActorSystem *pActorSystem = gEnv->pGame->GetIGameFramework()->GetIActorSystem(); IActorIteratorPtr actorIt = pActorSystem->CreateActorIterator(); int iNumPlayers = 0; IActor *pActor = actorIt->Next(); while(iNumPlayers < 4 && pActor) { if(pActor->GetChannelId()) { ActivateOutput(pActInfo, iNumPlayers, pActor->GetEntityId()); ++iNumPlayers; } pActor = actorIt->Next(); } } break; } }
//------------------------------------------------------------------------ void CVehicleDamageBehaviorCameraShake::ShakeClient(float angle, float shift, float duration, float frequency) { IActorSystem *pActorSystem = gEnv->pGame->GetIGameFramework()->GetIActorSystem(); assert(pActorSystem); EntityId clientId = g_pGame->GetIGameFramework()->GetClientActorId(); for (TVehicleSeatId seatId = InvalidVehicleSeatId + 1; seatId != m_pVehicle->GetLastSeatId(); seatId++) { if (IVehicleSeat *pSeat = m_pVehicle->GetSeatById(seatId)) { EntityId passengerId = pSeat->GetPassenger(); if (passengerId == clientId) { CActor *pActor = static_cast<CActor *>(pActorSystem->GetActor(passengerId)); if(pActor) { pActor->CameraShake(angle, shift, duration, frequency, Vec3(0.0f, 0.0f, 0.0f), 5, "VehicleDamageBehaviorCameraShake"); } } } } }
//------------------------------------------------------------------------ void CVehicleActionDeployRope::Update(const float deltaTime) { if (!m_ropeUpperId && !m_ropeLowerId && !m_actorId) return; IActorSystem* pActorSystem = gEnv->pGame->GetIGameFramework()->GetIActorSystem(); assert(pActorSystem); IActor* pActor = pActorSystem->GetActor(m_actorId); if (!pActor) return; Vec3 worldPos = pActor->GetEntity()->GetWorldTM().GetTranslation(); if (IRopeRenderNode* pRopeUpper = GetRopeRenderNode(m_ropeUpperId)) { Vec3 points[2]; points[0] = m_pRopeHelper->GetWorldTM().GetTranslation(); points[1] = worldPos; pRopeUpper->SetPoints(points, 2); float lenghtLeft = max(0.0f, g_ropeLenght - (points[0].z - points[1].z)); if (IRopeRenderNode* pRopeLower = GetRopeRenderNode(m_ropeLowerId)) { Vec3 points[2]; points[0] = worldPos; points[1] = Vec3(worldPos.x, worldPos.y, worldPos.z - lenghtLeft); pRopeLower->SetPoints(points, 2); } } }
EEntityType GetEntityType(EntityId id) { int type = eET_Unknown; IEntitySystem *pEntitySystem = gEnv->pEntitySystem; if (pEntitySystem) { IEntity *pEntity = pEntitySystem->GetEntity(id); if (pEntity) { type = eET_Valid; IEntityClass *pClass = pEntity->GetClass(); if (pClass) { const char* className = pClass->GetName(); // Check AI if (pEntity->GetAI()) { type |= eET_AI; } // Check actor IActorSystem *pActorSystem = gEnv->pGame->GetIGameFramework()->GetIActorSystem(); if (pActorSystem) { IActor *pActor = pActorSystem->GetActor(id); if (pActor) { type |= eET_Actor; } } // Check vehicle IVehicleSystem *pVehicleSystem = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem(); if (pVehicleSystem) { if (pVehicleSystem->IsVehicleClass(className)) { type |= eET_Vehicle; } } // Check item IItemSystem *pItemSystem = gEnv->pGame->GetIGameFramework()->GetIItemSystem(); if (pItemSystem) { if (pItemSystem->IsItemClass(className)) { type |= eET_Item; } } } } } return (EEntityType)type; }
//-------------------------------------------------------------- void CWeaponSystem::OnGameTokenEvent( EGameTokenEvent event,IGameToken *pGameToken ) { assert(pGameToken); if(EGAMETOKEN_EVENT_CHANGE == event) { bool handled = false; if(!strcmp("weapon.effects.ice",pGameToken->GetName())) { pGameToken->GetValueAs(m_frozenEnvironment); handled = true; } else if(!strcmp("weapon.effects.wet",pGameToken->GetName())) { pGameToken->GetValueAs(m_wetEnvironment); handled = true; } if (handled) { IGameFramework* pGF = gEnv->pGame->GetIGameFramework(); IActorSystem* pAS = pGF->GetIActorSystem(); int count = pAS->GetActorCount(); if (count) { IActorIteratorPtr it = pAS->CreateActorIterator(); while (CActor* pActor = (CActor*)it->Next()) { CPlayer *pPlayer = (pActor->GetActorClass() == CPlayer::GetActorClassType()) ? static_cast<CPlayer*>(pActor) : 0; if (pPlayer && pPlayer->GetNanoSuit()) { // go through all players and turn their ice effects on/off IEntityRenderProxy* pRenderProxy = (IEntityRenderProxy*)pPlayer->GetEntity()->GetProxy(ENTITY_PROXY_RENDER); if (pRenderProxy) { uint8 mask = pRenderProxy->GetMaterialLayersMask(); uint32 blend = pRenderProxy->GetMaterialLayersBlend(); mask = IsFrozenEnvironment() ? mask|MTL_LAYER_DYNAMICFROZEN : mask&~MTL_LAYER_DYNAMICFROZEN; mask = IsWetEnvironment() ? mask|MTL_LAYER_WET : mask&~MTL_LAYER_WET; pRenderProxy->SetMaterialLayersMask(mask); pRenderProxy->SetMaterialLayersBlend(blend); if (CItem* pItem = static_cast<CItem*>(pPlayer->GetCurrentItem(true))) { pItem->FrostSync(true); pItem->WetSync(true); } if (COffHand* pOffHand = static_cast<COffHand*>(pPlayer->GetItemByClass(CItem::sOffHandClass))) { pOffHand->FrostSync(pOffHand->GetOffHandState() != eOHS_INIT_STATE); pOffHand->WetSync(pOffHand->GetOffHandState() != eOHS_INIT_STATE); } } } } } } } }
void CAnimatedCharacter::RefreshAnimTarget() { if (m_pMannequinAGState) { IActorSystem* pActorSystem = CCryAction::GetCryAction()->GetIActorSystem(); assert(pActorSystem != NULL); IActor* pActor = pActorSystem->GetActor(GetEntity()->GetId()); IMovementController* pMovementController = pActor->GetMovementController(); m_pAnimTarget = pMovementController->GetExactPositioningTarget(); } }
//------------------------------------------------------------------------ void CVehicleSeatActionMovement::StopUsing() { IActorSystem* pActorSystem = CCryAction::GetCryAction()->GetIActorSystem(); CRY_ASSERT(pActorSystem); IVehicleMovement* pMovement = m_pVehicle->GetMovement(); if (!pMovement) return; CRY_ASSERT(m_pSeat); // default to continuing for a bit m_delayedStop = 0.8f; IActor* pActor = pActorSystem->GetActor(m_pSeat->GetPassenger()); if (pActor && pActor->IsPlayer()) { // if stopped already don't go anywhere IPhysicalEntity* pPhys = m_pVehicle->GetEntity()->GetPhysics(); pe_status_dynamics status; if (pPhys && pPhys->GetStatus(&status)) { if (status.v.GetLengthSquared() < 25.0f) m_delayedStop = 0.0f; } if (m_actionForward > 0.0f) m_delayedStop = 1.5f; if (pMovement->GetMovementType() == IVehicleMovement::eVMT_Air) m_delayedStop *= 2.0f; m_pVehicle->SetObjectUpdate(this, IVehicle::eVOU_AlwaysUpdate); // prevent full pedal being kept pressed, but give it a bit pMovement->OnAction(eVAI_MoveForward, eAAM_OnPress, 0.1f); } else { if (pMovement->GetMovementType() == IVehicleMovement::eVMT_Air) { m_delayedStop = 0.0f; m_pVehicle->SetObjectUpdate(this, IVehicle::eVOU_AlwaysUpdate); } else { pMovement->StopDriving(); } } }
//--------------------------------------- TAudioSignalID CAreaAnnouncer::BuildAnnouncement(const EntityId clientId) { const int k_areaCount = m_areaList.size(); if (k_areaCount > 0) { IActorSystem* pActorSystem = gEnv->pGame->GetIGameFramework()->GetIActorSystem(); if (CActor* pClientActor = static_cast<CActor*>(pActorSystem->GetActor(clientId))) { int actorCount[k_maxAnnouncementAreas]; memset(&actorCount, 0, sizeof(actorCount)); CActorManager * pActorManager = CActorManager::GetActorManager(); pActorManager->PrepareForIteration(); const int kNumActors = pActorManager->GetNumActors(); const int kPlayerTeamId = g_pGame->GetGameRules()->GetTeam(clientId); for (int i = 0; i < kNumActors; i++) { SActorData actorData; pActorManager->GetNthActorData(i, actorData); if(actorData.teamId != kPlayerTeamId && actorData.health > 0 && actorData.spectatorMode == CActor::eASM_None) { for (int areaIndex = 0; areaIndex < k_areaCount; areaIndex++) { IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_areaList[areaIndex].m_areaProxyId); if(pEntity) { IEntityAreaProxy *pArea = (IEntityAreaProxy*)pEntity->GetProxy(ENTITY_PROXY_AREA); if(pArea && pArea->CalcPointWithin(INVALID_ENTITYID, actorData.position, true)) { actorCount[areaIndex]++; break; } } } } } return GenerateAnnouncement(&actorCount[0], k_areaCount, clientId); } } return INVALID_AUDIOSIGNAL_ID; }
bool CPlayerInput::OnActionDebugNextActor(EntityId entityId, const ActionId& actionId, int activationMode, float value) { IActorSystem* pActorSystem = gEnv->pGame->GetIGameFramework()->GetIActorSystem(); if (pActorSystem->GetActorCount() > 1) { EntityId currentEntityId = pActorSystem->SwitchDemoSpectator(0); // Remote players should be viewed only in 3D mode with cl_cam_orbit set to 1 bool isPlayerViewed = (currentEntityId == entityId); m_pPlayer->SetThirdPerson(!isPlayerViewed); g_pGameCVars->cl_cam_orbit = isPlayerViewed ? 0 : 1; } return false; }
//------------------------------------------------------------------------- void CGameRulesStandardState::CleanUpAbortedIntro() { CGameRules::TPlayers players; m_pGameRules->GetPlayers(players); IActorSystem* pActorSystem = g_pGame->GetIGameFramework()->GetIActorSystem(); CGameRules::TPlayers::const_iterator iter = players.begin(); CGameRules::TPlayers::const_iterator end = players.end(); while(iter != end) { CPlayer* pPlayer = static_cast<CPlayer*>( pActorSystem->GetActor( *iter ) ); if(pPlayer) { pPlayer->OnIntroSequenceFinished(); } ++iter; } }
//------------------------------------------------------------------------ void CVehicleClient::OnEnterVehicleSeat(IVehicleSeat* pSeat) { m_bMovementFlagRight=m_bMovementFlagLeft=m_bMovementFlagForward=m_bMovementFlagBack=false; m_fLeftRight = m_fForwardBackward = 0.f; IVehicle* pVehicle = pSeat->GetVehicle(); assert(pVehicle); IActorSystem* pActorSystem = gEnv->pGame->GetIGameFramework()->GetIActorSystem(); assert(pActorSystem); IActor* pActor = pActorSystem->GetActor(pSeat->GetPassenger()); if (pActor) { bool isThirdPerson = pActor->IsThirdPerson() || m_tp; TVehicleViewId viewId = InvalidVehicleViewId; TVehicleViewId firstViewId = InvalidVehicleViewId; while (viewId = pSeat->GetNextView(viewId)) { if (viewId == firstViewId) break; if (firstViewId == InvalidVehicleViewId) firstViewId = viewId; if (IVehicleView* pView = pSeat->GetView(viewId)) { if (pView->IsThirdPerson() == isThirdPerson) break; } } if (viewId != InvalidVehicleViewId) pSeat->SetView(viewId); if(IActor *pPassengerActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pSeat->GetPassenger())) { if(pPassengerActor->IsPlayer()) { EnableActionMaps(pSeat, true); } } } }
//------------------------------------------------------------------------ void CVehicleClient::OnEnterVehicleSeat(IVehicleSeat* pSeat) { m_bMovementFlagRight=m_bMovementFlagLeft=m_bMovementFlagForward=m_bMovementFlagBack=false; m_fLeftRight = m_fForwardBackward = 0.f; IVehicle* pVehicle = pSeat->GetVehicle(); assert(pVehicle); IActorSystem* pActorSystem = gEnv->pGame->GetIGameFramework()->GetIActorSystem(); assert(pActorSystem); IActor* pActor = pActorSystem->GetActor(pSeat->GetPassenger()); bool isThirdPerson = pActor->IsThirdPerson() || m_tp; TVehicleViewId viewId = InvalidVehicleViewId; TVehicleViewId firstViewId = InvalidVehicleViewId; while (viewId = pSeat->GetNextView(viewId)) { if (viewId == firstViewId) break; if (firstViewId == InvalidVehicleViewId) firstViewId = viewId; if (IVehicleView* pView = pSeat->GetView(viewId)) { if (pView->IsThirdPerson() == isThirdPerson) break; } } if (viewId != InvalidVehicleViewId) pSeat->SetView(viewId); IActionMapManager* pMapManager = gEnv->pGame->GetIGameFramework()->GetIActionMapManager(); assert(pMapManager); pMapManager->EnableActionMap("landvehicle", false); pMapManager->EnableActionMap("seavehicle", false); pMapManager->EnableActionMap("helicopter", false); pMapManager->EnableActionMap("vtol", false); pMapManager->EnableFilter ( "vehicle_no_seat_change_and_exit", true ); }
//------------------------------------------------------------------------ bool CVehicleActionDeployRope::DeployRope() { IActorSystem* pActorSystem = gEnv->pGame->GetIGameFramework()->GetIActorSystem(); assert(pActorSystem); IActor* pActor = pActorSystem->GetActor(m_actorId); if (!pActor) return false; Vec3 upperPos = m_pRopeHelper->GetWorldTM().GetTranslation(); Vec3 lowerPos(upperPos.x, upperPos.y, upperPos.z - g_ropeLenght); m_ropeUpperId = CreateRope(m_pVehicle->GetEntity()->GetPhysics(), upperPos, upperPos); m_ropeLowerId = CreateRope(pActor->GetEntity()->GetPhysics(), upperPos, lowerPos); m_pVehicle->SetObjectUpdate(this, IVehicle::eVOU_AlwaysUpdate); return true; }
void CLocalPlayerComponent::Revive() { if(gEnv->bMultiplayer) { // Reset NotYetSpawned filter. IActionFilter* pNYSFilter = g_pGameActions->FilterNotYetSpawned(); if(pNYSFilter && pNYSFilter->Enabled()) { pNYSFilter->Enable(false); } // For Modes where we can swap teams per round, refresh everyone else's cloak colour on revive. CGameRules *pGameRules = g_pGame->GetGameRules(); if( pGameRules->GetGameMode()==eGM_Gladiator ) { IActorSystem* pActorSys = g_pGame->GetIGameFramework()->GetIActorSystem(); CActorManager* pActorManager = CActorManager::GetActorManager(); pActorManager->PrepareForIteration(); const int kNumActors = pActorManager->GetNumActors(); for(int i=0; i<kNumActors; i++) { SActorData actorData; pActorManager->GetNthActorData(i, actorData); if(CActor* pActor = static_cast<CActor*>(pActorSys->GetActor(actorData.entityId))) { if(pActor->IsCloaked()) { pActor->SetCloakLayer(false); pActor->SetCloakLayer(true); } } } } } m_bIsInFreeFallDeath = false; m_playedMidHealthSound = false; }
void CCheckpointSystem::WriteActorData(XmlNodeRef parentNode) { XmlNodeRef node = GetISystem()->CreateXmlNode(ACTOR_FLAGS_SECTION); //write only data for non-active or hidden actors XmlNodeRef activatedActors = GetISystem()->CreateXmlNode(ACTIVATED_ACTORS_SECTION); char buffer[100]; IActorSystem *pActorSystem = CCryAction::GetCryAction()->GetIActorSystem(); IActorIteratorPtr it = pActorSystem->CreateActorIterator(); while (IActor *pActor = it->Next()) { IEntity *pEntity = pActor->GetEntity(); if(!pEntity->IsHidden() && pEntity->IsActive()) { EntityId id = pEntity->GetId(); const char *name = pEntity->GetName(); //we have to rely on names, since Id's change on level reexport _snprintf(buffer, sizeof(buffer), "%s%i", "id", id); activatedActors->setAttr(buffer, name); } } node->addChild(activatedActors); parentNode->addChild(node); }
//------------------------------------------------------------------------ void CVehicleSeatActionMovement::StartUsing(EntityId passengerId) { IActorSystem* pActorSystem = CCryAction::GetCryAction()->GetIActorSystem(); CRY_ASSERT(pActorSystem); IActor* pActor = pActorSystem->GetActor(passengerId); CRY_ASSERT(pActor); IVehicleMovement* pMovement = m_pVehicle->GetMovement(); CRY_ASSERT(pMovement); if (!pMovement) return; if (m_delayedStop >= 0.0f) { m_pVehicle->SetObjectUpdate(this, IVehicle::eVOU_NoUpdate); m_delayedStop = 0.0f; pMovement->StopDriving(); } pMovement->StartDriving(passengerId); }
//------------------------------------------------------------------------ void CVehicleViewFirstPerson::HideEntitySlots(IEntity* pEnt, bool hide) { IActorSystem* pActorSystem = CCryAction::GetCryAction()->GetIActorSystem(); CRY_ASSERT(pActorSystem); if (hide) { for (int i=0; i<pEnt->GetSlotCount(); ++i) { if (pEnt->IsSlotValid(i) && pEnt->GetSlotFlags(i) & ENTITY_SLOT_RENDER) { if (pEnt->GetId() == m_pVehicle->GetEntity()->GetId()) { // set character to always update if (ICharacterInstance* pCharInstance = pEnt->GetCharacter(i)) { pCharInstance->SetFlags(pCharInstance->GetFlags() | CS_FLAG_UPDATE_ALWAYS); if (ISkeletonPose* pSkeletonPose = pCharInstance->GetISkeletonPose()) pSkeletonPose->SetForceSkeletonUpdate(10); } } pEnt->SetSlotFlags(i, pEnt->GetSlotFlags(i) & ~ENTITY_SLOT_RENDER); if (IActor* pActor = pActorSystem->GetActor(pEnt->GetId())) { pActor->HideAllAttachments(true); } // store slot; we must not reveal previously hidden slots later m_slotFlags.insert( std::pair<EntityId,int>(pEnt->GetId(), i) ); } } // hide all children for (int i=0; i<pEnt->GetChildCount(); ++i) HideEntitySlots(pEnt->GetChild(i), hide); } else { // unhide all stored slots for (TSlots::iterator it=m_slotFlags.begin(); it!=m_slotFlags.end(); ++it) { IEntity* pEntity = gEnv->pEntitySystem->GetEntity(it->first); if (pEntity && pEntity->IsSlotValid(it->second)) { pEntity->SetSlotFlags(it->second, pEntity->GetSlotFlags(it->second)|(ENTITY_SLOT_RENDER)); if (IActor* pActor = pActorSystem->GetActor(pEnt->GetId())) { pActor->HideAllAttachments(false); } if (pEntity->GetId() == m_pVehicle->GetEntity()->GetId()) { // reset character flags if (ICharacterInstance* pCharInstance = pEntity->GetCharacter(it->second)) { pCharInstance->SetFlags(pCharInstance->GetFlags() & ~CS_FLAG_UPDATE_ALWAYS); if (ISkeletonPose* pSkeletonPose = pCharInstance->GetISkeletonPose()) pSkeletonPose->SetForceSkeletonUpdate(0); } } } } m_slotFlags.clear(); } }
//------------------------------------------------------------------------ bool CGameRules::OnPromoteToServer(SHostMigrationInfo& hostMigrationInfo, uint32& state) { if (!g_pGame->GetIGameFramework()->ShouldMigrateNub(hostMigrationInfo.m_session)) { return true; } CryLogAlways("[Host Migration]: CGameRules::OnPromoteToServer() started"); // Server time will change after we migrate (change from old server time to new server time) m_gameStartedTime.SetValue(m_gameStartedTime.GetValue() - m_cachedServerTime.GetValue()); m_gameStartTime.SetValue(m_gameStartTime.GetValue() - m_cachedServerTime.GetValue()); // If this migration has reset (we're not the original anticipated host, remove any entities from the first attempt if (!m_hostMigrationCachedEntities.empty()) { HostMigrationRemoveDuplicateDynamicEntities(); } // Now we know we're the server, remove the actors for anyone we know isn't going to migrate CGameLobby *pGameLobby = g_pGame->GetGameLobby(); CRY_ASSERT(pGameLobby); if (pGameLobby) { TPlayers playersToRemove; IActorSystem *pActorSystem = g_pGame->GetIGameFramework()->GetIActorSystem(); playersToRemove.reserve(pActorSystem->GetActorCount()); IActorIteratorPtr actorIt = pActorSystem->CreateActorIterator(); IActor *pActor; while (pActor = actorIt->Next()) { if (pActor->IsPlayer()) { CRY_ASSERT(pActor->GetChannelId()); SCryMatchMakingConnectionUID conId = pGameLobby->GetConnectionUIDFromChannelID((int) pActor->GetChannelId()); if (pGameLobby->GetSessionNames().Find(conId) == SSessionNames::k_unableToFind) { CryLog(" player '%s' has not got a corresponding CGameLobby entry, removing actor", pActor->GetEntity()->GetName()); playersToRemove.push_back(pActor->GetEntityId()); } } } const int numPlayersToRemove = playersToRemove.size(); for (int i = 0; i < numPlayersToRemove; ++ i) { FakeDisconnectPlayer(playersToRemove[i]); } } for (uint32 i = 0; i < MAX_PLAYERS; ++ i) { m_migratedPlayerChannels[i] = 0; } IItemSystem *pItemSystem = g_pGame->GetIGameFramework()->GetIItemSystem(); IEntityItPtr it = gEnv->pEntitySystem->GetEntityIterator(); it->MoveFirst(); for (uint32 i = 0; i < m_hostMigrationItemMaxCount; ++ i) { m_pHostMigrationItemInfo[i].Reset(); } uint32 itemIndex = 0; IEntity *pEntity = NULL; while (pEntity = it->Next()) { IItem *pItem = pItemSystem->GetItem(pEntity->GetId()); if (pItem) { if (pItem->GetOwnerId()) { IEntity *pOwner = gEnv->pEntitySystem->GetEntity(pItem->GetOwnerId()); if (pOwner) { EntityId currentItemId = 0; IActor *pOwnerActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pOwner->GetId()); if (pOwnerActor) { IItem *pCurrentItem = pOwnerActor->GetCurrentItem(); currentItemId = pCurrentItem ? pCurrentItem->GetEntityId() : 0; } CryLog("[CG] Item '%s' is owned by '%s'", pEntity->GetName(), pOwner->GetName()); //m_pHostMigrationItemInfo[itemIndex].Set(pEntity->GetId(), pOwner->GetId(), pItem->IsUsed(), (pItem->GetEntityId() == currentItemId)); itemIndex ++; if (itemIndex >= m_hostMigrationItemMaxCount) { CRY_ASSERT(itemIndex < m_hostMigrationItemMaxCount); break; } } } } // Tell entities that we're host migrating // - Currently only used by ForbiddenArea but may well be needed for other entities later // - Currently only called on the new server, add to OnDemoteToClient if we need to use this on a client IScriptTable *pScript = pEntity->GetScriptTable(); if (pScript != NULL && pScript->GetValueType("OnHostMigration") == svtFunction) { m_pScriptSystem->BeginCall(pScript, "OnHostMigration"); m_pScriptSystem->PushFuncParam(pScript); m_pScriptSystem->PushFuncParam(true); m_pScriptSystem->EndCall(); } } // This needs initialising on the new server otherwise the respawn timer will be counting down // from uninitialised data. Likewise for the pre-round timer. ResetReviveCycleTime(); const int numRespawnParams = m_respawndata.size(); for (int i = 0; i < numRespawnParams; ++ i) { SEntityRespawnData *pData = &m_respawndata[i]; pEntity = gEnv->pEntitySystem->GetEntity(pData->m_currentEntityId); if (pEntity == NULL) { CryLog(" detected respawn entity (id=%u) is not present, scheduling for respawn", pData->m_currentEntityId); ScheduleEntityRespawn(pData->m_currentEntityId, false, g_pGameCVars->g_defaultItemRespawnTimer); } } CryLog("[Host Migration]: CGameRules::OnPromoteToServer() finished"); CCCPOINT(HostMigration_OnPromoteToServer); return true; }
//------------------------------------------------------------------------ void CVehicleMovementVTOL::Update(const float deltaTime) { FUNCTION_PROFILER( GetISystem(), PROFILE_GAME ); CVehicleMovementHelicopter::Update(deltaTime); CryAutoCriticalSection lk(m_lock); if (m_pWingsAnimation) { m_pWingsAnimation->SetTime(m_wingsAnimTime); } IActorSystem* pActorSystem = g_pGame->GetIGameFramework()->GetIActorSystem(); assert(pActorSystem); IActor* pActor = pActorSystem->GetActor(m_actorId); if (pActor && pActor->IsClient()) { float turbulence = m_turbulence; if (m_pAltitudeLimitVar) { float altitudeLimit = m_pAltitudeLimitVar->GetFVal(); float currentHeight = m_pEntity->GetWorldPos().z; if (!iszero(altitudeLimit)) { float altitudeLowerOffset; if (m_pAltitudeLimitLowerOffsetVar) { float r = 1.0f - min(1.0f, max(0.0f, m_pAltitudeLimitLowerOffsetVar->GetFVal())); altitudeLowerOffset = r * altitudeLimit; if (currentHeight >= altitudeLowerOffset) { if (currentHeight > altitudeLowerOffset) { float zone = altitudeLimit - altitudeLowerOffset; turbulence += (currentHeight - altitudeLowerOffset) / (zone); } } } } } if (turbulence > 0.0f) { static_cast<CActor*>(pActor)->CameraShake(0.50f * turbulence, 0.0f, 0.05f, 0.04f, Vec3(0.0f, 0.0f, 0.0f), 10, "VTOL_Update_Turbulence"); } float enginePowerRatio = m_enginePower / m_enginePowerMax; if (enginePowerRatio > 0.0f) { float rpmScaleDesired = 0.2f; rpmScaleDesired += abs(m_forwardAction) * 0.8f; rpmScaleDesired += abs(m_strafeAction) * 0.4f; rpmScaleDesired += abs(m_turnAction) * 0.25f; rpmScaleDesired = min(1.0f, rpmScaleDesired); Interpolate(m_rpmScale, rpmScaleDesired, 1.0f, deltaTime); } float turnParamGoal = min(1.0f, abs(m_turnAction)) * 0.6f; turnParamGoal *= (min(1.0f, max(0.0f, m_speedRatio)) + 1.0f) * 0.50f; turnParamGoal += turnParamGoal * m_boost * 0.25f; Interpolate(m_soundParamTurn, turnParamGoal, 0.5f, deltaTime); SetSoundParam(eSID_Run, "turn", m_soundParamTurn); float damage = GetSoundDamage(); if (damage > 0.1f) { //if (ISound* pSound = GetOrPlaySound(eSID_Damage, 5.f, m_enginePos)) //SetSoundParam(pSound, "damage", damage); } } }
//------------------------------------------------------------------------ void CGameRulesMPDamageHandling::SvOnExplosion(const ExplosionInfo &explosionInfo, const CGameRules::TExplosionAffectedEntities& affectedEntities) { // SinglePlayer.lua 1721 IActorSystem* pActorSystem = g_pGame->GetIGameFramework()->GetIActorSystem(); float totalDamage = 0.f; // calculate damage for each entity CGameRules::TExplosionAffectedEntities::const_iterator it = affectedEntities.begin(); for (; it != affectedEntities.end(); ++it) { bool success = false; IEntity* entity = it->first; float obstruction = 1.0f - it->second; bool incone=true; if (explosionInfo.angle > 0 && explosionInfo.angle < 2*3.1415f) { Vec3 explosionEntityPos = entity->GetWorldPos(); Vec3 entitypos = explosionEntityPos; float ha = explosionInfo.angle * 0.5f; Vec3 edir = entitypos - explosionInfo.pos; edir.normalize(); float dot = 1; if (edir != Vec3(ZERO)) { dot = edir.dot(explosionInfo.dir); } float angle = abs(acos_tpl(dot)); if (angle > ha) { incone = false; } } if (incone && gEnv->bServer) { float damage = explosionInfo.damage; damage = floor_tpl(0.5f + CalcExplosionDamage(entity, explosionInfo, obstruction)); bool dead = false; HitInfo explHit; Vec3 dir = entity->GetWorldPos() - explosionInfo.pos; explHit.pos = explosionInfo.pos; explHit.radius = explosionInfo.radius; explHit.partId = -1; dir.Normalize(); explHit.targetId = entity->GetId(); explHit.weaponId = explosionInfo.weaponId; explHit.shooterId = explosionInfo.shooterId; explHit.projectileId = explosionInfo.projectileId; explHit.projectileClassId = explosionInfo.projectileClassId; uint16 weaponClass = ~uint16(0); const IEntity* pWeaponEntity = gEnv->pEntitySystem->GetEntity(explosionInfo.weaponId); if (pWeaponEntity) { g_pGame->GetIGameFramework()->GetNetworkSafeClassId(weaponClass, pWeaponEntity->GetClass()->GetName()); } explHit.weaponClassId = weaponClass; explHit.material = 0; explHit.damage = damage; explHit.type = explosionInfo.type; explHit.hitViaProxy = explosionInfo.explosionViaProxy; explHit.dir = dir; explHit.normal = -dir; //set normal to reverse of direction to avoid backface cull of damage if (explHit.damage > 0.0f || explosionInfo.damage == 0.f) { CActor* pActor = static_cast<CActor*>(pActorSystem->GetActor(entity->GetId())); if (pActor) { const float damageMultiplier = pActor->GetBodyExplosionDamageMultiplier(explHit); explHit.damage *= damageMultiplier; // Protect players who are currently shielded if(pActor->IsPlayer() && static_cast<CPlayer*>(pActor)->ShouldFilterOutExplosion(explHit)) { explHit.damage = 0.0f; } } else { CInteractiveObjectEx* pInteractiveObject = static_cast<CInteractiveObjectEx*>(g_pGame->GetIGameFramework()->QueryGameObjectExtension(entity->GetId(), "InteractiveObjectEx")); if(pInteractiveObject) { pInteractiveObject->OnExploded(explHit.pos); } } if(!explosionInfo.explosionViaProxy) { if(pActor) { if(!pActor->IsFriendlyEntity(explHit.shooterId)) { totalDamage += damage; } } else { IVehicle* pVehicle = g_pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(entity->GetId()); if(pVehicle) { IActor* pDriver = pVehicle->GetDriver(); int seatNum = 0; int numSeats = pVehicle->GetSeatCount(); while(!pDriver && seatNum < numSeats) { IVehicleSeat* pSeat = pVehicle->GetSeatById(seatNum++); EntityId passengerId = pSeat ? pSeat->GetPassenger(true) : 0; pDriver = pActorSystem->GetActor(passengerId); } if(pDriver) { CActor* pDriverActor = static_cast<CActor*>(pDriver); if(!pDriverActor->IsFriendlyEntity(explHit.shooterId)) { totalDamage += damage; } } } } } m_pGameRules->ServerHit(explHit); } } } if (totalDamage > 0.f) { IGameRulesPlayerStatsModule* pPlayStatsMod = m_pGameRules->GetPlayerStatsModule(); if(pPlayStatsMod) { pPlayStatsMod->ProcessSuccessfulExplosion(explosionInfo.shooterId, totalDamage, explosionInfo.projectileClassId); } } }
//------------------------------------------------------------------------ // 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 CGameRulesMPDamageHandling::SvOnCollision(const IEntity *pVictimEntity, const CGameRules::SCollisionHitInfo& collisionHitInfo) { FUNCTION_PROFILER(gEnv->pSystem, PROFILE_GAME); CRY_ASSERT(gEnv->bMultiplayer); #if !defined(_RELEASE) if (g_pGameCVars->g_DisableCollisionDamage) return; #endif IGameFramework* gameFramwork = g_pGame->GetIGameFramework(); EntityId victimID = pVictimEntity->GetId(); EntityId offenderID = collisionHitInfo.targetId; const IEntity* pOffenderEntity = gEnv->pEntitySystem->GetEntity(offenderID); float currentTime = gEnv->pTimer->GetCurrTime(); CActor* victimActor = static_cast<CActor*>(gameFramwork->GetIActorSystem()->GetActor(victimID)); IVehicle* offenderVehicle = gameFramwork->GetIVehicleSystem()->GetVehicle(offenderID); IVehicle* victimVehicle = gameFramwork->GetIVehicleSystem()->GetVehicle(victimID); IActor* offenderActor = gameFramwork->GetIActorSystem()->GetActor(offenderID); if(pOffenderEntity && !offenderVehicle && !offenderActor) { if( IEntity* pParent = pOffenderEntity->GetParent() ) { offenderVehicle = gameFramwork->GetIVehicleSystem()->GetVehicle(pParent->GetId()); } } // Vehicles being flipped do no damage, for now if (offenderVehicle != NULL && offenderVehicle->GetStatus().beingFlipped) return; // Players can't damage vehicles if (victimVehicle && offenderActor) return; // Filter frequent collisions if (pOffenderEntity) { FRAME_PROFILER("Filter out recent collisions", gEnv->pSystem, PROFILE_GAME); EntityCollisionRecords::const_iterator collisionRecordIter = m_entityCollisionRecords.find(victimID); if (collisionRecordIter != m_entityCollisionRecords.end()) { const EntityCollisionRecord& record = collisionRecordIter->second; if (record.entityID == offenderID && record.time + EntityCollisionIgnoreTimeBetweenCollisions > currentTime) { return; } } } float offenderMass = collisionHitInfo.target_mass; enum { CollisionWithEntity, CollisionWithStaticWorld } collisionType = (pOffenderEntity || offenderMass > 0.0f) ? CollisionWithEntity : CollisionWithStaticWorld; const Vec3& victimVelocity = collisionHitInfo.velocity; const Vec3& offenderVelocity = collisionHitInfo.target_velocity; float relativeSpeedSq = 0.0f; float minSpeedToCareAboutCollisionSq = 0.0f; float contactMass = 0.0f; bool offenderIsBig = offenderMass > 1000.f; switch (collisionType) { case CollisionWithEntity: { Vec3 relativeVelocity = victimVelocity - offenderVelocity; relativeSpeedSq = relativeVelocity.GetLengthSquared(); minSpeedToCareAboutCollisionSq = sqr(10.0f); if (victimActor && offenderIsBig) { minSpeedToCareAboutCollisionSq = sqr(1.0f); } if (victimActor && offenderVehicle) { //Players won't be hurt by vehicles with a negative kill player speed if(offenderVehicle->GetDamageParams().aiKillPlayerSpeed < 0.f) { return; } minSpeedToCareAboutCollisionSq = sqr(2.0f); } const float offenderSpeedSq = offenderVelocity.GetLengthSquared(); if (offenderSpeedSq == 0.0f) // -- if collision target it not moving { minSpeedToCareAboutCollisionSq *= sqr(2.0f); } ////////////////////////////////////////////////////////////////////////// contactMass = offenderMass; break; } case CollisionWithStaticWorld: { // Actors don't take damage from running into walls! if (victimActor) { return; } relativeSpeedSq = victimVelocity.GetLengthSquared(); minSpeedToCareAboutCollisionSq = sqr(7.5f); contactMass = collisionHitInfo.mass; break; } } const bool contactMassIsTooLowToCare = contactMass < 0.01f; if (contactMassIsTooLowToCare) return; ////////////////////////////////////////////////////////////////////////// // Calculate the collision damage if (relativeSpeedSq >= minSpeedToCareAboutCollisionSq) { bool useDefaultCalculation = true; float fEnergy = 0.f; float damage = 0.f; EntityId kickerId = 0; // Calculate damage if (offenderVehicle && victimActor) { useDefaultCalculation = false; damage = ProcessActorVehicleCollision(victimActor, victimID, offenderVehicle, offenderID, damage, collisionHitInfo, kickerId); } else if (offenderIsBig && victimActor) // i.e. a kickable car { // Try to find the kicker CTimeValue time = gEnv->pTimer->GetAsyncTime(); IActorSystem* pActorSystem = gEnv->pGame->GetIGameFramework()->GetIActorSystem(); IActorIteratorPtr pActorIterator = pActorSystem->CreateActorIterator(); IActor* pActor = pActorIterator->Next(); float lowestTime = 5.f; while (pActor != NULL) { CPlayer* pPlayer = static_cast<CPlayer*>(pActor); EntityId kicked = pPlayer->GetLargeObjectInteraction().GetLastObjectId(); if (kicked==offenderID) { float timeSinceKick = (time - pPlayer->GetLargeObjectInteraction().GetLastObjectTime()).GetSeconds(); if (timeSinceKick < lowestTime) { // We found the kicker and the kicked kickerId = pActor->GetEntityId(); lowestTime = timeSinceKick; } } pActor = pActorIterator->Next(); } damage = ProcessActorKickedVehicle(victimActor, victimID, kickerId, offenderID, damage, collisionHitInfo); useDefaultCalculation = false; } if (useDefaultCalculation) { fEnergy = GetCollisionEnergy(pVictimEntity, collisionHitInfo); if (victimVehicle || offenderIsBig) { damage = 0.0005f * fEnergy; } else { damage = 0.0025f * fEnergy; } // Apply damage multipliers damage *= GetCollisionDamageMult(pVictimEntity, pOffenderEntity, collisionHitInfo); if (victimActor) { const bool victimIsPlayer = victimActor->IsPlayer(); if (victimIsPlayer) { damage = AdjustPlayerCollisionDamage(pVictimEntity, pOffenderEntity, collisionHitInfo, damage); } } } if (damage >= DAMAGE_THRESHOLD_COLLISIONS) { HitInfo hit; hit.damage = damage; hit.pos = collisionHitInfo.pos; if (collisionHitInfo.target_velocity.GetLengthSquared() > 1e-6) hit.dir = collisionHitInfo.target_velocity.GetNormalized(); hit.radius = 0.0f; hit.partId = collisionHitInfo.partId; hit.targetId = victimID; hit.weaponId = offenderID; hit.shooterId = kickerId != 0 ? kickerId : offenderID; hit.material = 0; hit.type = CGameRules::EHitType::Collision; hit.explosion = false; CGameRules *pGameRules = g_pGame->GetGameRules(); if (pGameRules->GetTeamCount() > 1) { int shooterTeamId = pGameRules->GetTeam(hit.shooterId); int targetTeamId = pGameRules->GetTeam(hit.targetId); if (shooterTeamId && (shooterTeamId == targetTeamId)) { damage = GetFriendlyFireDamage(damage, hit, victimActor); } } if (damage >= DAMAGE_THRESHOLD_COLLISIONS) { IScriptTable* pVictimScript = pVictimEntity ? pVictimEntity->GetScriptTable() : NULL; IScriptTable* pOffenderScript = pOffenderEntity ? pOffenderEntity->GetScriptTable() : NULL; if (!pOffenderEntity && pVictimEntity) { pOffenderEntity = pVictimEntity; offenderID = victimID; } m_entityCollisionRecords[victimID] = EntityCollisionRecord(offenderID, currentTime); if(victimVehicle) { victimVehicle->OnHit(hit); } else if (pVictimScript) { FRAME_PROFILER("Call to OnHit", gEnv->pSystem, PROFILE_GAME); if (!IsDead(victimActor, pVictimScript)) { if (IActor* offenderDriver = offenderVehicle ? offenderVehicle->GetDriver() : NULL) hit.shooterId = offenderDriver->GetEntityId(); DelegateServerHit(pVictimScript, hit, victimActor); } } } } } }
// //----------------------------------------------------------------------------------------------------------- // (MATT) Moved here from Scriptbind_AI when that was moved to the AI system {2008/02/15:15:23:16} int CScriptBind_Action::RegisterWithAI(IFunctionHandler *pH) { if (gEnv->bMultiplayer && !gEnv->bServer) return pH->EndFunction(); int type; ScriptHandle hdl; if (!pH->GetParams(hdl, type)) return pH->EndFunction(); EntityId entityID = (EntityId)hdl.n; IEntity *pEntity = gEnv->pEntitySystem->GetEntity(entityID); if(!pEntity) { GameWarning("RegisterWithAI: Tried to set register with AI nonExisting entity with id [%d]. ", entityID); return pH->EndFunction(); } // Apparently we can't assume that there is just one IGameObject to an entity, because we choose between (at least) Actor and Vehicle objects. // (MATT) Do we really need to check on the actor system here? {2008/02/15:18:38:34} IGameFramework *pGameFramework = gEnv->pGame->GetIGameFramework(); IVehicleSystem* pVSystem = pGameFramework->GetIVehicleSystem(); IActorSystem* pASystem = pGameFramework->GetIActorSystem(); if(!pASystem) { GameWarning("RegisterWithAI: no ActorSystem for %s.", pEntity->GetName()); return pH->EndFunction(); } AIObjectParams params(type, 0, entityID); bool autoDisable(true); // For most types, we need to parse the tables // For others we leave them blank switch (type) { case AIOBJECT_ACTOR: case AIOBJECT_2D_FLY: case AIOBJECT_BOAT: case AIOBJECT_CAR: case AIOBJECT_HELICOPTER: case AIOBJECT_INFECTED: case AIOBJECT_ALIENTICK: case AIOBJECT_HELICOPTERCRYSIS2: if(gEnv->pAISystem && ! gEnv->pAISystem->ParseTables(3, true, pH, params, autoDisable)) return pH->EndFunction(); default:; } // Most types check these, so just get them in advance IActor* pActor = pASystem->GetActor( pEntity->GetId() ); IVehicle* pVehicle = NULL; if( pVSystem ) pVehicle = pVSystem->GetVehicle( pEntity->GetId() ); // Set this if we've found something to create a proxy from IGameObject* pGameObject = NULL; switch(type) { case AIOBJECT_ACTOR: case AIOBJECT_2D_FLY: case AIOBJECT_INFECTED: case AIOBJECT_ALIENTICK: { // (MATT) The pActor/pVehicle test below - is it basically trying to distiguish between the two cases above? If so, separate them! {2008/02/15:19:38:08} if(!pActor) { GameWarning("RegisterWithAI: no Actor for %s.", pEntity->GetName()); return pH->EndFunction(); } pGameObject = pActor->GetGameObject(); } break; case AIOBJECT_BOAT: case AIOBJECT_CAR: { if(!pVehicle) { GameWarning("RegisterWithAI: no Vehicle for %s (Id %i).", pEntity->GetName(), pEntity->GetId()); return pH->EndFunction(); } pGameObject = pVehicle->GetGameObject(); } break; case AIOBJECT_HELICOPTER: case AIOBJECT_HELICOPTERCRYSIS2: { if(!pVehicle) { GameWarning("RegisterWithAI: no Vehicle for %s (Id %i).", pEntity->GetName(), pEntity->GetId()); return pH->EndFunction(); } pGameObject = pVehicle->GetGameObject(); params.m_moveAbility.b3DMove = true; } break; case AIOBJECT_PLAYER: { if(IsDemoPlayback()) return pH->EndFunction(); SmartScriptTable pTable; if (pH->GetParamCount() > 2) pH->GetParam(3,pTable); else return pH->EndFunction(); pGameObject = pActor->GetGameObject(); pTable->GetValue("groupid",params.m_sParamStruct.m_nGroup); const char* faction = 0; if (pTable->GetValue("esFaction", faction) && gEnv->pAISystem) { params.m_sParamStruct.factionID = gEnv->pAISystem->GetFactionMap().GetFactionID(faction); if (faction && *faction && (params.m_sParamStruct.factionID == IFactionMap::InvalidFactionID)) { GameWarning("Unknown faction '%s' being set...", faction); } } else { // Márcio: backwards compatibility int species = -1; if (!pTable->GetValue("eiSpecies", species)) pTable->GetValue("species", species); if (species > -1) params.m_sParamStruct.factionID = species; } pTable->GetValue("commrange",params.m_sParamStruct.m_fCommRange); //Luciano - added to use GROUPONLY signals SmartScriptTable pPerceptionTable; if(pTable->GetValue("Perception",pPerceptionTable)) { pPerceptionTable->GetValue( "sightrange", params.m_sParamStruct.m_PerceptionParams.sightRange); } } break; case AIOBJECT_SNDSUPRESSOR: { // (MATT) This doesn't need a proxy? {2008/02/15:19:45:58} SmartScriptTable pTable; // Properties table if (pH->GetParamCount() > 2) pH->GetParam(3,pTable); else return pH->EndFunction(); if (!pTable->GetValue("radius",params.m_moveAbility.pathRadius)) params.m_moveAbility.pathRadius = 10.f; break; } case AIOBJECT_WAYPOINT: break; /* // this block is commented out since params.m_sParamStruct is currently ignored in pEntity->RegisterInAISystem() // instead of setting the group id here, it will be set from the script right after registering default: // try to get groupid settings for anchors params.m_sParamStruct.m_nGroup = -1; params.m_sParamStruct.m_nSpecies = -1; { SmartScriptTable pTable; if ( pH->GetParamCount() > 2 ) pH->GetParam( 3, pTable ); if ( *pTable ) pTable->GetValue( "groupid", params.m_sParamStruct.m_nGroup ); } break; */ } // Remove any existing AI object pEntity->RegisterInAISystem(AIObjectParams(0)); // Register in AI to get a new AI object, deregistering the old one in the process pEntity->RegisterInAISystem(params); // (MATT) ? {2008/02/15:19:46:29} // AI object was not created (possibly AI System is disabled) if (IAIObject* aiObject = pEntity->GetAI()) { if(type==AIOBJECT_SNDSUPRESSOR) aiObject->SetRadius(params.m_moveAbility.pathRadius); else if(type>=AIANCHOR_FIRST) // if anchor - set radius { SmartScriptTable pTable; // Properties table if (pH->GetParamCount() > 2) pH->GetParam(3,pTable); else return pH->EndFunction(); float radius(0.f); pTable->GetValue("radius",radius); int groupId = -1; pTable->GetValue("groupid", groupId); aiObject->SetGroupId(groupId); aiObject->SetRadius(radius); } if (IAIActorProxy* proxy = aiObject->GetProxy()) proxy->UpdateMeAlways(!autoDisable); } return pH->EndFunction(); }
////////////////////////////////////////////////////////////////////////// //this respawns the active AI at their spawn locations void CCheckpointSystem::RespawnAI(XmlNodeRef data) { if(!data) return; XmlNodeRef actorData = data->findChild(ACTOR_FLAGS_SECTION); if(!actorData) { CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Failed reading actor data from checkpoint, actors won't be respawned"); return; } IActorSystem *pActorSystem = CCryAction::GetCryAction()->GetIActorSystem(); //first run through all actors and hide/deactivate them IActorIteratorPtr it = pActorSystem->CreateActorIterator(); while (IActor *pActor = it->Next()) { IEntity *pEntity = pActor->GetEntity(); //deactivate all actors pEntity->Hide(true); pEntity->Activate(false); } //load actorflags for active actors XmlNodeRef activatedActors = actorData->findChild(ACTIVATED_ACTORS_SECTION); if(activatedActors) { int actorFlags = activatedActors->getNumAttributes(); const char *key; const char *value; for(int i = 0; i < actorFlags; ++i) { activatedActors->getAttributeByIndex(i, &key, &value); //format is "idXXX" CRY_ASSERT(strlen(key)>2); EntityId id = (EntityId)(atoi(&key[2])); bool foundEntity = RepairEntityId(id, value); if(foundEntity) { IActor* pActor = pActorSystem->GetActor(id); if(pActor) { pActor->GetEntity()->Hide(false); pActor->GetEntity()->Activate(true); } else CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Failed finding actor %i from checkpoint.", (int)id); } else CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Failed finding actor %s from checkpoint, actor is not setup correctly.", value); } } else CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Deactivated actors section was missing in checkpoint."); it = pActorSystem->CreateActorIterator(); //iterate all actors and respawn if active while (IActor *pActor = it->Next()) { IEntity *pEntity = pActor->GetEntity(); if(pEntity->GetId() == LOCAL_PLAYER_ENTITY_ID) //don't respawn player continue; //we don't respawn deactivated actors if(!pEntity->IsHidden() && pEntity->IsActive()) { pActor->SetHealth(0); pActor->Respawn(); } else //but we still reset their position { pActor->ResetToSpawnLocation(); } } }
//------------------------------------------------------------------------ void CDebugGun::Update( SEntityUpdateContext& ctx, int update) { if (!IsSelected()) return; static float drawColor[4] = {1,1,1,1}; static const int dx = 5; static const int dy = 15; static const float font = 1.2f; static const float fontLarge = 1.4f; IRenderer* pRenderer = gEnv->pRenderer; IRenderAuxGeom* pAuxGeom = pRenderer->GetIRenderAuxGeom(); pAuxGeom->SetRenderFlags(e_Def3DPublicRenderflags); pRenderer->Draw2dLabel(pRenderer->GetWidth()/5.f, pRenderer->GetHeight()-35, fontLarge, drawColor, false, "Firemode: %s (%.1f)", m_fireModes[m_fireMode].first.c_str(), m_fireModes[m_fireMode].second); ray_hit rayhit; int hits = 0; unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any; if (m_fireModes[m_fireMode].first == "pierceability") { flags = (unsigned int)m_fireModes[m_fireMode].second & rwi_pierceability_mask; } // use cam, no need for firing pos/dir CCamera& cam = GetISystem()->GetViewCamera(); if (hits = gEnv->pPhysicalWorld->RayWorldIntersection(cam.GetPosition()+cam.GetViewdir(), cam.GetViewdir()*HIT_RANGE, ent_all, flags, &rayhit, 1)) { IMaterialManager* pMatMan = gEnv->p3DEngine->GetMaterialManager(); IActorSystem* pActorSystem = g_pGame->GetIGameFramework()->GetIActorSystem(); IVehicleSystem* pVehicleSystem = g_pGame->GetIGameFramework()->GetIVehicleSystem(); int x = (int)(pRenderer->GetWidth() *0.5f) + dx; int y = (int)(pRenderer->GetHeight()*0.5f) + dx - dy; // draw normal ColorB colNormal(200,0,0,128); Vec3 end = rayhit.pt + 0.75f*rayhit.n; pAuxGeom->DrawLine(rayhit.pt, colNormal, end, colNormal); pAuxGeom->DrawCone(end, rayhit.n, 0.1f, 0.2f, colNormal); IEntity * pEntity = (IEntity*)rayhit.pCollider->GetForeignData(PHYS_FOREIGN_ID_ENTITY); if(pEntity) { pRenderer->Draw2dLabel(x, y+=dy, fontLarge, drawColor, false, pEntity->GetName()); } // material const char* matName = pMatMan->GetSurfaceType(rayhit.surface_idx)->GetName(); if (matName[0]) pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%s (%i)", matName, rayhit.surface_idx); pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%.1f m", rayhit.dist); if (pEntity) { IScriptTable* pScriptTable = pEntity->GetScriptTable(); // physics if (IPhysicalEntity* pPhysEnt = pEntity->GetPhysics()) { pe_status_dynamics status; if (pPhysEnt->GetStatus(&status)) { if (status.mass > 0.f) pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%.1f kg", status.mass); pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "pe_type: %i", pPhysEnt->GetType()); if (status.submergedFraction > 0.f) pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%.2f submerged", status.submergedFraction); if (status.v.len2() > 0.0001f) pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%.2f m/s", status.v.len()); } } if (pScriptTable) { HSCRIPTFUNCTION func = 0; if (pScriptTable->GetValue("GetFrozenAmount", func) && func) { float frozen = 0.f; Script::CallReturn(gEnv->pScriptSystem, func, pScriptTable, frozen); gEnv->pScriptSystem->ReleaseFunc(func); if (frozen > 0.f) pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "Frozen: %.2f", frozen); } } // class-specific stuff if (IActor* pActor = pActorSystem->GetActor(pEntity->GetId())) { pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%i health", pActor->GetHealth()); } else if (IVehicle* pVehicle = pVehicleSystem->GetVehicle(pEntity->GetId())) { const SVehicleStatus& status = pVehicle->GetStatus(); pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%.0f%% health", 100.f*status.health); pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%i passengers", status.passengerCount); if (pVehicle->GetMovement() && pVehicle->GetMovement()->IsPowered()) { pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "Running"); } } else { if (pScriptTable) { HSCRIPTFUNCTION func = 0; if (pScriptTable->GetValue("GetHealth", func) && func) { float health = 0.f; if (Script::CallReturn(gEnv->pScriptSystem, func, pScriptTable, health)) { pRenderer->Draw2dLabel(x, y+=dy, font, drawColor, false, "%.0f health", health); } gEnv->pScriptSystem->ReleaseFunc(func); } } } } } }