void PlayerUIDialog::ExecuteMoveOrMeleeAttack(RPG_Character* characterEntity) { VASSERT(characterEntity); #if defined (SUPPORTS_MULTITOUCH) && (HAVOK_VISION_RESTRUCTURING) && !defined(_VISION_ANDROID) // Wait 0.1 seconds in case player uses multi touch if (m_wasPressedTime < 0.f) { m_wasPressedTime = Vision::GetTimer()->GetTime(); return; } else if (Vision::GetTimer()->GetTime() - m_wasPressedTime < 0.1f) { return; } #endif //#ifdef _DEBUG // const VString msg = "Execute Primary Action."; // //Vision::Error.SystemMessage(msg.AsChar()); // Vision::Message.Add(1, msg.AsChar()); //#endif const bool inputEdge = !m_wasDown_PlayerMoveOrMelee; // if primary action input is activated now, and wasn't previously, this is a press event. // Get the location of the player input and information about any hit object RPG_DamageableEntity* attackableEntity = NULL; hkvVec3 targetPoint(0.0f, 0.0f, 0.0f); GetFirstAttackableEntityUnderCursor(attackableEntity, targetPoint, characterEntity); if(attackableEntity) { // Hit an object if (inputEdge || attackableEntity != m_lastTargetEntity) { // Initial press event, or a continued press that slipped from one entity to another TryMeleeAttack(characterEntity, attackableEntity); } else { // Continued hold ContinueMeleeAttack(characterEntity, attackableEntity); } } else { // No object hit if (!characterEntity->IsAttacking()) // don't terminate an attack mid-swing { RequestMove(characterEntity, inputEdge); } } m_lastTargetEntity = attackableEntity; m_lastTargetPoint = targetPoint; m_wasDown_PlayerMoveOrMelee = true; }
void PlayerUIDialog::ExecutePowerAttack(RPG_Character* characterEntity) { VASSERT(characterEntity); if (!characterEntity->IsDoingSpecialAttack()) { if (TrySpendMana(characterEntity, characterEntity->GetCharacterActionData().GetPowerAttackManaCost())) // @todo: data-drive action mana costs { RPG_DamageableEntity* attackableEntity = NULL; hkvVec3 targetPoint(0.0f, 0.0f, 0.0f); if(GetFirstAttackableEntityUnderCursor(attackableEntity, targetPoint, characterEntity)) { characterEntity->GetActionHandler().PerformAction(AT_PowerAttack, true, attackableEntity, targetPoint); } else { characterEntity->GetActionHandler().PerformAction(AT_PowerAttack, true, NULL, m_lastTargetPoint); } m_lastTargetEntity = attackableEntity; m_lastTargetPoint = targetPoint; } } }
void PlayerUIDialog::ExecuteOrContinueRangedAttack(RPG_Character* characterEntity) { #ifdef _DEBUG const VString msg = "Execute or Continue Ranged Attack."; //Vision::Error.SystemMessage(msg.AsChar()); Vision::Message.Add(1, msg.AsChar()); #endif const bool inputEdge = !m_wasDown_PlayerRangedAttack; // if ranged attack input is activated now, and wasn't previously, this is a press event. RPG_DamageableEntity* attackableEntity = NULL; hkvVec3 targetPoint(0.0f, 0.0f, 0.0f); GetFirstAttackableEntityUnderCursor(attackableEntity, targetPoint, characterEntity); // TODO - intersect ray with horizontal plane at characterEntity's root node if this returns false // TODO - modify static mesh target height based on normal of interaction point if(inputEdge) { // Initial press event, or a continued press that slipped from one entity to another ExecuteRangedAttack(characterEntity, attackableEntity, targetPoint); } else { if(attackableEntity != m_lastTargetEntity || !targetPoint.isIdentical(m_lastTargetPoint)) { // updates interaction data for currently active ranged attack action ExecuteRangedAttack(characterEntity, attackableEntity, targetPoint); } // continued hold ContinueRangedAttack(characterEntity); } m_lastTargetEntity = attackableEntity; m_lastTargetPoint = targetPoint; m_wasDown_PlayerRangedAttack = true; }
void PlayerUIDialog::OnTick(float deltaTime) { VDialog::OnTick(deltaTime); #if defined (SUPPORTS_MULTITOUCH) && (HAVOK_VISION_RESTRUCTURING) && !defined(_VISION_ANDROID) if (m_touchInput != NULL) { int count = m_touchInput->GetNumberOfTouchPoints(); if (count > 1) return; } #endif RPG_Character *characterEntity = static_cast<RPG_Character *>(m_playerController->GetOwner()); if (!characterEntity) { // @todo: handle player death properly hkvLog::Warning("Player character has probably died, which isn't yet handled. Set the character's Unlimited Health entity property to true to prevent this."); return; } RPG_PlayerControllerInput input; { if(m_inputMap->GetTrigger(PI_PrimaryAction) > 0.0f) { if(m_inputMap->GetTrigger(PI_ShiftModifier) > 0.0f) { input.m_buttons |= RPG_PlayerControllerInput::B_RANGED; } else if(m_inputMap->GetTrigger(PI_SecondaryShiftModifier) > 0.0f) { input.m_buttons |= RPG_PlayerControllerInput::B_POWER; } else { input.m_buttons |= RPG_PlayerControllerInput::B_PRIMARY; } } if(m_inputMap->GetTrigger(PI_SecondaryAction) > 0.0f) { input.m_buttons |= RPG_PlayerControllerInput::B_POWER; } if(m_inputMap->GetTrigger(PI_SpecialAction01) > 0.0f) { input.m_buttons |= RPG_PlayerControllerInput::B_AOE; } GetFirstAttackableEntityUnderCursor(input.m_targetEntity, input.m_targetPoint, characterEntity); if(!input.m_targetEntity) { hkVector4 hitPoint, characterPos; RPG_VisionHavokConversion::VisionToHavokPoint(characterEntity->GetPosition(), characterPos); if(GetClosestPointOnNavMeshUnderCursor(hitPoint, characterPos)) { RPG_VisionHavokConversion::HavokToVisionPoint(hitPoint, input.m_targetPoint); } } m_playerController->SetInput(input); } RPG_GuiManager::GetInstance()->OnTick(deltaTime); }