void AiCombatStorage::startAttackIfReady(const MWWorld::Ptr& actor, CharacterController& characterController, const ESM::Weapon* weapon, bool distantCombat) { if (mReadyToAttack && characterController.readyToStartAttack()) { if (mAttackCooldown <= 0) { mAttack = true; // attack starts just now characterController.setAttackingOrSpell(true); if (!distantCombat) characterController.setAIAttackType(chooseBestAttack(weapon)); mStrength = Misc::Rng::rollClosedProbability(); const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); float baseDelay = store.get<ESM::GameSetting>().find("fCombatDelayCreature")->mValue.getFloat(); if (actor.getClass().isNpc()) { baseDelay = store.get<ESM::GameSetting>().find("fCombatDelayNPC")->mValue.getFloat(); //say a provoking combat phrase int chance = store.get<ESM::GameSetting>().find("iVoiceAttackOdds")->mValue.getInteger(); if (Misc::Rng::roll0to99() < chance) { MWBase::Environment::get().getDialogueManager()->say(actor, "attack"); } } mAttackCooldown = std::min(baseDelay + 0.01 * Misc::Rng::roll0to99(), baseDelay + 0.9); } else mAttackCooldown -= AI_REACTION_TIME; } }
bool InitializeControllerComponent(IActorComponent* cmp, ICMStream* stream) { ControllerComponent* controllerCmp = (ControllerComponent*)cmp; tinyxml2::XMLElement* pData = (tinyxml2::XMLElement*)stream; CharacterController* cc = new CharacterController(); cc->SetName(cmp->VGetActor()->GetName()); tinyxml2::XMLElement* speed = pData->FirstChildElement("Speed"); if(speed) { float mins = 1; float maxs = 1; speed->QueryFloatAttribute("min", &mins); speed->QueryFloatAttribute("max", &maxs); cc->VSetMinSpeed(mins); cc->VSetMaxSpeed(maxs); } std::unique_ptr<ActorController> ac(cc); tinyxml2::XMLElement* activate = pData->FirstChildElement("Activate"); if(activate) { cc->VActivate(); } CmGetApp()->VGetLogic()->VAttachView(std::move(ac), cmp->VGetActor()); return true; }
void AiCombatStorage::updateAttack(CharacterController& characterController) { if (mAttack && (characterController.getAttackStrength() >= mStrength || characterController.readyToPrepareAttack())) { mAttack = false; } characterController.setAttackingOrSpell(mAttack); }
bool PhysXCharacterController::filter(const PxController& a, const PxController& b) { CharacterController* controllerA = (CharacterController*)a.getUserData(); CharacterController* controllerB = (CharacterController*)b.getUserData(); bool canCollide = gPhysics().isCollisionEnabled(controllerA->getLayer(), controllerB->getLayer()); return canCollide; }
void Objects::updateObject(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) { PtrControllerMap::iterator iter = mObjects.find(old); if(iter != mObjects.end()) { CharacterController *ctrl = iter->second; mObjects.erase(iter); ctrl->updatePtr(ptr); mObjects.insert(std::make_pair(ptr, ctrl)); } }
EntityComponent *PhysicsEntityComponentFactory::createComponent(Entity *entity, EntityComponentTemplate *tpl) { PhysicsEntityComponentTemplate *ptpl = (PhysicsEntityComponentTemplate*)tpl; // Get world component (holds the simulation) World *world = entity->getWorld(); PhysicsWorldComponent *worldcomponent; worldcomponent = (PhysicsWorldComponent*)world->getComponent(EWCT_Physics); if (!worldcomponent) return 0; Simulation *simulation = worldcomponent->getSimulation(); // Create entity component PhysicsEntityComponent *component = new PhysicsEntityComponent(entity, simulation); // Create bodies for (unsigned int i = 0; i < ptpl->bodies.size(); i++) { PhysicsEntityComponentTemplate::BodyInfo &bodyinfo = ptpl->bodies[i]; // Create shapes std::vector<Shape*> shapes; for (unsigned int j = 0; j < bodyinfo.shapes.size(); j++) { std::cout << "Shape: " << bodyinfo.shapes[j] << std::endl; Shape *shape = bodyinfo.shapes[j]->create(entity); if (shape) shapes.push_back(shape); } if (shapes.size() == 0 || shapes.size() > 1) { std::cout << "0 or too many shapes provided." << std::endl; for (unsigned int i = 0; i < shapes.size(); i++) { delete shapes[i]; } continue; } // Create body Body *body = new Body(); body->init(simulation, shapes[0]); body->setPosition(bodyinfo.position); body->setRotation(bodyinfo.rotation); component->addBody(bodyinfo.name, body); } // Create character controllers for (unsigned int i = 0; i < ptpl->charcontrollers.size(); i++) { PhysicsEntityComponentTemplate::CharacterInfo &charinfo = ptpl->charcontrollers[i]; CharacterController *controller = new CharacterController(); controller->init(simulation); component->addCharacterController(charinfo.name, controller); } return component; }
void Activators::updateActivator(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) { PtrControllerMap::iterator iter = mActivators.find(old); if(iter != mActivators.end()) { CharacterController ctrl = iter->second; mActivators.erase(iter); ctrl.updatePtr(ptr); mActivators.insert(std::make_pair(ptr, ctrl)); } }
GameObject* GameObjectManager::CreateTott(const Ogre::Vector3& position, void* data, const Ogre::String& id){ static int tott_counter = 0; Ogre::String tott_id = "Tott" + NumberToString(tott_counter); TottDef& def = *static_cast<TottDef*>(data); GameObject* go = new GameObject(GAME_OBJECT_TOTT, tott_id); NodeComponent* node_comp = new NodeComponent; go->AddComponent(node_comp); TottAIComponent* ai_comp = new TottAIComponent; go->AddComponent(ai_comp); go->AddUpdateable(ai_comp); AnimationComponent* acomp = new AnimationComponent; go->AddComponent(acomp); go->AddUpdateable(acomp); CharacterController* contr = new CharacterController; go->AddComponent(contr); go->AddUpdateable(contr); node_comp->Init(position, m_scene_manager); node_comp->SetId(tott_id); def.node_name = node_comp->GetSceneNode()->getName(); acomp->Init(def.mesh_name, m_scene_manager); if (def.type_name == "Hidehog"){ acomp->AddAnimationState("Run", true); } else if (def.type_name == "Kittyshroom"){ acomp->AddAnimationState("walk", true); } else if (def.type_name == "Nightcap"){ acomp->AddAnimationState("walk", true); } else if (def.type_name == "Shroomfox"){ acomp->AddAnimationState("idle", true); } else{ acomp->AddAnimationState("Run", true); } ai_comp->Init(def.ai_states); m_sound_manager->GetTottNode(node_comp->GetSceneNode()->getName()); contr->Init(position, m_physics_engine, def.character_controller); contr->GetRigidbody()->setContactProcessingThreshold(btScalar(0)); contr->GetRigidbody()->setActivationState(DISABLE_DEACTIVATION); acomp->GetEntity()->setRenderingDistance(100.0f); tott_counter++; return go; }
void InitializeOutputFeature() { auto& parts = *pBlockArmature; auto& ucinfo = pController->GetUnitedClipinfo(); outputExtractor.InitPcas(parts.size()); outputExtractor.SetDefaultFrame(pBlockArmature->Armature().default_frame()); outputExtractor.InitializeWeights(parts); auto& facade = ucinfo.RcFacade; auto cutoff = facade.PcaCutoff(); for (auto part : parts) { int pid = part->Index; if (part->ActiveActions.size() > 0 || part->SubActiveActions.size() > 0) { auto &pca = facade.GetPartPca(pid); auto d = facade.GetPartPcaDim(pid); outputExtractor.SetPca(pid, pca.components(d), pca.mean()); } else { int odim = facade.GetPartDimension(pid); outputExtractor.SetPca(pid, MatrixXf::Identity(odim, odim), facade.GetPartMean(pid)); } } }
virtual void Transform(_Out_ frame_view target_frame, _In_ const_frame_view source_frame) override { const auto& blocks = *pBlockArmature; RowVectorXd X, Y; for (auto& block : blocks) { RowVectorXf xf = inputExtractor.Get(*block, source_frame); RowVectorXf yf; X = xf.cast<double>(); if (block->ActiveActions.size() > 0) { auto& sik = pController->GetStylizedIK(block->Index); auto& gpr = sik.Gplvm(); gpr.get_expectation(X, &Y); yf = Y.cast<float>(); yf *= block->Wx.cwiseInverse().asDiagonal(); outputExtractor.Set(*block, target_frame, yf); } else if (block->SubActiveActions.size() > 0) { } } FrameRebuildGlobal(*m_tArmature, target_frame); }
SelfLocalMotionTransform(CharacterController & controller) : pController(&controller), pHandles(nullptr) { pBlockArmature = &controller.ArmatureParts(); m_sArmature = &pBlockArmature->Armature(); m_tArmature = &pBlockArmature->Armature(); InitializeOutputFeature(); }
GameObject* GameObjectManager::CreateTott(const Ogre::Vector3& position, void* data){ CharControllerDef& def = *static_cast<CharControllerDef*>(data); GameObject* go = new GameObject(GAME_OBJECT_TOTT); AnimationComponent* acomp = new AnimationComponent; acomp->AddAnimationStates(1); go->AddComponent(acomp); go->AddUpdateable(acomp); CharacterController* contr = new CharacterController; go->AddComponent(contr); go->AddUpdateable(contr); go->AddLateUpdate(contr); acomp->Init("Yomi_2Yomi.mesh", m_scene_manager); contr->Init(position, acomp->GetEntity(), def.step_height, def.collider_type, m_physics_engine); contr->SetTurnSpeed(def.turn_speed); contr->SetVelocity(def.velocity); return go; }
GameObject* GameObjectManager::CreatePlayer(const Ogre::Vector3& position, void* data){ CharControllerDef& def = *static_cast<CharControllerDef*>(data); GameObject* go = new GameObject(GAME_OBJECT_PLAYER); AnimationComponent* acomp = new AnimationComponent; acomp->AddAnimationStates(2); go->AddComponent(acomp); go->AddUpdateable(acomp); CharacterController* contr = new CharacterController; go->AddComponent(contr); go->AddUpdateable(contr); go->AddLateUpdate(contr); FollowCameraComponent* fcc = new FollowCameraComponent; go->AddComponent(fcc); go->AddUpdateable(fcc); PlayerInputComponent* pccomp = new PlayerInputComponent; go->AddComponent(pccomp); go->AddUpdateable(pccomp); ChildSceneNodeComponent* csnc = new ChildSceneNodeComponent; go->AddComponent(csnc); Sound2DComponent* sound2D = new Sound2DComponent; go->AddComponent(sound2D); Sound3DComponent* sound3D = new Sound3DComponent; go->AddComponent(sound3D); Music2DComponent* music2D = new Music2DComponent; go->AddComponent(music2D); acomp->Init("Yomi_2Yomi.mesh", m_scene_manager); contr->Init(position, acomp->GetEntity(), def.step_height, def.collider_type, m_physics_engine); contr->SetTurnSpeed(def.turn_speed); contr->SetVelocity(def.velocity); contr->HasFollowCam(true); pccomp->Init(m_input_manager); sound2D->Init(m_sound_manager); sound3D->Init(m_sound_manager); music2D->Init(m_sound_manager); fcc->Init(m_scene_manager, m_viewport, true); fcc->GetCamera()->setNearClipDistance(0.1f); fcc->GetCamera()->setFarClipDistance(100); csnc->Init(Ogre::Vector3(0.0f, 0.0f, 1.0f), "CreateBubble", acomp->GetSceneNode()); return go; }
void Player::onUpdate() { Vector3 pos = getGameObject()->getTransform()->getPosition(); static float up = 0.0f; CharacterController* cc = getGameObject()->getComponent<CharacterController>(); Vector3 movement; if(cc->isGrounded() == true) { if(Input::getKey(KeyCode::UP) == true) { up = 10.0f; } } material->setFloat("in_Replace", up / 10.0f); movement.y = (-5 + up) * Time::getDeltaTime(); up -= 10.0f * Time::getDeltaTime(); if(up < 0) { up = 0; } if(Input::getKey(KeyCode::RIGHT) == true) { movement.x = 5 * Time::getDeltaTime(); } if(Input::getKey(KeyCode::LEFT) == true) { movement.x = -5 * Time::getDeltaTime(); } cc->simpleMove(movement); }
GameObject* GameObjectManager::CreateQuestTott(const Ogre::Vector3& position, void* data, const Ogre::String& id){ static int quest_tott_counter = 0; Ogre::String tott_id = "Tott" + NumberToString(quest_tott_counter); TottDef& def = *static_cast<TottDef*>(data); GameObject* go = new GameObject(GAME_OBJECT_QUEST_TOTT, tott_id); NodeComponent* node_comp = new NodeComponent; go->AddComponent(node_comp); TottAIComponent* ai_comp = new TottAIComponent; go->AddComponent(ai_comp); go->AddUpdateable(ai_comp); AnimationComponent* acomp = new AnimationComponent; go->AddComponent(acomp); go->AddUpdateable(acomp); CharacterController* contr = new CharacterController; go->AddComponent(contr); go->AddUpdateable(contr); ChildSceneNodeComponent* child_node = new ChildSceneNodeComponent; go->AddComponent(child_node); MeshRenderComponent* spbubble = new MeshRenderComponent; go->AddComponent(spbubble); SyncedTriggerComponent* trcomp = new SyncedTriggerComponent; go->AddComponent(trcomp); go->AddUpdateable(trcomp); TottController* tott_contr = new TottController; go->AddComponent(tott_contr); go->AddUpdateable(tott_contr); node_comp->Init(position, m_scene_manager); node_comp->SetId(tott_id); def.node_name = node_comp->GetSceneNode()->getName(); acomp->Init(def.mesh_name, m_scene_manager); child_node->Init(Ogre::Vector3(0,def.speech_bubble_y,0), "speech_bubble", node_comp->GetSceneNode()); child_node->SetId("speech_bubble"); spbubble->Init(def.quest_item_mesh_name, m_scene_manager, "speech_bubble"); child_node->GetNode()->attachObject(spbubble->GetEntity()); spbubble->GetEntity()->setCastShadows(false); child_node->GetNode()->setScale(0,0,0); if (def.type_name == "Hidehog"){ acomp->AddAnimationState("Run", true); } else if (def.type_name == "Kittyshroom"){ acomp->AddAnimationState("walk", true); } else if (def.type_name == "Nightcap"){ acomp->AddAnimationState("walk", true); } else if (def.type_name == "Shroomfox"){ acomp->AddAnimationState("idle", true); } else{ acomp->AddAnimationState("Run", true); } ai_comp->Init(def.ai_states); m_sound_manager->GetTottNode(node_comp->GetSceneNode()->getName()); contr->Init(position, m_physics_engine, def.character_controller); contr->GetRigidbody()->setContactProcessingThreshold(btScalar(0)); contr->GetRigidbody()->setActivationState(DISABLE_DEACTIVATION); tott_contr->Init(m_physics_engine, m_scene_manager, def.idle_anim, def.excited_anim, def.quest_item); TriggerDef trdef; trdef.body_type = STATIC_BODY; trdef.collider_type = COLLIDER_SPHERE; trdef.collision_filter.filter = COL_WORLD_TRIGGER; trdef.collision_filter.mask = COL_PLAYER; trdef.mass = 1.0f; trdef.radius = 4.0f; trcomp->Init(position, m_physics_engine, &trdef); acomp->GetEntity()->setRenderingDistance(100.0f); quest_tott_counter++; return go; };
void AiCombat::attack(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, AiCombatStorage& storage, CharacterController& characterController) { if (isTargetMagicallyHidden(target)) { storage.stopAttack(); return; // TODO: run away instead of doing nothing } const MWWorld::CellStore*& currentCell = storage.mCell; bool cellChange = currentCell && (actor.getCell() != currentCell); if(!currentCell || cellChange) { currentCell = actor.getCell(); } const MWWorld::Class& actorClass = actor.getClass(); actorClass.getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true); float& actionCooldown = storage.mActionCooldown; if (actionCooldown > 0) return; float &rangeAttack = storage.mAttackRange; boost::shared_ptr<Action>& currentAction = storage.mCurrentAction; if (characterController.readyToPrepareAttack()) { currentAction = prepareNextAction(actor, target); actionCooldown = currentAction->getActionCooldown(); } const ESM::Weapon *weapon = NULL; bool isRangedCombat = false; if (currentAction.get()) { rangeAttack = currentAction->getCombatRange(isRangedCombat); // Get weapon characteristics weapon = currentAction->getWeapon(); } ESM::Position pos = actor.getRefData().getPosition(); osg::Vec3f vActorPos(pos.asVec3()); osg::Vec3f vTargetPos(target.getRefData().getPosition().asVec3()); osg::Vec3f vAimDir = MWBase::Environment::get().getWorld()->aimToTarget(actor, target); float distToTarget = MWBase::Environment::get().getWorld()->getHitDistance(actor, target); storage.mReadyToAttack = (distToTarget <= rangeAttack); // can't fight if attacker can't go where target is. E.g. A fish can't attack person on land. if (distToTarget > rangeAttack && !actorClass.isNpc() && !MWMechanics::isEnvironmentCompatible(actor, target)) { // TODO: start fleeing? storage.stopAttack(); return; } if (storage.mReadyToAttack) { storage.startCombatMove(actorClass.isNpc(), isRangedCombat, distToTarget, rangeAttack); // start new attack storage.startAttackIfReady(actor, characterController, weapon, isRangedCombat); if (isRangedCombat) { // rotate actor taking into account target movement direction and projectile speed osg::Vec3f& lastTargetPos = storage.mLastTargetPos; vAimDir = AimDirToMovingTarget(actor, target, lastTargetPos, AI_REACTION_TIME, (weapon ? weapon->mData.mType : 0), storage.mStrength); lastTargetPos = vTargetPos; storage.mMovement.mRotation[0] = getXAngleToDir(vAimDir); storage.mMovement.mRotation[2] = getZAngleToDir(vAimDir); } else { storage.mMovement.mRotation[0] = getXAngleToDir(vAimDir); storage.mMovement.mRotation[2] = getZAngleToDir((vTargetPos-vActorPos)); // using vAimDir results in spastic movements since the head is animated } } }
void Player::onUpdate() { bool setToIdle = true; if(Application::getLoadedLevelName() == "introduction") { getGameObject()->getTransform()->setPosition(Vector3(-13, 0, -19)); getGameObject()->getTransform()->setRotation(Vector3(0, 180, 0)); return; } if(state == 0) { if(Input::getKey(KeyCode::RIGHT) == true) { mr->setAnimation(walkAnimation); getGameObject()->getTransform()->rotate(Vector3(0, 1, 0) * 100 * Time::getDeltaTime()); setToIdle = false; } else if(Input::getKey(KeyCode::LEFT) == true) { mr->setAnimation(walkAnimation); getGameObject()->getTransform()->rotate(Vector3(0, -1, 0) * 100 * Time::getDeltaTime()); setToIdle = false; } if(Input::getKey(KeyCode::UP) == true) { mr->setAnimation(walkAnimation); getGameObject()->getTransform()->translate( getGameObject()->getTransform()->getForward() * 8 * Time::getDeltaTime()); setToIdle = false; } if(setToIdle == true) mr->setAnimation(idleAnimation); if(Input::getKey(KeyCode::SPACE) == true) { gameScreen->getAudio()->playSound(6); mr->setAnimation(sprintAnimation); mr->setFps(4); state = 1; } } else if(state == 1) { if(Input::getKey(KeyCode::RIGHT) == true) getGameObject()->getTransform()->rotate(Vector3(0, 1, 0) * 100 * Time::getDeltaTime()); else if(Input::getKey(KeyCode::LEFT) == true) getGameObject()->getTransform()->rotate(Vector3(0, -1, 0) * 100 * Time::getDeltaTime()); getGameObject()->getTransform()->translate(getGameObject()->getTransform()->getForward() * speed * Time::getDeltaTime()); std::vector<GameObject*> sheepGos; GameObject::findGameObjectsWithTag("sheep", &sheepGos); for(int i = 0; i < sheepGos.size(); i++) { float dist = Vector3::getDistance(sheepGos.at(i)->getTransform()->getPosition(), getGameObject()->getTransform()->getPosition()); if(dist < 1) { hTarget = sheepGos.at(i); sheepGos.at(i)->getTransform()->setParent(getGameObject()->getTransform()); sheepGos.at(i)->getTransform()->setLocalRotation(Vector3(0, 0, 0)); sheepGos.at(i)->getTransform()->setLocalPosition(Vector3(0, 0, 2)); sheepGos.at(i)->getComponent<Sheep>()->freeze(); if(sheepGos.at(i)->getComponent<Sheep>()->isWolf() == true) { int rval = rand() % 100; if(rval > 80) gameScreen->getAudio()->playSound(7); else if(rval > 60) gameScreen->getAudio()->playSound(8); else if(rval > 40) gameScreen->getAudio()->playSound(9); else if(rval > 20) gameScreen->getAudio()->playSound(10); else gameScreen->getAudio()->playSound(11); } // Begin the breathing... gameScreen->getAudio()->playBreathing(); int rval = rand() % 100; if(rval > 80) gameScreen->getAudio()->playSound(17); else if(rval > 60) gameScreen->getAudio()->playSound(18); else if(rval > 40) gameScreen->getAudio()->playSound(19); else if(rval > 20) gameScreen->getAudio()->playSound(20); else if(rval > 10) gameScreen->getAudio()->playSound(21); else gameScreen->getAudio()->playSound(22); state = 2; gameScreen->getCamera()->toggleEventMode(); mr->setAnimation(humpAnimation); mr->setFps(6); if(firstTime == true) { hTimeout = 4000.0f; firstTime = false; } else hTimeout = 2000.0f; break; } } speed += 0.5f * Time::getDeltaTime(); if(speed > 15) speed = 15; } else if(state == 2) { hTimeout -= Time::getDeltaTime() * 1000; if(hTimeout < 0) { if(hTarget->getComponent<Sheep>()->isWolf() == true) { gameScreen->getAudio()->stopMusic(); Application::loadLevel("gameover"); GameOverScreen::score = score; return; } Audio::playMusicA(); Audio::playSound(19); Object::destroy(hTarget); gameScreen->getCamera()->toggleEventMode(); state = 1; mr->setAnimation(sprintAnimation); mr->setFps(4); score++; Sheep::create(gameScreen); } } CharacterController* cc = getGameObject()->getComponent<CharacterController>(); cc->simpleMove(Vector3(0, -5, 0) * Time::getDeltaTime()); Fence* fence = gameScreen->getFence()->getComponent<Fence>(); Transform* transform = getGameObject()->getTransform(); while(transform->getPosition().x > fence->getBounds().extents.x - 1) { if(state == 1) transform->setRotation(Vector3(0, rand() % 350 + 190, 0)); cc->simpleMove(Vector3(-0.1f, 0, 0)); } while(transform->getPosition().x < -fence->getBounds().extents.x + 1) { if(state == 1) transform->setRotation(Vector3(0, rand() % 170 + 10, 0)); cc->simpleMove(Vector3(0.1f, 0, 0)); } while(transform->getPosition().z > fence->getBounds().extents.z - 1) { if(state == 1) transform->setRotation(Vector3(0, rand() % 260 + 100, 0)); cc->simpleMove(Vector3(0, 0, -0.1f)); } while(transform->getPosition().z < -fence->getBounds().extents.z + 1) { if(state == 1) transform->setRotation(Vector3(0, rand() % 260 + 100, 0) * -1); cc->simpleMove(Vector3(0, 0, 0.1f)); } }
GameObject* GameObjectManager::CreatePlayer(const Ogre::Vector3& position, void* data, const Ogre::String& id){ PlayerDef& def = *static_cast<PlayerDef*>(data); CharacterControllerDef& char_def = *def.character_contr; GameObject* go = new GameObject(GAME_OBJECT_PLAYER, "player"); NodeComponent* node_comp = new NodeComponent; go->AddComponent(node_comp); AnimationComponent* acomp = new AnimationComponent; go->AddComponent(acomp); go->AddUpdateable(acomp); MeshRenderComponent* staff_mesh_comp = new MeshRenderComponent; go->AddComponent(staff_mesh_comp); CharacterController* contr = new CharacterController; go->AddComponent(contr); go->AddUpdateable(contr); FollowCameraComponent* fcc = new FollowCameraComponent; go->AddComponent(fcc); go->AddUpdateable(fcc); PlayerInputComponent* pccomp = new PlayerInputComponent; go->AddComponent(pccomp); go->AddUpdateable(pccomp); ChildSceneNodeComponent* csnc = new ChildSceneNodeComponent; go->AddComponent(csnc); Sound2DComponent* sound2D = new Sound2DComponent; go->AddComponent(sound2D); Sound3DComponent* sound3D = new Sound3DComponent; go->AddComponent(sound3D); Music2DComponent* music2D = new Music2DComponent; go->AddComponent(music2D); Music3DComponent* music3D = new Music3DComponent; go->AddComponent(music3D); CountableResourceGUI* gui = new CountableResourceGUI; go->AddComponent(gui); go->AddUpdateable(gui); TriggerComponent* tc = new TriggerComponent; go->AddComponent(tc); PlayerRaycastCollisionComponent* prcc = new PlayerRaycastCollisionComponent; go->AddComponent(prcc); TutorialGraphicsComponent* tutorial = new TutorialGraphicsComponent; go->AddComponent(tutorial); go->AddUpdateable(tutorial); /* TriggerComponent* camera_tc = new TriggerComponent; go->AddComponent(camera_tc); RaycastComponent* camera_rc = new RaycastComponent; go->AddComponent(camera_rc); CameraRaycastCollisionComponent* camera_rcc = new CameraRaycastCollisionComponent; go->AddComponent(camera_rcc); //RigidbodyComponent* camera_rb = new RigidbodyComponent; */ if (def.level_id == "try"){ tutorial->Init("Level1", def.level_id); } else{ tutorial->Init("Level2", def.level_id); } go->SetId("Player"); node_comp->Init(position, m_scene_manager); node_comp->SetId("player_node"); if(char_def.mesh == "" || char_def.mesh == "Yomi_2Yomi.mesh") char_def.mesh = "Yomi.mesh"; acomp->Init(char_def.mesh, m_scene_manager, node_comp->GetId(), true); acomp->AddAnimationState("Base_Idle"); acomp->AddAnimationState("Top_Idle"); //acomp->GetEntity()->setMaterialName("_YomiFBXASC039sFBXASC032staffMaterial__191"); TriggerDef tdef; tdef.body_type = STATIC_BODY; tdef.collider_type = COLLIDER_SPHERE; tdef.radius = 0.1f; tdef.collision_filter.filter = COL_NOTHING; tdef.collision_filter.mask = COL_NOTHING; tc->Init(position, m_physics_engine, tdef); tc->SetId("btrig"); contr->Init(position, m_physics_engine, char_def); contr->HasFollowCam(true); contr->SetId("body"); contr->GetRigidbody()->setContactProcessingThreshold(btScalar(0)); sound2D->Init(m_sound_manager); sound3D->Init(m_sound_manager); music2D->Init(m_sound_manager); music3D->Init(m_sound_manager); gui->Init(def.level_id); csnc->Init(Ogre::Vector3(0.0f, char_def.offset.y, 1.0f), "CreateBubble", node_comp->GetSceneNode()); m_sound_manager->GetYomiNode(node_comp->GetSceneNode()->getName()); prcc->Init(m_physics_engine); prcc->SetCustomVariables(VariableManager::GetSingletonPtr()->GetAsFloat("Bounce_Jump_Mod")); fcc->SetNode(node_comp->GetSceneNode()); fcc->Init(position, m_scene_manager, m_viewport, true); fcc->SetMovementSpeed(2.5f); fcc->SetPhysEngine(m_physics_engine); fcc->SetCustomVariables( //VariableManager::GetSingletonPtr()->GetAsInt("Camera_Inverted_Controller_Sticks"), VariableManager::GetSingletonPtr()->GetAsFloat("Camera_Zoom_Speed"), VariableManager::GetSingletonPtr()->GetAsFloat("Camera_Stick_Rotation_Acceleration"), VariableManager::GetSingletonPtr()->GetAsFloat("Camera_Change_Angle_After_Player"), VariableManager::GetSingletonPtr()->GetAsFloat("Camera_Start_Distance"), VariableManager::GetSingletonPtr()->GetAsFloat("Camera_Start_Pitch") ); staff_mesh_comp->Init("Staff.mesh", m_scene_manager, Ogre::StringUtil::BLANK); acomp->GetEntity()->attachObjectToBone("CATRigLArmDigit21", staff_mesh_comp->GetEntity(), Ogre::Quaternion(1.0f, 1.0f, 0.7f, 0.0f), Ogre::Vector3(0.01f, -0.02f, 0.0f)); pccomp->Init(m_input_manager, m_sound_manager, m_physics_engine, m_message_system); pccomp->SetCustomVariables( VariableManager::GetSingletonPtr()->GetAsFloat("Bubble_Min_Size"), VariableManager::GetSingletonPtr()->GetAsFloat("Bubble_Max_Size"), VariableManager::GetSingletonPtr()->GetAsFloat("On_Bubble_Speed_Mod"), VariableManager::GetSingletonPtr()->GetAsFloat("In_Bubble_Speed_Mod"), def.level_id ); return go; }
bool AiCombat::attack(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, AiCombatStorage& storage, CharacterController& characterController) { const MWWorld::CellStore*& currentCell = storage.mCell; bool cellChange = currentCell && (actor.getCell() != currentCell); if(!currentCell || cellChange) { currentCell = actor.getCell(); } bool forceFlee = false; if (!canFight(actor, target)) { storage.stopAttack(); characterController.setAttackingOrSpell(false); storage.mActionCooldown = 0.f; // Continue combat if target is player or player follower/escorter and an attack has been attempted const std::list<MWWorld::Ptr>& playerFollowersAndEscorters = MWBase::Environment::get().getMechanicsManager()->getActorsSidingWith(MWMechanics::getPlayer()); bool targetSidesWithPlayer = (std::find(playerFollowersAndEscorters.begin(), playerFollowersAndEscorters.end(), target) != playerFollowersAndEscorters.end()); if ((target == MWMechanics::getPlayer() || targetSidesWithPlayer) && ((actor.getClass().getCreatureStats(actor).getHitAttemptActorId() == target.getClass().getCreatureStats(target).getActorId()) || (target.getClass().getCreatureStats(target).getHitAttemptActorId() == actor.getClass().getCreatureStats(actor).getActorId()))) forceFlee = true; else // Otherwise end combat return true; } const MWWorld::Class& actorClass = actor.getClass(); actorClass.getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true); float& actionCooldown = storage.mActionCooldown; std::shared_ptr<Action>& currentAction = storage.mCurrentAction; if (!forceFlee) { if (actionCooldown > 0) return false; if (characterController.readyToPrepareAttack()) { currentAction = prepareNextAction(actor, target); actionCooldown = currentAction->getActionCooldown(); } } else { currentAction.reset(new ActionFlee()); actionCooldown = currentAction->getActionCooldown(); } if (!currentAction) return false; if (storage.isFleeing() != currentAction->isFleeing()) { if (currentAction->isFleeing()) { storage.startFleeing(); MWBase::Environment::get().getDialogueManager()->say(actor, "flee"); return false; } else storage.stopFleeing(); } bool isRangedCombat = false; float &rangeAttack = storage.mAttackRange; rangeAttack = currentAction->getCombatRange(isRangedCombat); // Get weapon characteristics const ESM::Weapon* weapon = currentAction->getWeapon(); ESM::Position pos = actor.getRefData().getPosition(); osg::Vec3f vActorPos(pos.asVec3()); osg::Vec3f vTargetPos(target.getRefData().getPosition().asVec3()); osg::Vec3f vAimDir = MWBase::Environment::get().getWorld()->aimToTarget(actor, target); float distToTarget = MWBase::Environment::get().getWorld()->getHitDistance(actor, target); storage.mReadyToAttack = (currentAction->isAttackingOrSpell() && distToTarget <= rangeAttack && storage.mLOS); if (storage.mReadyToAttack) { storage.startCombatMove(isRangedCombat, distToTarget, rangeAttack, actor, target); // start new attack storage.startAttackIfReady(actor, characterController, weapon, isRangedCombat); if (isRangedCombat) { // rotate actor taking into account target movement direction and projectile speed osg::Vec3f& lastTargetPos = storage.mLastTargetPos; vAimDir = AimDirToMovingTarget(actor, target, lastTargetPos, AI_REACTION_TIME, (weapon ? weapon->mData.mType : 0), storage.mStrength); lastTargetPos = vTargetPos; storage.mMovement.mRotation[0] = getXAngleToDir(vAimDir); storage.mMovement.mRotation[2] = getZAngleToDir(vAimDir); } else { storage.mMovement.mRotation[0] = getXAngleToDir(vAimDir); storage.mMovement.mRotation[2] = getZAngleToDir((vTargetPos-vActorPos)); // using vAimDir results in spastic movements since the head is animated } } return false; }
bool AiCombat::reactionTimeActions(const MWWorld::Ptr& actor, CharacterController& characterController, AiCombatStorage& storage, MWWorld::Ptr target) { MWMechanics::Movement& movement = storage.mMovement; if (isTargetMagicallyHidden(target)) { storage.stopAttack(); return false; // TODO: run away instead of doing nothing } const MWWorld::CellStore*& currentCell = storage.mCell; bool cellChange = currentCell && (actor.getCell() != currentCell); if(!currentCell || cellChange) { currentCell = actor.getCell(); } const MWWorld::Class& actorClass = actor.getClass(); actorClass.getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true); float& actionCooldown = storage.mActionCooldown; if (actionCooldown > 0) return false; float rangeAttack = 0; float rangeFollow = 0; boost::shared_ptr<Action>& currentAction = storage.mCurrentAction; if (characterController.readyToPrepareAttack()) { currentAction = prepareNextAction(actor, target); actionCooldown = currentAction->getActionCooldown(); } if (currentAction.get()) currentAction->getCombatRange(rangeAttack, rangeFollow); // FIXME: consider moving this stuff to ActionWeapon::getCombatRange const ESM::Weapon *weapon = NULL; MWMechanics::WeaponType weaptype = WeapType_None; float weapRange = 1.0f; // Get weapon characteristics MWBase::World* world = MWBase::Environment::get().getWorld(); if (actorClass.hasInventoryStore(actor)) { //Get weapon range MWWorld::ContainerStoreIterator weaponSlot = MWMechanics::getActiveWeapon(actorClass.getCreatureStats(actor), actorClass.getInventoryStore(actor), &weaptype); if (weaptype == WeapType_HandToHand) { static float fHandToHandReach = world->getStore().get<ESM::GameSetting>().find("fHandToHandReach")->getFloat(); weapRange = fHandToHandReach; } else if (weaptype != WeapType_PickProbe && weaptype != WeapType_Spell && weaptype != WeapType_None) { // All other WeapTypes are actually weapons, so get<ESM::Weapon> is safe. weapon = weaponSlot->get<ESM::Weapon>()->mBase; weapRange = weapon->mData.mReach; } weapRange *= 100.0f; } else //is creature { weaptype = actorClass.getCreatureStats(actor).getDrawState() == DrawState_Spell ? WeapType_Spell : WeapType_HandToHand; weapRange = 150.0f; //TODO: use true attack range (the same problem in Creature::hit) } bool distantCombat = false; if (weaptype != WeapType_Spell) { // TODO: move to ActionWeapon if (weaptype == WeapType_BowAndArrow || weaptype == WeapType_Crossbow || weaptype == WeapType_Thrown) { rangeAttack = 1000; rangeFollow = 0; // not needed in ranged combat distantCombat = true; } else { rangeAttack = weapRange; rangeFollow = 300; } } else { distantCombat = (rangeAttack > 500); } bool& readyToAttack = storage.mReadyToAttack; // start new attack storage.startAttackIfReady(actor, characterController, weapon, distantCombat); /* * Some notes on meanings of variables: * * rangeAttack: * * - Distance where attack using the actor's weapon is possible: * longer for ranged weapons (obviously?) vs. melee weapons * - Determined by weapon's reach parameter; hardcoded value * for ranged weapon and for creatures * - Once within this distance mFollowTarget is triggered * * rangeFollow: * * - Applies to melee weapons or hand to hand only (or creatures without * weapons) * - Distance a little further away than the actor's weapon reach * i.e. rangeFollow > rangeAttack for melee weapons * - Hardcoded value (0 for ranged weapons) * - Once the target gets beyond this distance mFollowTarget is cleared * and a path to the target needs to be found * * mFollowTarget: * * - Once triggered, the actor follows the target with LOS shortcut * (the shortcut really only applies to cells where pathgrids are * available, since the default path without pathgrids is direct to * target even if LOS is not achieved) */ ESM::Position pos = actor.getRefData().getPosition(); osg::Vec3f vActorPos(pos.asVec3()); osg::Vec3f vTargetPos(target.getRefData().getPosition().asVec3()); osg::Vec3f vAimDir = MWBase::Environment::get().getWorld()->aimToTarget(actor, target); float distToTarget = MWBase::Environment::get().getWorld()->getHitDistance(actor, target); osg::Vec3f& lastActorPos = storage.mLastActorPos; bool& followTarget = storage.mFollowTarget; bool isStuck = false; float speed = 0.0f; if(movement.mPosition[1] && (lastActorPos - vActorPos).length() < (speed = actorClass.getSpeed(actor)) * REACTION_INTERVAL / 2) isStuck = true; lastActorPos = vActorPos; // check if actor can move along z-axis bool canMoveByZ = (actorClass.canSwim(actor) && world->isSwimming(actor)) || world->isFlying(actor); // can't fight if attacker can't go where target is. E.g. A fish can't attack person on land. if (distToTarget >= rangeAttack && !actorClass.isNpc() && !MWMechanics::isEnvironmentCompatible(actor, target)) { // TODO: start fleeing? storage.stopAttack(); return false; } // for distant combat we should know if target is in LOS even if distToTarget < rangeAttack bool inLOS = distantCombat ? world->getLOS(actor, target) : true; // (within attack dist) || (not quite attack dist while following) if(inLOS && (distToTarget < rangeAttack || (distToTarget <= rangeFollow && followTarget && !isStuck))) { mPathFinder.clearPath(); //Melee and Close-up combat // getXAngleToDir determines vertical angle to target: // if actor can move along z-axis it will control movement dir // if can't - it will control correct aiming. // note: in getZAngleToDir if we preserve dir.z then horizontal angle can be inaccurate if (distantCombat) { osg::Vec3f& lastTargetPos = storage.mLastTargetPos; vAimDir = AimDirToMovingTarget(actor, target, lastTargetPos, REACTION_INTERVAL, weaptype, storage.mStrength); lastTargetPos = vTargetPos; movement.mRotation[0] = getXAngleToDir(vAimDir); movement.mRotation[2] = getZAngleToDir(vAimDir); } else { movement.mRotation[0] = getXAngleToDir(vAimDir); movement.mRotation[2] = getZAngleToDir((vTargetPos-vActorPos)); // using vAimDir results in spastic movements since the head is animated } // (not quite attack dist while following) if (followTarget && distToTarget > rangeAttack) { //Close-up combat: just run up on target storage.stopCombatMove(); movement.mPosition[1] = 1; } else // (within attack dist) { storage.startCombatMove(actorClass.isNpc(), distantCombat, distToTarget, rangeAttack); readyToAttack = true; //only once got in melee combat, actor is allowed to use close-up shortcutting followTarget = true; } } else // remote pathfinding { bool preferShortcut = false; if (!distantCombat) inLOS = world->getLOS(actor, target); // check if shortcut is available bool& forceNoShortcut = storage.mForceNoShortcut; ESM::Position& shortcutFailPos = storage.mShortcutFailPos; if(inLOS && (!isStuck || readyToAttack) && (!forceNoShortcut || (shortcutFailPos.asVec3() - vActorPos).length() >= PATHFIND_SHORTCUT_RETRY_DIST)) { if(speed == 0.0f) speed = actorClass.getSpeed(actor); // maximum dist before pit/obstacle for actor to avoid them depending on his speed float maxAvoidDist = REACTION_INTERVAL * speed + speed / MAX_VEL_ANGULAR_RADIANS * 2; // *2 - for reliability preferShortcut = checkWayIsClear(vActorPos, vTargetPos, osg::Vec3f(vAimDir.x(), vAimDir.y(), 0).length() > maxAvoidDist*1.5? maxAvoidDist : maxAvoidDist/2); } // don't use pathgrid when actor can move in 3 dimensions if (canMoveByZ) { preferShortcut = true; movement.mRotation[0] = getXAngleToDir(vAimDir); } if(preferShortcut) { movement.mRotation[2] = getZAngleToDir((vTargetPos-vActorPos)); forceNoShortcut = false; shortcutFailPos.pos[0] = shortcutFailPos.pos[1] = shortcutFailPos.pos[2] = 0; mPathFinder.clearPath(); } else // if shortcut failed stick to path grid { if(!isStuck && shortcutFailPos.pos[0] == 0.0f && shortcutFailPos.pos[1] == 0.0f && shortcutFailPos.pos[2] == 0.0f) { forceNoShortcut = true; shortcutFailPos = pos; } followTarget = false; buildNewPath(actor, target); // should always return a path (even if it's just go straight on target.) assert(mPathFinder.isPathConstructed()); } if (readyToAttack) { // to stop possible sideway moving after target moved out of attack range storage.stopCombatMove(); readyToAttack = false; } movement.mPosition[1] = 1; } return false; }
virtual void Transform(_Out_ frame_view target_frame, _In_ const_frame_view source_frame, _In_ const_frame_view last_frame, float frame_time) override { //if (!g_UseVelocity) //{ // Transform(target_frame, source_frame); // return; //} const auto& blocks = *pBlockArmature; int pvDim = inputExtractor.GetDimension(*blocks[0]); RowVectorXd X(g_UseVelocity ? pvDim * 2 : pvDim), Y; double semga = 1000; RowVectorXf yf; std::vector<RowVectorXd> Xabs; for (auto& block : blocks) { //X[0] *= 13; if (block->Index > 0 && block->ActiveActions.size() > 0) { auto& sik = pController->GetStylizedIK(block->Index); auto& gpr = sik.Gplvm(); auto& joints = block->Joints; RowVectorXf xf = inputExtractor.Get(*block, source_frame); RowVectorXf xfl = inputExtractor.Get(*block, last_frame); yf = outputExtractor.Get(*block, target_frame); auto xyf = inputExtractor.Get(*block, target_frame); auto pDecoder = sik.getDecoder(); auto baseRot = target_frame[block->parent()->Joints.back()->ID].GblRotation; sik.setBaseRotation(baseRot); sik.setChain(block->Joints, target_frame); //sik.SetGplvmWeight(block->Wx.cast<double>()); //std::vector<DirectX::Quaternion, XMAllocator> corrrots(joints.size()); //std::vector<DirectX::Quaternion, XMAllocator> rots(joints.size()); //for (int i = 0; i < joints.size(); i++) //{ // corrrots[i] = target_frame[joints[i]->ID].LclRotation; //} //(*pDecoder)(rots.data(), yf.cast<double>()); ////outputExtractor.Set(*block, target_frame, yf); //auto ep = sik.EndPosition(reinterpret_cast<XMFLOAT4A*>(rots.data())); X.segment(0, pvDim) = xf.cast<double>(); auto Xd = X.segment(0, pvDim); auto uXd = gpr.uX.segment(0, pvDim); //auto uXv = block->PdGpr.uX.segment<3>(3); //Xv = (Xv - uXv).array() * g_NoiseInterpolation.array() + uXv.array(); Xd = (Xd - uXd).array(); double varZ = (Xd.array() * (g_NoiseInterpolation.array() - 1.0)).cwiseAbs2().sum(); // if no noise varZ = std::max(varZ, 1e-5); Xd = Xd.array() * g_NoiseInterpolation.array() + uXd.array(); RowVector3d Xld = (xfl.cast<double>() - uXd).array() * g_NoiseInterpolation.array() + uXd.array(); if (g_UseVelocity) { auto Xv = X.segment(pvDim, pvDim); Xv = (Xd - Xld) / (frame_time * g_FrameTimeScaleFactor); } xf = X.cast<float>(); SetVisualizeHandle(block, xf); //m_Xs.row(block->Index) = X; Xabs.emplace_back(X); // Beyesian majarnlize over X //size_t detail = 3; //MatrixXd Xs(detail*2+1,g_PvDimension), Ys; //Xs = gaussian_sample(X, X, detail); //VectorXd Pxs = (Xs - X.replicate(detail * 2 + 1, 1)).cwiseAbs2().rowwise().sum(); //Pxs = (-Pxs.array() / semga).exp(); //VectorXd Py_xs = block->PdGpr.get_expectation_and_likelihood(Xs, &Ys); //Py_xs = (-Py_xs.array()).exp() * Pxs.array(); //Py_xs /= Py_xs.sum(); //Y = (Ys.array() * Py_xs.replicate(1, Ys.cols()).array()).colwise().sum(); MatrixXd covObsr(g_PvDimension, g_PvDimension); covObsr.setZero(); covObsr.diagonal() = g_NoiseInterpolation.replicate(1, g_PvDimension / 3).transpose() * varZ; //block->PdGpr.get_expectation_from_observation(X, covObsr, &Y); //block->PdGpr.get_expectation(X, &Y); //auto yc = yf; //yf = Y.cast<float>(); //yf.array() *= block->Wx.cwiseInverse().array().transpose(); //block->PdStyleIk.SetHint(); if (!g_UseVelocity) Y = sik.apply(X.transpose(), baseRot).cast<double>(); else Y = sik.apply(X.segment(0, pvDim).transpose(), Vector3d(X.segment(pvDim, pvDim).transpose()), baseRot).cast<double>(); //block->PdStyleIk.SetGoal(X.leftCols<3>()); //auto scoref = block->PdStyleIk.objective(X, yf.cast<double>()); //auto scorec = block->PdStyleIk.objective(X, yc.cast<double>()); //std::cout << "Gpr score : " << scoref << " ; Cannonical score : " << scorec << endl; //auto ep = sik.EndPosition(yf.cast<double>()); //Y = yf.cast<double>(); outputExtractor.Set(*block, target_frame, Y.cast<float>()); for (int i = 0; i < block->Joints.size(); i++) { target_frame[block->Joints[i]->ID].UpdateGlobalData(target_frame[block->Joints[i]->parent()->ID]); } auto ep2 = target_frame[block->Joints.back()->ID].GblTranslation - target_frame[block->Joints[0]->parent()->ID].GblTranslation; //break; } } // Fill Xabpv if (g_EnableDependentControl) { RowVectorXd Xabpv; Xabpv.resize(pController->uXabpv.size()); int i = 0; for (const auto& xab : Xabs) { auto Yi = Xabpv.segment(i, xab.size()); Yi = xab; i += xab.size(); } auto _x = (Xabpv.cast<float>() - pController->uXabpv) * pController->XabpvT; auto _xd = _x.cast<double>().eval(); for (auto& block : blocks) { if (block->ActiveActions.size() == 0 && block->SubActiveActions.size() > 0) { auto& sik = pController->GetStylizedIK(block->Index); auto& gpr = sik.Gplvm(); auto lk = gpr.get_expectation_and_likelihood(_xd, &Y); yf = Y.cast<float>(); //yf *= block->Wx.cwiseInverse().asDiagonal(); outputExtractor.Set(*block, target_frame, yf); } } } target_frame[0].LclTranslation = source_frame[0].LclTranslation; target_frame[0].GblTranslation = source_frame[0].GblTranslation; FrameRebuildGlobal(*m_tArmature, target_frame); }