///////////////////////////////////////////////////////////////////////////////// // // FILE : AnimatedModelEntity.cpp // PURPOSE : // AUTHOR : Thomas French // ///////////////////////////////////////////////////////////////////////////////// //Rage Headers #include "cutfile/cutfobject.h" #include "cutscene/cutsevent.h" #include "cutscene/cutsmanager.h" #include "cutscene/cutseventargs.h" #include "cranimation/animation.h" #include "fwanimation/animdirector.h" #include "fwanimation/directorcomponentfacialrig.h" //Game Headers #include "animation/debug/AnimDebug.h" #include "animation/debug/AnimViewer.h" #include "animation/EventTags.h" #include "animation/FacialData.h" #include "animation/MovePed.h" #include "animation/MoveObject.h" #include "camera/CamInterface.h" #include "camera/Cutscene/CutsceneDirector.h" #include "camera/cutscene/AnimatedCamera.h" #include "cutscene/CutSceneCameraEntity.h" #include "cutscene/AnimatedModelEntity.h" #include "Cutscene/cutscene_channel.h" #include "cutscene/CutSceneAnimManager.h" #include "cutscene/CutSceneManagerNew.h" #include "cutscene/CutSceneDefine.h" #include "cutscene/CutsceneCustomEvents.h" #include "event/Events.h" #include "Network/NetworkInterface.h" #include "Objects/ObjectIntelligence.h" #include "Objects/Door.h" #include "Peds/PedFactory.h" #include "peds/ped.h" #include "Peds/PedHelmetComponent.h" #include "peds/PedIntelligence.h" #include "peds/rendering/PedVariationStream.h" #include "peds/rendering/PedVariationPack.h" #include "physics/gtaInst.h" #include "physics/physics.h" #include "physics/simulator.h" #include "physics/Archetype.h" #include "control/record.h" #include "scene/entities/compEntity.h" #include "scene/world/GameWorld.h" #include "script/script.h" #include "script/commands_object.h" #include "script/Handlers/GameScriptEntity.h" #include "task/motion/TaskMotionBase.h" #include "task/system/TaskManager.h" #include "task/System/Task.h" #include "task/Animation/TaskAnims.h" #include "task/Animation/TaskCutScene.h" #include "task/system/TaskTypes.h" #include "task/general/TaskBasic.h" #include "vehicleAi/VehicleAILodManager.h" #include "vehicleAI/VehicleIntelligence.h" #include "vehicles/VehicleFactory.h" #include "vehicles/train.h" #include "weapons/inventory/PedInventoryLoadOut.h" //ANIM_OPTIMISATIONS() /////////////////////////////////////////////////////////////////////////////////////////////////// // Animated model entity /////////////////////////////////////////////////////////////////////////////////////////////////// const fwMvPropertyId CCutsceneAnimatedModelEntity::ms_VisibleToScriptKey("VisibleToScript",0xF301E135); u32 CCutsceneAnimatedModelEntity::ms_EventKey = ATSTRINGHASH("Event", 2915749078); Mat34V identityMat(V_IDENTITY); #if RECORDING_VERTS namespace rage { extern dbgRecords g_DbgRecordCustomClothEvents; EXT_PFD_DECLARE_ITEM( DebugRecords ); } #endif CCutsceneAnimatedModelEntity::CCutsceneAnimatedModelEntity(const cutfObject* pObject) :cutsUniqueEntity() , m_CollisionBound(NULL) , m_bUpdateCollisionBound(false) { m_pCutfObject = pObject; //create a real game side object (CPed, CObject or CVehicle) not a cut scene type object which all derive from CObject m_bCreateGameObject = false; if(pObject->GetType() == CUTSCENE_MODEL_OBJECT_TYPE) { const cutfModelObject* pModel = static_cast(pObject); if(pModel) { m_ModelNameHash = pModel->GetStreamingName(); m_SceneHandleHash = pModel->GetHandle(); } if (m_SceneHandleHash.GetHash()==0) { m_SceneHandleHash = atHashString(atFinalizeHash(pModel->GetAnimStreamingBase())); } } cutsceneAssert(m_ModelNameHash.GetHash()>0); //creation position m_vCreatePos = CutSceneManager::GetInstance()->GetSceneOffset(); //Pointer to a game side object m_pEntity = NULL; //Pointer to a registered entity that is just hidden and repositioned by the cut scene m_pEntityForRepositionOnly = NULL; m_pClip = NULL; m_vVelocity = VEC3_ZERO; m_pCutSceneTask = NULL; m_HasBeenDeletedByCutscene = false; m_bWasInvincible = false; m_fOriginalLODMultiplier = 1.0f; m_fOriginalHairScale = 0.0f; m_CurrentPosition = VEC3_ZERO; m_CurrentHeading = 0.0f; m_bComputeInitialVariationsForGameEntity = false; m_bComputeVariationsForSkipForRepositionOnlyEntity = false; m_bRequestRepositionOnlyEntity = false; m_SectionAnimWasRecieved = 0; m_bIsReadyForGame = false; m_bStoppedCalled = false; m_bIsRegisteredEntityScriptControlled = false; m_bCreatedByCutscene = false; m_bClearedOrSetAnimThisFrame = false; m_bShouldProcessTags = false; m_FrameTagsAreProcessed = 0; m_OptionFlags.ClearAllFlags(); m_StreamingOptionFlags.ClearAllFlags(); #if !__NO_OUTPUT m_bIsloggingEntityCalls = false; #endif } /////////////////////////////////////////////////////////////////////////////////////////////////// CCutsceneAnimatedModelEntity::~CCutsceneAnimatedModelEntity() { bool bDeleteRegisteredEntities = CutSceneManager::GetInstancePtr() && CutSceneManager::GetInstance()->ShouldDeleteAllRegisteredEntites(); DeleteNonRegisteredEntities(); if (m_pEntity && m_pEntity->GetPortalTracker()) { m_pEntity->GetPortalTracker()->SetIsCutsceneControlled(false); } if (bDeleteRegisteredEntities) { if (m_pEntity && (!m_pEntity->GetIsTypePed() || !((CPed*)m_pEntity.Get())->IsPlayer())) RemoveEntityFromTheWorld(m_pEntity, true); if (m_pEntityForRepositionOnly && (!m_pEntityForRepositionOnly->GetIsTypePed() || !((CPed*)m_pEntityForRepositionOnly.Get())->IsPlayer())) RemoveEntityFromTheWorld(m_pEntityForRepositionOnly, true); } m_pEntity = NULL; m_pEntityForRepositionOnly = NULL; if(m_pClip != NULL) { m_pClip->Release(); m_pClip = NULL; } m_pCutSceneTask = NULL; } void CCutsceneAnimatedModelEntity::DeleteNonRegisteredEntities() { if(RemoveEntityFromTheWorld(m_pEntity)) { m_pEntity = NULL; } if(RemoveEntityFromTheWorld(m_pEntityForRepositionOnly)) { m_pEntityForRepositionOnly = NULL; } } void CCutsceneAnimatedModelEntity::RegisterPlayer(cutsManager* pManager, const cutfObject* pObject) { CutSceneManager* pCutsManager = static_cast(pManager); //Register the player if(pCutsManager->GetPlayerSceneId() == pObject->GetObjectId()) { if(m_pEntity == NULL) { CPed *pPed = CGameWorld::FindLocalPlayer(); if(pPed) { if(pObject->GetType() == CUTSCENE_MODEL_OBJECT_TYPE) { pCutsManager->RegisterGameEntity(pPed, GetSceneHandleHash(), GetModelNameHash(), false, false); m_bWasInvincible = pPed->m_nPhysicalFlags.bNotDamagedByAnything; } } } } } void CCutsceneAnimatedModelEntity::SetVisibility(CEntity* pEnt, bool Visible) { if(pEnt) { #if !__NO_OUTPUT CPhysical* phys = NULL; bool reactivateLogging = false; if(pEnt->GetIsPhysical()) { phys = static_cast(pEnt); if(phys && m_bIsloggingEntityCalls && phys->m_LogVisibiltyCalls) { phys->m_LogVisibiltyCalls = false; reactivateLogging = true; } #endif //!__NO_OUTPUT pEnt->SetIsVisibleForModule(SETISVISIBLE_MODULE_CUTSCENE, Visible); #if !__NO_OUTPUT if(phys && m_bIsloggingEntityCalls && reactivateLogging) { phys->m_LogVisibiltyCalls = true; } } #endif //!__NO_OUTPUT } } void CCutsceneAnimatedModelEntity::SetUpScriptRegisteredEntity(cutsManager* UNUSED_PARAM(pManager), const cutfObject* pObject) { //going to animate this version of the entity its has a valid scene handle and model hash if (IsRegisteredWithScript()) { //the id is stored as it could be used later for creating script required entities m_RegisteredEntityFromScript.iSceneId = pObject->GetObjectId(); if(IsScriptRegisteredGameEntity()) { if(m_RegisteredEntityFromScript.bAppearInScene == false) { //remove our initial entity its not going to be needed if(m_pEntity) { if(m_pEntity->GetIsTypePed()) { SetVisibility(m_pEntity, false); cutsceneModelEntityDebugf2("CCutsceneAnimatedModelEntity::SetUpScriptRegisteredEntity1: Hiding entity (%s)", m_pEntity->GetModelName()); //have to add to the world to safely delete, though check its not already in the world if( !m_pEntity->GetIsAddedToWorld() ) { CGameWorld::Add((CPed*)m_pEntity.Get(), CGameWorld::OUTSIDE); } } #if !__NO_OUTPUT if(m_pEntity->GetIsPhysical() && m_bIsloggingEntityCalls) { ((CPhysical*)m_pEntity.Get())->m_LogDeletions = false; } #endif m_pEntity->FlagToDestroyWhenNextProcessed(); m_pEntity = NULL; } } //animating the script given entity, not a CS version else if(m_RegisteredEntityFromScript.pEnt ) { //remove our initial entity its not going to be needed if(m_pEntity) { if(m_pEntity->GetIsTypePed()) { SetVisibility(m_pEntity, false); cutsceneModelEntityDebugf2("CCutsceneAnimatedModelEntity::SetUpScriptRegisteredEntity2: Hiding entity (%s)", m_pEntity->GetModelName()); //have to add to the world to safely release if( !m_pEntity->GetIsAddedToWorld() ) { CGameWorld::Add((CPed*)m_pEntity.Get(), CGameWorld::OUTSIDE); } } #if !__NO_OUTPUT if(m_pEntity->GetIsPhysical() && m_bIsloggingEntityCalls) { ((CPhysical*)m_pEntity.Get())->m_LogDeletions = false; } #endif m_pEntity->FlagToDestroyWhenNextProcessed(); m_pEntity = NULL; } //check that there is no game entity already if(m_pEntity == NULL) { m_pEntity = m_RegisteredEntityFromScript.pEnt; m_pEntity->GetPortalTracker()->SetIsCutsceneControlled(true); if(m_pEntity->GetIsPhysical()) { CPhysical* pPhys = static_cast(m_pEntity.Get()); m_bWasInvincible = pPhys->m_nPhysicalFlags.bNotDamagedByAnything; } } } } else { //check if its registered by scene handle only if(IsScriptRegisteredRepositionOnlyEntity()) { if(m_RegisteredEntityFromScript.pEnt) { //assign this reposition only, as this is a ig version of the cutscene m_pEntityForRepositionOnly = m_RegisteredEntityFromScript.pEnt; SetRepositionOnlyEntityReadyForCutscene(); } } } } } #if !__NO_OUTPUT void CCutsceneAnimatedModelEntity::CommonDebugStr(const cutfObject* pObject, char * debugStr) { if (!pObject) { return; } CutSceneManager::CommonDebugStr(debugStr); // first write in cutscene manager debug sprintf(debugStr, "%sModel Entity(%p, %d, %s), G-Ent(%p, %s), RO-Ent(%p, %s) - ", debugStr, pObject, pObject->GetObjectId(), m_SceneHandleHash.TryGetCStr(), GetGameEntity(), m_ModelNameHash.TryGetCStr(), GetGameRepositionOnlyEntity(), m_RegisteredEntityFromScript.ModelNameHash.TryGetCStr()); } #endif // !__NO_OUTPUT void CCutsceneAnimatedModelEntity::CreateRepositionOnlyGameEntityWhenModelLoaded(cutsManager* pManager, const cutfObject* pObject, bool bRequestVariations, bool bApplyVariations) { if(m_bRequestRepositionOnlyEntity && m_pEntityForRepositionOnly == NULL) { CutSceneManager* pCutsManager = static_cast(pManager); //set the model index to invalid and then check that we have made a request, if not the model index will remain at zero s32 iModelIndex = strLocalIndex::INVALID_INDEX; pCutsManager->GetAssetManager()->GetModelStreamingRequestId(pObject->GetObjectId(), m_RegisteredEntityFromScript.ModelNameHash, iModelIndex); if(iModelIndex != strLocalIndex::INVALID_INDEX) { if(pCutsManager->GetAssetManager()->HasRequestedModelLoaded(pObject->GetObjectId(), m_RegisteredEntityFromScript.ModelNameHash)) { cutsceneModelEntityDebugf2("CreateRepositionOnlyGameEntity - Actor - bRequestVariations(%s), bApplyVariations(%s)", bRequestVariations ? "T" : "F", bApplyVariations ? "T" : "F"); CreateGameEntity(strLocalIndex(iModelIndex), true, bRequestVariations, bApplyVariations); SetRepositionOnlyEntityReadyForCutscene(); m_RegisteredEntityFromScript.pEnt = m_pEntityForRepositionOnly; pCutsManager->GetAssetManager()->RemoveStreamingRequest(pObject->GetObjectId(), true, MODEL_TYPE, m_RegisteredEntityFromScript.ModelNameHash); } } } } /////////////////////////////////////////////////////////////////////////////////////////////////// void CCutsceneAnimatedModelEntity::CreateAnimatedEntityWhenModelLoaded(cutsManager* pManager, const cutfObject* pObject, bool bRequestVariations, bool bApplyVariations) { if(m_RegisteredEntityFromScript.bAppearInScene) { CutSceneManager* pCutsManager = static_cast(pManager); if (pCutsManager->GetAssetManager()->HasRequestedModelLoaded(pObject->GetObjectId(), m_ModelNameHash)) { cutsceneModelEntityDebugf2("CreateAnimatedEntity - Actor - Model Loaded - bRequestVariations(%s), bApplyVariations(%s)", bRequestVariations ? "T" : "F", bApplyVariations ? "T" : "F"); //set the model index to invalid and then check that we have made a request, if not the model index will remain at zero s32 iModelIndex = strLocalIndex::INVALID_INDEX; //we are now creating our game entity just before we play an anim on it if(pCutsManager->GetAssetManager()->GetModelStreamingRequestId(pObject->GetObjectId(), m_ModelNameHash, iModelIndex)) { m_vCreatePos = pCutsManager->GetSceneOffset(); CreateGameEntity(strLocalIndex(iModelIndex), false, bRequestVariations, bApplyVariations); if(m_RegisteredEntityFromScript.bCreatedForScript) { if(m_RegisteredEntityFromScript.pEnt == NULL) { if(IsScriptRegisteredGameEntity()) { if(GetGameEntity()) { m_RegisteredEntityFromScript.pEnt = m_pEntity; } } else { if(IsScriptRegisteredRepositionOnlyEntity()) { if(GetGameRepositionOnlyEntity()) { m_RegisteredEntityFromScript.pEnt = m_pEntityForRepositionOnly; } } } } } m_HasBeenDeletedByCutscene = false; } } } } CTaskCutScene* CCutsceneAnimatedModelEntity::GetCutsceneTaskForEntity() { CTask* pTask = NULL; if(GetGameEntity()) { if(GetGameEntity()->GetIsTypeObject()) { const CObject* pObject = static_cast(GetGameEntity()); if(pObject->GetObjectIntelligence()) { pTask = pObject->GetObjectIntelligence()->FindTaskByType(CTaskTypes::TASK_CUTSCENE); } } if(GetGameEntity()->GetIsTypeVehicle()) { const CVehicle* pVeh = static_cast(GetGameEntity()); if( pVeh->GetIntelligence() && pVeh->GetIntelligence()->GetTaskManager()) { aiTask* CurrentVehicleTask = pVeh->GetIntelligence()->GetTaskManager()->GetTree(VEHICLE_TASK_TREE_SECONDARY)->GetTask(VEHICLE_TASK_SECONDARY_ANIM); if(CurrentVehicleTask && CurrentVehicleTask->GetTaskType() == CTaskTypes::TASK_CUTSCENE) { pTask = static_cast(CurrentVehicleTask); } } } if(GetGameEntity()->GetIsTypePed()) { CPed* pPed = static_cast(GetGameEntity()); if(pPed->GetPedIntelligence()) { pTask = pPed->GetPedIntelligence()->FindTaskByType(CTaskTypes::TASK_CUTSCENE); } } } if(pTask) { CTaskCutScene* pCutScene = static_cast(pTask); return pCutScene; } return NULL; } /////////////////////////////////////////////////////////////////////////////////////////////////// void CCutsceneAnimatedModelEntity::DispatchEvent( cutsManager* pManager, const cutfObject* pObject, s32 iEventId, const cutfEventArgs* pEventArgs, const float UNUSED_PARAM(fTime), const u32 UNUSED_PARAM(StickyId) ) { switch ( iEventId ) { case CUTSCENE_START_OF_SCENE_EVENT: { CutSceneManager* pCutSceneManager = static_cast (pManager); m_ExitSceneTime = pCutSceneManager->GetTotalSeconds(); //register the player if (!NetworkInterface::IsGameInProgress()) RegisterPlayer(pManager, pObject); //possibly need to set the object matrix to be the same as the local space SetUpScriptRegisteredEntity(pManager, pObject); //create any cutscene animated entities that were loaded before the cutscene starts CreateAnimatedEntityWhenModelLoaded(pManager, pObject, true, true); //create any reposition only entities that were loaded before the cutscene starts //CreateRepositionOnlyGameEntityWhenModelLoaded(pManager, pObject, true, true); //Set the entity game ready to enter the scene SetGameEntityReadyForCutscene(); if (GetGameEntity() ) { if (pObject) { cutsceneModelEntityDebugf2("CUTSCENE_START_OF_SCENE_EVENT"); } //have a game side object if(GetGameEntity()) { if(m_pClip) { SetVisibility(GetGameEntity(), true); cutsceneModelEntityDebugf2("CUTSCENE_START_OF_SCENE_EVENT: Showing GetGameEntity (%s)", GetGameEntity()->GetModelName()); } else { SetVisibility(GetGameEntity(), false); cutsceneModelEntityDebugf2("CUTSCENE_START_OF_SCENE_EVENT: Hiding GetGameEntity (%s)", GetGameEntity()->GetModelName()); } } } } break; case CUTSCENE_SKIPPED_EVENT: { CutSceneManager* pCutSceneManager = static_cast (pManager); // Is a reposition only entity model needed RequestRepositionOnlyEntityModelWhenNeeded(pCutSceneManager, pObject); if( GetGameEntity() && GetGameEntity()->GetIsTypePed() ) { CPed* pPed = static_cast(GetGameEntity()); if( pPed ) { for( int i = 0; i < PV_MAX_COMP; ++i ) { if( pPed->m_CClothController[i] ) { pPed->m_CClothController[i]->SetFlag( characterClothController::enIsQueuedPinning, true ); } } } // end if( pPed ) } } break; case CUTSCENE_UPDATE_EVENT: { if( m_bUpdateCollisionBound ) { CEntity* pEntity = GetGameEntity(); if( pEntity ) { crSkeleton* pSkel = pEntity->GetSkeleton(); if( pSkel ) { Mat34V rootBoneMat; pSkel->GetGlobalMtx(0, rootBoneMat); Vec3V col1 = rootBoneMat.GetCol1(); rootBoneMat.SetCol1( rootBoneMat.GetCol0() ); rootBoneMat.SetCol0( col1 ); Assert( m_CollisionBound ); m_CollisionBound->SetCurrentMatrix(0, rootBoneMat); } } } if (m_bIsReadyForGame) { return; } CutSceneManager* pCutSceneManager = static_cast (pManager); // Is a reposition only entity model needed? Check if we are n seconds before the scene ends if (pCutSceneManager->GetCutSceneCurrentTime() > (m_ExitSceneTime - DEFAULT_STREAMING_OFFSET)) { RequestRepositionOnlyEntityModelWhenNeeded(pCutSceneManager, pObject); } // RequestRepositionOnlyEntityModel is called on skip or n seconds before the scene ends // Created a reposition only game entity during the cutscene (as opposed to before the cutscene or after it ends) CreateRepositionOnlyGameEntityWhenModelLoaded(pManager, pObject, true, true); // Has the associated entity (ped/vehicle/prop) been created? if(GetGameEntity()) { m_CurrentPosition = VEC3V_TO_VECTOR3(m_pEntity->GetTransform().GetPosition()); m_CurrentHeading = m_pEntity->GetTransform().GetHeading(); atHashString modelHash(GetModelNameHash()); // the streaming request has been removed we can now delete the object managed by this entity if (!pCutSceneManager->GetAssetManager()->IsModelInRequestList(pObject->GetObjectId(), modelHash)) { if(!IsScriptRegisteredGameEntity() || (IsScriptRegisteredGameEntity() && m_RegisteredEntityFromScript.bDeleteBeforeEnd)) { if(GetGameEntity()->GetIsTypeVehicle()) { //set it to be ambient so it can be deleted by the population cont CVehicle* pVeh = static_cast(GetGameEntity()); pVeh->PopTypeSet(POPTYPE_RANDOM_AMBIENT); } if(GetGameEntity()->GetIsTypePed()) { //set it to be ambient so it can be deleted by the population cont CPed* pPed = static_cast(GetGameEntity()); pPed->PopTypeSet(POPTYPE_RANDOM_AMBIENT); } cutsceneModelEntityDebugf2("CUTSCENE_UPDATE_EVENT - Deleting entity as its model is no longer in the request list."); #if !__NO_OUTPUT if(GetGameEntity()->GetIsPhysical() && m_bIsloggingEntityCalls) { ((CPhysical*)GetGameEntity())->m_LogDeletions = false; } #endif GetGameEntity()->FlagToDestroyWhenNextProcessed(); GetGameEntity()->DisableCollision(); SetVisibility(GetGameEntity(), false); cutsceneModelEntityDebugf2("CUTSCENE_UPDATE_EVENT: Show GetGameEntity (%s)", GetGameEntity()->GetModelName()); m_pEntity = NULL; m_pCutSceneTask = NULL; m_HasBeenDeletedByCutscene = true; } } } else { // // The associated entity (ped/vehicle/prop) has not been created yet? // // Do script want us to create the associated entity (e.g. the character is dead and therefore not needed in the scene) if(m_RegisteredEntityFromScript.bAppearInScene) { bool bCanCreate = false; // If the script has not "registered" the game entity we can create the ped if(!IsScriptRegisteredGameEntity()) { bCanCreate = true; } else { // If the script has "registered" the game entity. Script can decide if they want // the cutscene to create the reposition only entity or if they want to create it themselves bCanCreate = m_RegisteredEntityFromScript.bCreatedForScript; } // Check we are not under script control (in the exit state) if(!m_bIsRegisteredEntityScriptControlled) { if(cutsceneVerifyf(m_HasBeenDeletedByCutscene || bCanCreate, "The registered entity %s owned by the cutscene has been deleted whilst the scene active", pObject->GetDisplayName().c_str())) { // Created an animated actor during the cutscene (as opposed to before the cutscene or after it ends) CreateAnimatedEntityWhenModelLoaded( pManager, pObject, true, true); SetGameEntityReadyForCutscene(); //have a game side object if(GetGameEntity()) { if(m_pClip) { PlayClip(pCutSceneManager, m_pClip, pManager->GetSectionStartTime(pManager->GetCurrentSection()), m_AnimDict); ComputeScriptVisibleTagsOnAnimSet(pCutSceneManager); SetVisibility(GetGameEntity(), true); cutsceneModelEntityDebugf2("CUTSCENE_UPDATE_EVENT: Showing GetGameEntity (%s)", GetGameEntity()->GetModelName()); } else { SetVisibility(GetGameEntity(), false); cutsceneModelEntityDebugf2("CUTSCENE_UPDATE_EVENT: Hiding GetGameEntity (%s)", GetGameEntity()->GetModelName()); } cutsceneModelEntityDebugf2("CUTSCENE_UPDATE_EVENT - Created entity."); } } } } } ComputeScriptVisibleTagsOnUpdate(pCutSceneManager); m_bClearedOrSetAnimThisFrame = false; } break; case CUTSCENE_DICTIONARY_LOADED_EVENT: { if (m_ExitSceneTime==pManager->GetTotalSeconds()) { const cutsDictionaryLoadedEventArgs *pDictEventArgs = static_cast( pEventArgs ); crClipDictionary* pDict = pDictEventArgs->GetDictionary(); if (pDict && pObject) { if(pObject->GetAnimStreamingType() == CUTSCENE_NAMED_STREAMED_ANIMATED_OBJECT ) { const cutfNamedAnimatedStreamedObject* pAnimNamedStreamed = static_cast(pObject); u32 animBaseHash = pAnimNamedStreamed->GetAnimStreamingBase(); s32 iSectionIndex = pDictEventArgs->GetSection(); char indexBuff[8]; formatf(indexBuff, 8, "-%d", iSectionIndex); atHashString FinalHash = atStringHash(indexBuff, animBaseHash); crClip* pClip = pDict->GetClip(FinalHash); if (pClip) { // search for the const crTag* pTag = CClipEventTags::FindFirstEventTag(pClip, CClipEventTags::TagSyncBlendOut); if(pTag) { CutSceneManager* pCutSceneManager = static_cast (pManager); m_ExitSceneTime = pCutSceneManager->GetSectionStartTime(pDictEventArgs->GetSection()) + pClip->ConvertPhaseToTime(pTag->GetStart()); } } } } } } break; case CUTSCENE_SET_CLIP_EVENT: { if (m_bIsReadyForGame) { return; } CutSceneManager* pCutSceneManager = static_cast (pManager); // set the clip and the initial playback time if (pEventArgs && pEventArgs->GetType() == CUTSCENE_CLIP_EVENT_ARGS_TYPE ) { const cutsClipEventArgs *pClipEventArgs = static_cast( pEventArgs ); //store the clip dictionary and anim dict we may not have an object to play an anim on yet const crClip* pClip = pClipEventArgs->GetClip(); if(pClip != NULL) { pClip->AddRef(); } if(m_pClip != NULL) { ComputeScriptVisibleTagsOnAnimClear(pCutSceneManager); m_pClip->Release(); } m_pClip = pClip; m_SectionAnimWasRecieved = pCutSceneManager->GetCurrentSection(); formatf(m_AnimDict, sizeof(m_AnimDict), pClipEventArgs->GetAnimDict()); cutsceneAssertf(m_pClip, "CUTSCENE_SET_CLIP_EVENT has a null clip on %s, anim dict %s", pObject->GetDisplayName().c_str(), pClipEventArgs->GetAnimDict()); //Here we have a created our own cut scene object CutSceneManager* pCutManager = static_cast(pManager); if(GetGameEntity()) { PlayClip(pCutManager, pClipEventArgs->GetClip(), pManager->GetSectionStartTime(pManager->GetCurrentSection()), pClipEventArgs->GetAnimDict()); ComputeScriptVisibleTagsOnAnimSet(pCutManager); SetVisibility(GetGameEntity(), true); cutsceneModelEntityDebugf2("SET_CLIP_EVENT: Showing GetGameEntity (%s)", GetGameEntity()->GetModelName()); } cutsceneModelEntityDebugf2("SET_CLIP_EVENT %s : pClip:%s", pClipEventArgs->GetAnimDict(), m_pClip ? m_pClip->GetName() : "Clip not found!"); } else { cutsceneModelEntityDebugf2("NO_SET_CLIP_EVENT"); } } break; case CUTSCENE_SCENE_ORIENTATION_CHANGED_EVENT: { if (m_bIsReadyForGame) { return; } CTaskCutScene* pTask = GetCutsceneTaskForEntity(); if(pTask) { Matrix34 SceneMat; pManager->GetSceneOrientationMatrix(SceneMat); pTask->SetAnimOrigin(SceneMat); } } break; case CUTSCENE_CLEAR_ANIM_EVENT: { cutsceneModelEntityDebugf2("CUTSCENE_CLEAR_ANIM_EVENT"); CutSceneManager* pCutSceneManager = static_cast (pManager); bool bDuringCutscene = (pCutSceneManager->GetCutSceneCurrentTime() > pCutSceneManager->GetStartTime()) && (pCutSceneManager->GetCutSceneCurrentTime() < pCutSceneManager->GetEndTime()); ComputeScriptVisibleTagsOnAnimClear(pCutSceneManager); if(m_pClip != NULL) { m_pClip->Release(); m_pClip = NULL; } if (bDuringCutscene) { if (m_pCutSceneTask) { Matrix34 SceneMat; pManager->GetSceneOrientationMatrix(SceneMat); m_pCutSceneTask->SetClip(m_pClip,SceneMat, 0.0f); } } if (m_bIsReadyForGame) { return; } if(bDuringCutscene) { // stop event has been called already and the ped is being returned to the game don't set them to be invisible. if(GetGameEntity() && !m_bStoppedCalled) { SetVisibility(GetGameEntity(), false); cutsceneModelEntityDebugf2("CUTSCENE_CLEAR_ANIM_EVENT: Hiding GetGameEntity (%s)", GetGameEntity()->GetModelName()); } } } break; case CUTSCENE_END_OF_SCENE_EVENT: { m_CollisionBound = NULL; m_bUpdateCollisionBound = false; cutsceneModelEntityDebugf2("CUTSCENE_END_OF_SCENE_EVENT"); // make sure our entity has been returned to game mode if necessary SetGameEntityReadyForGame(pManager); DeleteNonRegisteredEntities(); // Force update the ai for the ped so we don't see the final frame twice if (GetGameEntity() && GetCutsceneTaskForEntity()) { cutsceneModelEntityDebugf2("CUTSCENE_END_OF_SCENE_EVENT - Force AI Update"); ForceUpdateAi(pManager); } } break; case CUTSCENE_STOP_EVENT: { cutsceneModelEntityDebugf3("CUTSCENE_STOP_EVENT"); m_bStoppedCalled = true; } break; case CUTSCENE_RESTART_EVENT: { m_pCutSceneTask = NULL; } break; case CutSceneCustomEvents::CUTSCENE_CUSTOM_CLOTH_EVENT: { //cutsceneModelEntityDebugf("CCutsceneAnimatedModelEntity::DispatchEvent: CUTSCENE_CUSTOM_CLOTH_EVENT"); const CutSceneCustomEvents::ICutsceneCustomCustomEventArgs* pObjectVar = static_cast(pEventArgs); CEntity* pEntity = GetGameEntity(); if ( pEntity && pObjectVar && pObjectVar->GetEventType() == CCEVENT_TYPE_CUSTOM_0 ) { crSkeleton* pSkel = pEntity->GetSkeleton(); if( pSkel ) { Mat34V rootBoneMat; pSkel->GetGlobalMtx(0, rootBoneMat); atHashString ModelNameHash("cs_mrs_thornhill"); CCutsceneAnimatedModelEntity* pAnimatedModel = ((CutSceneManager*)pManager)->GetAnimatedModelEntityFromModelHash(ModelNameHash); CEntity* pEntity = pAnimatedModel->GetGameEntity(); if( pEntity && pEntity->GetIsTypePed() ) { CPed* pPed = static_cast(pEntity); if( pPed ) { for( int i = 0; i < PV_MAX_COMP; ++i ) { if( pPed->m_CClothController[i] ) { phVerletCloth* pVerletCloth = pPed->m_CClothController[i]->GetCloth(0); Assert( pVerletCloth ); if( !pVerletCloth->m_VirtualBound ) { float fCapsuleLen = pObjectVar->GetCapsuleLength(); float fCapsuleRad = pObjectVar->GetCapsuleRadius(); pVerletCloth->SetFlag(phVerletCloth::FLAG_COLLIDE_EDGES, true); pVerletCloth->SetFlag(phVerletCloth::FLAG_IGNORE_OFFSET, true); pVerletCloth->CreateVirtualBound( 1, &identityMat ); pVerletCloth->AttachVirtualBoundCapsule( fCapsuleRad, fCapsuleLen, rootBoneMat, 0 ); m_CollisionBound = (phBoundComposite*)pVerletCloth->m_VirtualBound.ptr; #if USE_CAPSULE_EXTRA_EXTENTS Assert( m_CollisionBound ); phBound* pColBound = m_CollisionBound->GetBound(0); Assert( pColBound ); static float fCapsuleHalfHeight = 0.15f; ((phBoundCapsule*)pColBound)->SetHalfHeight( fCapsuleHalfHeight ); #endif m_bUpdateCollisionBound = true; } } } } // if( pPed ) } } // if( pSkel ) } break; } case CUTSCENE_SET_ANIMATION_EVENT: case CUTSCENE_PLAY_EVENT: case CUTSCENE_PAUSE_EVENT: case CUTSCENE_UPDATE_LOADING_EVENT: case CUTSCENE_STEP_FORWARD_EVENT: case CUTSCENE_STEP_BACKWARD_EVENT: case CUTSCENE_FAST_FORWARD_EVENT: case CUTSCENE_REWIND_EVENT: break; } //this is here to dispatch debug draw event for this entity. #if __BANK cutsEntity::DispatchEvent(pManager, pObject, iEventId, pEventArgs); #endif } #if !__NO_OUTPUT XPARAM(cutscenecallstacklogging); #endif //!__NO_OUTPUT #if !__NO_OUTPUT void CCutsceneAnimatedModelEntity::SetUpEntityForCallStackLogging() { if(GetGameEntity() && GetGameEntity()->GetIsPhysical()) { if(PARAM_cutscenecallstacklogging.Get() BANK_ONLY (&& (CutSceneManager::GetInstance() && CutSceneManager::GetInstance()->IsCallStackLogging())) ) { CPhysical* phys = static_cast(GetGameEntity()); phys->m_LogSetMatrixCalls = true; phys->m_LogVisibiltyCalls = true; phys->m_LogDeletions = true; phys->m_LogVariationCalls = true; m_bIsloggingEntityCalls = true; } } }; #endif //!__NO_OUTPUT #if !__NO_OUTPUT void CCutsceneAnimatedModelEntity::ResetEntityForCallStackLogging() { if(GetGameEntity() && GetGameEntity()->GetIsPhysical()) { if(PARAM_cutscenecallstacklogging.Get() BANK_ONLY (&& (CutSceneManager::GetInstance() && CutSceneManager::GetInstance()->IsCallStackLogging())) ) { CPhysical* phys = static_cast(GetGameEntity()); phys->m_LogSetMatrixCalls = false; phys->m_LogVisibiltyCalls = false; phys->m_LogDeletions = false; phys->m_LogVariationCalls = false; m_bIsloggingEntityCalls = false; } } }; #endif //!__NO_OUTPUT bool CCutsceneAnimatedModelEntity::HasScriptVisibleTagPassed(s32 TagHash) { for(int i=0; i < SIZE_OF_SCRIPT_VISIBLE_TAG_LIST; i++) { if(m_ScriptVisibleTags[i] != 0) { if(m_ScriptVisibleTags[i] == TagHash) { return true; } } } return false; } void CCutsceneAnimatedModelEntity::ResetScriptVisibleTags() { for(int i=0; i < SIZE_OF_SCRIPT_VISIBLE_TAG_LIST; i++) { m_ScriptVisibleTags[i] = 0; } } void CCutsceneAnimatedModelEntity::FindScriptVisibleTags(const crClip* pClip, float startPhase, float endPhase) { if(m_FrameTagsAreProcessed != fwTimer::GetFrameCount()) { ResetScriptVisibleTags(); m_FrameTagsAreProcessed = fwTimer::GetFrameCount(); } startPhase = Clamp(startPhase, 0.0f, 1.0f); endPhase = Clamp(endPhase, 0.0f, 1.0f); crTagIterator it(*pClip->GetTags(), startPhase, endPhase, ms_VisibleToScriptKey); int numOfTags =0; while (*it) { const crTag* pTag = *it; if(pTag) { const crPropertyAttribute* pAttr = pTag->GetAttribute(ms_EventKey ); if(pAttr && pAttr->GetType() == crPropertyAttribute::kTypeHashString) { const crPropertyAttributeHashString *pAttrHashString = static_cast< const crPropertyAttributeHashString * >(pAttr); for(int i=0; i < SIZE_OF_SCRIPT_VISIBLE_TAG_LIST; i++) { if(m_ScriptVisibleTags[i] == 0) { m_ScriptVisibleTags[i] = pAttrHashString->GetHashString().GetHash(); cutsceneModelEntityDebugf3("Found Script Visible Tag: %s (%d) in Clip: %s between phases: (s:%f , e:%f)", pAttrHashString->GetHashString().TryGetCStr(), pAttrHashString->GetHashString().GetHash(), m_pClip->GetName(), startPhase, endPhase); break; } } } } ++it; numOfTags++; } cutsceneAssertf(numOfTags < SIZE_OF_SCRIPT_VISIBLE_TAG_LIST, "Found more than %d script visible tags between phases: %f, %f for clip: %s ", SIZE_OF_SCRIPT_VISIBLE_TAG_LIST, startPhase, endPhase, pClip->GetName()); } void CCutsceneAnimatedModelEntity::ComputeScriptVisibleTagsOnAnimClear(CutSceneManager* pCutSceneManager) { if (m_pClip && m_bShouldProcessTags) { if(!pCutSceneManager->IsConcatted()) { float startPhase = (pCutSceneManager->GetCutScenePreviousTime() - m_fStartTime) / m_pClip->GetDuration(); if(startPhase != 1.0f) { FindScriptVisibleTags(m_pClip, startPhase, 1.0f); cutsceneModelEntityDebugf3("Non Concat - ComputeScriptVisibleTagsOnAnimClear: %s (s:%f , e:%f)", m_pClip->GetName(), startPhase, 1.0f); } } else { //compute anim phases based on concat boundaries s32 currentConcatSection = pCutSceneManager->GetConcatSectionForTime(pCutSceneManager->GetCutSceneCurrentTime()); s32 previousConcatSection = pCutSceneManager->GetConcatSectionForTime(pCutSceneManager->GetCutScenePreviousTime()); if(currentConcatSection != previousConcatSection && ((currentConcatSection-previousConcatSection) > 1)) { //compute the anim end time based concat boundary of the next concat section float animEndEndTime = pCutSceneManager->GetConcatSectionStartTime(previousConcatSection + 1); float endPhase = (animEndEndTime - m_fStartTime) / m_pClip->GetDuration(); float startPhase = (pCutSceneManager->GetCutScenePreviousTime() - m_fStartTime) / m_pClip->GetDuration(); if(endPhase != startPhase) { FindScriptVisibleTags(m_pClip, startPhase, endPhase); cutsceneModelEntityDebugf3("Concat Boundary - ComputeScriptVisibleTagsOnAnimClear: %s (s:%f , e:%f)", m_pClip->GetName(), startPhase, endPhase); } } else { //search for tags to the end of the anim, still in the same concat section float startPhase = (pCutSceneManager->GetCutScenePreviousTime() - m_fStartTime) / m_pClip->GetDuration(); float endPhase = (pCutSceneManager->GetCutSceneCurrentTime() - m_fStartTime) / m_pClip->GetDuration(); endPhase = Clamp(endPhase, startPhase, 1.0f); if(startPhase != endPhase) { FindScriptVisibleTags(m_pClip, startPhase, endPhase); cutsceneModelEntityDebugf3("Concat Non-Boundary - ComputeScriptVisibleTagsOnAnimClear: %s (s:%f , e:%f)", m_pClip->GetName(), startPhase, endPhase); } } } m_bClearedOrSetAnimThisFrame = true; } } void CCutsceneAnimatedModelEntity::ComputeScriptVisibleTagsOnUpdate(CutSceneManager* pCutSceneManager) { if (m_pClip && !m_bClearedOrSetAnimThisFrame && m_bShouldProcessTags) { float startPhase = (pCutSceneManager->GetCutScenePreviousTime() - m_fStartTime) / m_pClip->GetDuration(); float endPhase = (pCutSceneManager->GetCutSceneCurrentTime() - m_fStartTime) / m_pClip->GetDuration(); if(endPhase != startPhase) { FindScriptVisibleTags(m_pClip, startPhase, endPhase); } } } void CCutsceneAnimatedModelEntity::ComputeScriptVisibleTagsOnAnimSet(CutSceneManager* pCutSceneManager) { if (m_pClip) { m_bShouldProcessTags = false; const crTag* pTag = CClipEventTags::FindFirstEventTag(m_pClip, ms_VisibleToScriptKey); if(pTag) { m_bShouldProcessTags = true; } if(m_bShouldProcessTags) { if(!pCutSceneManager->IsConcatted()) { //get the last anim phase //set end phase = 1.0f we are about to get a new anim float endPhase = (pCutSceneManager->GetCutSceneCurrentTime() - m_fStartTime) / m_pClip->GetDuration(); if(endPhase != 0.0f) { FindScriptVisibleTags(m_pClip, 0.0f, endPhase); cutsceneModelEntityDebugf3("Non Concat - ComputeScriptVisibleTagsOnAnimSet: %s (s:%f , e:%f)", m_pClip->GetName(), 0.0f, endPhase ); } } else { float previousTime = pCutSceneManager->GetCutScenePreviousTime(); if(pCutSceneManager->GetInternalTime() == pCutSceneManager->GetStartTime()) { if(!pCutSceneManager->IsConcatSectionValidForPlayBack(0)) { previousTime = -1.0f; } } //Crossed a concat boundary compute the tag from the start of concat boundary to the current time s32 currentConcatSection = pCutSceneManager->GetConcatSectionForTime(pCutSceneManager->GetCutSceneCurrentTime()); s32 previousConcatSection = pCutSceneManager->GetConcatSectionForTime(previousTime); if(currentConcatSection != previousConcatSection && ((currentConcatSection-previousConcatSection) > 1)) { //we compute the phase from this point into the anim float concatStartTime = pCutSceneManager->GetConcatSectionStartTime(currentConcatSection); s32 currentAnimSection = pCutSceneManager->GetSectionForTime( pCutSceneManager->GetCutSceneCurrentTime() ); float animSectionStartTime = pCutSceneManager->GetSectionStartTime(currentAnimSection); float startPhase = 0.0f; float endPhase = 0.0f; //The start of the concat section is further on in time so need to calculate the phase of the anim relative to the concat section //because it's the concat section that defines what to play not the anim section. Other wise the anim time is in a valid part of the //concat so just use a start phase of zero and whatever has progressed. //Showing how anim and cocnat sections can vary. //e.g anim section: Start:0 | A1 end: 10 | A2 end:20| A3 end:30| // concat section start:0 | end 12| end:18| end:30| if(concatStartTime >= animSectionStartTime) { startPhase = (concatStartTime - animSectionStartTime) / m_pClip->GetDuration(); } endPhase = (pCutSceneManager->GetCutSceneCurrentTime() - animSectionStartTime) / m_pClip->GetDuration(); if(endPhase != startPhase) { FindScriptVisibleTags(m_pClip, startPhase, endPhase); cutsceneModelEntityDebugf3("Concat Boundary - ComputeScriptVisibleTagsOnAnimSet: %s (s:%f , e:%f)", m_pClip->GetName(), startPhase, endPhase ); } } else { float startPhase = (pCutSceneManager->GetCutScenePreviousTime() - m_fStartTime) / m_pClip->GetDuration(); float endPhase = (pCutSceneManager->GetCutSceneCurrentTime() - m_fStartTime) / m_pClip->GetDuration(); startPhase = Clamp(startPhase, 0.0f, endPhase); if(endPhase != startPhase) { FindScriptVisibleTags(m_pClip, startPhase, endPhase); } cutsceneModelEntityDebugf3("Concat Non Boundary - ComputeScriptVisibleTagsOnAnimSet: %s (s:%f , e:%f)", m_pClip->GetName(), startPhase, endPhase ); } } } m_bClearedOrSetAnimThisFrame = true; } } ////////////////////////////////////////////////////////////////////////// void CCutsceneAnimatedModelEntity::RequestRepositionOnlyEntityModelWhenNeeded(CutSceneManager* pManager, const cutfObject* pObject) { // check if we want to request a reposition only entity if (!IsScriptRegisteredGameEntity() // check that script have not registered this as a game entity && IsScriptRegisteredRepositionOnlyEntity() // check that script have registered this as a reposition only entity && !m_RegisteredEntityFromScript.pEnt // check the entity has not been assigned to script already && m_pEntityForRepositionOnly == NULL // reposition entity has not been made yet && m_RegisteredEntityFromScript.bCreatedForScript // entity is to be created by the cutscene for the script && !m_bRequestRepositionOnlyEntity // request has not been made yet ) { cutsceneModelEntityDebugf2("RequestRepositionOnlyEntityModel ------------------------------------------- "); // add the streaming request pManager->GetAssetManager()->SetModelStreamingRequest(m_RegisteredEntityFromScript.ModelNameHash, pObject->GetObjectId(), MODEL_TYPE); m_bRequestRepositionOnlyEntity = true; } } /////////////////////////////////////////////////////////////////////////////////////////////////// void CCutsceneAnimatedModelEntity::SetAnimPlayBackEventTime(float fEventTime) { m_fStartTime = fEventTime; } void CCutsceneAnimatedModelEntity::GetMoverTrackVelocity(const crClip* pClip, float fCurrentPhase, float fLastPhase, float fTimeStep) { if(m_pEntity) { if(fTimeStep > 0.0f) { if(pClip) { const float time = pClip->ConvertPhaseToTime(fCurrentPhase); const float timeOnPreviousUpdate = pClip->ConvertPhaseToTime(fLastPhase); bool bIsWarpFrame = pClip->CalcBlockPassed(timeOnPreviousUpdate, time); if (bIsWarpFrame) { m_vVelocity.Zero(); } else { m_vVelocity = fwAnimHelpers::GetMoverTrackDisplacement(*pClip, fLastPhase, fCurrentPhase); m_vVelocity /= fTimeStep; } //printf("CCutsceneAnimatedModelEntity::GetMoverTrackVelocity: %s, m_vVelocity: %.2f, %.2f, %.2f, Phases: %.2f - %.2f\n", pClip->GetName(), m_vVelocity.x, m_vVelocity.y, m_vVelocity.z, fLastPhase, fCurrentPhase); } else { m_vVelocity.Zero(); } cutsceneAssertf(rage::FPIsFinite(m_vVelocity.x), "Exit x velocity from cutscene is not finite" ); cutsceneAssertf(rage::FPIsFinite(m_vVelocity.y), "Exit y velocity from cutscene is not finite" ); cutsceneAssertf(rage::FPIsFinite(m_vVelocity.z), "Exit z velocity from cutscene is not finite" ); Matrix34 mEntityMat = MAT34V_TO_MATRIX34(m_pEntity->GetMatrix()); mEntityMat.Transform3x3(m_vVelocity); } } } void CCutsceneAnimatedModelEntity::UpdateCutSceneTaskPhase(CTask* pTask, cutsManager* pManager) { CutSceneManager* pCutsManager = static_cast(pManager); if(ShouldUpdateCutSceneTask(pTask, pManager)) { if(pTask && pTask->GetTaskType() == CTaskTypes::TASK_CUTSCENE) { CTaskCutScene* pCutSceneTask = static_cast(pTask); const crClip* pClip = pCutSceneTask->GetClip(); if (pClip) { float fPhase = pCutsManager->GetPhaseUpdateAmount(pClip, GetAnimEventStartTime()); pCutSceneTask->SetPhase(fPhase); if(pCutSceneTask->WillFinishThisPhase(fPhase)) { cutsceneModelEntityDebugf1("CUTSCENE_BLEND_OUT_TAG"); m_bStoppedCalled = true; } } } } } bool CCutsceneAnimatedModelEntity::ShouldUpdateCutSceneTask(CTask* pTask, cutsManager* pManager) { CutSceneManager* pCutsManager = static_cast(pManager); if(m_SectionAnimWasRecieved != pCutsManager->GetCurrentSection()) { if(pTask && pTask->GetTaskType() == CTaskTypes::TASK_CUTSCENE) { CTaskCutScene* pCutSceneTask = static_cast(pTask); pCutSceneTask->SetPhase(1.0f); } return false; } return true; } bool CCutsceneAnimatedModelEntity::RemoveEntityFromTheWorld(CEntity* pEntity, bool bDeleteScriptRegistered) { bool ShouldRemove = false; if (pEntity) { bool CanDelete = m_RegisteredEntityFromScript.pEnt != pEntity || bDeleteScriptRegistered; if(CanDelete|| m_RegisteredEntityFromScript.bDeleteBeforeEnd) { cutsceneModelEntityDebugf2("RemoveEntityFromWorld"); if(pEntity->GetIsPhysical()) { //about to delete a script registered object CTheScripts::UnregisterEntity((CPhysical*)pEntity, true); } #if !__NO_OUTPUT if(pEntity->GetIsPhysical() && m_bIsloggingEntityCalls) { ((CPhysical*)pEntity)->m_LogDeletions = false; } #endif //!__NO_OUTPUT pEntity->FlagToDestroyWhenNextProcessed(); pEntity->DisableCollision(); SetVisibility(pEntity, false); cutsceneModelEntityDebugf2("CCutsceneAnimatedModelEntity::RemoveEntityFromTheWorld: Hide entity (%s)", pEntity->GetModelName()); ShouldRemove = true; } } return ShouldRemove; } /////////////////////////////////////////////////////////////////////////////////////////////////// #if __DEV void CCutsceneAnimatedModelEntity::DebugDraw() const { Vector3 vGameEntityPosition; Vector3 vPos; Color32 Colour (Color_blue); const CEntity* pEnt = NULL; if(GetGameEntity()) { pEnt = GetGameEntity(); } if(!pEnt) { return; } if(pEnt) { if(CutSceneManager::GetInstance()->GetDebugManager().m_bDisplayAllSkeletons) { const crSkeleton* pSkeleton = pEnt->GetSkeleton(); CAnimViewer::RenderSkeleton(*pSkeleton, Color_red, Color_blue, 0.01f); Matrix34 m = MAT34V_TO_MATRIX34(pEnt->GetMatrix()); grcDebugDraw::Axis(m, 0.5f, true); } vGameEntityPosition = VEC3V_TO_VECTOR3(pEnt->GetTransform().GetPosition()); } //draw the scene handles vPos = vGameEntityPosition; vPos.z += 1.0f; grcDebugDraw::Line(vGameEntityPosition,vPos,Colour); char text [128]; const cutfModelObject* pModel = NULL; if(GetCutfObject()->GetType() == CUTSCENE_MODEL_OBJECT_TYPE) { pModel = static_cast(GetCutfObject()); } if(pModel) { grcDebugDraw::Text(vPos, Colour, formatf(text, "Display Name: %s Scene Handle: %s", GetCutfObject()->GetDisplayName().c_str(), pModel->GetHandle().GetCStr())); } else { grcDebugDraw::Text(vPos, Colour, formatf(text, "Display Name: %s", GetCutfObject()->GetDisplayName().c_str())); } } #endif /////////////////////////////////////////////////////////////////////////////////////////////////// // Animated Prop Entity /////////////////////////////////////////////////////////////////////////////////////////////////// CCutSceneAnimatedPropEntity::CCutSceneAnimatedPropEntity(const cutfObject* pObject) :CCutsceneAnimatedModelEntity(pObject) { } CCutSceneAnimatedPropEntity::~CCutSceneAnimatedPropEntity() { //check that the script registered entity is being picked up by the script if(m_RegisteredEntityFromScript.SceneNameHash > 0 && m_RegisteredEntityFromScript.bCreatedForScript) { if(m_RegisteredEntityFromScript.pEnt != NULL) { const CScriptEntityExtension* pExtension = m_RegisteredEntityFromScript.pEnt->GetExtension(); if(!CutSceneManager::GetInstance()->ShouldDeleteAllRegisteredEntites()) { if(!IsRegisteredGameEntityUnderScriptControl()) { cutsceneAssertf(pExtension, "Deleting a cutscene entity (\"%s\" %u) scene handle (\"%s\" %u) that was registered with CU_CREATE_AND_ANIMATE_NEW_SCRIPT_ENTITY use GET_ENTITY_INDEX_OF_REGISTERED_ENTITY to make sure it is pickup up by the script", m_RegisteredEntityFromScript.ModelNameHash.TryGetCStr(), m_RegisteredEntityFromScript.ModelNameHash.GetHash(), m_RegisteredEntityFromScript.SceneNameHash.TryGetCStr(), m_RegisteredEntityFromScript.SceneNameHash.GetHash()); } } if(!pExtension) { m_RegisteredEntityFromScript.bDeleteBeforeEnd = true; if(m_bCreatedByCutscene) { if(GetGameEntity()) { GetGameEntity()->SetOwnedBy(ENTITY_OWNEDBY_TEMP); } } } } } } ////////////////////////////////////////////////////////////////////////////////////////////////// //need to implement a game version of this void CCutSceneAnimatedPropEntity::CreateGameEntity(strLocalIndex iModelIndex, bool CreateRepositionEntity, bool UNUSED_PARAM(bRequestVariations), bool UNUSED_PARAM(bApplyVariations)) { if(GetGameEntity() == NULL) { cutsceneModelEntityDebugf2("CreateGameEntity - Prop"); fwModelId modelId((strLocalIndex(iModelIndex))); CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfo(modelId); if(pModelInfo) { cutsceneAssertf(pModelInfo->GetIsTypeObject(), "CUTSCENE ASSET (Assign to *Default Anim Cutscene*): Exported incorrectly, %s is not a PropModel type", pModelInfo->GetModelName()); if(pModelInfo->GetIsTypeObject()) { // By default objects are created at the origin and their drawables are created automatically this flag allows objects to be created without // their drawable they are then moved to the scene origin and then their drawable is created // this matters if the drawable contains lights as these lights will only be updated to be relative to the object when the lights bounding box // is on screen and not when the object is moved (FTR I think this is the real bug) // We don't want to make this the default behavior at this stage for fear of "fixing" things and causing double lighting etc bool bCreateObjectsAtSceneOrigin = CutSceneManager::GetInstance()->GetOptionFlags().IsFlagSet(CUTSCENE_CREATE_OBJECTS_AT_SCENE_ORIGIN); CObject* pObject = CObjectPopulation::CreateObject(modelId, ENTITY_OWNEDBY_CUTSCENE, bCreateObjectsAtSceneOrigin? false : true, true, false); if (pObject) { #if GTA_REPLAY CReplayMgr::RecordObject(pObject); #endif //GTA_REPLAY Matrix34 TempMat; TempMat.Identity(); TempMat.d = m_vCreatePos; //cant create objects on top of each other, the game complains about it. TempMat.d.z += 0.001f * m_pCutfObject->GetObjectId(); pObject->SetMatrix(TempMat); if (bCreateObjectsAtSceneOrigin) { pObject->CreateDrawable(); } // Add Object to world after its position has been set CGameWorld::Add(pObject, CGameWorld::OUTSIDE ); pObject->GetPortalTracker()->ScanUntilProbeTrue(); pObject->GetPortalTracker()->Update(VEC3V_TO_VECTOR3(pObject->GetTransform().GetPosition())); pObject->GetPortalTracker()->SetIsCutsceneControlled(true); if(CreateRepositionEntity) { SetRepositionOnlyEntity(pObject); } else { SetGameEntity(pObject); } m_bCreatedByCutscene = true; } } } } } void CCutSceneAnimatedPropEntity::ForceUpdateAi(cutsManager* pManager) { if(pManager) { CutSceneManager* pCutSceneManager = static_cast (pManager); if(pCutSceneManager->GetShutDownMode() != SHUTDOWN_SESSION) { CObject* pObj = GetGameEntity(); if (pObj && pObj->GetObjectIntelligence()) { pObj->GetObjectIntelligence()->Process(); } } } }; void CCutSceneAnimatedPropEntity::SetRepositionOnlyEntityReadyForCutscene() { if(GetGameRepositionOnlyEntity()) { GetGameRepositionOnlyEntity()->m_nPhysicalFlags.bNotDamagedByAnything = true; GetGameRepositionOnlyEntity()->SetIsVisibleForModule(SETISVISIBLE_MODULE_CUTSCENE, false); cutsceneModelEntityDebugf2("CCutSceneAnimatedPropEntity::SetRepositionOnlyEntityReadyForCutscene: Hiding GetGameRepositionOnlyEntity (%s)", GetGameRepositionOnlyEntity()->GetModelName()); NetworkInterface::CutsceneStartedOnEntity(*GetGameRepositionOnlyEntity()); } } void CCutSceneAnimatedPropEntity::SetGameEntityReadyForCutscene() { if(GetGameEntity()) { #if !__NO_OUTPUT SetUpEntityForCallStackLogging(); #endif GetGameEntity()->SetFixedPhysics(true); GetGameEntity()->m_nPhysicalFlags.bNotDamagedByAnything = true; GetGameEntity()->m_nDEflags.bForcePrePhysicsAnimUpdate = true; GetGameEntity()->DisableCollision(); NetworkInterface::CutsceneStartedOnEntity(*GetGameEntity()); if(!m_RegisteredEntityFromScript.bCreatedForScript) { if(GetGameEntity()->IsADoor() && m_OptionFlags.IsFlagSet(CEO_UPDATE_AS_REAL_DOOR)) { CDoor* door = static_cast(GetGameEntity()); door->SetRegisteredWithCutscene(true); } } } } void CCutSceneAnimatedPropEntity::SetGameEntityReadyForGame(cutsManager* UNUSED_PARAM(pManager)) { if(!m_bIsReadyForGame) { if(GetGameEntity()) { NetworkInterface::CutsceneFinishedOnEntity(*GetGameEntity()); if(!m_RegisteredEntityFromScript.bCreatedForScript) { if(GetGameEntity()->IsADoor() && m_OptionFlags.IsFlagSet(CEO_UPDATE_AS_REAL_DOOR)) { CDoor* door = static_cast(GetGameEntity()); door->SetRegisteredWithCutscene(false); } } #if !__NO_OUTPUT ResetEntityForCallStackLogging(); #endif if(m_RegisteredEntityFromScript.bCreatedForScript || !m_RegisteredEntityFromScript.bDeleteBeforeEnd) { cutsceneModelEntityDebugf2("SetGameEntityReadyForGame - Prop"); GetGameEntity()->m_nPhysicalFlags.bNotDamagedByAnything = m_bWasInvincible; GetGameEntity()->m_nDEflags.bForcePrePhysicsAnimUpdate = false; GetGameEntity()->EnableCollision(); GetGameEntity()->SetFixedPhysics(false); } bool CanDelete = m_RegisteredEntityFromScript.pEnt != GetGameEntity(); if(CanDelete|| m_RegisteredEntityFromScript.bDeleteBeforeEnd) { GetGameEntity()->SetOwnedBy(ENTITY_OWNEDBY_TEMP); } else { GetGameEntity()->SetOwnedBy(ENTITY_OWNEDBY_SCRIPT); SetVisibility(GetGameEntity(), true); cutsceneModelEntityDebugf2("CCutSceneAnimatedPropEntity::SetGameEntityReadyForGame: Showing GetGameEntity (%s)", GetGameEntity()->GetModelName()); } } if(GetGameRepositionOnlyEntity()) { cutsceneModelEntityDebugf2("SetGameEntityReadyForGame - Prop (reposition only)"); GetGameRepositionOnlyEntity()->SetPosition(m_CurrentPosition); GetGameRepositionOnlyEntity()->SetHeading(m_CurrentHeading); GetGameRepositionOnlyEntity()->m_nPhysicalFlags.bNotDamagedByAnything = m_bWasInvincible; GetGameRepositionOnlyEntity()->SetIsVisibleForModule(SETISVISIBLE_MODULE_CUTSCENE, true); cutsceneModelEntityDebugf2("CCutSceneAnimatedPropEntity::SetGameEntityReadyForGame: Showing GetGameRepositionOnlyEntity (%s)", GetGameRepositionOnlyEntity()->GetModelName()); if(m_bCreatedByCutscene) { GetGameRepositionOnlyEntity()->SetOwnedBy(ENTITY_OWNEDBY_SCRIPT); } } if (m_pCutSceneTask) { m_pCutSceneTask->SetExitNextUpdate(); } m_bIsReadyForGame = true; } } void CCutSceneAnimatedPropEntity::PlayClip (CutSceneManager* pCutManager, const crClip* pClip, float fEventTime, const strStreamingObjectName UNUSED_PARAM(pAnimDict)) { if(GetGameEntity()) { if(!m_pCutSceneTask) { m_pCutSceneTask = CreateCutsceneTask(pCutManager, pClip, fEventTime); GetGameEntity()->SetTask(m_pCutSceneTask); } else { if(cutsceneVerifyf(m_pCutSceneTask->GetTaskType() == CTaskTypes::TASK_CUTSCENE, "Trying to set the clip on a CTaskCutscene, but entity %s is not running a cutscene task", m_pCutfObject->GetDisplayName().c_str())) { Matrix34 SceneMat; pCutManager->GetSceneOrientationMatrix(SceneMat); m_pCutSceneTask->SetClip(pClip,SceneMat, fEventTime); } } } //store info about the which section the anim started at. SetAnimPlayBackEventTime(fEventTime); } void CCutSceneAnimatedPropEntity::UpdateCutSceneTask(cutsManager* pManager) { if(GetGameEntity()) { const CObject* pObject = GetGameEntity(); if(pObject && pObject->GetObjectIntelligence()) { CTask* pTask = pObject->GetObjectIntelligence()->FindTaskByType(CTaskTypes::TASK_CUTSCENE); UpdateCutSceneTaskPhase(pTask, pManager); } } } ///////////////////////////////////////////////////////////////////////// CTaskCutScene* CCutsceneAnimatedModelEntity::CreateCutsceneTask(CutSceneManager* pManager, const crClip* pClip, float fEventTime) { Matrix34 SceneMat(M34_IDENTITY); pManager->GetSceneOrientationMatrix(SceneMat); float fPhase = pManager->GetPhaseUpdateAmount(pClip,fEventTime); CTaskCutScene* pTask = rage_new CTaskCutScene(pClip, SceneMat, fPhase, fEventTime); return pTask; } ///////////////////////////////////////////////////////////////////////// void CCutSceneAnimatedPropEntity::DispatchEvent( cutsManager* pManager, const cutfObject* pObject, s32 iEventId, const cutfEventArgs* pEventArgs, const float UNUSED_PARAM(fTime), const u32 UNUSED_PARAM(StickyId) ) { switch ( iEventId ) { case CUTSCENE_PAUSE_EVENT: case CUTSCENE_UPDATE_EVENT: { if (iEventId==CUTSCENE_UPDATE_EVENT && m_bStoppedCalled) { CreateRepositionOnlyGameEntityWhenModelLoaded(pManager, pObject, true, true ); SetGameEntityReadyForGame(pManager); } UpdateCutSceneTask(pManager); } break; } CCutsceneAnimatedModelEntity::DispatchEvent( pManager,pObject, iEventId,pEventArgs); } /////////////////////////////////////////////////////////////////////////////////////////////////// // Animated Weapon Entity /////////////////////////////////////////////////////////////////////////////////////////////////// CCutSceneAnimatedWeaponEntity::CCutSceneAnimatedWeaponEntity(const cutfObject* pObject) :CCutSceneAnimatedPropEntity(pObject) { m_RegisteredGenericWeaponType = 0; } CCutSceneAnimatedWeaponEntity::~CCutSceneAnimatedWeaponEntity() { } u32 CCutSceneAnimatedWeaponEntity::GetCutObjectGenericWeaponType () const { u32 GenericWeaponType = 0; if(m_pCutfObject && m_pCutfObject->GetType() == CUTSCENE_MODEL_OBJECT_TYPE) { const cutfModelObject* pModelObject = static_cast(m_pCutfObject); if(pModelObject && pModelObject->GetModelType() == CUTSCENE_WEAPON_MODEL_TYPE) { const cutfWeaponModelObject* pWeapon = static_cast(pModelObject); if(pWeapon) { GenericWeaponType = pWeapon->GetGenericWeaponType(); } } } return GenericWeaponType; } bool CCutSceneAnimatedWeaponEntity::IsScriptRegisteredGameEntity() { if(m_RegisteredGenericWeaponType == 0) { return CCutsceneAnimatedModelEntity::IsScriptRegisteredGameEntity(); } else { if(m_pCutfObject) { const cutfWeaponModelObject* pWeapon = static_cast(m_pCutfObject); if(pWeapon) { return ((m_RegisteredEntityFromScript.SceneNameHash.GetHash()>0 && (m_RegisteredEntityFromScript.SceneNameHash.GetHash() == GetSceneHandleHash().GetHash())) && pWeapon->GetGenericWeaponType() == m_RegisteredGenericWeaponType); } } } return false; } void CCutSceneAnimatedWeaponEntity::SetGameEntityReadyForCutscene() { // Base CCutSceneAnimatedPropEntity::SetGameEntityReadyForCutscene(); CObject* pGameObject = GetGameEntity(); if (pGameObject && !pGameObject->m_pWeapon && pGameObject->GetBaseModelInfo() && pGameObject->GetBaseModelInfo()->GetModelType() == MI_TYPE_WEAPON) { CWeaponModelInfo* pWeaponModelInfo = static_cast(pGameObject->GetBaseModelInfo()); // Get the weapon info from the model hash const u32 uWeaponModelHash = pWeaponModelInfo->GetModelNameHash(); const CWeaponInfo* pWeaponInfo = CWeaponInfoManager::GetInfoFromModelNameHash(uWeaponModelHash ASSERT_ONLY(, true)); if(pWeaponInfo) { CPedEquippedWeapon::SetupAsWeapon(pGameObject, pWeaponInfo, 0); } } } /////////////////////////////////////////////////////////////////////////////////////////////////// // Animated Actor Entity /////////////////////////////////////////////////////////////////////////////////////////////////// #if __DEV //THIS CURRENTLY DOES NOTHING TO FILTER ANY ANIMS BECAUSE THERE IS NO FILTER TO REMOVE ALL ANIM EXCEPT FACIAL void CCutsceneAnimatedActorEntity::UpdateWithFaceViewer(CutSceneManager* pManager, CTaskCutScene* pCutSceneTask) { if(!pCutSceneTask || !pManager) { return; } const CCutSceneCameraEntity* pCam = pManager->GetCamEntity(); //camera is pointing at ped if(pCam && pCam->IsCameraPointingAtThisObject(this)) { pCutSceneTask->SetCanApplyMoverTrackUpdate(false); Matrix34 mSceneMat(M34_IDENTITY); pManager->GetSceneOrientationMatrix(mSceneMat); //pCutSceneTask->SetFilter(BONEMASK_HEADONLY); //removed because facial anims are applied by extra dofs that arent bones //apply the new ped pos mSceneMat.d.z+=1000.0f; GetGameEntity()->SetMatrix(mSceneMat); } else { //if(pCutSceneTask->GetFilter().GetHash() != BONEMASK_ALL) //{ //removed because facial anims are applied by extra dofs that arent bones this filter will remove facial anims // pCutSceneTask->SetFilter(BONEMASK_ALL); pCutSceneTask->SetCanApplyMoverTrackUpdate(true); //} } }; #endif ///////////////////////////////////////////////////////////////////////// void CCutsceneAnimatedActorEntity::InitActor(CPed* pPed) { if (pPed) { pPed->PopTypeSet(POPTYPE_MISSION); pPed->SetDefaultDecisionMaker(); pPed->SetBlockingOfNonTemporaryEvents(true); pPed->SetPedConfigFlag( CPED_CONFIG_FLAG_DrownsInWater, false ); pPed->GetPedIntelligence()->SetDefaultRelationshipGroup(); pPed->m_nPhysicalFlags.bNotDamagedByAnything = true; //possibly add the rag doll and low lod physics commands here pPed->SetCharParamsBasedOnManagerType(); CGameWorld::Add(pPed, CGameWorld::OUTSIDE); pPed->SetFixedPhysics(true); } }; ///////////////////////////////////////////////////////////////////////// // store the ped variation for when a ped has to be recreated void CCutsceneAnimatedActorEntity::StoreActorVariationData(u32 iComponent, s32 iDrawable, s32 iTexture, sActorVariationData& ActorData ) { cutsceneAssertf((iDrawable>-1 && iTexture>-1) || (iComponent>=PV_MAX_COMP && iDrawable>-2), "Component, Drawable or Texture is invalid (Component: %d (%s), Drawable: %d, Texture: %d)", iComponent, CPedVariationData::GetVarOrPropSlotName(iComponent), iDrawable, iTexture); for (int i =0; i < ActorData.iPedVarData.GetCount(); i++) { if(iComponent == ActorData.iPedVarData[i].iComponent) { ActorData.iPedVarData[i].iDrawable = iDrawable; ActorData.iPedVarData[i].iTexture = iTexture; return; } } sPedComponentVar& NewPedComponent = ActorData.iPedVarData.Grow(); NewPedComponent.iComponent = iComponent; NewPedComponent.iDrawable = iDrawable; NewPedComponent.iTexture = iTexture; } ///////////////////////////////////////////////////////////////////////// // Pass the latest setup to a newly streamed ped void CCutsceneAnimatedActorEntity::RestoreEntityProperties(CEntity * pEnt) { if(pEnt && pEnt->GetIsTypePed()) { CPed* pPed = static_cast(pEnt); for(int i =0; i < m_sCurrentActorVariationData.iPedVarData.GetCount(); i ++) { SetCurrentActorVariation(pPed, m_sCurrentActorVariationData.iPedVarData[i].iComponent, m_sCurrentActorVariationData.iPedVarData[i].iDrawable, m_sCurrentActorVariationData.iPedVarData[i].iTexture); } } } bool CCutsceneAnimatedActorEntity::RemoveEntityFromTheWorld(CEntity * pEnt, bool bDeleteRegistered) { if(pEnt && pEnt->GetIsTypePed()) { CPed* pPed = static_cast(pEnt); { pPed->CleanUpPreloadData(); } } return CCutsceneAnimatedModelEntity::RemoveEntityFromTheWorld(pEnt, bDeleteRegistered); } ///////////////////////////////////////////////////////////////////////// CCutsceneAnimatedActorEntity::CCutsceneAnimatedActorEntity(const cutfObject* pObject) :CCutsceneAnimatedModelEntity(pObject) { GetEntityVariationEvents(); m_VariationStreamingIndex = 0; m_fVehicleLightingScalar = 0.0f; m_fVehicleLightingScalarTargetValue = 0.0f; m_fVehicleLightingScalarBlendRate = 1000.0f; } ///////////////////////////////////////////////////////////////////////// //create our ingame ped void CCutsceneAnimatedActorEntity::CreateGamePed(u32 iModelIndex, bool CreateRepositionEntity) { fwModelId modelId((strLocalIndex(iModelIndex))); CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfo(modelId); cutsceneModelEntityDebugf2("CreateGamePed - Actor"); if(pModelInfo) { cutsceneAssertf(pModelInfo->GetModelType() == MI_TYPE_PED, "CUTSCENE ASSET (Assign to *Default Anim Cutscene*): Exported incorrectly, %s is not a PedModel type", pModelInfo->GetModelName()); if(pModelInfo->GetModelType() == MI_TYPE_PED) { Matrix34 TempMat; TempMat.Identity(); TempMat.d = m_vCreatePos; if(iModelIndex != strLocalIndex::INVALID_INDEX) { const CControlledByInfo localAiControl(false, false); CPedModelInfo* pPedModelInfo = static_cast(pModelInfo); CPed* pPed = NULL; if (CreateRepositionEntity) { pPed = CPedFactory::GetFactory()->CreatePedFromSource(localAiControl, modelId, &TempMat, GetGameEntity(), true, false, false); } else { if(m_sScriptActorVariationData.iPedVarData.GetCount() > 0) { // Previously we called CreatePed with bApplyDefaultVariation = true but this still generated random // peds if the ped was non streamed. Now we use bApplyDefaultVariation = false in order minimise streaming // bandwidth on streamed peds. Either way we need to manually set non streamed peds to default after creation pPed = CPedFactory::GetFactory()->CreatePed(localAiControl, modelId, &TempMat, false, false, false); if (!pPedModelInfo->GetIsStreamedGfx()) { pPed->SetVarDefault(); } } else { pPed = CPedFactory::GetFactory()->CreatePedFromSource(localAiControl, modelId, &TempMat, GetGameRepositionOnlyEntity(), true, false, false); } } CPedInventoryLoadOutManager::SetDefaultLoadOut(pPed); if (Verifyf(pPed, "trying to store a null ped pointer something has gone wrong with the registration")) { if(CreateRepositionEntity) { SetRepositionOnlyEntity(pPed); } else { SetGameEntity(pPed); } } } } } } void CCutsceneAnimatedActorEntity::GetEntityVariationEvents() { m_pVariationEvents.Reset(); atArray AllEventList; const cutfCutsceneFile2* pCutfile = const_cast(CutSceneManager::GetInstance())->GetCutfFile(); pCutfile->FindEventsForObjectIdOnly( m_pCutfObject->GetObjectId(), pCutfile->GetEventList(), AllEventList ); for ( int i = 0; i < AllEventList.GetCount(); ++i ) { if (AllEventList[i]->GetEventId() == CUTSCENE_SET_VARIATION_EVENT) { cutfEventArgs *pEventArgs = const_cast( AllEventList[i]->GetEventArgs()); if(pEventArgs && pEventArgs->GetType() == CUTSCENE_ACTOR_VARIATION_EVENT_ARGS_TYPE) { if(CutSceneManager::GetInstance()->IsConcatted()) { // Are the events in a concat section that is going to be played #if !__NO_OUTPUT const cutfObjectVariationEventArgs* pVariationEventFlag = static_cast( pEventArgs ); int Component = pVariationEventFlag->GetComponent(); int Drawable = pVariationEventFlag->GetDrawable(); int Texture = pVariationEventFlag->GetTexture(); s32 section = CutSceneManager::GetInstance()->GetConcatSectionForTime(AllEventList[i]->GetTime()); #endif bool bValidEventTime = CutSceneManager::GetInstance()->ValidateEventTime(AllEventList[i]->GetTime()); if (bValidEventTime) { cutsceneModelEntityDebugf3("GetEntityVariationEvents:: Variation event has valid section/time (%d/%f) : (Component: %d (%s), Drawable: %d, Texture: %d)", section, AllEventList[i]->GetTime(), Component, CPedVariationData::GetVarOrPropSlotName(Component), Drawable, Texture); m_pVariationEvents.PushAndGrow(AllEventList[i]); } else { cutsceneModelEntityDebugf3("GetEntityVariationEvents:: Variation event has invalid section/time (%d/%f) : (Component: %d (%s), Drawable: %d, Texture: %d)", section, AllEventList[i]->GetTime(), Component, CPedVariationData::GetVarOrPropSlotName(Component), Drawable, Texture ); } } else { m_pVariationEvents.PushAndGrow(AllEventList[i]); } } } } } void CCutsceneAnimatedActorEntity::PreStreamVariations(CutSceneManager* pManager, float CurrentTime, float LookAhead) { float StreamingOffsetBuffer = pManager->CalculateStreamingOffset(LookAhead, CurrentTime); float LookAheadTime = pManager->GetTime() + StreamingOffsetBuffer; //cutsceneModelEntityDebugf("PreStreamVariations - Current Time (%6.4f) -> Streaming time(%6.4f)", pManager->GetTime(), pManager->GetTime() + StreamingOffsetBuffer); for ( int i = m_VariationStreamingIndex; i < m_pVariationEvents.GetCount(); ++i ) { if(m_pVariationEvents[i]->GetTime() <= LookAheadTime) { bool bIsValidEventTime = true; if (pManager->IsConcatted()) { bIsValidEventTime = pManager->ValidateEventTime(m_pVariationEvents[i]->GetTime()); } if ( bIsValidEventTime) { const cutfObjectVariationEventArgs *pEventArgs = static_cast( m_pVariationEvents[i]->GetEventArgs() ); if(pEventArgs) { s32 Component = pEventArgs->GetComponent(); s32 Drawable = pEventArgs->GetDrawable(); s32 Texture = pEventArgs->GetTexture(); if((Component>-1 && Drawable>-1 && Texture>-1) || (Component>=PV_MAX_COMP && Drawable>-1)) { pManager->GetAssetManager()->SetActorVariationStreamingRequest(Component, Drawable, Texture, m_ModelNameHash, m_pCutfObject->GetObjectId()); } else { if (Component-1 && Drawable>-1 && Texture>-1) || (Component>=PV_MAX_COMP && Drawable>-2)) { cutsceneModelEntityDebugf3("ComputeInitialVariations - Script variation (Component: %d (%s), Drawable: %d, Texture: %d)", Component, CPedVariationData::GetVarOrPropSlotName(Component), Drawable, Texture); StoreActorVariationData(Component, Drawable, Texture, m_sCurrentActorVariationData); } } // For each cutscene variation event that happened on the start frame (may or may not be 0.0 depending on if the cutscene in branched) for ( int i = m_VariationStreamingIndex; i < m_pVariationEvents.GetCount(); ++i ) { float fEventTime = m_pVariationEvents[i]->GetTime(); float fStartTime = CutSceneManager::GetInstance()->GetStartTime(); if(fEventTime <= fStartTime) { bool bIsValidEventTime = true; if (CutSceneManager::GetInstance()->IsConcatted()) { bIsValidEventTime = CutSceneManager::GetInstance()->ValidateEventTime(fEventTime); } if (bIsValidEventTime) { bool bUseVariationFromCutsceneStartFrame = true; const cutfObjectVariationEventArgs *pEventArgs = static_cast( m_pVariationEvents[i]->GetEventArgs() ); if(pEventArgs) { s32 Component = pEventArgs->GetComponent(); s32 Drawable = pEventArgs->GetDrawable(); s32 Texture = pEventArgs->GetTexture(); if((Component>-1 && Drawable>-1 && Texture>-1) || (Component>=PV_MAX_COMP && Drawable>-2)) { // Favour script variation events over cutscene variation events on the first frame for(int j = 0; j < m_sScriptActorVariationData.iPedVarData.GetCount(); j++ ) { if((u32)Component == m_sScriptActorVariationData.iPedVarData[j].iComponent) { cutsceneModelEntityDebugf3("ComputeInitialVariations - Script variation (Component: %d (%s), Drawable: %d, Texture: %d) used rather than cutscene start frame variation (Component: %d (%s), Drawable: %d, Texture: %d)", m_sScriptActorVariationData.iPedVarData[j].iComponent, CPedVariationData::GetVarOrPropSlotName(m_sScriptActorVariationData.iPedVarData[j].iComponent), m_sScriptActorVariationData.iPedVarData[j].iDrawable, m_sScriptActorVariationData.iPedVarData[j].iTexture, Component, CPedVariationData::GetVarOrPropSlotName(Component), Drawable, Texture); bUseVariationFromCutsceneStartFrame = false; break; } } if(bUseVariationFromCutsceneStartFrame) { cutsceneModelEntityDebugf3("ComputeInitialVariations - Cutscene start frame variation (Component: %d (%s), Drawable: %d, Texture: %d)", Component, CPedVariationData::GetVarOrPropSlotName(Component), Drawable, Texture); StoreActorVariationData(Component, Drawable, Texture, m_sCurrentActorVariationData); } } else { cutsceneModelEntityDebugf3( "ComputeInitialVariations: Ignoring invalid cutscene variation event (Component: %d (%s), Drawable: %d, Texture: %d)", Component, CPedVariationData::GetVarOrPropSlotName(Component), Drawable, Texture); } } else { cutsceneModelEntityDebugf3( "ComputeInitialVariations: Ignoring invalid cutscene variation args"); } } // Cutscene variations events are so increment m_VariationStreamingIndex so we don't consider this variation again m_VariationStreamingIndex++; } } // // Make sure all variation kinds have at least a default entry // // For each kind of variation component for(u32 i = 0; i < PV_MAX_COMP; i++) { // Search for a valid entry bool bFoundValidVariationEntry = false; for(u32 j=0; j-1 && Drawable>-1 && Texture>-1) || (Component>=PV_MAX_COMP && Drawable>-1)) { eStreamingRequestReturnValue streamingRequestReturnValue = CutSceneManager::GetInstance()->GetAssetManager()->SetActorVariationStreamingRequest((u32)Component, (u32)Drawable, (u32)Texture, m_ModelNameHash, m_pCutfObject->GetObjectId()); if(Component < PV_MAX_COMP) { if ((streamingRequestReturnValue == ESRRV_INVALID_VARIATION) && (Drawable > 0 || Texture > 0)) { cutsceneModelEntityDebugf3( "ComputeInitialVariations: Ignoring invalid cutscene variation request (Component: %d (%s), Drawable: %d, Texture: %d) (requesting default instead)", Component, CPedVariationData::GetVarOrPropSlotName(Component), Drawable, Texture); CutSceneManager::GetInstance()->GetAssetManager()->SetActorVariationStreamingRequest((u32)Component, 0, 0, m_ModelNameHash, m_pCutfObject->GetObjectId()); } } } else { if (ComponentGetEndTime(); float fStartTime = CutSceneManager::GetInstance()->GetStartTime(); // Search through all the variation events for this ped from the current time to the end time for ( int i = 0; i < m_pVariationEvents.GetCount(); ++i ) { float fEventTime = m_pVariationEvents[i]->GetTime(); if((fEventTime > fStartTime) && (fEventTime <= fEndTime)) { bool bIsValidEventTime = true; if (CutSceneManager::GetInstance()->IsConcatted()) { bIsValidEventTime = CutSceneManager::GetInstance()->ValidateEventTime(fEventTime); } if (bIsValidEventTime) { const cutfObjectVariationEventArgs *pEventArgs = static_cast( m_pVariationEvents[i]->GetEventArgs() ); if(pEventArgs) { s32 Component = pEventArgs->GetComponent(); s32 Drawable = pEventArgs->GetDrawable(); s32 Texture = pEventArgs->GetTexture(); if((Component>-1 && Drawable>-1 && Texture>-1) || (Component>=PV_MAX_COMP)) { cutsceneModelEntityDebugf3("ComputeVariationsForSkip - Cutscene variation (not start frame) (Component: %d (%s), Drawable: %d, Texture: %d)", Component, CPedVariationData::GetVarOrPropSlotName(Component), Drawable, Texture); StoreActorVariationData(Component, Drawable, Texture, m_sCurrentActorVariationData); } else { cutsceneModelEntityDebugf3( "ComputeVariationsForSkip: Ignoring invalid cutscene variation event (Component: %d (%s), Drawable: %d, Texture: %d)", Component, CPedVariationData::GetVarOrPropSlotName(Component), Drawable, Texture); } } else { cutsceneModelEntityDebugf3( "ComputeVariationsForSkip: Ignoring invalid cutscene variation args"); } } } } // // Make sure all variation kinds have at least a default entry // // For each kind of variation for(u32 i = 0; i < PV_MAX_COMP; i++) { // Search for a matching entry bool bFoundComponent = false; for(int j=0; j-1 && Drawable>-1 && Texture>-1) || (Component>=PV_MAX_COMP && Drawable>-1)) { eStreamingRequestReturnValue streamingRequestReturnValue = CutSceneManager::GetInstance()->GetAssetManager()->SetActorVariationStreamingRequest((u32)Component, (u32)Drawable, (u32)Texture, modelNameHash, m_pCutfObject->GetObjectId()); if(Component < PV_MAX_COMP) { if ((streamingRequestReturnValue == ESRRV_INVALID_VARIATION) && (Drawable > 0 || Texture > 0)) { cutsceneModelEntityDebugf3( "ComputeVariationsForSkip: Ignoring invalid cutscene variation request (Component: %d (%s), Drawable: %d, Texture: %d) (requesting default instead)", Component, CPedVariationData::GetVarOrPropSlotName(Component), Drawable, Texture); CutSceneManager::GetInstance()->GetAssetManager()->SetActorVariationStreamingRequest((u32)Component, 0, 0, modelNameHash, m_pCutfObject->GetObjectId()); } } } else { if (ComponentGetPortalTracker()->SetIsCutsceneControlled(true); if (IsScriptRegisteredGameEntity()) { m_RegisteredEntityFromScript.pEnt = pPed; } m_bCreatedByCutscene = true; } } void CCutsceneAnimatedActorEntity::CreateGameEntity(strLocalIndex iModelIndex, bool CreateRepositionEntity, bool bRequestVariations, bool bApplyVariations) { CPed* pPed = NULL; if(CreateRepositionEntity) { pPed = GetGameRepositionOnlyEntity(); } else { pPed = GetGameEntity(); } if(pPed == NULL) { cutsceneModelEntityDebugf2("CreateGameEntity - Actor - bRequestVariations(%s), bApplyVariations(%s)", bRequestVariations ? "T" : "F", bApplyVariations ? "T" : "F"); CreateGamePed(iModelIndex.Get(), CreateRepositionEntity); if(CreateRepositionEntity) { pPed = GetGameRepositionOnlyEntity(); } else { pPed = GetGameEntity(); } } if(pPed && !pPed->GetIsAddedToWorld()) { AddActorToWorld(pPed); } if (pPed) { if (bRequestVariations && !IsBlockingVariationStreamingAndApplication()) { // // Make sure all variation kinds have at least a default entry // // For each kind of variation component for(u32 i = 0; i < PV_MAX_COMP; i++) { // Search for a valid entry bool bFoundValidVariationEntry = false; for(u32 j=0; j-1 && Drawable>-1 && Texture>-1) || (Component>=PV_MAX_COMP && Drawable>-1)) { if (pPed && pPed->GetPedModelInfo() && pPed->GetPedModelInfo()->GetIsStreamedGfx()) { atHashString modelNameHash(m_ModelNameHash); if (CreateRepositionEntity && m_RegisteredEntityFromScript.ModelNameHash.GetHash()>0) { modelNameHash = m_RegisteredEntityFromScript.ModelNameHash.GetHash(); } // Now we have a ped pointer we can check the variation requested by the cutscene or script is valid if (pPed->IsVariationInRange(static_cast(Component), Drawable, Texture)) { CutSceneManager::GetInstance()->GetAssetManager()->SetActorVariationStreamingRequest((u32)Component, (u32)Drawable, (u32)Texture, modelNameHash, m_pCutfObject->GetObjectId()); } else { if (Drawable > 0 || Texture > 0) { cutsceneModelEntityDebugf2( "CreateGameEntity: Ignoring out of range cutscene variation request (Component: %d (%s), Drawable: %d, Texture: %d) (requesting default instead)", Component, CPedVariationData::GetVarOrPropSlotName(Component), Drawable, Texture); CutSceneManager::GetInstance()->GetAssetManager()->SetActorVariationStreamingRequest((u32)Component, 0, 0, modelNameHash, m_pCutfObject->GetObjectId()); } else { cutsceneModelEntityDebugf2( "CreateGameEntity: Ignoring out of range cutscene variation request (Component: %d (%s), Drawable: %d, Texture: %d) (no valid default)", Component, CPedVariationData::GetVarOrPropSlotName(Component), Drawable, Texture); } } } } else { //cutsceneModelEntityDebugf( "CCutsceneAnimatedActorEntity: Ignoring invalid cutscene variation event (Component: %d (%s), Drawable: %d, Texture: %d)", Component, CPedVariationData::GetVarOrPropSlotName(Component), Drawable, Texture); } } } if (bApplyVariations && !IsBlockingVariationStreamingAndApplication()) { // Apply the current variations RestoreEntityProperties(pPed); } } } void CCutsceneAnimatedActorEntity::UpdateCutSceneTask(cutsManager* pManager) { CutSceneManager* pCutsManager = static_cast(pManager); if(GetGameEntity()) { CTask* pTask = GetGameEntity()->GetPedIntelligence()->FindTaskByType(CTaskTypes::TASK_CUTSCENE); if(pTask && pTask->GetTaskType() == CTaskTypes::TASK_CUTSCENE) { CTaskCutScene* pCutSceneTask = static_cast(pTask); const crClip* pClip = pCutSceneTask->GetClip(); if (pClip) { float fPhase = pCutsManager->GetPhaseUpdateAmount(pClip, GetAnimEventStartTime()); float fLastPhase = pCutsManager->GetAnimPhaseForSection(pClip->GetDuration(),GetAnimEventStartTime(),pCutsManager->GetCutScenePreviousTime()); GetMoverTrackVelocity(pClip,fPhase,fLastPhase, pCutsManager->GetCurrentCutSceneTimeStep()); //Vector3 localEuler = pCutSceneTask->GetAnimOrigin().GetEulers(); //printf("Rotation for %s: %7.4f, %7.4f, %7.4f \n", pClip->GetName(), localEuler.x*RtoD, localEuler.y*RtoD, localEuler.z*RtoD); //UpdateActorMotionState(); GetGameEntity()->SetDesiredHeading(GetGameEntity()->GetTransform().GetHeading()); UpdateCutSceneTaskPhase(pTask, pManager); #if __DEV //THIS CURRENTLY DOES NOTHING TO FILTER ANY ANIMS BECAUSE THERE IS NO FILTER TO REMOVE ALL ANIM EXCEPT FACIAL UpdateWithFaceViewer(pCutsManager, pCutSceneTask); #endif // Vehicle lighting - Have we crossed any CutsceneBlendToVehicleLighting tags? const crTags* pTags = pClip->GetTags(); if (pTags) { for (int i=0; i < pTags->GetNumTags(); i++) { const crTag* pTag = pTags->GetTag(i); if (pTag) { //static CClipEventTags::Key cutsceneBlendToVehicleLightingKey("CutsceneBlendToVehicleLighting",0xB8336AF5); if (pTag->GetKey() == CClipEventTags::CutsceneBlendToVehicleLighting.GetHash()) { // Tag phase const float fTagPhase = pTag->GetStart(); // Process this tag? if (fTagPhase >= fLastPhase && fTagPhase <= fPhase) { const crProperty& rProperty = pTag->GetProperty(); const crPropertyAttribute* pAttribTarget = rProperty.GetAttribute(CClipEventTags::TargetValue.GetHash()); const crPropertyAttribute* pAttribTime = rProperty.GetAttribute(CClipEventTags::BlendTime.GetHash()); // Target value if (pAttribTarget && pAttribTarget->GetType() == crPropertyAttribute::kTypeFloat) { const crPropertyAttributeFloat* pTagTargetValueFloat = static_cast(pAttribTarget); { m_fVehicleLightingScalarTargetValue = pTagTargetValueFloat->GetFloat(); m_fVehicleLightingScalarTargetValue = Clamp(m_fVehicleLightingScalarTargetValue, 0.0f, 1.0f); } } // Blend time - converted to rate if (pAttribTime && pAttribTime->GetType() == crPropertyAttribute::kTypeFloat) { const crPropertyAttributeFloat* pTagBlendTimeFloat = static_cast(pAttribTime); { const float fBlendTime = pTagBlendTimeFloat->GetFloat(); if (fBlendTime > VERY_SMALL_FLOAT) { // Blend up or down? if (m_fVehicleLightingScalarTargetValue < m_fVehicleLightingScalar) { m_fVehicleLightingScalarBlendRate = -(1.0f / fBlendTime); } else { m_fVehicleLightingScalarBlendRate = 1.0f / fBlendTime; } } else { m_fVehicleLightingScalarBlendRate = 1000.0f; } } } } } } } } } // Vehicle lighting - Update vehicle lighting scalar. if (m_fVehicleLightingScalar != m_fVehicleLightingScalarTargetValue) { Assert(m_fVehicleLightingScalarTargetValue >= 0.0f && m_fVehicleLightingScalarTargetValue <= 1.0f); if (m_fVehicleLightingScalarBlendRate == 1000.0f || m_fVehicleLightingScalarBlendRate == -1000.0f) { // Instant m_fVehicleLightingScalar = m_fVehicleLightingScalarTargetValue; } else { // Blend const float fDelta = pCutsManager->GetCutSceneCurrentTime() - pCutsManager->GetCutScenePreviousTime(); m_fVehicleLightingScalar += (fDelta * m_fVehicleLightingScalarBlendRate); // Clamp if (m_fVehicleLightingScalarBlendRate < 0.0f && m_fVehicleLightingScalar < m_fVehicleLightingScalarTargetValue) { m_fVehicleLightingScalar = m_fVehicleLightingScalarTargetValue; } else if (m_fVehicleLightingScalarBlendRate > 0.0f && m_fVehicleLightingScalar > m_fVehicleLightingScalarTargetValue) { m_fVehicleLightingScalar = m_fVehicleLightingScalarTargetValue; } } } // Set the vehicle lighting scalar on the cutscene task Assert(m_fVehicleLightingScalar >= 0.0f && m_fVehicleLightingScalar <= 1.0f); pCutSceneTask->SetVehicleLightingScalar(m_fVehicleLightingScalar); } } } void CCutsceneAnimatedActorEntity:: ForceUpdateAi(cutsManager* pManager) { if(pManager) { CutSceneManager* pCutSceneManager = static_cast (pManager); if(pCutSceneManager->GetShutDownMode() != SHUTDOWN_SESSION) { CPed* pPed = GetGameEntity(); if (pPed) { pPed->InstantAIUpdate(); } } } }; ///////////////////////////////////////////////////////////////////////// void CCutsceneAnimatedActorEntity::SetGameEntityReadyForGame(cutsManager* pManager) { if(!m_bIsReadyForGame) { cutsceneModelEntityDebugf2("SetGameEntityReadyForGame - Actor"); if (GetGameEntity()) { NetworkInterface::CutsceneFinishedOnEntity(*GetGameEntity()); } if (GetGameRepositionOnlyEntity()) { NetworkInterface::CutsceneFinishedOnEntity(*GetGameRepositionOnlyEntity()); } if (GetGameEntity() && !GetGameRepositionOnlyEntity()) { #if !__NO_OUTPUT ResetEntityForCallStackLogging(); #endif //only set entities needed for the game ready for the game if(m_RegisteredEntityFromScript.bCreatedForScript || !m_RegisteredEntityFromScript.bDeleteBeforeEnd) { cutsceneModelEntityDebugf2("SetGameEntityReadyForGame: Setting cutscene ped (%s) ready for game", GetGameEntity()->GetModelName()); SetVisibility(GetGameEntity(), true); cutsceneModelEntityDebugf2("CCutsceneAnimatedActorEntity::SetGameEntityReadyForGame1 : Showing GetGameEntity (%s)", GetGameEntity()->GetModelName()); GetGameEntity()->SetDesiredHeading(GetGameEntity()->GetTransform().GetHeading()); GetGameEntity()->SetFixedPhysics(false); GetGameEntity()->EnableCollision(); GetGameEntity()->SetUseExtractedZ(false); GetGameEntity()->m_nPhysicalFlags.bNotDamagedByAnything = m_bWasInvincible; GetGameEntity()->SetVelocity(GetAnimatedVelocity()); if (m_OptionFlags.IsFlagSet(CEO_RESET_CAPSULE_AT_END)) { GetGameEntity()->ClearBound(); GetGameEntity()->SetBoundPitch(0.0f); GetGameEntity()->SetBoundHeading(0.0f); GetGameEntity()->SetBoundOffset(VEC3_ZERO); } if(m_pCutfObject && !GetGameEntity()->GetPedAiLod().IsSafeToSwitchToFullPhysics()) { cutsceneModelEntityWarningf("Scene %s has left %s where it's unsafe to turn physics on. Check that the anim is leaving the player out of collision with objects or map", pManager->GetCutsceneName(), m_pCutfObject->GetDisplayName().c_str()); } GetGameEntity()->GetPedAiLod().ClearLowLodPhysicsFlag(); //if the entity is created by the scene lets reset these variables if(m_bCreatedByCutscene) { GetGameEntity()->SetBlockingOfNonTemporaryEvents(false); GetGameEntity()->SetPedConfigFlag( CPED_CONFIG_FLAG_DrownsInWater, true ); } CutSceneManager* pCutSceneManager = static_cast(pManager); //Set the matrices to be the same for the ragdoll if the scene has been skipped if(pCutSceneManager->WasSkipped()) { if(GetGameEntity()->GetRagdollInst() && GetGameEntity()->GetRagdollInst()->IsInLevel() && GetGameEntity()->GetRagdollState()!=RAGDOLL_STATE_PHYS && GetGameEntity()->GetRagdollState()!=RAGDOLL_STATE_ANIM_DRIVEN) { GetGameEntity()->GetRagdollInst()->SetMatrix(GetGameEntity()->GetMatrix()); PHSIM->SetLastInstanceMatrix(GetGameEntity()->GetRagdollInst(), GetGameEntity()->GetMatrix()); GetGameEntity()->GetRagdollInst()->PoseBoundsFromSkeleton(true, true); GetGameEntity()->GetRagdollInst()->PoseBoundsFromSkeleton(true, true); } } CPed* pPed = GetGameEntity(); if (pPed->GetFacialData()) { pPed->GetFacialData()->ResetFacialIdleAnimation(pPed); } if (!m_OptionFlags.IsFlagSet(CEO_PRESERVE_FACE_BLOOD_DAMAGE)) { pPed->HideBloodDamage(kDamageZoneHead, false); } if (!m_OptionFlags.IsFlagSet(CEO_PRESERVE_BODY_BLOOD_DAMAGE)) { if (m_OptionFlags.IsFlagSet(CEO_REMOVE_BODY_BLOOD_DAMAGE)) { pPed->HideBloodDamage(kDamageZoneTorso, false); pPed->HideBloodDamage(kDamageZoneLeftArm, false); pPed->HideBloodDamage(kDamageZoneRightArm, false); pPed->HideBloodDamage(kDamageZoneLeftLeg, false); pPed->HideBloodDamage(kDamageZoneRightLeg, false); } else { pPed->LimitBloodDamage(kDamageZoneTorso, -1); pPed->LimitBloodDamage(kDamageZoneLeftArm, -1); pPed->LimitBloodDamage(kDamageZoneRightArm, -1); pPed->LimitBloodDamage(kDamageZoneLeftLeg, -1); pPed->LimitBloodDamage(kDamageZoneRightLeg, -1); } } } else { cutsceneModelEntityDebugf2("SetGameEntityReadyForGame: Disabling collision on cutscene ped (%s) as it is to be deleted", GetGameEntity()->GetModelName()); //Switch off the collision flags as this entity is to be deleted if(GetGameEntity()->GetCurrentPhysicsInst()->IsInLevel()) { CPhysics::GetLevel()->SetInstanceIncludeFlags(GetGameEntity()->GetCurrentPhysicsInst()->GetLevelIndex(), 0); } } } else { //Switch off the collision flags as this entity is to be deleted if(GetGameEntity() && GetGameEntity()->GetCurrentPhysicsInst()->IsInLevel()) { cutsceneModelEntityDebugf2("SetGameEntityReadyForGame: Disabling collision on cutscene ped (%s) as it is to be deleted", GetGameEntity()->GetModelName()); CPhysics::GetLevel()->SetInstanceIncludeFlags(GetGameEntity()->GetCurrentPhysicsInst()->GetLevelIndex(), 0); } } if (GetGameRepositionOnlyEntity() && !m_RegisteredEntityFromScript.bDeleteBeforeEnd) { cutsceneModelEntityDebugf2("SetGameEntityReadyForGame: Setting reposition ped (%s) ready for game", GetGameRepositionOnlyEntity()->GetModelName()); GetGameRepositionOnlyEntity()->SetFixedPhysics(false); GetGameRepositionOnlyEntity()->SetPosition(m_CurrentPosition); GetGameRepositionOnlyEntity()->SetHeading(m_CurrentHeading); GetGameRepositionOnlyEntity()->SetDesiredHeading(m_CurrentHeading); GetGameRepositionOnlyEntity()->GetPortalTracker()->RequestRescanNextUpdate(); GetGameRepositionOnlyEntity()->EnableCollision(); GetGameRepositionOnlyEntity()->SetVelocity(GetAnimatedVelocity()); if (m_OptionFlags.IsFlagSet(CEO_RESET_CAPSULE_AT_END)) { GetGameRepositionOnlyEntity()->ClearBound(); GetGameRepositionOnlyEntity()->SetBoundPitch(0.0f); GetGameRepositionOnlyEntity()->SetBoundHeading(0.0f); GetGameRepositionOnlyEntity()->SetBoundOffset(VEC3_ZERO); } GetGameRepositionOnlyEntity()->m_nPhysicalFlags.bNotDamagedByAnything = m_bWasInvincible; GetGameRepositionOnlyEntity()->SetIsVisibleForModule(SETISVISIBLE_MODULE_CUTSCENE, true); cutsceneModelEntityDebugf2("CCutsceneAnimatedActorEntity::SetGameEntityReadyForGame2: Showing GetGameRepositionOnlyEntity (%s)", GetGameRepositionOnlyEntity()->GetModelName()); CPed* pPed = GetGameRepositionOnlyEntity(); if (pPed->GetFacialData()) { pPed->GetFacialData()->ResetFacialIdleAnimation(pPed); } if (GetGameEntity()) { SetVisibility(GetGameEntity(), false); cutsceneModelEntityDebugf2("CCutsceneAnimatedActorEntity::SetGameEntityReadyForGame3: Hiding GetGameEntity (%s)", GetGameEntity()->GetModelName()); } } if (m_pCutSceneTask) { m_pCutSceneTask->SetExitNextUpdate(); } m_bIsReadyForGame = true; } } ///////////////////////////////////////////////////////////////////////// void CCutsceneAnimatedActorEntity::SetGameEntityReadyForCutscene() { if (GetGameEntity()) { #if !__NO_OUTPUT SetUpEntityForCallStackLogging(); #endif cutsceneModelEntityDebugf2("SetGameEntityReadyForCutscene - Actor"); m_fOriginalLODMultiplier = GetGameEntity()->GetLodMultiplier(); GetGameEntity()->SetLodMultiplier(4.0f); //remove any tasks or motion on the peds before scene starts // PedIntelligence->FlushImmediately should be done before EquipWeapon to ensure correct prop cleanup [12/21/2012 mdawe] GetGameEntity()->GetPedIntelligence()->FlushImmediately(true); // Set the ped's hands to be empty [12/21/2012 mdawe] if(GetGameEntity()->GetWeaponManager()) { GetGameEntity()->GetWeaponManager()->EquipWeapon(GetGameEntity()->GetDefaultUnarmedWeaponHash(), -1, true); } // Kill off any non-facial idle animations if (GetGameEntity()->GetAnimDirector()) { fwAnimDirectorComponentFacialRig* pFacialRigComp = GetGameEntity()->GetAnimDirector()->GetComponentByPhase(fwAnimDirectorComponent::kPhaseAll); if (pFacialRigComp) { pFacialRigComp->RemoveAllNonIdleFacialAnims(); } } if (GetGameEntity()->GetIsAttachedToGround()) { GetGameEntity()->DetachFromGround(); } GetGameEntity()->SetPedResetFlag(CPED_RESET_FLAG_DisableGroundAttachment, true); GetGameEntity()->SetIsCrouching(false); GetGameEntity()->RemoveMovementAnims(); GetGameEntity()->BlendOutAnyNonMovementAnims(INSTANT_BLEND_OUT_DELTA); GetGameEntity()->StopAllMotion(true); if(!m_OptionFlags.IsFlagSet(CEO_DONT_RESET_PED_CAPSULE)) { GetGameEntity()->InstantResetDesiredMainMoverCapsuleDataForCutscene(); } GetGameEntity()->SetFixedPhysics(true); GetGameEntity()->DisableCollision(); GetGameEntity()->m_nPhysicalFlags.bNotDamagedByAnything = true; // Clone damage from reposition only entity? if(GetGameRepositionOnlyEntity() && m_OptionFlags.IsFlagSet(CEO_CLONE_DAMAGE_TO_CS_MODEL)) { GetGameEntity()->CloneDamage(GetGameRepositionOnlyEntity(), true); } if (m_OptionFlags.IsFlagSet(CEO_PRESERVE_HAIR_SCALE)) { m_fOriginalHairScale = GetGameEntity()->GetTargetHairScale(); } if (!m_OptionFlags.IsFlagSet(CEO_PRESERVE_FACE_BLOOD_DAMAGE)) { GetGameEntity()->HideBloodDamage(kDamageZoneHead, true); PEDDAMAGEMANAGER.ClearDamageDecals( GetGameEntity()->GetDamageSetID(), kDamageZoneHead, ATSTRINGHASH("bruise",0xe838afb1)); } if (!m_OptionFlags.IsFlagSet(CEO_PRESERVE_BODY_BLOOD_DAMAGE)) { if (m_OptionFlags.IsFlagSet(CEO_REMOVE_BODY_BLOOD_DAMAGE)) { GetGameEntity()->HideBloodDamage(kDamageZoneTorso, true); GetGameEntity()->HideBloodDamage(kDamageZoneLeftArm, true); GetGameEntity()->HideBloodDamage(kDamageZoneRightArm, true); GetGameEntity()->HideBloodDamage(kDamageZoneLeftLeg, true); GetGameEntity()->HideBloodDamage(kDamageZoneRightLeg, true); } else { static s32 s_maxBloodDamageForCutscene = 2; GetGameEntity()->LimitBloodDamage(kDamageZoneTorso, s_maxBloodDamageForCutscene); GetGameEntity()->LimitBloodDamage(kDamageZoneLeftArm, s_maxBloodDamageForCutscene); GetGameEntity()->LimitBloodDamage(kDamageZoneRightArm, s_maxBloodDamageForCutscene); GetGameEntity()->LimitBloodDamage(kDamageZoneLeftLeg, s_maxBloodDamageForCutscene); GetGameEntity()->LimitBloodDamage(kDamageZoneRightLeg, s_maxBloodDamageForCutscene); } } if (m_OptionFlags.IsFlagSet(CEO_IS_CASCADE_SHADOW_FOCUS_ENTITY_DURING_EXIT) && CutSceneManager::GetInstance() && CutSceneManager::GetInstance()->GetCamEntity()) { // Register this with the camera CCutSceneCameraEntity* pCam = const_cast(CutSceneManager::GetInstance()->GetCamEntity()); if (pCam) { if (GetGameRepositionOnlyEntity()) { pCam->SetCascadeShadowFocusEntityForSeamlessExit(GetGameRepositionOnlyEntity()); } else { pCam->SetCascadeShadowFocusEntityForSeamlessExit(GetGameEntity()); } } } NetworkInterface::CutsceneStartedOnEntity(*GetGameEntity()); } } void CCutsceneAnimatedActorEntity::SetRepositionOnlyEntityReadyForCutscene() { if(GetGameRepositionOnlyEntity()) { m_fOriginalLODMultiplier = GetGameRepositionOnlyEntity()->GetLodMultiplier(); GetGameRepositionOnlyEntity()->SetLodMultiplier(4.0f); if(GetGameRepositionOnlyEntity()->GetWeaponManager()) { GetGameRepositionOnlyEntity()->GetWeaponManager()->EquipWeapon(GetGameRepositionOnlyEntity()->GetDefaultUnarmedWeaponHash(), -1, true); } if(GetGameRepositionOnlyEntity()->IsNetworkClone()) { GetGameRepositionOnlyEntity()->GetPedIntelligence()->FlushImmediately(false); GetGameRepositionOnlyEntity()->GetPedIntelligence()->AddTaskDefault(rage_new CTaskNetworkClone()); } else { GetGameRepositionOnlyEntity()->GetPedIntelligence()->FlushImmediately(true); } GetGameRepositionOnlyEntity()->SetIsCrouching(false); GetGameRepositionOnlyEntity()->RemoveMovementAnims(); GetGameRepositionOnlyEntity()->BlendOutAnyNonMovementAnims(INSTANT_BLEND_OUT_DELTA); GetGameRepositionOnlyEntity()->StopAllMotion(true); GetGameRepositionOnlyEntity()->DisableCollision(); GetGameRepositionOnlyEntity()->SetFixedPhysics(true); GetGameRepositionOnlyEntity()->m_nPhysicalFlags.bNotDamagedByAnything = true; GetGameRepositionOnlyEntity()->SetIsVisibleForModule(SETISVISIBLE_MODULE_CUTSCENE, false); cutsceneModelEntityDebugf2("CCutsceneAnimatedActorEntity::SetRepositionOnlyEntityReadyForCutscene: Hiding GetGameRepositionOnlyEntity (%s)", GetGameRepositionOnlyEntity()->GetModelName()); NetworkInterface::CutsceneStartedOnEntity(*GetGameRepositionOnlyEntity()); } } ///////////////////////////////////////////////////////////////////////// void CCutsceneAnimatedActorEntity::UpdateActorMotionState() { if(GetGameEntity()) { GetGameEntity()->ForceMotionStateThisFrame(CPedMotionStates::MotionState_DoNothing); } } ///////////////////////////////////////////////////////////////////////// namespace { void* g_pCharClothController = NULL; int g_capsuleLeftT = 0; int g_capsuleRightT = 1; float g_customLength = -1.0f; float g_customRadius = -1.0f; } void CCutsceneAnimatedActorEntity::DispatchEvent(cutsManager* pManager, const cutfObject* pObject, s32 iEventId, const cutfEventArgs* pEventArgs,const float fEventTime, const u32 UNUSED_PARAM(StickyId)) { switch ( iEventId ) { case CUTSCENE_UPDATE_EVENT: case CUTSCENE_PAUSE_EVENT: { if (m_bIsReadyForGame) { return; } /*if ( iEventId == CUTSCENE_UPDATE_EVENT) { cutsceneModelEntityDebugf("CCutsceneAnimatedActorEntity::DispatchEvent: CUTSCENE_UPDATE_EVENT"); } else { cutsceneModelEntityDebugf("CCutsceneAnimatedActorEntity::DispatchEvent: CUTSCENE_PAUSE_EVENT"); }*/ CutSceneManager* pCutSceneManager = static_cast(pManager); if (GetGameEntity()) GetGameEntity()->SetPedResetFlag(CPED_RESET_FLAG_OverridePhysics, true); if(GetGameEntity() && m_pCutSceneTask == NULL) { GetGameEntity()->SetPedResetFlag(CPED_RESET_FLAG_DisablePotentialBlastReactions, true); } if(!IsBlockingVariationStreamingAndApplication()) { PreStreamVariations(pCutSceneManager, pManager->GetTime(), PED_VARIATION_STREAMING_OFFSET); } if (iEventId==CUTSCENE_UPDATE_EVENT && m_bStoppedCalled) { CreateRepositionOnlyGameEntityWhenModelLoaded(pManager, pObject, true, true ); SetGameEntityReadyForGame(pManager); } UpdateCutSceneTask(pManager); //Need to prevent time slicing if being updated by the cut scene system, cant just rely on the task blocking it if (GetGameEntity()) { GetGameEntity()->GetPedAiLod().SetForceNoTimesliceIntelligenceUpdate(true); GetGameEntity()->GetPedAiLod().SetBlockedLodFlag(CPedAILod::AL_LodTimesliceIntelligenceUpdate | CPedAILod::AL_LodTimesliceAnimUpdate); } } break; case CUTSCENE_SET_VARIATION_EVENT: { if(IsBlockingVariationStreamingAndApplication()) { return; } if (m_bIsReadyForGame) { //cutsceneModelEntityDebugf("CCutsceneAnimatedActorEntity::DispatchEvent: Ignoring CUTSCENE_SET_VARIATION_EVENT m_bIsReadyForGame = false"); return; } CutSceneManager* pCutSceneManager = static_cast(pManager); //dont set the variations from the first frame, it has already been done. if((pCutSceneManager->GetCutSceneCurrentTime() > pCutSceneManager->GetStartTime()) && (fEventTime > pCutSceneManager->GetStartTime()) && !m_bIsReadyForGame ) { if(!GetGameEntity()) { cutsceneModelEntityWarningf("No ped entity to set a variation on %s", pObject->GetDisplayName().c_str()); } //cutsceneModelEntityDebugf("CCutsceneAnimatedActorEntity::DispatchEvent - CUTSCENE_SET_VARIATION_EVENT"); cutsceneAssertf(pEventArgs, "Cutscene content bug! CUTSCENE_SET_VARIATION_EVENT (object name=%s type=%s)(event id=%i) is corrupted and needs to be recreated, variation will not be applied!", pObject->GetDisplayName().c_str(), pObject->GetTypeName(), iEventId); if (pEventArgs && pEventArgs->GetType() == CUTSCENE_ACTOR_VARIATION_EVENT_ARGS_TYPE) { CutSceneManager* pCutSceneManager = static_cast(pManager); CCutSceneAssetMgrEntity* pAssetManager = pCutSceneManager->GetAssetManager(); const cutfObjectVariationEventArgs* pVariationEventFlag = static_cast( pEventArgs ); int Component = pVariationEventFlag->GetComponent(); int Drawable = pVariationEventFlag->GetDrawable(); int Texture = pVariationEventFlag->GetTexture(); if ((Component>-1 && Drawable>-1 && Texture>-1) || (Component>=PV_MAX_COMP && Drawable>-2)) { cutsceneModelEntityDebugf3("CCutsceneAnimatedActorEntity::DispatchEvent: CUTSCENE_SET_VARIATION_EVENT: (Component: %d (%s), Drawable: %d, Texture: %d)", Component, CPedVariationData::GetVarOrPropSlotName(Component), Drawable, Texture); SetCurrentActorVariation(GetGameEntity(), Component, Drawable, Texture); if (ComponentRemoveVariationStreamRequest(Component, Drawable, Texture, m_ModelNameHash, pObject->GetObjectId()); } else { cutsceneModelEntityDebugf3("CCutsceneAnimatedActorEntity::DispatchEvent: Ignoring CUTSCENE_SET_VARIATION_EVENT with invalid data: (Component: %d (%s), Drawable: %d, Texture: %d)", Component, CPedVariationData::GetVarOrPropSlotName(Component), Drawable, Texture); } } else { cutsceneModelEntityDebugf3("CCutsceneAnimatedActorEntity::DispatchEvent: Ignoring CUTSCENE_SET_VARIATION_EVENT with invalid or null event arguments"); } } else { //cutsceneModelEntityDebugf("CCutsceneAnimatedActorEntity::DispatchEvent: Ignoring CUTSCENE_SET_VARIATION_EVENT pCutSceneManager->GetCutSceneCurrentTime() != pCutSceneManager->GetStartTimeFromStartFrame() && !m_bIsReadyForGame"); } } break; case CUTSCENE_SET_DUAL_CLIP_EVENT: { if (pEventArgs && pEventArgs->GetType() == CUTSCENE_DUAL_CLIP_EVENT_ARGS_TYPE) { if (pObject) { cutsceneAssertf (0,"Not supported : CUTSCENE_SET_DUAL_CLIP_EVENT %s ",pObject->GetDisplayName().c_str()); } } } break; case CUTSCENE_END_OF_SCENE_EVENT: { cutsceneModelEntityDebugf3("CCutsceneAnimatedActorEntity::DispatchEvent - CUTSCENE_END_OF_SCENE_EVENT"); #if RECORDING_VERTS if( PFD_DebugRecords.WillDraw() ) { g_DbgRecordCustomClothEvents.Reset(); } #endif if( GetGameEntity() && GetGameEntity()->GetIsTypePed() ) { CPed* pPed = static_cast(GetGameEntity()); if( pPed ) { for( int i = 0; i < PV_MAX_COMP; ++i ) { characterClothController* pCharClothController = pPed->m_CClothController[i]; if( pCharClothController ) { pCharClothController->CheckQueuedPinning(); pCharClothController->SetPinRadiusSetThreshold( PIN_RADIUSSETS_PACKAGE_THRESHOLD ); pCharClothController->SetFlag( characterClothController::enIsForceSkin, false); pCharClothController->SetFlag( characterClothController::enIsProne, false ); pCharClothController->SetFlag( characterClothController::enIsProneFlipped, false ); pCharClothController->SetFlag( characterClothController::enIsEndCutscene, true ); pCharClothController->SetPackageIndex(0); if( (i == PV_COMP_UPPR) && (g_pCharClothController == pCharClothController) ) { characterCloth* pCharCloth = (characterCloth*)pCharClothController->GetOwner(); Assert( pCharCloth ); const phBoundComposite* pCustomBound = pCharCloth->GetBoundComposite(); Assert( pCustomBound ); if( pCustomBound ) { Assert( g_customLength > 0.0f ); Assert( g_customRadius > 0.0f ); phBound* pBoundPart = pCustomBound->GetBound(g_capsuleLeftT); Assert( pBoundPart ); Assert( pBoundPart->GetType() == phBound::CAPSULE ); phBoundCapsule* pBoundCapsule = (phBoundCapsule*)pBoundPart; Assert( pBoundCapsule ); pBoundCapsule->SetCapsuleSize( g_customRadius, g_customLength ); pBoundPart = pCustomBound->GetBound(g_capsuleRightT); Assert( pBoundPart ); Assert( pBoundPart->GetType() == phBound::CAPSULE ); pBoundCapsule = (phBoundCapsule*)pBoundPart; Assert( pBoundCapsule ); pBoundCapsule->SetCapsuleSize( g_customRadius, g_customLength ); g_pCharClothController = NULL; g_customLength = -1.0f; g_customRadius = -1.0f; } } phVerletCloth* verletCloth = pCharClothController->GetCloth(0); Assert( verletCloth ); verletCloth->DetachVirtualBound(); verletCloth->SetFlag(phVerletCloth::FLAG_COLLIDE_EDGES, false); verletCloth->SetFlag(phVerletCloth::FLAG_IGNORE_OFFSET, false); } // if( pPed->m_CClothController[i] ) } // for( int i = 0; i < PV_MAX_COMP; ++i ) pPed->SetPedConfigFlag( CPED_CONFIG_FLAG_ForceSkinCharacterCloth, false ); pPed->SetPedConfigFlag( CPED_CONFIG_FLAG_ForcePoseCharacterCloth, false ); pPed->SetPedConfigFlag( CPED_CONFIG_FLAG_ForcePackageCharacterCloth, false ); } // CPed* pPed = static_cast(GetGameEntity()); } // if( GetGameEntity() && GetGameEntity()->GetIsTypePed() ) } break; case CutSceneCustomEvents::CUTSCENE_CUSTOM_CLOTH_EVENT: { //cutsceneModelEntityDebugf("CCutsceneAnimatedActorEntity::DispatchEvent: CUTSCENE_CUSTOM_CLOTH_EVENT"); const CutSceneCustomEvents::ICutsceneCustomCustomEventArgs* pObjectVar = static_cast(pEventArgs); if( GetGameEntity() && GetGameEntity()->GetIsTypePed() && pObjectVar ) { clothDebugf1("CUTSCENE_CUSTOM_CLOTH_EVENT: eventType = %d", pObjectVar->GetEventType() ); CPed* pPed = static_cast(GetGameEntity()); if( pPed ) { const int eventType = pObjectVar->GetEventType(); AssertMsg( (eventType > 0 && eventType < CCEVENT_TYPE_MAX), "The event type value is not correct" ); if( eventType == CCEVENT_TYPE_SET_SKIN_ON_ONCREATE ) { pPed->SetPedConfigFlag( CPED_CONFIG_FLAG_ForceSkinCharacterCloth, true ); } else if( eventType == CCEVENT_TYPE_SET_SKIN_OFF_ONCREATE ) { pPed->SetPedConfigFlag( CPED_CONFIG_FLAG_ForceSkinCharacterCloth, false ); } else if( eventType == CCEVENT_TYPE_QUEUE_POSE_ON || eventType == CCEVENT_TYPE_SET_POSE ) { pPed->SetPedConfigFlag( CPED_CONFIG_FLAG_ForcePoseCharacterCloth, true ); pPed->QueueClothPoseIndex( (u8)pObjectVar->GetCapsuleLength() ); } else if( eventType == CCEVENT_TYPE_QUEUE_POSE_OFF ) { pPed->SetPedConfigFlag( CPED_CONFIG_FLAG_ForcePoseCharacterCloth, false ); } else if( eventType == CCEVENT_TYPE_SET_PACKAGE_INDEX ) { pPed->SetPedConfigFlag( CPED_CONFIG_FLAG_ForcePackageCharacterCloth, true ); pPed->QueueClothPackageIndex( (u8)pObjectVar->GetCapsuleLength() ); } else if( eventType == CCEVENT_TYPE_SET_PRONE_ON ) { pPed->SetPedConfigFlag( CPED_CONFIG_FLAG_ForceProneCharacterCloth, true ); } for( int i = 0; i < PV_MAX_COMP; ++i ) { characterClothController* pCharClothController = pPed->m_CClothController[i]; if( pCharClothController ) { phVerletCloth* verletCloth = pCharClothController->GetCloth(0); Assert( verletCloth ); #if RECORDING_VERTS if( PFD_DebugRecords.WillDraw() && eventType != CCEVENT_TYPE_ATTACH_COLLISION && eventType != CCEVENT_TYPE_SET_PACKAGE_INDEX && eventType != CCEVENT_TYPE_SET_POSE ) { recordCustomClothEvent rec; rec.m_Text = "CUTSCENE_CUSTOM_CLOTH_EVENT"; rec.m_ClothControllerName = pPed->m_CClothController[i]->GetName(); rec.m_EventType = eventType; //rec.m_Frames = 60; g_DbgRecordCustomClothEvents.Push( rec ); } #endif // TODO: add debug text showing warning on the screen if bound exists already ? if( eventType == CCEVENT_TYPE_ATTACH_COLLISION && !verletCloth->m_VirtualBound ) { Vector3 vPos = VEC3_ZERO; vPos.x = pObjectVar->GetPositionX(); vPos.y = pObjectVar->GetPositionY(); vPos.z = pObjectVar->GetPositionZ(); Vector3 vRot = VEC3_ZERO; vRot.x = pObjectVar->GetRotationX(); vRot.y = pObjectVar->GetRotationY(); vRot.z = pObjectVar->GetRotationZ(); Mat34V boundMat; Mat34VFromEulersXYZ( boundMat, VECTOR3_TO_VEC3V(vRot) ); boundMat.SetCol3( VECTOR3_TO_VEC3V(vPos) ); float fCapsuleLen = pObjectVar->GetCapsuleLength(); float fCapsuleRad = pObjectVar->GetCapsuleRadius(); verletCloth->SetFlag(phVerletCloth::FLAG_COLLIDE_EDGES, true); verletCloth->SetFlag(phVerletCloth::FLAG_IGNORE_OFFSET, true); verletCloth->CreateVirtualBound( 1, &identityMat ); verletCloth->AttachVirtualBoundCapsule( fCapsuleRad, fCapsuleLen, boundMat, 0 ); #if RECORDING_VERTS if( PFD_DebugRecords.WillDraw() ) { recordCustomClothEvent rec; rec.m_Text = "CUTSCENE_CUSTOM_CLOTH_EVENT"; rec.m_ClothControllerName = pPed->m_CClothController[i]->GetName(); rec.m_EventType = eventType; rec.m_Position = VECTOR3_TO_VEC3V(vPos); rec.m_Rotation = VECTOR3_TO_VEC3V(vRot); rec.m_CapsuleLength = fCapsuleLen; rec.m_CapsuleRadius = fCapsuleRad; //rec.m_Frames = 60; g_DbgRecordCustomClothEvents.Push( rec ); } #endif } else if( eventType == CCEVENT_TYPE_DETACH_COLLISION ) { verletCloth->DetachVirtualBound(); verletCloth->SetFlag(phVerletCloth::FLAG_COLLIDE_EDGES, false); verletCloth->SetFlag(phVerletCloth::FLAG_IGNORE_OFFSET, false); } else if( eventType == CCEVENT_TYPE_SET_SKIN_ON ) { pCharClothController->SetFlag( characterClothController::enIsForceSkin, true); } else if( eventType == CCEVENT_TYPE_SET_SKIN_OFF ) { pCharClothController->SetFlag( characterClothController::enIsForceSkin, false); } else if( eventType == CCEVENT_TYPE_FORCE_PIN ) { pCharClothController->SetForcePin(1); } else if( eventType == CCEVENT_TYPE_SET_PACKAGE_INDEX ) { pCharClothController->SetPackageIndex( (u8)pObjectVar->GetCapsuleLength() ); pPed->SetPedConfigFlag( CPED_CONFIG_FLAG_ForcePackageCharacterCloth, false ); #if RECORDING_VERTS if( PFD_DebugRecords.WillDraw() ) { recordCustomClothEvent rec; rec.m_Text = "CUTSCENE_CUSTOM_CLOTH_EVENT"; rec.m_ClothControllerName = pPed->m_CClothController[i]->GetName(); rec.m_EventType = eventType; rec.m_CapsuleLength = pObjectVar->GetCapsuleLength(); //rec.m_Frames = 60; g_DbgRecordCustomClothEvents.Push( rec ); } #endif } else if( eventType == CCEVENT_TYPE_SET_PRONE_ON ) { pCharClothController->SetFlag( characterClothController::enIsProneFlipped, true ); pPed->SetPedConfigFlag( CPED_CONFIG_FLAG_ForceProneCharacterCloth, false ); } else if( eventType == CCEVENT_TYPE_SET_PRONE_OFF ) { pCharClothController->SetFlag( characterClothController::enIsProne, false ); pCharClothController->SetFlag( characterClothController::enIsProneFlipped, false ); } else if( eventType == CCEVENT_TYPE_SET_PIN_RADIUS_THRESHOLD ) { pCharClothController->SetPinRadiusSetThreshold( pObjectVar->GetCapsuleLength() ); } else if( eventType == CCEVENT_TYPE_SET_POSE ) { // NOTE: if we set a pose then don't skin pCharClothController->SetFlag( characterClothController::enIsForceSkin, false ); pCharClothController->SetForcePin( 0 ); characterCloth* pCharCloth = (characterCloth*)pCharClothController->GetOwner(); Assert( pCharCloth ); pCharCloth->SetPose( (u8)pObjectVar->GetCapsuleLength() ); pPed->SetPedConfigFlag( CPED_CONFIG_FLAG_ForcePoseCharacterCloth, false ); #if RECORDING_VERTS if( PFD_DebugRecords.WillDraw() ) { recordCustomClothEvent rec; rec.m_Text = "CUTSCENE_CUSTOM_CLOTH_EVENT"; rec.m_ClothControllerName = pPed->m_CClothController[i]->GetName(); rec.m_EventType = eventType; rec.m_CapsuleLength = pObjectVar->GetCapsuleLength(); g_DbgRecordCustomClothEvents.Push( rec ); } #endif } else if( eventType == CCEVENT_TYPE_CUSTOM_1 && i == PV_COMP_UPPR ) { // TODO: hacky way to increase the raduis on the collision bounds from cutscene characterCloth* pCharCloth = (characterCloth*)pCharClothController->GetOwner(); Assert( pCharCloth ); const phBoundComposite* pCustomBound = pCharCloth->GetBoundComposite(); Assert( pCustomBound ); if( pCustomBound ) { phBound* pBoundPart = pCustomBound->GetBound(g_capsuleLeftT); Assert( pBoundPart ); Assert( pBoundPart->GetType() == phBound::CAPSULE ); phBoundCapsule* pBoundCapsule = (phBoundCapsule*)pBoundPart; Assert( pBoundCapsule ); pBoundCapsule->SetCapsuleSize( pObjectVar->GetCapsuleRadius(), pObjectVar->GetCapsuleLength() ); pBoundPart = pCustomBound->GetBound(g_capsuleRightT); Assert( pBoundPart ); Assert( pBoundPart->GetType() == phBound::CAPSULE ); pBoundCapsule = (phBoundCapsule*)pBoundPart; Assert( pBoundCapsule ); pBoundCapsule->SetCapsuleSize( pObjectVar->GetCapsuleRadius(), pObjectVar->GetCapsuleLength() ); Assert( !g_pCharClothController ); g_pCharClothController = pCharClothController; g_customLength = pObjectVar->GetCapsuleLength(); g_customRadius = pObjectVar->GetCapsuleRadius(); } } } } // for } // if( pPed ) } // if ( GetGameEntity ... } break; case CUTSCENE_STOP_EVENT: { } break; } //this is here to dispatch debug draw event for this entity. #if __BANK cutsEntity::DispatchEvent(pManager, pObject, iEventId, pEventArgs); #endif CCutsceneAnimatedModelEntity::DispatchEvent(pManager, pObject, iEventId, pEventArgs); } /////////////////////////////////////////////////////////////////////////////////////////////////// void CCutsceneAnimatedActorEntity::PlayClip (CutSceneManager* pCutManager, const crClip* pClip, float fEventTime, const strStreamingObjectName UNUSED_PARAM(pAnimDict)) { //Assertf(CutSceneManager::GetInstance()->GetAssetManager()->HaveAllVariationsLoaded(PED_VARIATION_TYPE), "Variations not yet loaded"); //CutSceneManager::GetInstance()->GetAssetManager()->DumpAllVariationsLoaded(m_pCutfObject->GetObjectId()); if(GetGameEntity()) { if(!m_pCutSceneTask) { GetGameEntity()->SetPedResetFlag( CPED_RESET_FLAG_AllowUpdateIfNoCollisionLoaded, true ); // Make sure we don't timeslice the ai / animation this frame. GetGameEntity()->GetPedAiLod().SetForceNoTimesliceIntelligenceUpdate(true); GetGameEntity()->GetPedAiLod().SetBlockedLodFlag(CPedAILod::AL_LodTimesliceIntelligenceUpdate | CPedAILod::AL_LodTimesliceAnimUpdate); if(GetGameEntity()->IsProtectedBaseFlagSet(fwEntity::IS_FIXED_UNTIL_COLLISION)) { GetGameEntity()->UpdateFixedWaitingForCollision(false); } if(GetGameEntity()->GetPedIntelligence()->GetTaskEventResponse()) { GetGameEntity()->GetPedIntelligence()->FlushImmediately(true); } m_pCutSceneTask = CreateCutsceneTask(pCutManager, pClip, fEventTime); m_pCutSceneTask->SetPreserveHairScale(m_OptionFlags.IsFlagSet(CEO_PRESERVE_HAIR_SCALE)); m_pCutSceneTask->SetInstantHairScaleUpdate(m_OptionFlags.IsFlagSet(CEO_INSTANT_HAIR_SCALE_SETUP)); m_pCutSceneTask->SetOriginalHairScale(m_fOriginalHairScale); if(GetGameEntity()->IsNetworkClone()) { GetGameEntity()->GetPedIntelligence()->AddLocalCloneTask(m_pCutSceneTask, PED_TASK_PRIORITY_PRIMARY); } else { GetGameEntity()->GetPedIntelligence()->AddTaskAtPriority(m_pCutSceneTask, PED_TASK_PRIORITY_PRIMARY, TRUE); } GetGameEntity()->SetFixedPhysics(false); } else { if(cutsceneVerifyf(m_pCutSceneTask->GetTaskType() == CTaskTypes::TASK_CUTSCENE, "Trying to set the clip on a CTaskCutscene, but entity %s is not running a cutscene task", m_pCutfObject->GetDisplayName().c_str())) { Matrix34 SceneMat; pCutManager->GetSceneOrientationMatrix(SceneMat); m_pCutSceneTask->SetClip(pClip,SceneMat, fEventTime); } } } #if __DEV if(GetGameEntity() && m_pCutSceneTask && m_pCutSceneTask->GetTaskType() == CTaskTypes::TASK_CUTSCENE) { //THIS CURRENTLY DOES NOTHING TO FILTER ANY ANIMS BECAUSE THERE IS NO FILTER TO REMOVE ALL ANIM EXCEPT FACIAL UpdateWithFaceViewer(pCutManager, m_pCutSceneTask); } #endif SetAnimPlayBackEventTime(fEventTime); } ///////////////////////////////////////////////////////////////////////// //Gets the position of an actors bone (used for face zoom but could use for hands etc bool CCutsceneAnimatedActorEntity::GetActorBonePosition(eAnimBoneTag ePedBone, Matrix34 &mMat) const { const crSkeleton* pSkel = NULL; s32 nBoneIndex = -1; if (GetGameEntity()) { pSkel = GetGameEntity()->GetSkeleton(); nBoneIndex = GetGameEntity()->GetBoneIndexFromBoneTag(ePedBone); } if (pSkel && nBoneIndex!= -1) { pSkel->GetGlobalMtx(nBoneIndex, RC_MAT34V(mMat)); return true; } return false; } ///////////////////////////////////////////////////////////////////////// //set the variation on an actor void CCutsceneAnimatedActorEntity::SetCurrentActorVariation(CPed* pPed, u32 iComponent, s32 iDrawable, s32 iTexture) { if(IsBlockingVariationStreamingAndApplication()) { return; } //setting the variation on a ped if (pPed && pPed->GetPedModelInfo() && pPed->GetPedModelInfo()->GetVarInfo()) { if(iComponent < PV_MAX_COMP) { if(pPed->IsVariationInRange(static_cast(iComponent),iDrawable,iTexture)) { //if(!pPed->HasVariation(static_cast(iComponent), iDrawable, iTexture)) { if (pPed->GetPedModelInfo()->GetIsStreamedGfx()) { // Check the variation is loaded eVariationStreamingStatus variationStreamingStatus = CutSceneManager::GetInstance()->GetAssetManager()->GetVariationLoadingState(iComponent, iDrawable, iTexture, m_ModelNameHash, m_pCutfObject->GetObjectId()); if( variationStreamingStatus == LOADING_VARIATION) { cutsceneModelEntityDebugf3("SetCurrentActorVariation (%s, %p) - Variation is still loading (Component: %d (%s), Drawable: %d, Texture: %d) ", pPed->GetModelName(), pPed, iComponent, CPedVariationData::GetVarOrPropSlotName(iComponent), iDrawable, iTexture ); } else if ( variationStreamingStatus == NO_REQUEST_FOR_VARIATION ) { cutsceneModelEntityDebugf3("SetCurrentActorVariation (%s, %p) - Variation has no request (Component: %d (%s), Drawable: %d, Texture: %d) ", pPed->GetModelName(), pPed, iComponent, CPedVariationData::GetVarOrPropSlotName(iComponent), iDrawable, iTexture ); } } #if !__NO_OUTPUT bool ReactivateLogging = false; if(pPed->m_LogVariationCalls) { pPed->m_LogVariationCalls = false; ReactivateLogging = true; } #endif //!__NO_OUTPUT pPed->SetVariation(static_cast(iComponent), iDrawable, 0, iTexture, 0, 0, true); #if !__NO_OUTPUT if(ReactivateLogging) { pPed->m_LogVariationCalls = true; } #endif //!__NO_OUTPUT cutsceneModelEntityDebugf3("SetCurrentActorVariation (%s, %p) - Actual SetVariation - (Component: %d (%s), Drawable: %d/%d, Texture: %d/%d)", pPed->GetModelName(), pPed, iComponent, CPedVariationData::GetVarOrPropSlotName(iComponent), iDrawable, pPed->GetPedModelInfo()->GetVarInfo()->GetMaxNumDrawbls(static_cast(iComponent)), iTexture, pPed->GetPedModelInfo()->GetVarInfo()->GetMaxNumTex(static_cast(iComponent),iDrawable)); } /*else { cutsceneModelEntityDebugf("SetCurrentActorVariation (%s, %p) - Already has variation - (Component: %d (%s), Drawable: %d/%d, Texture: %d/%d)", pPed->GetModelName(), pPed, iComponent, CPedVariationData::GetVarOrPropSlotName(iComponent), iDrawable, pPed->GetPedModelInfo()->GetVarInfo()->GetMaxNumDrawbls(static_cast(iComponent)), iTexture, pPed->GetPedModelInfo()->GetVarInfo()->GetMaxNumTex(static_cast(iComponent),iDrawable)); }*/ } else { cutsceneModelEntityDebugf3("SetCurrentActorVariation (%s, %p) - Variation not in range - (Component: %d (%s), Drawable: %d/%d, Texture: %d/%d) (using default instead) ", pPed->GetModelName(), pPed, iComponent, CPedVariationData::GetVarOrPropSlotName(iComponent), iDrawable, pPed->GetPedModelInfo()->GetVarInfo()->GetMaxNumDrawbls(static_cast(iComponent)), iTexture, pPed->GetPedModelInfo()->GetVarInfo()->GetMaxNumTex(static_cast(iComponent),iDrawable)); // Check the default variation is loaded eVariationStreamingStatus variationStreamingStatus = CutSceneManager::GetInstance()->GetAssetManager()->GetVariationLoadingState(iComponent, 0, 0, m_ModelNameHash, m_pCutfObject->GetObjectId()); if( variationStreamingStatus == LOADING_VARIATION) { cutsceneModelEntityDebugf3("SetCurrentActorVariation (%s, %p) - Variation is still loading (Component: %d (%s), Drawable: %d, Texture: %d) ", pPed->GetModelName(), pPed, iComponent, CPedVariationData::GetVarOrPropSlotName(iComponent), 0, 0 ); } else if ( variationStreamingStatus == NO_REQUEST_FOR_VARIATION ) { cutsceneModelEntityDebugf3("SetCurrentActorVariation (%s, %p) - Variation has no request (Component: %d (%s), Drawable: %d, Texture: %d) ", pPed->GetModelName(), pPed, iComponent, CPedVariationData::GetVarOrPropSlotName(iComponent), 0, 0 ); } #if !__NO_OUTPUT bool ReactivateLogging = false; if(pPed->m_LogVariationCalls) { pPed->m_LogVariationCalls = false; ReactivateLogging = true; } #endif //!__NO_OUTPUT pPed->SetVariation(static_cast(iComponent), 0, 0, 0, 0, 0, true); #if !__NO_OUTPUT if(ReactivateLogging) { pPed->m_LogVariationCalls = true; } #endif //!__NO_OUTPUT cutsceneModelEntityDebugf3("SetCurrentActorVariation (%s, %p) - Actual SetVariation - (Component: %d (%s), Drawable: %d/%d, Texture: %d/%d)", pPed->GetModelName(), pPed, iComponent, CPedVariationData::GetVarOrPropSlotName(0), 0, pPed->GetPedModelInfo()->GetVarInfo()->GetMaxNumDrawbls(static_cast(0)), 0, pPed->GetPedModelInfo()->GetVarInfo()->GetMaxNumTex(static_cast(0),0)); } } else { int iPropComponent = iComponent - PV_MAX_COMP; if(iDrawable != -1) { CPedPropsMgr::SetPedProp(pPed, (eAnchorPoints)iPropComponent , iDrawable, iTexture, ANCHOR_NONE, NULL, NULL); cutsceneModelEntityDebugf3("SetCurrentActorVariation (%s, %p) - Actual SetPedProp - (Component: %d (%s), Drawable: %d, Texture: %d)", pPed->GetModelName(), pPed, iComponent, CPedVariationData::GetVarOrPropSlotName(iComponent), iDrawable, iTexture); } else { CPedPropsMgr::ClearPedProp(pPed, (eAnchorPoints)iPropComponent ); if(iComponent == PV_COMP_HEAD && pPed->GetHelmetComponent()) { pPed->GetHelmetComponent()->DisableHelmet(false); } cutsceneModelEntityDebugf3("SetActorCurrentVariation (%s, %p) - Actual ClearPedProp - (Component: %d (%s))", pPed->GetModelName(), pPed, iComponent, CPedVariationData::GetVarOrPropSlotName(iComponent)); } } } else { cutsceneModelEntityDebugf3("SetCurrentActorVariation - Ped not loaded (or malformed). Failed to set variation on ped but storing the variation to apply once the ped is loaded. - (Component: %d (%s), Drawable: %d, Texture: %d)", iComponent, CPedVariationData::GetVarOrPropSlotName(iComponent),iDrawable, iTexture); } if ((iDrawable>-1 && iTexture>-1) || (iComponent>=PV_MAX_COMP && iDrawable>-2)) { StoreActorVariationData( iComponent, iDrawable, iTexture, m_sCurrentActorVariationData); } } void CCutsceneAnimatedActorEntity::SetScriptActorVariationData( u32 iComponent, s32 iDrawable, s32 iTexture) { if((iDrawable>-1 && iTexture>-1) || (iComponent>=PV_MAX_COMP && iDrawable>-2)) { // Store the variations set by script in their own array // These will be used in favour of cutscene variations on the start frame StoreActorVariationData(iComponent, iDrawable, iTexture, m_sScriptActorVariationData); // Also copy the variations into the current array // Peds not loaded before the scene dotn get ComputeInitialVariations called on them StoreActorVariationData(iComponent, iDrawable, iTexture, m_sCurrentActorVariationData); } } ///////////////////////////////////////////////////////////////////////// CCutsceneAnimatedActorEntity::~CCutsceneAnimatedActorEntity() { //check that the script registered entity is being picked up by the script if(m_RegisteredEntityFromScript.pEnt != NULL) { if(m_RegisteredEntityFromScript.pEnt->GetIsTypePed()) { CPed* pPed = (CPed*)m_RegisteredEntityFromScript.pEnt.Get(); if(!pPed->IsLocalPlayer()) { if(m_RegisteredEntityFromScript.SceneNameHash > 0 && m_RegisteredEntityFromScript.bCreatedForScript) { const CScriptEntityExtension* pExtension = m_RegisteredEntityFromScript.pEnt->GetExtension(); if(!CutSceneManager::GetInstance()->ShouldDeleteAllRegisteredEntites()) { if(!IsRegisteredGameEntityUnderScriptControl()) { cutsceneAssertf(pExtension, "Deleting a cutscene entity (\"%s\" %u) scene handle (\"%s\" %u) that was registered with CU_CREATE_AND_ANIMATE_NEW_SCRIPT_ENTITY use GET_ENTITY_INDEX_OF_REGISTERED_ENTITY to make sure it is pickup up by the script", m_RegisteredEntityFromScript.ModelNameHash.TryGetCStr(), m_RegisteredEntityFromScript.ModelNameHash.GetHash(), m_RegisteredEntityFromScript.SceneNameHash.TryGetCStr(), m_RegisteredEntityFromScript.SceneNameHash.GetHash()); } } if(!pExtension) { m_RegisteredEntityFromScript.bDeleteBeforeEnd = true; } } } } } if (GetGameEntity()) { bool CanDelete = m_RegisteredEntityFromScript.pEnt != GetGameEntity(); if(CanDelete|| m_RegisteredEntityFromScript.bDeleteBeforeEnd) { GetGameEntity()->PopTypeSet(POPTYPE_RANDOM_AMBIENT); } } } /////////////////////////////////////////////////////////////////////////////////////////////////// // Vehicle /////////////////////////////////////////////////////////////////////////////////////////////////// CCutsceneAnimatedVehicleEntity::CCutsceneAnimatedVehicleEntity(const cutfObject* pObject) :CCutsceneAnimatedModelEntity(pObject) { m_iAnimDict = -1; #if __BANK InitaliseVehicleExtraList(); #endif } ///////////////////////////////////////////////////////////////////////// CCutsceneAnimatedVehicleEntity::~CCutsceneAnimatedVehicleEntity() { //check that the script registered entity is being picked up by the script if(m_RegisteredEntityFromScript.SceneNameHash > 0 && m_RegisteredEntityFromScript.bCreatedForScript) { if(m_RegisteredEntityFromScript.pEnt != NULL) { const CScriptEntityExtension* pExtension = m_RegisteredEntityFromScript.pEnt->GetExtension(); if(!CutSceneManager::GetInstance()->ShouldDeleteAllRegisteredEntites()) { if(!IsRegisteredGameEntityUnderScriptControl()) { cutsceneAssertf(pExtension, "Deleting a cutscene entity (\"%s\" %u) scene handle (\"%s\" %u) that was registered with CU_CREATE_AND_ANIMATE_NEW_SCRIPT_ENTITY use GET_ENTITY_INDEX_OF_REGISTERED_ENTITY to make sure it is pickup up by the script", m_RegisteredEntityFromScript.ModelNameHash.TryGetCStr(), m_RegisteredEntityFromScript.ModelNameHash.GetHash(), m_RegisteredEntityFromScript.SceneNameHash.TryGetCStr(), m_RegisteredEntityFromScript.SceneNameHash.GetHash()); } } if(!pExtension) { m_RegisteredEntityFromScript.bDeleteBeforeEnd = true; } } } } ///////////////////////////////////////////////////////////////////////// void CCutsceneAnimatedVehicleEntity::DispatchEvent(cutsManager* pManager, const cutfObject* pObject, s32 iEventId, const cutfEventArgs* pEventArgs, const float UNUSED_PARAM(fTime), const u32 UNUSED_PARAM(StickyId)) { switch ( iEventId ) { case CUTSCENE_UPDATE_EVENT: case CUTSCENE_PAUSE_EVENT: { if (iEventId==CUTSCENE_UPDATE_EVENT && m_bStoppedCalled) { CreateRepositionOnlyGameEntityWhenModelLoaded(pManager, pObject, true, true ); SetGameEntityReadyForGame(pManager); } UpdateCutSceneTask(pManager); if (GetGameEntity() && !m_bIsReadyForGame) { CVehicleAILodManager::DisableTimeslicingImmediately(*GetGameEntity()); } } break; case CUTSCENE_SET_VARIATION_EVENT: { if (m_bIsReadyForGame) { return; } cutsceneModelEntityDebugf3("CCutsceneAnimatedVehicleEntity:CUTSCENE_SET_VARIATION_EVENT"); cutsceneAssertf(pEventArgs, "Cutscene content bug! CUTSCENE_SET_VARIATION_EVENT (object name=%s type=%s)(event id=%i) is corrupted and needs to be recreated, variation will not be applied!", pObject->GetDisplayName().c_str(), pObject->GetTypeName(), iEventId); if (pEventArgs && pEventArgs->GetType() == CUTSCENE_VEHICLE_VARIATION_EVENT_ARGS_TYPE) { const cutfVehicleVariationEventArgs* pVariationEventFlag = static_cast( pEventArgs ); SetVariation(pVariationEventFlag->GetBodyColour() , pVariationEventFlag->GetSecondaryBodyColour(), pVariationEventFlag->GetSpecularBodyColour(), pVariationEventFlag->GetWheelTrimColour(), pVariationEventFlag->GetBodyColour5(), pVariationEventFlag->GetBodyColour6(), pVariationEventFlag->GetLiveryId(), pVariationEventFlag->GetLivery2Id(), pVariationEventFlag->GetDirtLevel() ); cutsceneDebugf1("%s CCutsceneAnimatedVehicleEntity:CUTSCENE_SET_VARIATION_EVENT BodyColor: %d, Second BodyColor: %d, SpecBody: %d, Wheel Trim Col: %d, BodyColor5: %d, BodyColor6: %d, Livery id: %d, Livery2 id: %d, Dirt Lev: %f " , pObject->GetDisplayName().c_str(), pVariationEventFlag->GetBodyColour(), pVariationEventFlag->GetSecondaryBodyColour(), pVariationEventFlag->GetSpecularBodyColour(), pVariationEventFlag->GetWheelTrimColour(), pVariationEventFlag->GetBodyColour5(), pVariationEventFlag->GetBodyColour6(), pVariationEventFlag->GetLiveryId(), pVariationEventFlag->GetLivery2Id(), pVariationEventFlag->GetDirtLevel()); } if (pEventArgs && pEventArgs->GetType() == CUTSCENE_VEHICLE_EXTRA_EVENT_ARGS_TYPE) { const cutfVehicleExtraEventArgs* pExtraEventFlag = static_cast( pEventArgs ); if(GetGameEntity()) { SetGameVehicleExtra(pExtraEventFlag->GetBoneIdList()); } } } break; case CutSceneCustomEvents::CUTSCENE_SET_VEHICLE_DAMAGE_EVENT: { if (m_bIsReadyForGame) { return; } cutsceneDebugf1("%s CCutsceneAnimatedVehicleEntity:CUTSCENE_SET_VEHICLE_DAMAGE_EVENT", pObject->GetDisplayName().c_str()); if (pEventArgs && pEventArgs->GetType() == CUTSCENE_NAME_EVENT_ARGS_TYPE) { const cutfNameEventArgs* pObjectVar = static_cast(pEventArgs); Vector3 vDamage = VEC3_ZERO; float fDamage = 0.0f; float fDeform = 0.0f; if(pObjectVar->GetAttributeList().FindAttributeAnyCase("vPos.x")) { vDamage.x = pObjectVar->GetAttributeList().FindAttributeAnyCase("vPos.x")->FindFloatValue(); } if(pObjectVar->GetAttributeList().FindAttributeAnyCase("vPos.y")) { vDamage.y = pObjectVar->GetAttributeList().FindAttributeAnyCase("vPos.y")->FindFloatValue(); } if(pObjectVar->GetAttributeList().FindAttributeAnyCase("vPos.z")) { vDamage.z = pObjectVar->GetAttributeList().FindAttributeAnyCase("vPos.z")->FindFloatValue(); } if(pObjectVar->GetAttributeList().FindAttributeAnyCase("fDamage")) { fDamage = pObjectVar->GetAttributeList().FindAttributeAnyCase("fDamage")->FindFloatValue(); } if(pObjectVar->GetAttributeList().FindAttributeAnyCase("fDeform")) { fDeform = pObjectVar->GetAttributeList().FindAttributeAnyCase("fDeform")->FindFloatValue(); } //cutsceneDebugf1("%s CCutsceneAnimatedVehicleEntity:CUTSCENE_SET_VEHICLE_DAMAGE_EVENT pos: x:%f, y:%f, z:%f, ", pObject->GetDisplayName(), ) SetVehicleDamage(vDamage,fDamage,fDeform, true); } } break; } CCutsceneAnimatedModelEntity::DispatchEvent(pManager, pObject, iEventId, pEventArgs); } void CCutsceneAnimatedVehicleEntity::ForceUpdateAi(cutsManager* pManager) { if(pManager) { CutSceneManager* pCutSceneManager = static_cast (pManager); if(pCutSceneManager->GetShutDownMode() != SHUTDOWN_SESSION) { CVehicle* pVeh = GetGameEntity(); if (pVeh && pVeh->GetIntelligence() && pVeh->GetIntelligence()->GetTaskManager() && GetCutsceneTaskForEntity()) { // TODO - Update the vehicle a.i. properly if we find we need to cross blend between vehicle anims, etc // For now lets just get rid of the cutscene task. pVeh->GetIntelligence()->GetTaskManager()->ClearTask(VEHICLE_TASK_TREE_SECONDARY, VEHICLE_TASK_SECONDARY_ANIM); } } } }; ///////////////////////////////////////////////////////////////////////// void CCutsceneAnimatedVehicleEntity::PlayClip (CutSceneManager* pCutManager, const crClip* pClip, float fEventTime, const strStreamingObjectName UNUSED_PARAM(pAnimDict)) { if (GetGameEntity()) { if(!m_pCutSceneTask) { // Ready the vehicle for animation GetGameEntity()->SetFixedPhysics(true); GetGameEntity()->m_nVehicleFlags.bAnimateWheels = true; GetGameEntity()->m_nVehicleFlags.bAnimatePropellers = true; GetGameEntity()->m_nVehicleFlags.bAnimateJoints = true; CVehicleAILodManager::DisableTimeslicingImmediately(*GetGameEntity()); GetGameEntity()->InitAnimLazy(); GetGameEntity()->SetDriveMusclesToAnimation(true); m_pCutSceneTask = CreateCutsceneTask(pCutManager, pClip, fEventTime); GetGameEntity()->GetIntelligence()->GetTaskManager()->GetTree(VEHICLE_TASK_TREE_SECONDARY)->SetTask(m_pCutSceneTask, VEHICLE_TASK_SECONDARY_ANIM); } else { if(cutsceneVerifyf(m_pCutSceneTask->GetTaskType() == CTaskTypes::TASK_CUTSCENE, "Trying to set the clip on a CTaskCutscene, but entity %s is not running a cutscene task", m_pCutfObject->GetDisplayName().c_str())) { Matrix34 SceneMat; pCutManager->GetSceneOrientationMatrix(SceneMat); m_pCutSceneTask->SetClip(pClip,SceneMat, fEventTime); } } } SetAnimPlayBackEventTime(fEventTime); } ///////////////////////////////////////////////////////////////////////// //Restore a vehicle to a previous setting void CCutsceneAnimatedVehicleEntity::RestoreEntityProperties(CEntity* UNUSED_PARAM(pEnt)) { SetVariation(m_sVehicleData.iBodyColour, m_sVehicleData.iSecondColour, m_sVehicleData.iSpecColour, m_sVehicleData.iWheelColour, m_sVehicleData.iBodyColour5, m_sVehicleData.iBodyColour6, m_sVehicleData.iLiveryId, m_sVehicleData.iLivery2Id, m_sVehicleData.fDirt); if(m_sVehicleData.HiddenBones.GetCount() > 0 ) { if(GetGameEntity()) { SetGameVehicleExtra(m_sVehicleData.HiddenBones); } } } ///////////////////////////////////////////////////////////////////////// void CCutsceneAnimatedVehicleEntity::SetVariation(int iBodyColour, int iSecondColour, int iSpecColour, int iWheelColour, int iBodyColour5, int iBodyColour6, int LiveryId, int Livery2Id, float fDirt) { //store the variation for later use if we delete and need to recreate the vehicle m_sVehicleData.iBodyColour = iBodyColour; m_sVehicleData.iSecondColour = iSecondColour; m_sVehicleData.iSpecColour = iSpecColour; m_sVehicleData.iWheelColour = iWheelColour; m_sVehicleData.iBodyColour5 = iBodyColour5; m_sVehicleData.iBodyColour6 = iBodyColour6; m_sVehicleData.iLiveryId = LiveryId; m_sVehicleData.iLivery2Id = Livery2Id; m_sVehicleData.fDirt = fDirt; if(GetGameEntity()) { GetGameEntity()->SetBodyColour1( static_cast(iBodyColour) ); GetGameEntity()->SetBodyColour2( static_cast(iSecondColour) ); GetGameEntity()->SetBodyColour3( static_cast(iSpecColour)); GetGameEntity()->SetBodyColour4( static_cast(iWheelColour) ); GetGameEntity()->SetBodyColour5( static_cast(iBodyColour5) ); GetGameEntity()->SetBodyColour6( static_cast(iBodyColour6) ); GetGameEntity()->SetLiveryId(LiveryId); GetGameEntity()->SetLivery2Id(Livery2Id); GetGameEntity()->SetBodyDirtLevel(fDirt); GetGameEntity()->UpdateBodyColourRemapping(); } } ///////////////////////////////////////////////////////////////////////// //Game side vehicles have a hierarchy that describes various components, need to map our bone ids to its hierachy void CCutsceneAnimatedVehicleEntity::SetGameVehicleExtra(const atArray& Bones) { //store the variation for later use if we delete and need to recreate the vehicle for streaming. m_sVehicleData.HiddenBones.Reset(); for (int i =0; i < Bones.GetCount(); i++) { m_sVehicleData.HiddenBones.PushAndGrow(Bones[i]); } //m_sVehicleData.HiddenBones.CopyFrom(Bones, Bones.GetCount()); //have reserved the first array to be 0 if extras have been reactivated if(Bones.GetCount()> 0 && Bones[0] != 0) { //Reactivate any previous turned off bones for(int i=0; i < 10; i ++) { int VehicleHeirachy = i + VEH_EXTRA_1; bool bReactivateExtra = true; if (!GetGameEntity()->GetIsExtraOn(((eHierarchyId)VehicleHeirachy))) //extra is off do we need ot turn it off or is it on the list. { //look through our list of bones for(int i = 0; i < Bones.GetCount(); i++ ) { s32 iMappedNewBoneId = (Bones[i] - VEHICLE_HEIRACHY_MODIFIER) + (VEH_EXTRA_1 - 1); //if its on our list already, leave it. if(VehicleHeirachy == iMappedNewBoneId ) { bReactivateExtra = false; break; } } if (bReactivateExtra) { GetGameEntity()->TurnOffExtra(((eHierarchyId)VehicleHeirachy), false ); } } } //Turn off any bones on our list for(int i = 0; i < Bones.GetCount(); i++ ) { s32 iBoneId = Bones[i]; //store the bone id //remap to the heirchy- iboneids are u16hash of the bone name, starting at extra_1 //VEHICLE_HEIRACHY_MODIFIER is the hash of extra_0 so we subtract to get 1, 2, 3 etc //and add to a zeroed VEH_EXTRA_X int iMappedNewBoneId = (iBoneId - VEHICLE_HEIRACHY_MODIFIER) + (VEH_EXTRA_1 - 1); if (GetGameEntity()->GetIsExtraOn(((eHierarchyId)iMappedNewBoneId))) { GetGameEntity()->TurnOffExtra(((eHierarchyId)iMappedNewBoneId), true ); } } } else { //Careful: reactivating vehicle extras actually repairs the whole vehicle for(int i=0; i < 10; i ++) { int VehicleHeirachy = i + VEH_EXTRA_1; if (!GetGameEntity()->GetIsExtraOn(((eHierarchyId)VehicleHeirachy))) { GetGameEntity()->TurnOffExtra(((eHierarchyId)VehicleHeirachy), false); } } } }; void CCutsceneAnimatedVehicleEntity::SetVehicleDamage(const Vector3& scrVecDamage, float damageAmount, float deformationScale, bool localDamage) { CVehicle *pVehicle = GetGameEntity(); if (pVehicle) { const Vector3 passedPos(scrVecDamage); Vector3 impactPos = passedPos; if( localDamage ) { impactPos = pVehicle->TransformIntoWorldSpace(impactPos); } Vector3 impactImpulse = -passedPos; impactImpulse.Normalize(); Vector3 normalizedImpulse = impactImpulse; impactImpulse *= damageAmount; if( localDamage ) { impactImpulse = VEC3V_TO_VECTOR3(pVehicle->GetTransform().Transform3x3(VECTOR3_TO_VEC3V(impactImpulse))); } // Deformation pVehicle->GetVehicleDamage()->GetDeformation()->ApplyCollisionImpact(impactImpulse*deformationScale, impactPos, NULL); // Damage pVehicle->GetVehicleDamage()->ApplyDamage(NULL,DAMAGE_TYPE_UNKNOWN, 0, damageAmount, impactPos, normalizedImpulse, -normalizedImpulse, 0); } } ///////////////////////////////////////////////////////////////////////// void CCutsceneAnimatedVehicleEntity::CreateGameEntity(strLocalIndex iModelIndex, bool CreateRepositionEntity, bool UNUSED_PARAM(bRequestVariations), bool UNUSED_PARAM(bApplyVariations)) { if(GetGameEntity() == NULL) { cutsceneModelEntityDebugf2("CreateGameEntity - Vehicle"); CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfo(fwModelId(iModelIndex)); if(pModelInfo) { cutsceneAssertf(pModelInfo->GetModelType() == MI_TYPE_VEHICLE, "CUTSCENE ASSET (Assign to *Default Anim Cutscene*): Exported incorrectly, %s is not a VehicleModel type", pModelInfo->GetModelName()); if(pModelInfo->GetModelType() == MI_TYPE_VEHICLE) { Matrix34 TempMat; TempMat.Identity(); TempMat.d = m_vCreatePos; const CControlledByInfo localAiControl(false, false); fwModelId modelId(iModelIndex); CVehicle* pVehicle = CVehicleFactory::GetFactory()->Create(modelId, ENTITY_OWNEDBY_CUTSCENE, POPTYPE_MISSION, &TempMat, false); if (Verifyf(pVehicle, "trying to store a null ped pointer something has gone wrong with the registration")) { //store the vehicle pointer if(CreateRepositionEntity) { SetRepositionOnlyEntity(pVehicle); } else { SetGameEntity(pVehicle); } if(pVehicle) { pVehicle->SetIsAbandoned(); pVehicle->m_nPhysicalFlags.bNotDamagedByAnything = true; CGameWorld::Add(pVehicle, CGameWorld::OUTSIDE); pVehicle->SetFixedPhysics(true); pVehicle->GetPortalTracker()->RequestRescanNextUpdate(); pVehicle->GetPortalTracker()->SetIsCutsceneControlled(true); pVehicle->m_nDEflags.bForcePrePhysicsAnimUpdate = true; if (pVehicle->GetVehicleType() == VEHICLE_TYPE_TRAIN) { ((CTrain*)pVehicle)->m_nTrainFlags.bIsCutsceneControlled = true; } m_bCreatedByCutscene = true; //if (bApplyVariations) //{ // Apply the current variations //RestoreEntityProperties(pVehicle); //} } } } } } } void CCutsceneAnimatedVehicleEntity::HideVehicleFragmentComponent() { if(GetCutfObject() && GetGameEntity()) { if(m_pCutfObject->GetType() == CUTSCENE_MODEL_OBJECT_TYPE) { const cutfModelObject* pModel = static_cast(m_pCutfObject); if(pModel->GetModelType() == CUTSCENE_VEHICLE_MODEL_TYPE) { const cutfVehicleModelObject* pModelObject = static_cast(m_pCutfObject); if(pModelObject->GetRemoveBoneNameList().GetCount() > 0) { for (int i = 0; i < pModelObject->GetRemoveBoneNameList().GetCount(); i++) { const crBoneData* pBoneData = GetGameEntity()->GetSkeletonData().FindBoneData(pModelObject->GetRemoveBoneNameList()[i].c_str()); if(pBoneData) { int BoneIndex = pBoneData->GetIndex(); CVehicleModelInfo* pModel = GetGameEntity()->GetVehicleModelInfo(); if(pModel) { CVehicleStructure* pVehicleStruct = pModel->GetStructure(); if(pVehicleStruct) { for(int j=0; j < VEH_NUM_NODES; j++) { if (pVehicleStruct->m_nBoneIndices[j] == BoneIndex) { eHierarchyId HeirarchyId = (eHierarchyId)j; if(GetGameEntity()->HasFragmentComponent(HeirarchyId)) { GetGameEntity()->RemoveFragmentComponent(HeirarchyId); cutsceneModelEntityDebugf2("HideVehicleFragmentComponent: Removing component %s from vehicle", pModelObject->GetRemoveBoneNameList()[i].c_str()); } else { cutsceneModelEntityDebugf2("HideVehicleFragmentComponent: Couldn't remove component %s, it may have already been removed", pModelObject->GetRemoveBoneNameList()[i].c_str()); } } } } } } } } } } } } void CCutsceneAnimatedVehicleEntity::SetGameEntityReadyForCutscene() { if(GetGameEntity()) { #if !__NO_OUTPUT SetUpEntityForCallStackLogging(); #endif GetGameEntity()->SetOwnedBy(ENTITY_OWNEDBY_CUTSCENE); GetGameEntity()->SetFixedPhysics(true); GetGameEntity()->m_nPhysicalFlags.bNotDamagedByAnything = true; GetGameEntity()->m_nDEflags.bForcePrePhysicsAnimUpdate = true; GetGameEntity()->DisableCollision(); GetGameEntity()->ResetSuspension(); GetGameEntity()->SetForceHd(true); CVehicleRecordingMgr::StopPlaybackRecordedCar(GetGameEntity()); HideVehicleFragmentComponent(); if (m_OptionFlags.IsFlagSet(CEO_IS_CASCADE_SHADOW_FOCUS_ENTITY_DURING_EXIT) && CutSceneManager::GetInstance() && CutSceneManager::GetInstance()->GetCamEntity()) { // Register this with the camera CCutSceneCameraEntity* pCam = const_cast(CutSceneManager::GetInstance()->GetCamEntity()); if (pCam) { pCam->SetCascadeShadowFocusEntityForSeamlessExit(GetGameEntity()); } } NetworkInterface::CutsceneStartedOnEntity(*GetGameEntity()); } } void CCutsceneAnimatedVehicleEntity::SetRepositionOnlyEntityReadyForCutscene() { if(GetGameRepositionOnlyEntity()) { cutsceneModelEntityDebugf2("SetRepositionOnlyEntityReadyForCutscene - Vehicle"); GetGameRepositionOnlyEntity()->m_nPhysicalFlags.bNotDamagedByAnything = true; GetGameRepositionOnlyEntity()->SetIsVisibleForModule(SETISVISIBLE_MODULE_CUTSCENE, false); cutsceneModelEntityDebugf2("CCutsceneAnimatedVehicleEntity::SetRepositionOnlyEntityReadyForCutscene: Hiding GetGameRepositionOnlyEntity (%s)", GetGameRepositionOnlyEntity()->GetModelName()); NetworkInterface::CutsceneStartedOnEntity(*GetGameRepositionOnlyEntity()); } } void CCutsceneAnimatedVehicleEntity::SetGameEntityReadyForGame(cutsManager* UNUSED_PARAM(pManager)) { if(!m_bIsReadyForGame) { if(GetGameEntity()) { NetworkInterface::CutsceneFinishedOnEntity(*GetGameEntity()); #if !__NO_OUTPUT ResetEntityForCallStackLogging(); #endif GetGameEntity()->SetLodMultiplier(m_fOriginalLODMultiplier); cutsceneModelEntityDebugf2("CCutsceneAnimatedVehicleEntity::SetGameEntityReadyForGame - Vehicle"); if (GetGameEntity()->GetVehicleType() == VEHICLE_TYPE_TRAIN) { ((CTrain*)GetGameEntity())->m_nTrainFlags.bIsCutsceneControlled = false; } bool canEnableCollision = true; if(NetworkInterface::IsGameInProgress() && GetGameEntity()->GetNetworkObject()) { canEnableCollision = !SafeCast(CNetObjPhysical, GetGameEntity()->GetNetworkObject())->GetKeepCollisionDisabledAfterAnimScene(); } if(canEnableCollision) { GetGameEntity()->EnableCollision(); } GetGameEntity()->SetForceHd(false); GetGameEntity()->SetFixedPhysics(false); GetGameEntity()->m_nVehicleFlags.bAnimateWheels = false; GetGameEntity()->m_nVehicleFlags.bAnimatePropellers = false; GetGameEntity()->m_nVehicleFlags.bAnimateJoints = false; GetGameEntity()->m_nPhysicalFlags.bNotDamagedByAnything = m_bWasInvincible; GetGameEntity()->m_nDEflags.bForcePrePhysicsAnimUpdate = false; GetGameEntity()->SetDriveMusclesToAnimation(false); if(!GetGameEntity()->m_nVehicleFlags.bUseCutsceneWheelCompression) { GetGameEntity()->PlaceOnRoadAdjust(); } if(GetGameEntity()->InheritsFromTrailer()) { //Need to enforce constraint limits on trailers to avoid pops GetGameEntity()->ActivatePhysics(); } bool CanDelete = m_RegisteredEntityFromScript.pEnt != GetGameEntity(); if(CanDelete|| m_RegisteredEntityFromScript.bDeleteBeforeEnd) { GetGameEntity()->SetOwnedBy(ENTITY_OWNEDBY_TEMP); GetGameEntity()->PopTypeSet(POPTYPE_RANDOM_AMBIENT); } else { GetGameEntity()->SetOwnedBy(ENTITY_OWNEDBY_SCRIPT); SetVisibility(GetGameEntity(), true); cutsceneModelEntityDebugf3("CCutsceneAnimatedVehicleEntity::SetGameEntityReadyForGame1: Showing GetGameEntity (%s)", GetGameEntity()->GetModelName()); } } if(GetGameRepositionOnlyEntity()) { cutsceneModelEntityDebugf2("SetGameEntityReadyForGame - Vehicle (reposition only"); GetGameRepositionOnlyEntity()->SetLodMultiplier(m_fOriginalLODMultiplier); GetGameRepositionOnlyEntity()->SetHeading(m_CurrentHeading); GetGameRepositionOnlyEntity()->SetPosition(m_CurrentPosition); GetGameRepositionOnlyEntity()->SetFixedPhysics(false); GetGameRepositionOnlyEntity()->m_nPhysicalFlags.bNotDamagedByAnything = m_bWasInvincible; GetGameRepositionOnlyEntity()->SetIsVisibleForModule(SETISVISIBLE_MODULE_CUTSCENE, true); cutsceneModelEntityDebugf2("CCutsceneAnimatedVehicleEntity::SetGameEntityReadyForGame2: Showing GetGameRepositionOnlyEntity (%s)", GetGameRepositionOnlyEntity()->GetModelName()); GetGameRepositionOnlyEntity()->m_nDEflags.bForcePrePhysicsAnimUpdate = false; } if (m_pCutSceneTask) { m_pCutSceneTask->SetExitNextUpdate(); } m_bIsReadyForGame = true; } } void CCutsceneAnimatedVehicleEntity::SetupSuspension() { for(int i = 0; i < GetGameEntity()->GetNumWheels(); i++) { CWheel *pWheel = GetGameEntity()->GetWheel(i); pWheel->UpdateSuspension(NULL, false); } if(GetGameEntity()->GetCurrentPhysicsInst() && CPhysics::GetLevel()->IsInactive(GetGameEntity()->GetCurrentPhysicsInst()->GetLevelIndex())) { fragInstGta * pVehicleFragInst = GetGameEntity()->GetVehicleFragInst(); if(pVehicleFragInst && pVehicleFragInst->GetCacheEntry() && pVehicleFragInst->GetCacheEntry()->GetHierInst() && pVehicleFragInst->GetCacheEntry()->GetHierInst()->articulatedCollider) { GetGameEntity()->GetVehicleFragInst()->GetCacheEntry()->GetHierInst()->articulatedCollider->SetColliderMatrixFromInstance(); } } GetGameEntity()->GetVehicleFragInst()->SyncSkeletonToArticulatedBody(true); } void CCutsceneAnimatedVehicleEntity::UpdateCutSceneTask(cutsManager* pManager) { if(GetGameEntity() && GetGameEntity()->GetIntelligence()) { aiTask* CurrentVehicleTask = GetGameEntity()->GetIntelligence()->GetTaskManager()->GetTree(VEHICLE_TASK_TREE_SECONDARY)->GetTask(VEHICLE_TASK_SECONDARY_ANIM); if(CurrentVehicleTask && CurrentVehicleTask->GetTaskType() == CTaskTypes::TASK_CUTSCENE) { CTask* pTask = static_cast(CurrentVehicleTask); UpdateCutSceneTaskPhase(pTask, pManager); // Update vehicle velocity if (!m_bStoppedCalled) { CTaskCutScene* pCutSceneTask = static_cast(pTask); const crClip* pClip = pCutSceneTask->GetClip(); if (pClip) { CutSceneManager* pCutsManager = static_cast(pManager); float fPhase = pCutsManager->GetPhaseUpdateAmount(pClip, GetAnimEventStartTime()); float fLastPhase = pCutsManager->GetAnimPhaseForSection(pClip->GetDuration(),GetAnimEventStartTime(), pCutsManager->GetCutScenePreviousTime()); const float time = pClip->ConvertPhaseToTime(fPhase); const float timeOnPreviousUpdate = pClip->ConvertPhaseToTime(fLastPhase); bool bIsWarpFrame = pClip->CalcBlockPassed(timeOnPreviousUpdate, time); const float fCurrentTimeStep = pCutsManager->GetCurrentCutSceneTimeStep(); if (bIsWarpFrame || fCurrentTimeStep <= 0.0001f) { GetGameEntity()->SetVelocity(VEC3_ZERO); } else { Vector3 vehVelocity(VEC3_ZERO); Vector3 vehDistance = fwAnimHelpers::GetMoverTrackTranslationDiff(*pClip, fLastPhase, fPhase); vehVelocity = vehDistance/fCurrentTimeStep; pCutSceneTask->GetAnimOrigin().Transform3x3(vehVelocity); #if __ASSERT if (vehVelocity.Mag2() > 62500.0f) { cutsceneAssertf(0, "Cutscene vehicle (%s) velocity is > 250 ms-1. Moved distance (%.2f, %.2f, %.2f) meters in %6.4f seconds\n", GetGameEntity()->GetModelName(), vehDistance.x, vehDistance.y, vehDistance.z, fCurrentTimeStep); } #endif //__ASSERT GetGameEntity()->SetVelocity( vehVelocity ); } } } } } } ///////////////////////////////////////////////////////////////////////// //Allow for manual adding and subtraction of bones #if __BANK void CCutsceneAnimatedVehicleEntity::SetBoneToHide(s32 Boneid, bool bHide) { for(int i=0; i < m_HiddenBones.GetCount(); i++) { if(m_HiddenBones[i] == Boneid ) { if(!bHide) { m_HiddenBones.Delete(i); } return; } } m_HiddenBones.PushAndGrow(Boneid); } ///////////////////////////////////////////////////////////////////////// //When debugging a real vehicle find the extras that are already switched off. void CCutsceneAnimatedVehicleEntity::InitaliseVehicleExtraList() { if(GetGameEntity()) { for(int i=0; i < 10; i ++) { int VehicleHeirachy = i + VEH_EXTRA_1; if (!GetGameEntity()->GetIsExtraOn(((eHierarchyId)VehicleHeirachy))) { m_HiddenBones.PushAndGrow((VEHICLE_HEIRACHY_MODIFIER+1) + i ); } } } } #endif /////////////////////////////////////////////////////////////////////////////////////////////////// // Rayfire /////////////////////////////////////////////////////////////////////////////////////////////////// CCutSceneRayFireEntity::CCutSceneRayFireEntity(const cutfObject* pObject) : cutsUniqueEntity(pObject) { m_fEventTime = 0.0f; m_iRayFireId = -1; } CCutSceneRayFireEntity::~CCutSceneRayFireEntity() { if (m_iRayFireId>-1) { CCompEntity* pCompEntity = CCompEntity::GetPool()->GetAt(m_iRayFireId); if (pCompEntity) { pCompEntity->SetIsCutsceneDriven(false); } } m_iRayFireId = -1; } void CCutSceneRayFireEntity::DispatchEvent(cutsManager* pManager, const cutfObject* pObject, s32 iEventId, const cutfEventArgs* UNUSED_PARAM(pEventArgs), const float fTime, const u32 UNUSED_PARAM(StickyId)) { switch ( iEventId ) { case CUTSCENE_START_OF_SCENE_EVENT: { } break; case CUTSCENE_PAUSE_EVENT: case CUTSCENE_UPDATE_EVENT: { if(m_iRayFireId > -1 ) { CCompEntity* pCompEntity = CCompEntity::GetPool()->GetAt(m_iRayFireId); if(pCompEntity && pCompEntity->GetPrimaryAnimatedObject()) { if(object_commands::CommandGetCompositeEntityState(m_iRayFireId) == CE_STATE_ANIMATING) { CObject* pObj = pCompEntity->GetPrimaryAnimatedObject(); if(cutsceneVerifyf(pObj, "CUTSCENE_UPDATE_EVENT: Component entity failed to create the animated rayfire object: %s", pObj->GetModelName())) { if(cutsceneVerifyf(pObj->GetAnimDirector(), "CUTSCENE_UPDATE_EVENT: Rayfire object %s has failed to create an anim director", pObj->GetModelName())) { CMoveObject& move = pObj->GetMoveObject(); const crClip* pClip = move.GetClipHelper().GetClip(); CutSceneManager* pCutSceneManager = static_cast(pManager); if(pClip) { float fPhase = pCutSceneManager->GetAnimPhaseForSection(pClip->GetDuration(), m_fEventTime, pCutSceneManager->GetCutSceneCurrentTime() ); pCompEntity->SetIsCutsceneDriven(true); move.GetClipHelper().SetRate(0.0f); move.GetClipHelper().SetPhase(fPhase); for(u32 i=1; iGetChildObjects().GetCount(); i++){ if (pCompEntity->GetChild(i)){ CMoveObject& move = pCompEntity->GetChild(i)->GetMoveObject(); move.GetClipHelper().SetRate(0.0f); move.GetClipHelper().SetPhase(fPhase); } } } } } } } } } break; case CUTSCENE_SET_ANIM_EVENT: { CutSceneManager* pCutSceneManager = static_cast(pManager); CCutSceneAssetMgrEntity* pAssetManager = pCutSceneManager->GetAssetManager(); s32 iIndex = pAssetManager->GetGameIndex(pObject->GetObjectId()); if(iIndex > -1) { if(object_commands::CommandGetCompositeEntityState(iIndex) != 0 ) { if(object_commands::CommandGetCompositeEntityState(iIndex) == CE_STATE_PRIMED) { object_commands::CommandSetCompositeEntityState(iIndex, CE_STATE_START_ANIM); CCompEntity* pCompEntity = CCompEntity::GetPool()->GetAt(iIndex); //calling update to make sure we create the anim director pCompEntity->Update(); if(pCompEntity && pCompEntity->GetPrimaryAnimatedObject()) { CObject* pObj = pCompEntity->GetPrimaryAnimatedObject(); if(cutsceneVerifyf(pObj, "CUTSCENE_SET_ANIM_EVENT: Component entity failed to create the animated rayfire object: %s", pObj->GetModelName())) { if(cutsceneVerifyf(pObj->GetAnimDirector(), "CUTSCENE_SET_ANIM_EVENT: Rayfire object %s has failed to create an anim director", pObj->GetModelName())) { CMoveObject& move = pObj->GetMoveObject(); const crClip* pClip = move.GetClipHelper().GetClip(); CutSceneManager* pCutSceneManager = static_cast(pManager); m_fEventTime = fTime; if(pClip) { //m_HaveAnimToUpdate = true; float fPhase = pCutSceneManager->GetAnimPhaseForSection(pClip->GetDuration(), m_fEventTime, pCutSceneManager->GetCutSceneCurrentTime() ); move.GetClipHelper().SetRate(0.0f); move.GetClipHelper().SetPhase(fPhase); pCompEntity->SetIsCutsceneDriven(true); for(u32 i=1; iGetChildObjects().GetCount(); i++){ if (pCompEntity->GetChild(i)){ CMoveObject& move = pCompEntity->GetChild(i)->GetMoveObject(); move.GetClipHelper().SetRate(0.0f); move.GetClipHelper().SetPhase(fPhase); } } } m_iRayFireId = pAssetManager->GetGameIndex(pObject->GetObjectId()); } } } } } } } break; } }