/* * Copyright (C) 2006-2010 - Frictional Games * * This file is part of Penumbra Overture. * * Penumbra Overture is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Penumbra Overture is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Penumbra Overture. If not, see . */ #include "StdAfx.h" #include "PlayerState_WeaponHaptX.h" #include "Init.h" #include "Player.h" #include "HudModel_Weapon.h" #include "HudModel_Throw.h" #include "HapticGameCamera.h" #include "GameEntity.h" #include "GameEnemy.h" #include "MapHandler.h" #include "EffectHandler.h" #include ////////////////////////////////////////////////////////////////////////// // THROW STATE ////////////////////////////////////////////////////////////////////////// cPlayerState_ThrowHaptX::cPlayerState_ThrowHaptX(cInit *apInit,cPlayer *apPlayer) : iPlayerState(apInit,apPlayer,ePlayerState_Throw) { mfLastForward = 1.0f; mfLastSideways = 1.0f; mpHudObject = NULL; } //----------------------------------------------------------------------- void cPlayerState_ThrowHaptX::OnUpdate(float afTimeStep) { if( mpInit->mpNotebook->IsActive()==false && mpInit->mpInventory->IsActive()==false && mpInit->mpNumericalPanel->IsActive()==false && mpInit->mpDeathMenu->IsActive()==false) { mpPlayer->ResetCrossHairPos(); } ///////////////////////////////////// // If run is down, run!! cInput *pInput = mpInit->mpGame->GetInput(); if( pInput->IsTriggerd("Run") && mpPlayer->GetMoveState() == ePlayerMoveState_Walk) { mpPlayer->ChangeMoveState(ePlayerMoveState_Run); } ///////////////////////////////////////////////// // Cast ray to see if anything is picked. iPhysicsWorld *pPhysicsWorld = mpInit->mpGame->GetScene()->GetWorld3D()->GetPhysicsWorld(); cVector3f vStart,vEnd; vStart = mpPlayer->GetCamera()->GetPosition(); vEnd = vStart + mpPlayer->GetCamera()->GetForward() * mpPlayer->GetPickRay()->mfMaxDistance; mpPlayer->GetPickRay()->Clear(); pPhysicsWorld->CastRay(mpPlayer->GetPickRay(),vStart,vEnd,true,false,true); mpPlayer->GetPickRay()->CalculateResults(); if(mpPlayer->GetPickedBody()) { iGameEntity *pEntity = (iGameEntity*)mpPlayer->GetPickedBody()->GetUserData(); //Set cross hair state eCrossHairState CrossState = pEntity->GetPickCrossHairState(mpPlayer->GetPickedBody()); if(CrossState != eCrossHairState_None && pEntity->GetDescription()!=_W("") && !pEntity->GetHasBeenExamined()) { mpPlayer->SetCrossHairState(eCrossHairState_Examine); } else { mpPlayer->SetCrossHairState(eCrossHairState_None); } //Call entity //pEntity->PlayerPick(); } else { mpPlayer->SetCrossHairState(eCrossHairState_None); } //Quick fix but works, the OnLeave of the previous states sets an old cross hair state. //mpPlayer->SetCrossHairState(eCrossHairState_None); } //----------------------------------------------------------------------- void cPlayerState_ThrowHaptX::OnDraw() { } //----------------------------------------------------------------------- void cPlayerState_ThrowHaptX::OnPostSceneDraw() { //mpHudObject->PostSceneDraw(); } //----------------------------------------------------------------------- bool cPlayerState_ThrowHaptX::OnJump() { return true; } //----------------------------------------------------------------------- void cPlayerState_ThrowHaptX::OnStartInteractMode() { } //----------------------------------------------------------------------- void cPlayerState_ThrowHaptX::OnStartInteract() { mpHudObject->OnAttackDown(); } //----------------------------------------------------------------------- void cPlayerState_ThrowHaptX::OnStopInteract() { mpHudObject->OnAttackUp(); } //----------------------------------------------------------------------- void cPlayerState_ThrowHaptX::OnStartExamine() { //mpInit->mpPlayerHands->SetCurrentModel(1,""); //mpInit->mpPlayer->ChangeState(ePlayerState_Normal); if(mpPlayer->GetPickedBody()) { iGameEntity *pEntity = (iGameEntity*)mpPlayer->GetPickedBody()->GetUserData(); pEntity->PlayerExamine(); } } //----------------------------------------------------------------------- void cPlayerState_ThrowHaptX::OnStartHolster() { mpInit->mpPlayerHands->SetCurrentModel(1,""); mpInit->mpPlayer->ChangeState(ePlayerState_Normal); } //----------------------------------------------------------------------- bool cPlayerState_ThrowHaptX::OnAddYaw(float afVal) { return true;//mpHudObject->OnMouseMove(cVector2f(afVal,0)); } bool cPlayerState_ThrowHaptX::OnAddPitch(float afVal) { return true;//return mpHudObject->OnMouseMove(cVector2f(0,afVal)); } //----------------------------------------------------------------------- bool cPlayerState_ThrowHaptX::OnMoveForwards(float afMul, float afTimeStep) { mfLastForward = afMul; return true; } //----------------------------------------------------------------------- bool cPlayerState_ThrowHaptX::OnMoveSideways(float afMul, float afTimeStep) { mfLastSideways = afMul; return true; } //----------------------------------------------------------------------- void cPlayerState_ThrowHaptX::EnterState(iPlayerState* apPrevState) { mpHudObject->OnStart(); //Haptic mpPlayer->GetHapticCamera()->SetRenderActive(false); mpPlayer->GetHapticCamera()->SetType(eHapticGameCameraType_Centre); mpPlayer->GetHapticCamera()->SetHandVisible(false); } //----------------------------------------------------------------------- void cPlayerState_ThrowHaptX::LeaveState(iPlayerState* apNextState) { if( apNextState->mType != ePlayerState_Message && apNextState->mType != ePlayerState_WeaponMelee && mpInit->mpPlayerHands->GetCurrentModel(1) == mpHudObject) { mpInit->mpPlayerHands->SetCurrentModel(1,""); } //Haptic mpPlayer->GetHapticCamera()->SetRenderActive(true); mpPlayer->GetHapticCamera()->SetType(eHapticGameCameraType_Frame); mpPlayer->GetHapticCamera()->SetHandVisible(true); } //----------------------------------------------------------------------- // No running when you have a weapon: void cPlayerState_ThrowHaptX::OnStartRun() { if(mpPlayer->GetMoveState() == ePlayerMoveState_Walk) mpPlayer->ChangeMoveState(ePlayerMoveState_Run); if( mpPlayer->GetMoveState() == ePlayerMoveState_Jump) { mpPlayer->SetPrevMoveState(ePlayerMoveState_Run); } } void cPlayerState_ThrowHaptX::OnStopRun() { if(mpPlayer->GetMoveState() == ePlayerMoveState_Run) mpPlayer->ChangeMoveState(ePlayerMoveState_Walk); else if(mpPlayer->GetMoveState() == ePlayerMoveState_Jump) mpPlayer->SetPrevMoveState(ePlayerMoveState_Walk); } //----------------------------------------------------------------------- void cPlayerState_ThrowHaptX::OnStartCrouch() { if(mpPlayer->GetMoveState() == ePlayerMoveState_Jump)return; if(mpInit->mpButtonHandler->GetToggleCrouch()) { if(mpPlayer->GetMoveState() == ePlayerMoveState_Crouch) mpPlayer->ChangeMoveState(ePlayerMoveState_Walk); else mpPlayer->ChangeMoveState(ePlayerMoveState_Crouch); } else { mpPlayer->ChangeMoveState(ePlayerMoveState_Crouch); } } void cPlayerState_ThrowHaptX::OnStopCrouch() { if( mpPlayer->GetMoveState() == ePlayerMoveState_Crouch && mpInit->mpButtonHandler->GetToggleCrouch()==false) { mpPlayer->ChangeMoveState(ePlayerMoveState_Walk); } } //----------------------------------------------------------------------- bool cPlayerState_ThrowHaptX::OnStartInventory() { //mpPlayer->ChangeState(ePlayerState_Normal); return true; } //----------------------------------------------------------------------- bool cPlayerState_ThrowHaptX::OnStartInventoryShortCut(int alNum) { return true; } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // WEAPON MELEE STATE ////////////////////////////////////////////////////////////////////////// cPlayerState_WeaponMeleeHaptX::cPlayerState_WeaponMeleeHaptX(cInit *apInit,cPlayer *apPlayer) : iPlayerState(apInit,apPlayer,ePlayerState_WeaponMelee) { mfLastForward = 1.0f; mfLastSideways = 1.0f; mpLowLevelHaptic = mpInit->mpGame->GetHaptic()->GetLowLevel(); mpSlowdownForce = mpLowLevelHaptic->CreateViscosityForce(0,6,0.5f,50.0f); mpSlowdownForce->SetActive(false); mbInteractDown = false; mpFeedbackForce = mpLowLevelHaptic->CreateImpulseForce(0); mpFeedbackForce->SetActive(false); mpImpulseForce = mpLowLevelHaptic->CreateImpulseForce(0); mpImpulseForce->SetActive(false); mbCollided = false; } //----------------------------------------------------------------------- static cVector3f gvPrevPos; static bool gbFirstTime=true; static std::list glsVelList; void cPlayerState_WeaponMeleeHaptX::OnUpdate(float afTimeStep) { ///////////////////////////////////// // Set crosshair to centre of screen if( mpInit->mpNotebook->IsActive()==false && mpInit->mpInventory->IsActive()==false && mpInit->mpNumericalPanel->IsActive()==false && mpInit->mpDeathMenu->IsActive()==false) { mpPlayer->ResetCrossHairPos(); } ///////////////////////////////////// // If run is down, run!! cInput *pInput = mpInit->mpGame->GetInput(); if( pInput->IsTriggerd("Run") && mpPlayer->GetMoveState() == ePlayerMoveState_Walk) { mpPlayer->ChangeMoveState(ePlayerMoveState_Run); } /////////////////////////////////////////////// // Calculate proxy movement speed mpLowLevelHaptic = mpInit->mpGame->GetHaptic()->GetLowLevel(); cVector3f vMovement= mpLowLevelHaptic->GetHardwarePosition(); if(gbFirstTime) { gvPrevPos = vMovement; gbFirstTime = false; } cVector3f vVelocity = (vMovement - gvPrevPos); vVelocity = cVector3f(vVelocity.x , vVelocity.y, vVelocity.z ); glsVelList.push_back(vVelocity); //Change here to let the average speed consist of more samples if(glsVelList.size() > 10) glsVelList.pop_front(); cVector3f vAvg(0); for(std::list::iterator it = glsVelList.begin(); it != glsVelList.end(); ++it) { vAvg += *it; } vAvg = vAvg / (float)glsVelList.size(); /////////////////////////////////////////////// // If button is pressed then turn weapon according to speed of proxy if(mbInteractDown) { //Log("Avg: %s\n",vAvg.ToString().c_str()); //mvGoalRotation.z =cMath::ToRad(0); bool bXSet = true; if(vAvg.x > 0.75f){ mvGoalRotation.y =cMath::ToRad(65.0f); mvGoalRotation.z = cMath::ToRad(90.0f); } else if(vAvg.x < -0.75f){ mvGoalRotation.y =cMath::ToRad(-65.0f); mvGoalRotation.z = cMath::ToRad(90.0f); } else { mvGoalRotation.y =cMath::ToRad(0.0f); bXSet = false; } if(vAvg.y > 0.75f) { mvGoalRotation.x =cMath::ToRad(-90.0f - 50.0f); if(bXSet){ if(mvGoalRotation.y > 0) mvGoalRotation.z = cMath::ToRad(45.0f); if(mvGoalRotation.y < 0) mvGoalRotation.z = cMath::ToRad(135.0f); } else { mvGoalRotation.z =0; } } else if(vAvg.y < -0.75f) { mvGoalRotation.x =cMath::ToRad(-90.0f + 50.0f); if(bXSet){ if(mvGoalRotation.y < 0) mvGoalRotation.z = cMath::ToRad(45.0f); if(mvGoalRotation.y > 0) mvGoalRotation.z = cMath::ToRad(135.0f); } else { mvGoalRotation.z =0; } } else { mvGoalRotation.x =cMath::ToRad(-90.0f); } } /////////////////////////////////////////////// // Calculate weapon and collider matrix cVector3f vProxyPos = mpPlayer->GetHapticCamera()->GetHandEntity()->GetWorldPosition(); float fYaw = mpPlayer->GetCamera()->GetYaw(); cMatrixf mtxWeapon = cMath::MatrixScale(mpHudWeapon->GetHapticScale()); mtxWeapon = cMath::MatrixMul(cMath::MatrixRotate(mpHudWeapon->GetHapticRot(),eEulerRotationOrder_XYZ),mtxWeapon); mtxWeapon = cMath::MatrixMul(cMath::MatrixRotate(cVector3f(0,mvRotation.z,0),eEulerRotationOrder_YXZ),mtxWeapon); mtxWeapon = cMath::MatrixMul(cMath::MatrixRotate(cVector3f(mvRotation.x,mvRotation.y,0),eEulerRotationOrder_XZY),mtxWeapon); mtxWeapon = cMath::MatrixMul(cMath::MatrixRotateY(fYaw),mtxWeapon); mtxWeapon = cMath::MatrixMul(cMath::MatrixTranslate(vProxyPos),mtxWeapon); mpHudWeapon->GetEntity()->SetMatrix(mtxWeapon); cMatrixf mtxCollider = cMatrixf::Identity; mtxCollider = cMath::MatrixMul(cMath::MatrixRotate(cVector3f(0,mvRotation.z,0),eEulerRotationOrder_YXZ),mtxCollider); mtxCollider = cMath::MatrixMul(cMath::MatrixRotate(cVector3f(mvRotation.x,mvRotation.y,0),eEulerRotationOrder_XZY),mtxCollider); mtxCollider = cMath::MatrixMul(cMath::MatrixRotateY(fYaw),mtxCollider); mtxCollider = cMath::MatrixMul(cMath::MatrixTranslate(vProxyPos),mtxCollider); //mpBody->SetMatrix(mtxCollider); /////////////////////////////////////////////// // Update angles and turn towards goal //Y float fAngleStep = cMath::ToRad(90.0f*afTimeStep*1.2f); if(mvGoalRotation.y != mvRotation.y) { mvRotation.y = cMath::TurnAngleRad(mvRotation.y, mvGoalRotation.y,fAngleStep); } //X fAngleStep = cMath::ToRad(90.0f*afTimeStep*1.2f); if(mvGoalRotation.x != mvRotation.x) { mvRotation.x = cMath::TurnAngleRad(mvRotation.x, mvGoalRotation.x,fAngleStep); } //Z fAngleStep = cMath::ToRad(90.0f*afTimeStep*5.2f); if(mvGoalRotation.z != mvRotation.z) { mvRotation.z = cMath::TurnAngleRad(mvRotation.z, mvGoalRotation.z,fAngleStep); } /////////////////////////////////////////////// // Make an attack float fSpeed = vAvg.Length(); //This speed is used to if( mbInteractDown && //Interaction must be down (fSpeed > 0.5 || vAvg.z >0.3f) && //The minimum speed required for attack (z needs to be a bit lower) mfAttackCount <=0 && //Do not allow a newer attack too soon after mbCollided == false //Makes sure that something that just collided can not make an attack, this removes double hits, but //may skips some hits too. ) { if(CheckAttack(mtxCollider, cMath::Min(fSpeed * 0.3f, 1.0f))) { mfAttackCount = 0.5f; //Force at hit, removed for now. //if(mpFeedbackForce->IsActive()) mpFeedbackForce->SetActive(false); //cVector3f vDir = cMath::Vector3Normalize(vAvg); //mpFeedbackForce->SetForce(vDir * -1.0f * fSpeed * 0.08f); //mpFeedbackForce->SetTimeControl(false, 0.1f,0,0,0.1f); //mpFeedbackForce->SetActive(true); } } if(mfAttackCount >0) mfAttackCount -= afTimeStep; /////////////////////////////////////////////// // Check of collsion with any body and add force if there is. // this so weapon does not go into objects. cCamera3D *pCamera = mpInit->mpPlayer->GetCamera(); iPhysicsWorld *pPhysicsWorld = mpInit->mpGame->GetScene()->GetWorld3D()->GetPhysicsWorld(); cMatrixf mtxProxy = cMath::MatrixRotate(cVector3f(-pCamera->GetPitch(),-pCamera->GetYaw(), -pCamera->GetRoll()),eEulerRotationOrder_YXZ); if(mbInteractDown) { cVector3f vNewPos = mtxCollider.GetTranslation(); bool bCollide = pPhysicsWorld->CheckShapeWorldCollision(&vNewPos,mpCollider,mtxCollider,NULL,false,false,NULL,false); if(bCollide && vNewPos != mtxWeapon.GetTranslation()) { cVector3f vDiff = vNewPos - mtxCollider.GetTranslation(); float fMaxDiffLength =0.1f; if(vDiff.Length() > fMaxDiffLength) { vDiff.Normalise(); vDiff = vDiff * fMaxDiffLength; } mvPushBackVec = vDiff; mvPushBackPos = mtxCollider.GetTranslation(); vDiff = cMath::MatrixMul(mtxProxy, vDiff); mpImpulseForce->SetForce(cMath::Vector3Normalize(vDiff)*2); //Log("Collide %s\n",vDiff.ToString().c_str()); mbCollided = true; //Set so that we must be out of collision before making an attack. } else { mbCollided = false; mvPushBackVec =0; mpImpulseForce->SetForce(0); //mpImpulseForce->SetActive(false); } } else { mvPushBackVec =0; mpImpulseForce->SetForce(0); mbCollided = false; } ///////////////////////////////////////////////// // Cast Ray, To see if anything is picked. So you can still look at stuff cVector3f vStart,vEnd; vStart = mpPlayer->GetCamera()->GetPosition(); vEnd = vStart + mpPlayer->GetCamera()->GetForward() * mpPlayer->GetPickRay()->mfMaxDistance; mpPlayer->GetPickRay()->Clear(); pPhysicsWorld->CastRay(mpPlayer->GetPickRay(),vStart,vEnd,true,false,true); mpPlayer->GetPickRay()->CalculateResults(); if(mpPlayer->GetPickedBody() && mpHudWeapon->IsAttacking()==false) { iGameEntity *pEntity = (iGameEntity*)mpPlayer->GetPickedBody()->GetUserData(); //Set cross hair state eCrossHairState CrossState = pEntity->GetPickCrossHairState(mpPlayer->GetPickedBody()); if(CrossState != eCrossHairState_None && pEntity->GetDescription()!=_W("") && !pEntity->GetHasBeenExamined()) { mpPlayer->SetCrossHairState(eCrossHairState_Examine); } else { mpPlayer->SetCrossHairState(eCrossHairState_None); } //Call entity //pEntity->PlayerPick(); } else { mpPlayer->SetCrossHairState(eCrossHairState_None); } ////////////////////////////////////// //Set the previous movement gvPrevPos = vMovement; //Quick fix but works, the OnLeave of the previous states sets an old cross hair state. //mpPlayer->SetCrossHairState(eCrossHairState_None); } //----------------------------------------------------------------------- void cPlayerState_WeaponMeleeHaptX::OnDraw() { } //----------------------------------------------------------------------- void cPlayerState_WeaponMeleeHaptX::OnPostSceneDraw() { //Comment out this to see debug info! return; cCamera3D *pCamera = static_cast(mpInit->mpGame->GetScene()->GetCamera()); mpInit->mpGame->GetGraphics()->GetLowLevel()->DrawLine(mvPushBackPos,mvPushBackPos+mvPushBackVec,cColor(1,1)); cVector3f vProxyPos = mpPlayer->GetHapticCamera()->GetHandEntity()->GetWorldPosition(); float fYaw = mpPlayer->GetCamera()->GetYaw(); cVector3f vSize = mpCollider->GetSize(); cMatrixf mtxWeapon = cMatrixf::Identity;//cMath::MatrixTranslate(cVector3f(0,vSize.y*0.5f,0)); mtxWeapon = cMath::MatrixMul(cMath::MatrixRotate(cVector3f(0,mvRotation.z,0),eEulerRotationOrder_YXZ),mtxWeapon); mtxWeapon = cMath::MatrixMul(cMath::MatrixRotate(cVector3f(mvRotation.x,mvRotation.y,0),eEulerRotationOrder_XZY),mtxWeapon); mtxWeapon = cMath::MatrixMul(cMath::MatrixRotateY(fYaw),mtxWeapon); mtxWeapon = cMath::MatrixMul(cMath::MatrixTranslate(vProxyPos),mtxWeapon); cMatrixf mtxCollider = cMath::MatrixMul(pCamera->GetViewMatrix(),mtxWeapon); cBoundingVolume boundingVolume = mpCollider->GetBoundingVolume(); boundingVolume.SetTransform(cMath::MatrixMul(mtxWeapon, boundingVolume.GetTransform())); mpInit->mpGame->GetGraphics()->GetLowLevel()->DrawBoxMaxMin(boundingVolume.GetMax(),boundingVolume.GetMin(),cColor(0,0,1,1)); mpInit->mpGame->GetGraphics()->GetLowLevel()->SetMatrix(eMatrix_ModelView,mtxCollider); mpInit->mpGame->GetGraphics()->GetLowLevel()->DrawBoxMaxMin(vSize*0.5f,vSize*-0.5f,cColor(0,1,0,1)); mpInit->mpGame->GetGraphics()->GetLowLevel()->SetMatrix(eMatrix_ModelView,pCamera->GetViewMatrix()); //mpBody->RenderDebugGeometry(mpInit->mpGame->GetGraphics()->GetLowLevel(),cColor(0,1,0,1)); } //----------------------------------------------------------------------- bool cPlayerState_WeaponMeleeHaptX::OnJump() { return true; } //----------------------------------------------------------------------- void cPlayerState_WeaponMeleeHaptX::OnStartInteractMode() { } //----------------------------------------------------------------------- void cPlayerState_WeaponMeleeHaptX::OnStartInteract() { mbInteractDown = true; mpPlayer->GetHapticCamera()->SetUseFrame(false); mpImpulseForce->SetActive(true); mpImpulseForce->SetForce(0); mpSlowdownForce->SetActive(true); } //----------------------------------------------------------------------- void cPlayerState_WeaponMeleeHaptX::OnStopInteract() { mbInteractDown = false; mvGoalRotation = 0; mpPlayer->GetHapticCamera()->SetUseFrame(true); mpImpulseForce->SetActive(false); mpSlowdownForce->SetActive(false); } //----------------------------------------------------------------------- void cPlayerState_WeaponMeleeHaptX::OnStartExamine() { //mpPlayer->ChangeState(ePlayerState_Normal); if(mpPlayer->GetPickedBody() && mpHudWeapon->IsAttacking()==false) { iGameEntity *pEntity = (iGameEntity*)mpPlayer->GetPickedBody()->GetUserData(); pEntity->PlayerExamine(); } } //----------------------------------------------------------------------- void cPlayerState_WeaponMeleeHaptX::OnStartHolster() { mpInit->mpPlayer->ChangeState(ePlayerState_Normal); //mpHudWeapon = NULL; } //----------------------------------------------------------------------- bool cPlayerState_WeaponMeleeHaptX::OnAddYaw(float afVal) { return true; } bool cPlayerState_WeaponMeleeHaptX::OnAddPitch(float afVal) { return true; } //----------------------------------------------------------------------- bool cPlayerState_WeaponMeleeHaptX::OnMoveForwards(float afMul, float afTimeStep) { return true; } //----------------------------------------------------------------------- bool cPlayerState_WeaponMeleeHaptX::OnMoveSideways(float afMul, float afTimeStep) { return true; } //----------------------------------------------------------------------- void cPlayerState_WeaponMeleeHaptX::EnterState(iPlayerState* apPrevState) { gbFirstTime = false; //Show the darn weapon mpHudWeapon->LoadEntities(); mpHudWeapon->GetEntity()->SetVisible(true); mpHudWeapon->GetEntity()->SetCastsShadows(true); //Create collider iPhysicsWorld *pPhysicsWorld = mpInit->mpGame->GetScene()->GetWorld3D()->GetPhysicsWorld(); cVector3f vSize = mpHudWeapon->GetHapticSize(); cMatrixf mtxOffset = cMath::MatrixTranslate(cVector3f(0,vSize.y*0.5f,0)); mpCollider = pPhysicsWorld->CreateBoxShape(vSize, &mtxOffset); //mpBody = pPhysicsWorld->CreateBody("",mpCollider); //mpBody->SetActive(false); mvRotation =0; mfAttackCount =0; } //----------------------------------------------------------------------- void cPlayerState_WeaponMeleeHaptX::LeaveState(iPlayerState* apNextState) { mpSlowdownForce->SetActive(false); mpImpulseForce->SetActive(false); mpHudWeapon->GetEntity()->SetVisible(false); mpHudWeapon->DestroyEntities(); iPhysicsWorld *pPhysicsWorld = mpInit->mpGame->GetScene()->GetWorld3D()->GetPhysicsWorld(); pPhysicsWorld->DestroyShape(mpCollider); //pPhysicsWorld->DestroyBody(mpBody); mpPlayer->GetHapticCamera()->SetUseFrame(true); //mpHudWeapon = NULL; } //----------------------------------------------------------------------- // No running when you have a weapon: void cPlayerState_WeaponMeleeHaptX::OnStartRun() { if(mpPlayer->GetMoveState() == ePlayerMoveState_Walk) mpPlayer->ChangeMoveState(ePlayerMoveState_Run); if( mpPlayer->GetMoveState() == ePlayerMoveState_Jump) { mpPlayer->SetPrevMoveState(ePlayerMoveState_Run); } } void cPlayerState_WeaponMeleeHaptX::OnStopRun() { if(mpPlayer->GetMoveState() == ePlayerMoveState_Run) mpPlayer->ChangeMoveState(ePlayerMoveState_Walk); else if(mpPlayer->GetMoveState() == ePlayerMoveState_Jump) mpPlayer->SetPrevMoveState(ePlayerMoveState_Walk); } //----------------------------------------------------------------------- void cPlayerState_WeaponMeleeHaptX::OnStartCrouch() { if(mpPlayer->GetMoveState() == ePlayerMoveState_Jump)return; if(mpInit->mpButtonHandler->GetToggleCrouch()) { if(mpPlayer->GetMoveState() == ePlayerMoveState_Crouch) mpPlayer->ChangeMoveState(ePlayerMoveState_Walk); else mpPlayer->ChangeMoveState(ePlayerMoveState_Crouch); } else { mpPlayer->ChangeMoveState(ePlayerMoveState_Crouch); } } void cPlayerState_WeaponMeleeHaptX::OnStopCrouch() { if( mpPlayer->GetMoveState() == ePlayerMoveState_Crouch && mpInit->mpButtonHandler->GetToggleCrouch()==false) { mpPlayer->ChangeMoveState(ePlayerMoveState_Walk); } } //----------------------------------------------------------------------- bool cPlayerState_WeaponMeleeHaptX::OnStartInventory() { //mpPlayer->ChangeState(ePlayerState_Normal); return true; } //----------------------------------------------------------------------- void cPlayerState_WeaponMeleeHaptX::PlaySound(const tString &asSound) { cSoundHandler *pSoundHandler = mpInit->mpGame->GetSound()->GetSoundHandler(); pSoundHandler->PlayGui(asSound,false,1.0f); } //----------------------------------------------------------------------- bool cPlayerState_WeaponMeleeHaptX::CheckAttack(const cMatrixf& a_mtxTransform, float afSpeed) { mpInit->mbWeaponAttacking = true; //Log("----------------- BEGIN ATTACK WITH WEAPON ------------ \n"); cMeleeWeaponAttack* pAttack = mpHudWeapon->GetAttack(0); float fMaxImpulse = pAttack->mfMaxImpulse * afSpeed; float fMinImpulse = pAttack->mfMinImpulse * afSpeed; float fMinMass = pAttack->mfMinMass * afSpeed; float fMaxMass = pAttack->mfMaxMass * afSpeed; float fMinDamage = pAttack->mfMinDamage * afSpeed; float fMaxDamage = pAttack->mfMaxDamage * afSpeed; int lStrength = pAttack->mlAttackStrength; cCamera3D *pCamera = mpInit->mpPlayer->GetCamera(); cBoundingVolume tempBV = mpCollider->GetBoundingVolume(); tempBV.SetTransform(cMath::MatrixMul(a_mtxTransform, tempBV.GetTransform())); cCollideData collideData; collideData.SetMaxSize(1); bool bHit = false; cWorld3D *pWorld = mpInit->mpGame->GetScene()->GetWorld3D(); iPhysicsWorld *pPhysicsWorld = pWorld->GetPhysicsWorld(); tVector3fList lstPostions; //////////////////////////////// //Iterate Enemies tGameEnemyIterator enemyIt = mpInit->mpMapHandler->GetGameEnemyIterator(); while(enemyIt.HasNext()) { iGameEnemy *pEnemy = enemyIt.Next(); iPhysicsBody *pBody = pEnemy->GetMover()->GetCharBody()->GetBody(); float fMass = pBody->GetMass(); if(pEnemy->GetMover()->GetCharBody()->IsActive()==false) continue; if(cMath::CheckCollisionBV(tempBV, *pBody->GetBV())) { if(pEnemy->GetMeshEntity()->CheckColliderShapeCollision(pPhysicsWorld, mpCollider, a_mtxTransform,&lstPostions,NULL)==false) { continue; } //Calculate force float fForceSize =0; if(fMass > fMaxMass) fForceSize =0; else if(fMass <= fMinMass) fForceSize = fMaxImpulse; else{ float fT = (fMass - fMinMass) / (fMaxMass - fMinMass); fForceSize = fMinImpulse * fT + fMaxImpulse * (1-fT); } cVector3f vForceDir = pCamera->GetForward(); vForceDir.Normalise(); //Add force to bodies for(int i=0; i < pEnemy->GetBodyNum(); ++i) { iPhysicsBody* pBody = pEnemy->GetBody(i); pBody->AddImpulse(vForceDir *fForceSize*0.5f); cVector3f vTorque = cVector3f(0,1,0) * fMass * fForceSize *0.5f; pBody->AddTorque(vTorque); } //Calculate damage float fDamage = cMath::RandRectf( fMinDamage, fMaxDamage); pEnemy->Damage(fDamage,lStrength); //Get closest position float fClosestDist = 9999.0f; cVector3f vClosestPostion = a_mtxTransform.GetTranslation(); for(tVector3fListIt it = lstPostions.begin(); it != lstPostions.end(); ++it) { cVector3f &vPos = *it; float fDist = cMath::Vector3DistSqr(pCamera->GetPosition(),vPos); if(fDist < fClosestDist) { fClosestDist = fDist; vClosestPostion = vPos; } } //Particle system if(pEnemy->GetHitPS()!="") { pWorld->CreateParticleSystem("Hit",pEnemy->GetHitPS(),1, cMath::MatrixTranslate(vClosestPostion)); } lstPostions.clear(); bHit = true; } } std::set m_setHitBodies; //////////////////////////////// //Iterate bodies float fClosestHitDist = 9999.0f; cVector3f vClosestHitPos; iPhysicsMaterial* pClosestHitMat = NULL; cPhysicsBodyIterator it = pPhysicsWorld->GetBodyIterator(); while(it.HasNext()) { iPhysicsBody *pBody = it.Next(); float fMass = pBody->GetMass(); if(pBody->IsActive()==false) continue; if(pBody->GetCollide()==false) continue; if(pBody->IsCharacter()) continue; if(cMath::CheckCollisionBV(tempBV, *pBody->GetBV())) { if(pPhysicsWorld->CheckShapeCollision(pBody->GetShape(),pBody->GetLocalMatrix(), mpCollider,a_mtxTransform,collideData,1)==false) { continue; } cVector3f vHitPos = collideData.mvContactPoints[0].mvPoint; m_setHitBodies.insert(pBody); //Deal damage and force HitBody(pBody,fMinImpulse,fMaxImpulse,fMinMass,fMaxMass,fMinDamage,fMaxDamage,lStrength); //Check if this is the closest hit body float fDist = cMath::Vector3DistSqr(vHitPos, pCamera->GetPosition()); if(fDist < fClosestHitDist) { fClosestHitDist = fDist; vClosestHitPos = collideData.mvContactPoints[0].mvPoint; pClosestHitMat = pBody->GetMaterial(); } bHit = true; } } //////////////////////////////////////////// //Check the closest material and play sounds and effects depending on it. if(pClosestHitMat) { bHit = true; cMatrixf mtxPosition = cMath::MatrixTranslate(vClosestHitPos); cSurfaceData *pData = pClosestHitMat->GetSurfaceData(); cSurfaceImpactData *pImpact = pData->GetHitDataFromSpeed(pAttack->mfAttackSpeed); if(pImpact) { cSoundEntity *pSound = pWorld->CreateSoundEntity("Hit",pImpact->GetSoundName(),true); if(pSound) pSound->SetPosition(vClosestHitPos); if(pAttack->mlHitPSPrio <= pImpact->GetPSPrio()) { if(pImpact->GetPSName()!="") pWorld->CreateParticleSystem("Hit",pImpact->GetPSName(),1,mtxPosition); } else { if(pAttack->msHitPS!="") pWorld->CreateParticleSystem("Hit",pAttack->msHitPS,1,mtxPosition); } } } //Log("----------------- END ATTACK WITH WEAPON ------------ \n"); ///////////////////////// //Play hit sound if(bHit) { PlaySound(pAttack->msHitSound); } mpInit->mbWeaponAttacking = false; return bHit; } //----------------------------------------------------------------------- void cPlayerState_WeaponMeleeHaptX::HitBody(iPhysicsBody *apBody, float afMinImpulse, float afMaxImpulse, float afMinMass, float afMaxMass, float afMinDamage, float afMaxDamage, int alStrength) { iGameEntity *pEntity = (iGameEntity*)apBody->GetUserData(); if(pEntity && pEntity->GetType() == eGameEntityType_Enemy) return; cCamera3D *pCamera =mpInit->mpPlayer->GetCamera(); cVector3f vSpinMul = cVector3f(0,1,0); vSpinMul = pCamera->GetRight() * vSpinMul.x + pCamera->GetUp() * vSpinMul.y + pCamera->GetForward() * vSpinMul.z; float fMass = apBody->GetMass(); //Calculate force float fForceSize =0; if(fMass > afMaxMass) fForceSize =0; else if(fMass <= afMinMass) fForceSize = afMaxImpulse; else{ float fT = (fMass - afMinMass) / (afMaxMass - afMinMass); fForceSize = afMinImpulse * fT + afMaxImpulse * (1-fT); } //Calculate damage float fDamage = cMath::RandRectf( afMinDamage,afMaxDamage); cVector3f vForceDir = pCamera->GetForward(); if(fMass>0 && fForceSize >0) { vForceDir.Normalise(); //pBody->AddForce(vForceDir * fForceSize); apBody->AddImpulse(vForceDir *fForceSize); cVector3f vTorque = vSpinMul * fMass * fForceSize; //vTorque = cMath::MatrixMul(pBody->GetInertiaMatrix(),vTorque); apBody->AddTorque(vTorque); } if(pEntity) { pEntity->SetLastImpulse(vForceDir *fForceSize); pEntity->Damage(fDamage,alStrength); } } //-----------------------------------------------------------------------