Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "StdAfx.h"
- #include "Character.h"
- #include "Movement/CharacterMovement.h"
- #include "Animations/CharacterAnimations.h"
- #include "Path/CharacterPath.h"
- //for path finding
- #include "Player/Player.h"
- #include "Player/Movement/PlayerMovement.h"
- #include "ISimpleDamageable.h"
- #include "Game/GameFactory.h"
- #include "Game/GameRules.h"
- #include "FlowNodes/Helpers/FlowGameEntityNode.h"
- #include <CryRenderer/IRenderAuxGeom.h>
- //#include <CryPhysics/IPhysics.h>
- class CCharacterRegistrator
- : public IEntityRegistrator
- , public CCharacter::SExternalCVars
- {
- virtual void Register() override
- {
- //CGameFactory::RegisterGameObject<CCharacter>("Character");
- // Finally, register the entity class so that instances can be created later on either via Launcher or Editor
- CCharacter::Register();
- CGameFactory::RegisterGameObjectExtension<CCharacterMovement>("CharacterMovement");
- CGameFactory::RegisterGameObjectExtension<CCharacterAnimations>("CharacterAnimations");
- CGameFactory::RegisterGameObjectExtension<CCharacterPath>("CharacterPath");
- RegisterCVars();
- }
- void RegisterCVars()
- {
- REGISTER_CVAR2("ch_mass", &m_mass, 50.f, VF_CHEAT, "Mass of the player entity in kg");
- REGISTER_CVAR2("ch_moveSpeed", &m_moveSpeed, 4.0f, VF_CHEAT, "Speed at which the player moves");
- REGISTER_CVAR2("ch_eyeHeight", &m_playerEyeHeight, 0.935f, VF_CHEAT, "Height of the player's eyes from ground");
- m_pCharacterGeometry = REGISTER_STRING("ch_thirdPersonGeometry", "Assets/Objects/Characters/panda/panda.cdf", VF_CHEAT, "Sets the third person geometry to load");
- m_pCharacterMannequinContext = REGISTER_STRING("ch_thirdPersonMannequinContext", "Character", VF_CHEAT, "The name of the third person context used in Mannequin");
- m_pCharacterAnimationDatabase = REGISTER_STRING("ch_thirdPersonAnimationDatabase", "Assets/Animations/Mannequin/ADB/panda.adb", VF_CHEAT, "Path to the animation database file to load");
- m_pCharacterControllerDefinition = REGISTER_STRING("ch_thirdPersonControllerDefinition", "Animations/Mannequin/ADB/pandaControllerDefinition.xml", VF_CHEAT, "Path to the controller definition file to load");
- }
- };
- CCharacterRegistrator g_playerRegistrator;
- CCharacter::CCharacter()
- : m_pMovement(nullptr)
- , m_bAlive(false)
- , m_bHit(false)
- , m_pPlayer(nullptr)
- , m_pPath(nullptr)
- , fgActionTryToFindPlayer(false)
- {
- }
- CCharacter::~CCharacter()
- {
- }
- const CCharacter::SExternalCVars &CCharacter::GetCVars() const
- {
- return g_playerRegistrator;
- }
- bool CCharacter::Init(IGameObject *pGameObject)
- {
- if (!CNativeEntityBase::Init(pGameObject))
- return false;
- SetGameObject(pGameObject);
- return true;
- }
- void CCharacter::PostInit(IGameObject *pGameObject)
- {
- CNativeEntityBase::PostInit(pGameObject);
- pGameObject->EnablePhysicsEvent(true, eEPE_OnCollisionLogged);
- const int requiredEvents[] = { eGFE_OnCollision };
- pGameObject->UnRegisterExtForEvents(this, NULL, 0);
- pGameObject->RegisterExtForEvents(this, requiredEvents, sizeof(requiredEvents) / sizeof(int));
- m_pMovement = static_cast<CCharacterMovement *>(GetGameObject()->AcquireExtension("CharacterMovement"));
- m_pAnimations = static_cast<CCharacterAnimations *>(GetGameObject()->AcquireExtension("CharacterAnimations"));
- m_pPath = static_cast<CCharacterPath *>(GetGameObject()->AcquireExtension("CharacterPath"));
- //gEnv->pGame->GetIGameFramework()->GetIActorSystem()->AddActor(GetEntityId(), this);
- //pGameObject->EnableUpdateSlot(this, 0);
- }
- void CCharacter::ProcessEvent(SEntityEvent& event)
- {
- switch (event.event)
- {
- case ENTITY_EVENT_START_LEVEL:
- // Editor specific, physicalize on reset, property change or transform change
- case ENTITY_EVENT_RESET:
- {
- // Make sure to revive player when respawning in Editor
- Reset();
- m_pPath->InitAI();
- break;
- }
- case ENTITY_EVENT_EDITOR_PROPERTY_CHANGED:
- case ENTITY_EVENT_XFORM_FINISHED_EDITOR:
- Reset();
- break;
- case ENTITY_EVENT_HIDE:
- case ENTITY_EVENT_UNHIDE:
- break;
- }
- }
- void CCharacter::Update(SEntityUpdateContext& ctx, int updateSlot)
- {
- //if (fgActionTryToFindPlayer)
- //{
- //
- // Vec3 playerPos = m_pPlayer->GetMovement()->GetWorldPosition();
- // Vec3 characterPos = GetEntity()->GetWorldPos();
- // float distance = (characterPos - playerPos).len();
- // // if near player stop
- // if (distance < 2.0f)
- // {
- // m_pPath->CancelCurrentRequest();
- // m_pPath->ClearMovementState();
- // fgActionTryToFindPlayer = false;
- // }
- // // else, try to reach player
- //}
- }
- void CCharacter::Reset()
- {
- // Note that this implementation does not handle the concept of death, SetHealth(0) will still revive the player.
- //if (m_bAlive)
- // return;
- m_bAlive = true;
- m_bHit = false;
- // Unhide the entity in case hidden by the Editor
- GetEntity()->Hide(false);
- // Make sure that the player spawns upright
- GetEntity()->SetWorldTM(Matrix34::Create(Vec3(1.0, 1.0, 1.0), IDENTITY, GetEntity()->GetWorldPos()));
- // Set the player geometry, this also triggers physics proxy creation
- SetCharacterModel();
- }
- void CCharacter::SetCharacterModel()
- {
- // Load the third person model
- //GetEntity()->LoadCharacter(eGeometry_Character, GetCVars().m_pCharacterGeometry->GetString());
- // Do the same for animations so that Mannequin data can be initialized
- m_pAnimations->OnCharacterModelChanged();
- // Now create the physical representation of the entity
- m_pMovement->Physicalize();
- m_pMovement->PhysicalizeAfter();
- StartColor();
- }
- void CCharacter::OutputAllFG()
- {
- OutputFG_IsGrouded(m_pMovement->IsOnGround());
- OutputFG_Direction(m_pMovement->GetLocalMoveDirection());
- OutputFG_EntityId(GetEntityId());
- if (lastSpeed > 0.01f)
- OutputFG_IsMove();
- OutputFG_Speed(lastSpeed);
- }
- void CCharacter::OutputFG_IsMove()
- {
- TFlowInputData data;
- data.SetUserFlag(true);
- ActivateFlowNodeOutput(eOutputPort_IsMove, data);
- }
- void CCharacter::OutputFG_Speed(float value)
- {
- TFlowInputData data;
- data.SetUserFlag(true);
- data.Set<float>(value);
- ActivateFlowNodeOutput(eOutputPort_Speed, data);
- }
- void CCharacter::OutputFG_EntityId(EntityId value)
- {
- TFlowInputData data;
- data.SetUserFlag(true);
- data.Set<EntityId>(value);
- ActivateFlowNodeOutput(eOutputPort_EntityId, data);
- }
- void CCharacter::OutputFG_Direction(Vec3 value)
- {
- TFlowInputData data;
- data.SetUserFlag(true);
- data.Set<Vec3>(value);
- ActivateFlowNodeOutput(eOutputPort_Direction, data);
- }
- void CCharacter::OutputFG_IsGrouded(bool value)
- {
- TFlowInputData data;
- data.SetUserFlag(true);
- data.Set<bool>(value);
- ActivateFlowNodeOutput(eOutputPort_IsGrounded, data);
- }
- void CCharacter::HandleEvent(const SGameObjectEvent &event)
- {
- // Handle the OnCollision event, in order to have the entity removed on collision
- if (event.event == eGFE_OnCollision)
- {
- // Collision info can be retrieved using the event pointer
- //EventPhysCollision *physCollision = reinterpret_cast<EventPhysCollision *>(event.ptr);
- }
- }
- void CCharacter::StartColor()
- {
- //// clone and red
- //IStatObj* ob = GetEntity()->GetStatObj(0);
- //IMaterial* pMaterial = ob->GetMaterial();
- //IMaterial* pMaterialClone = gEnv->p3DEngine->GetMaterialManager()->CloneMaterial(pMaterial);
- //pMaterialClone->SetGetMaterialParamVec3("diffuse", Vec3(1.0f, 0.0f, 0.0f), false);
- //ob->SetMaterial(pMaterialClone);
- ICharacterInstance* const pCharacterInstance = GetEntity()->GetCharacter(CCharacter::eGeometry_Character);
- IMaterial* pMaterial = pCharacterInstance->GetMaterial();
- pMaterial->SetGetMaterialParamVec3("diffuse", Vec3(0.0f, 1.0f, 0.0f), false);
- }
- void CCharacter::MarkAsHited()
- {
- if (m_bHit)
- {
- ICharacterInstance* const pCharacterInstance = GetEntity()->GetCharacter(CCharacter::eGeometry_Character);
- IMaterial* pMaterial = pCharacterInstance->GetMaterial();
- IMaterial* pMaterialClone = gEnv->p3DEngine->GetMaterialManager()->CloneMaterial(pMaterial);
- pMaterialClone->SetGetMaterialParamVec3("diffuse", Vec3(1.0f, 0.0f, 0.0f), false);
- m_bHit = true;
- pCharacterInstance->SetIMaterial_Instance(pMaterialClone);
- //IEntityPhysicalProxy* pProxy = (IEntityPhysicalProxy*)GetEntity()->GetProxy(ENTITY_PROXY_PHYSICS);
- //IPhysicalEntity* phy = GetEntity()->GetPhysics();
- }
- //IEntityRenderProxy* pProxy = (IEntityRenderProxy *)GetEntity()->GetProxy(ENTITY_PROXY_RENDER);
- //pProxy->SetOpacity(0.5f);
- }
- // Static function
- void CCharacter::Register()
- {
- auto properties = new SNativeEntityPropertyInfo[eNumProperties];
- memset(properties, 0, sizeof(SNativeEntityPropertyInfo) * eNumProperties);
- RegisterEntityProperty<bool>(properties, eProperty_Active, "Active", "1", "", 0, 1);
- //RegisterEntityProperty<float>(properties, eProperty_Radius, "Radius", "4", "", 0.1f, 100.f);
- // Finally, register the entity class so that instances can be created later on either via Launcher or Editor
- CGameFactory::RegisterNativeEntity<CCharacter>("Character", "UserStuff", "character.bmp", 0u, properties, eNumProperties);
- // Create flownode
- CGameEntityNodeFactory &nodeFactory = CGameFactory::RegisterEntityFlowNode("Character");
- // Define input ports, and the callback function for when they are triggered
- std::vector<SInputPortConfig> inputs;
- inputs.push_back(InputPortConfig_Void("TurnOn", "Turns the Area on"));
- inputs.push_back(InputPortConfig_Void("TurnOff", "Turns the Area off"));
- inputs.push_back(InputPortConfig_Void("GetStates", "Query Character states into outputs"));
- inputs.push_back(InputPortConfig_Void("TryToFindPlayer", "Query Character for going closer to the Player"));
- nodeFactory.AddInputs(inputs, OnFlowgraphActivation);
- std::vector<SOutputPortConfig> outputs;
- outputs.push_back(OutputPortConfig_Void("IsMove", "If character moves"));
- outputs.push_back(OutputPortConfig<float>("Speed", "Character speed"));
- outputs.push_back(OutputPortConfig<int>("EntityId", "Character Entity id"));
- outputs.push_back(OutputPortConfig<Vec3>("Direction", "Move Direction"));
- outputs.push_back(OutputPortConfig<bool>("IsGrounded", "Character on ground"));
- //outputs.push_back(OutputPortConfig_AnyType("IsActive", "If player leave area"));
- nodeFactory.AddOutputs(outputs);
- // Mark the factory as complete, indicating that there will be no additional ports
- nodeFactory.Close();
- }
- void CCharacter::OnFlowgraphActivation(EntityId entityId, IFlowNode::SActivationInfo *pActInfo, const class CFlowGameEntityNode *pNode)
- {
- if (auto *pCharacter = static_cast<CCharacter *>(QueryExtension(entityId)))
- {
- if (IsPortActive(pActInfo, eInputPort_TurnOn))
- {
- pCharacter->GetEntity()->Hide(false);
- }
- else if (IsPortActive(pActInfo, eInputPort_TurnOff))
- {
- pCharacter->GetEntity()->Hide(true);
- }
- else if (IsPortActive(pActInfo, eInputPort_GetState))
- {
- pCharacter->OutputAllFG();
- }
- else if (IsPortActive(pActInfo, eInputPort_TryToFindPlayer))
- {
- pCharacter->FGAction_TryToFindPlayer();
- }
- }
- }
- void CCharacter::FindPlayer()
- {
- // We only handle default spawning below for the Launcher
- // Editor has special logic in CEditorGame
- if (gEnv->IsEditor())
- return;
- // Spawn at first default spawner
- auto *pEntityIterator = gEnv->pEntitySystem->GetEntityIterator();
- pEntityIterator->MoveFirst();
- auto *pSpawnerClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("Player");
- auto extensionId = gEnv->pGame->GetIGameFramework()->GetIGameObjectSystem()->GetID("Player");
- while (!pEntityIterator->IsEnd())
- {
- IEntity *pEntity = pEntityIterator->Next();
- if (pEntity->GetClass() != pSpawnerClass)
- continue;
- auto *pGameObject = gEnv->pGame->GetIGameFramework()->GetGameObject(pEntity->GetId());
- if (pGameObject == nullptr)
- continue;
- auto *pPlayer = static_cast<CPlayer *>(pGameObject->QueryExtension(extensionId));
- if (pPlayer == nullptr)
- continue;
- //pSpawner->SpawnEntity(*GetEntity());
- m_pPlayer = pPlayer;
- // add
- break;
- }
- }
- void CCharacter::FGAction_TryToFindPlayer()
- {
- if (gEnv->IsEditor())
- return;
- if (m_pPlayer == nullptr)
- FindPlayer(); // get pointer to m_pPlayer from world
- if (m_pPlayer != nullptr)
- {
- Vec3 playerPos = m_pPlayer->GetMovement()->GetWorldPosition();
- Vec3 characterPos = GetEntity()->GetWorldPos();
- float distance = (characterPos - playerPos).len();
- bool isCharacterMoving = m_pPath->IsProcessingRequest();
- if (isCharacterMoving)
- m_pPath->CancelCurrentRequest();
- // only if player do not near
- if (distance > 3.0f)
- {
- m_pPath->CancelCurrentRequest();
- m_pPath->RequestMoveTo(playerPos);
- //fgActionTryToFindPlayer = true;
- }
- else
- {
- m_pPath->CancelCurrentRequest();
- //m_pPath->ClearMovementState();
- //fgActionTryToFindPlayer = false;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement