//===========================================================================// // File: NonCom.cpp //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 05/06/99 DPB Inital base class //---------------------------------------------------------------------------// // Copyright (C) 1998, Fasa Interactive // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #include "MW4Headers.hpp" #include "NonCom.hpp" #include "ai.hpp" #include "MWDamageObject.hpp" #include "adept\CameraComponent.hpp" //############################################################################# //############################### NonCom ################################ //############################################################################# NonCom::ClassData* NonCom::DefaultData = NULL; DWORD MechWarrior4::Executed_NonCom_Count = 0; const int MAX_NONCOM_FRAME = 8; const Stuff::Scalar NONCOM_FRAME_WIDTH = 256/16; const Stuff::Scalar NONCOM_ANIMAL_FRAME_WIDTH = 256/8; const Stuff::Scalar NONCOM_FRAME_HEIGHT = 256/8; const Stuff::Scalar RUN_FRAME_RATE = 15.0f; // frames per second const Stuff::Scalar WALK_FRAME_RATE = 8.0f; // frames per second const Stuff::Scalar ANIMAL_FRAME_RATE = 15.0f; // frames per second const Stuff::Scalar RUN_SPEED = 5.99f; // meters per second to use run frame const Stuff::Scalar min_index_change_duration = 1.5f; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NonCom::InitializeClass() { Verify(!DefaultData); DefaultData = new ClassData( NonComClassID, "MechWarrior4::NonCom", MWObject::DefaultData, 0, NULL, (Entity::Factory)Make, (Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage, ExecutionStateEngine::DefaultData, (Entity::GameModel::Factory)GameModel::ConstructGameModel, (Entity::GameModel::Factory)GameModel::ConstructOBBStream, (Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify, (Entity::GameModel::ModelWrite)GameModel::WriteToText, (Entity::GameModel::ModelSave)GameModel::SaveGameModel, AnimationStateEngine::Make ); Register_Object(DefaultData); CUSTOM_DIRECT_ATTRIBUTE( NonCom, UVMatrix, UVMatrix, AffineMatrix4D, AffineMatrix4DClassID ); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NonCom::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // NonCom* NonCom::Make(CreateMessage *message,ReplicatorID *base_id) { gos_PushCurrentHeap(Heap); NonCom *new_entity = new NonCom(DefaultData, message, base_id, NULL); gos_PopCurrentHeap(); Check_Object(new_entity); return new_entity; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // NonCom::NonCom(ClassData *class_data,CreateMessage *message,ReplicatorID *base_id,ElementRenderer::Element *element): MWObject(class_data, message, base_id, element) { Check_Pointer(this); Check_Object(message); CommonCreation(message); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NonCom::CommonCreation(CreateMessage *message) { Check_Object(this); Check_Object(message); m_UVs[0] = Point3D (0,0,0); m_UVs[1] = Point3D (0,0,0); m_UVs[2] = Point3D (0,0,0); m_UVs[3] = Point3D (0,0,0); m_TextureID = 0; UVMatrix = AffineMatrix4D::Identity; m_AnimFrame = (objectID & 0x07); m_FrameTime = 0; m_Speed = 0; m_IsAnimal = false; m_LastPos = Point3D::Identity; m_LastFacing = 0; // executionState->RequestState(ExecutionStateEngine::NeverExecuteState); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NonCom::Respawn(Entity::CreateMessage *message) { Check_Object(this); Check_Object(message); MWObject::Respawn(message); CreateMessage *NonCom_message = Cast_Pointer(CreateMessage *, message); CommonCreation(NonCom_message); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // NonCom::~NonCom() { } void NonCom::TurnOn (void) { lastParameterization = gos_GetElapsedTime (); executionState->RequestState(ExecutionStateEngine::AlwaysExecuteState); } void NonCom::TurnOff (void) { executionState->RequestState(ExecutionStateEngine::NeverExecuteState); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NonCom::Reuse(const CreateMessage *message,ReplicatorID *base_id) { Check_Object(this); STOP(("Not implemented")); MWObject::Reuse(message, base_id); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NonCom::PreCollisionExecute(Stuff::Time till) { Check_Object(this); Check_Object(animStateEngine); PRECOLLISION_LOGIC("NonCom"); Verify(executionState->GetState() != ExecutionStateEngine::NeverExecuteState); Set_Statistic(Executed_NonCom_Count, Executed_NonCom_Count+1); DetermineUV (GetTimeSlice (till)); MWObject::PreCollisionExecute(till); } void NonCom::DetermineUV (Stuff::Time slice) { Check_Object (this); bool flip,run=false; Scalar gridx,gridy; // index into grid int index; Point3D distance_to_target; Point3D loc (GetLocalToWorld ()); LinearMatrix4D tempmat (GetLocalToWorld ()); tempmat.AlignLocalAxisToWorldVector (Vector3D::Up,Y_Axis,X_Axis,Z_Axis); CameraComponent *camera = VideoRenderer::Instance->GetSceneCamera(); // camera can be null on dedicated servers and in prerender. if (camera == NULL) return; Check_Object(camera); Stuff::Vector2DOf lastPos2D; camera->ComputeCursor(&lastPos2D,m_LastPos); Stuff::Vector2DOf curPos2D; camera->ComputeCursor(&curPos2D,loc); if (lastPos2D.x < curPos2D.x) { if (lastPos2D.y < curPos2D.y) { index = 2; } else { index = 3; } } else { if (lastPos2D.y < curPos2D.y) { index = 0; } else { index = 1; } } /* ElementRenderer::CameraElement* camelement = camera->GetElement(); Point3D camera_pos(camelement->GetLocalToWorld()); if (m_LastPos == Point3D::Identity) { m_LastPos = camelement->GetLocalToWorld(); } Stuff::UnitVector3D forward_vector; camelement->GetLocalToWorld().GetLocalForwardInWorld(&forward_vector); Point3D delta; delta.Subtract(m_LastPos,loc); if (!Small_Enough(delta.GetLengthSquared())) { delta.Normalize(delta); } Scalar angle = delta * forward_vector; bool left = (angle < 0); if (GetLengthSquared(camera_pos,loc) > GetLengthSquared(camera_pos,m_LastPos)) { if (left == true) { index = 1; } else { index = 3; } // 1 or 3 } else { if (left == true) { index = 0; } else { index = 2; } // 0 or 2 } */ /* Stuff::UnitVector3D forward_vector; camelement->GetLocalToWorld().GetLocalForwardInWorld(&forward_vector); if (m_LastPos == Point3D::Identity) { m_LastPos = camelement->GetLocalToWorld(); } Point3D delta; delta.Subtract(m_LastPos,loc); if (!Small_Enough(delta.GetLengthSquared())) { delta.Normalize(delta); } Scalar angle = delta * forward_vector; if ((angle <= -1) || (angle >= 1)) { angle = 0; } else { angle = Arccos(angle); } if (angle < 0) { angle = Two_Pi + angle; } m_LastFacing = angle; if (angle < Pi_Over_4) { index = 0; } else { if (angle < Pi_Over_2) { index = 1; } else { if (angle < Pi_Over_4 + Pi_Over_2) { index = 2; } else { index = 3; } } } */ m_LastIndex = index; if ((m_Speed >= RUN_SPEED) && (m_IsAnimal == false)) { index += 4; run = true; } flip = false; Verify (index >=0); Verify (index <= 7); gridx = gridy = 0; if (m_IsAnimal == true) { switch (index) { case 0: gridx = 0; gridy = 0; break; case 1: gridx = 0; gridy = 1; break; case 2: gridx = 0; gridy = 0; flip = true; break; case 3: gridx = 0; gridy = 1; flip = true; break; } } else { switch (index) { case 0: gridx = 0; gridy = 0; break; case 1: gridx = 8; gridy = 0; break; case 2: gridx = 0; gridy = 0; flip = true; break; case 3: gridx = 8; gridy = 0; flip = true; break; case 4: gridx = 0; gridy = 1; break; case 5: gridx = 8; gridy = 1; break; case 6: gridx = 0; gridy = 1; flip = true; break; case 7: gridx = 8; gridy = 1; flip = true; break; } } if (m_Speed == 0) m_AnimFrame = (objectID & 0x07); else { m_FrameTime += slice; Scalar frame_rate; if (m_IsAnimal == true) { frame_rate = ANIMAL_FRAME_RATE; } else { frame_rate = run ? RUN_FRAME_RATE : WALK_FRAME_RATE; } while (m_FrameTime >= (1.0/frame_rate)) { m_FrameTime -= (1.0/frame_rate); m_AnimFrame++; } } if ((m_IsAnimal == true) && (m_TextureID == 0)) { flip = (flip == true) ? false : true; } Verify (m_TextureID >=0); Verify (m_TextureID <= 3); gridy += (m_TextureID * 2); m_AnimFrame = m_AnimFrame & 0x07; UVMatrix = AffineMatrix4D::Identity; if (flip) UVMatrix(0,0) = -1.0f; else UVMatrix(0,0) = 1.0f; UVMatrix(1,1) = 1.0f; UVMatrix(3,0) = (FrameWidth() / 256.0f) * (m_AnimFrame + gridx); if (flip) UVMatrix(3,0) += (FrameWidth() / 256.0f); UVMatrix(3,1) = (FrameHeight() / 256.0f) * gridy; // UVMatrix(3,0) = m_UVs[2].x / 256.0f; // UVMatrix(3,1) = m_UVs[2].y / 256.0f; #if 0 for (i=0;i<4;i++) // normalize values { m_UVs[i].x /= 256.0f; m_UVs[i].y /= 256.0f; } #endif m_LastPos = loc; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NonCom::ReactToDestruction(int damage_mode, int damage_type) { Check_Object(this); if (!IsDestroyed()) { if (m_AI) { Check_Object(m_AI); m_AI->Die(); } SetDestroyedFlag(damage_mode); if (damage_type != SplashDamageType) DealSplashDamage(); const GameModel *model = GetGameModel(); Check_Object(model); CreateEffect(model->destroyedEffectResource, (Point3D)GetLocalToWorld()); if(!m_deathEntity.GetCurrent()) { Entity *death_entity = CreateStaticHermitEntity(model->deathEntityResource); if(death_entity) { m_deathEntity.Remove(); m_deathEntity.Add(death_entity); } } RemoveFromExecution(); } Entity::ReactToDestruction(damage_mode, damage_type); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NonCom::TestInstance() const { Verify(IsDerivedFrom(DefaultData)); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NonCom::ReactToHit(const Entity__TakeDamageMessage *message,Adept::DamageObject *part_hit) { Check_Object(this); Check_Object(message); MWObject::ReactToHit(message,part_hit); } void NonCom::SetAsAnimal() { m_IsAnimal = true; } Scalar NonCom::FrameWidth() const { if (m_IsAnimal == true) { return (NONCOM_ANIMAL_FRAME_WIDTH); } return (NONCOM_FRAME_WIDTH); } Scalar NonCom::FrameHeight() const { return (NONCOM_FRAME_HEIGHT); }