//===========================================================================// // File: Effect.cpp // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 2/8/99 DPB Created File //---------------------------------------------------------------------------// // Copyright (C) 1995-97, Virtual World Entertainment, Inc. // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #include "AdeptHeaders.hpp" #include "Effect.hpp" #include "EntityClassData.hpp" #include "Tool.hpp" #include "RendererManager.hpp" #include "Site.hpp" #include #include "EntityManager.hpp" //############################################################################# //################## Effect::ExecutionStateEngine ####################### //############################################################################# const StateEngine::StateEntry Effect::ExecutionStateEngine::StateEntries[]= { STATE_ENTRY(Effect__ExecutionStateEngine, Stopped), STATE_ENTRY(Effect__ExecutionStateEngine, Stopping), STATE_ENTRY(Effect__ExecutionStateEngine, Running), STATE_ENTRY(Effect__ExecutionStateEngine, Killing) }; Effect::ExecutionStateEngine::ClassData* Effect::ExecutionStateEngine::DefaultData = NULL; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Effect::ExecutionStateEngine::InitializeClass() { Check_Object(StateEngine::DefaultData); Verify(!DefaultData); DefaultData = new ClassData( Effect__ExecutionStateEngineClassID, "Adept::Effect::ExecutionStateEngine", BaseClass::DefaultData, ELEMENTS(StateEntries), StateEntries, (Entity::ExecutionStateEngine::Factory)Make, (Entity::ExecutionStateEngine::FactoryRequest::Factory) &FactoryRequest::ConstructFactoryRequest ); Register_Object(DefaultData); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Effect::ExecutionStateEngine::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Effect::ExecutionStateEngine* Effect::ExecutionStateEngine::Make( Effect *effect, FactoryRequest *request ) { Check_Object(effect); Check_Object(request); Effect::ExecutionStateEngine* engine = new Effect::ExecutionStateEngine(DefaultData, effect, request); return engine; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int Effect::ExecutionStateEngine::RequestState( int new_state, void* data ) { Check_Object(this); Check_Object(owningEntity); // //---------------------------------------------- // Now, switch the state and tickle the watchers //---------------------------------------------- // switch (StateEngine::RequestState(new_state, data)) { case StoppingState: { // //-------------------------------------------------------------------- //We need to tell both our webs that we are going through a Stop state //-------------------------------------------------------------------- // for (unsigned i=1; iGetComponentWeb(i); if (web) { Check_Object(web); web->SendCommand(Renderer::StopEffectCommandID); } } break; } case RunningState: { // //-------------------------------------------------------------------- //We need to tell both our webs that we are going through a Stop state //-------------------------------------------------------------------- // for (unsigned i=1; iGetComponentWeb(i); if (web) { Check_Object(web); web->SendCommand(Renderer::StartEffectCommandID); } } break; } } return currentState; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Effect::ExecutionStateEngine::TestInstance() { Verify(IsDerivedFrom(DefaultData)); } //############################################################################# //############################# Effect ################################## //############################################################################# Effect::ClassData* Effect::DefaultData = NULL; static DWORD Effect_Entities_Count; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Effect::InitializeClass() { Verify(!DefaultData); DefaultData = new ClassData( EffectClassID, "Adept::Effect", BaseClass::DefaultData, 0, NULL, (Entity::Factory)Make, (Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage, ExecutionStateEngine::DefaultData, (Entity::GameModel::Factory)GameModel::ConstructGameModel, NULL, (Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify, (Entity::GameModel::ModelWrite)GameModel::WriteToText, (Entity::GameModel::ModelSave)GameModel::SaveGameModel ); Register_Object(DefaultData); CUSTOM_DIRECT_ATTRIBUTE( Effect, VideoStatus, videoStatus, bool, BoolClassID ); CUSTOM_DIRECT_ATTRIBUTE( Effect, AudioStatus, audioStatus, int, IntClassID ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Effect__GameModel, StartsRunning, startsRunning, bool, BoolClassID ); DIRECT_GAME_MODEL_ATTRIBUTE( Effect__GameModel, Translation, translation, Point3D ); DIRECT_GAME_MODEL_ATTRIBUTE( Effect__GameModel, Rotation, rotation, UnitQuaternion ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Effect__GameModel, KillOnAttachedEntityDeath, killOnAttachedEntityDeath, bool, BoolClassID ); Effect_Entities_Count = 0; #if !defined(NO_STATS) AddStatistic("Effect entities Executed", "entities", gos_DWORD, &Effect_Entities_Count, Stat_AutoReset); #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Effect::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Effect* Effect::Make( const CreateMessage *message, ReplicatorID *base_id ) { Check_Object(EntityManager::GetInstance()); Effect *new_entity; Entity *entity = EntityManager::GetInstance()->RequestFromArmory(message->dataListID); if (entity) { new_entity = Cast_Object(Effect*, entity); new_entity->Reuse(message, base_id); } else { gos_PushCurrentHeap(s_Heap); new_entity = new Effect(DefaultData, message, base_id, NULL); gos_PopCurrentHeap(); } Check_Object(new_entity); return new_entity; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Effect::Effect( ClassData *class_data, const CreateMessage *message, ReplicatorID *base_id, ElementRenderer::Element *element ): Mover(class_data, message, base_id, element), followEntity(this), followSite(this) { Check_Pointer(this); const GameModel *model = GetGameModel(); Check_Object(model); audioStatus = 0; videoStatus = false; if (model->startsRunning) executionState->RequestState(ExecutionStateEngine::RunningState); else executionState->RequestState(ExecutionStateEngine::StoppedState); effectOffset = LinearMatrix4D::Identity; switch(model->rotationType) { case Effect__GameModel::AgainstMotionRotation: { YawPitchRoll effect_rotation_offset(gosFX::Effect_Against_Motion); effectOffset.BuildRotation(effect_rotation_offset); break; } case Effect__GameModel::IntoMotionRotation: { YawPitchRoll effect_rotation_offset(gosFX::Effect_Into_Motion); effectOffset.BuildRotation(effect_rotation_offset); break; } case Effect__GameModel::UseRotation: { effectOffset = model->rotation; break; } } effectOffset.BuildTranslation(model->translation); #if defined (_ARMOR) iAmDead = false; #endif // SPEW(("daberger", "CREATING EFFECT %x at time %f", this, gos_GetElapsedTime())); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Effect::~Effect() { DESTRUCTOR("Effect"); // SPEW(("daberger", "DELETING EFFECT %x at time %f", this, gos_GetElapsedTime())); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Effect::Reuse( const CreateMessage *message, ReplicatorID *base_id ) { Check_Pointer(this); Check_Object(message); BaseClass::Reuse(message, base_id); Check_Pointer(this); const GameModel *model = GetGameModel(); Check_Object(model); audioStatus = 0; videoStatus = false; if (model->startsRunning) executionState->RequestState(ExecutionStateEngine::RunningState); else executionState->RequestState(ExecutionStateEngine::StoppedState); effectOffset = LinearMatrix4D::Identity; switch(model->rotationType) { case Effect__GameModel::AgainstMotionRotation: { YawPitchRoll effect_rotation_offset(gosFX::Effect_Against_Motion); effectOffset.BuildRotation(effect_rotation_offset); break; } case Effect__GameModel::IntoMotionRotation: { YawPitchRoll effect_rotation_offset(gosFX::Effect_Into_Motion); effectOffset.BuildRotation(effect_rotation_offset); break; } case Effect__GameModel::UseRotation: { effectOffset = model->rotation; break; } } effectOffset.BuildTranslation(model->translation); #if defined (_ARMOR) iAmDead = false; #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int Effect::GetExecutionSlot() { Check_Object(this); return EffectExecutionSlot; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Effect::PreCollisionExecute(Time till) { Check_Object(this); PRECOLLISION_LOGIC("Effect"); Set_Statistic(Effect_Entities_Count, Effect_Entities_Count+1); UsePostCollision(); BaseClass::PreCollisionExecute(till); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #if defined(LAB_ONLY) void Effect::SyncMatrices(bool update_matrix) { SYNC_LOGIC("Effect"); BaseClass::SyncMatrices(update_matrix); } #endif //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Effect::PostCollisionExecute(Time till) { Check_Object(this); POSTCOLLISION_LOGIC("Effect"); if (IsFollowing()) { if(followEntity.GetCurrent()) PlaceOnEntity(); else if(followSite.GetCurrent()) PlaceOnSite(); else if (executionState->GetState() != ExecutionStateEngine::StoppingState) executionState->RequestState(ExecutionStateEngine::StoppingState); } BaseClass::PostCollisionExecute(till); #if defined (_ARMOR) Verify(!iAmDead); #endif Check_Object(executionState); switch(executionState->GetState()) { case ExecutionStateEngine::StoppingState: { if (!(videoStatus || audioStatus)) { #if defined (_ARMOR) iAmDead = true; #endif executionState->RequestState(ExecutionStateEngine::StoppedState); SentenceToDeathRow(); } break; } case ExecutionStateEngine::RunningState: { // //-------------------------------------------------------------------- //If the video and audio components are looping this will never happen //It is just for the one time play effects //-------------------------------------------------------------------- // if (!(videoStatus || audioStatus)) { executionState->RequestState(ExecutionStateEngine::StoppingState); } break; } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Effect::BecomeInteresting(bool render_me) { LOAD_LOGIC("Become Interesting::Effect"); if (Application::GetInstance()->serverFlag && Application::GetInstance()->m_localMissionParameters->m_runDedicated) { videoStatus = false; audioStatus = 0; SetInterestMask(SimulationInterestLevel); } else { const GameModel *model = GetGameModel(); Check_Object(model); if (model->startsRunning) executionState->RequestState(ExecutionStateEngine::RunningState); else executionState->RequestState(ExecutionStateEngine::StoppedState); BaseClass::BecomeInteresting(render_me); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Effect::SetFollowEntity(Entity *entity) { Check_Object(this); Check_Object(entity); SetFollowing(); followEntity.Remove(); followEntity.Add(entity); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Effect::SetFollowEntity(Site *site) { Check_Object(this); Check_Object(site); SetFollowing(); followSite.Remove(); followSite.Add(site); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Effect::PlaceOnEntity(LinearMatrix4D offsetOnEntity) { Check_Object(this); Entity *entity; entity = followEntity.GetCurrent(); Check_Object(entity); if ((entity->IsDestroyed()) && (GetGameModel()->killOnAttachedEntityDeath)) { Check_Object(executionState); SentenceToDeathRow(); } else { // // Rather than add additional data to the object I'm going tack onto the // current effect offset. // LinearMatrix4D effect_local_to_parent; effect_local_to_parent.Multiply(offsetOnEntity, effectOffset); effectOffset = effect_local_to_parent; LinearMatrix4D new_position; new_position.Multiply(effectOffset, entity->GetLocalToWorld()); UnitVector3D direction_vector; new_position.GetLocalForwardInWorld(&direction_vector); SetNewLocalToParent(new_position); SyncMatrices(true); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Effect::PlaceOnEntity() { Check_Object(this); Entity *entity; entity = followEntity.GetCurrent(); Check_Object(entity); if ((entity->IsDestroyed()) && (GetGameModel()->killOnAttachedEntityDeath)) { Check_Object(executionState); SentenceToDeathRow(); } else { LinearMatrix4D new_position; new_position.Multiply(effectOffset, entity->GetLocalToWorld()); UnitVector3D direction_vector; new_position.GetLocalForwardInWorld(&direction_vector); SetNewLocalToParent(new_position); SyncMatrices(true); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Effect::PlaceOnSite() { Check_Object(this); Site *site; site = followSite.GetCurrent(); Check_Object(site); LinearMatrix4D new_position; new_position.Multiply(effectOffset, site->GetLocalToWorld()); UnitVector3D direction_vector; new_position.GetLocalForwardInWorld(&direction_vector); SetNewLocalToParent(new_position); SyncMatrices(true); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Effect::TestInstance() { Verify(IsDerivedFrom(DefaultData)); }