void CN3FXBundleGame::Trigger(int iSourceID, __Vector3 TargetPos, int iSndID) { m_bRegion = true; CPlayerBase* pSource = CGameProcedure::s_pProcMain->CharacterGetByID(iSourceID, true); if(pSource) { if(pSource->m_pShapeExtraRef) { __Vector3 vMin = pSource->m_pShapeExtraRef->Min(); __Vector3 vMax = pSource->m_pShapeExtraRef->Max(); m_vPos = vMin + ((vMax-vMin)*0.5f); } else { const __Matrix44* pMtx = pSource->JointMatrixGet(m_iSourceJoint); if(!pMtx) m_vPos = pSource->Position(); else pSource->JointPosGet(m_iSourceJoint, m_vPos); } } m_vDestPos = TargetPos; m_fDistance = (m_vDestPos - m_vPos).Magnitude(); m_fHeight = m_fDistance/2.0f; m_vDir = m_vDestPos - m_vPos; m_vDir.Normalize(); CN3FXBundle::Trigger(iSourceID, -1, -1, iSndID); }
void CN3FXBundleGame::SetPreBundlePos(int iSourceID, int iJoint) { CPlayerBase* pSource = CGameProcedure::s_pProcMain->CharacterGetByID(iSourceID, true); if(pSource) { if(pSource->m_pShapeExtraRef) { __Vector3 vMin = pSource->m_pShapeExtraRef->Min(); __Vector3 vMax = pSource->m_pShapeExtraRef->Max(); m_vPrePos = vMin + ((vMax-vMin)*0.5f); } else { const __Matrix44* pMtx = pSource->JointMatrixGet(iJoint); if(!pMtx) m_vPrePos = pSource->Position(); else pSource->JointPosGet(iJoint, m_vPrePos); } } }
void CPlayerMySelf::Tick() { BOOL bAnim = TRUE; if( PSA_DEATH == m_eState) // 죽는 상태이고... 죽는 에니메이션이 끝나면.. // 한번 보내면 다시 죽을때까지 안보내는 플래그 { if(0 == m_iSendRegeneration) { // std::string szMsg; ::_LoadStringFromResource(IDS_REGENERATION, szMsg); // CGameProcedure::MessageBoxPost(szMsg, "", MB_OK, BEHAVIOR_REGENERATION); // CLogWriter::Write("Dead!!!"); m_iSendRegeneration = 1; } return; } if(m_fTimeAfterDeath > 0) // 강제로 죽여야 한다.. { if(m_fTimeAfterDeath > 3.0f) this->Action(PSA_DYING, false); // 3 초가 지나야 죽는다. CPlayerBase::Tick(); // 회전, 지정된 에니메이션 Tick 및 색깔 지정 처리.. 등등.. return; } if(IsDead()) // 죽은 상태면 돌아간다. { CGameProcedure::s_pProcMain->CommandEnableAttackContinous(false, NULL); CPlayerBase::Tick(); // 회전, 지정된 에니메이션 Tick 및 색깔 지정 처리.. 등등.. return; } //////////////////////////////////////////////////////////////////////////////// // 내 플레이어는 움직이는게 다른넘들과 다르기 때문에 특별하게 처리.. if( PSM_WALK == m_eStateMove || PSM_WALK_BACKWARD == m_eStateMove || PSM_RUN == m_eStateMove ) // 앞뒤로 걸어가거나 달려가면. { this->MoveSpeedCalculationAndCheckCollision(); // 움직이는 속도 및 충돌체크... if(0 == m_fMoveSpeedPerSec) // 속도가 없으면 충돌체크 결과 못가는 거다... { this->ActionMove(PSM_STOP); CGameProcedure::s_pProcMain->MsgSend_Move(false, false); // 정지 패킷 보내기.. } __Vector3 vPos = this->Position(); CPlayerBase::m_pSnd_MyMove = m_pSnd_Move; if(m_pSnd_Move && m_Chr.NeedPlaySound0()) m_pSnd_Move->Play(&vPos); if(m_pSnd_Move && m_Chr.NeedPlaySound1()) m_pSnd_Move->Play(&vPos); TargetOrPosMove(); } else { CPlayerBase::m_pSnd_MyMove = NULL; m_fMoveSpeedPerSec = 0; } // 내 플레이어는 움직이는게 다른넘들과 다르기 때문에 특별하게 처리.. //////////////////////////////////////////////////////////////////////////////// CPlayerBase* pTarget = NULL; // if(true == m_bAttackContinous || m_iSkillStep > 0) if(true == m_bAttackContinous && m_iSkillStep <= 0) { pTarget = TargetPointerCheck(false); if(NULL == pTarget) { CGameProcedure::s_pProcMain->CommandEnableAttackContinous(false, NULL); } else { float fTime = CN3Base::TimeGet(); // 활쏘기, 석궁 쏘기 등 스킬로 처리한다.. if( (m_pItemPlugBasics[PLUG_POS_LEFTHAND] && ITEM_CLASS_BOW == m_pItemPlugBasics[PLUG_POS_LEFTHAND]->byClass ) || (m_pItemPlugBasics[PLUG_POS_LEFTHAND] && ITEM_CLASS_BOW_LONG == m_pItemPlugBasics[PLUG_POS_LEFTHAND]->byClass ) || (m_pItemPlugBasics[PLUG_POS_RIGHTHAND] && ITEM_CLASS_BOW_CROSS == m_pItemPlugBasics[PLUG_POS_RIGHTHAND]->byClass) ) { __TABLE_UPC_SKILL* pSkill = s_pTbl_Skill->Find(102003); // 스킬 테이블에서 기본 활 스킬을 찾고 if(pSkill) { if(pTarget->IsAlive())//임시 유저가 살아 있는 상태에서만... { float fInterval = (pSkill->iCastTime / 10.f) + 0.15f; if(m_fAttackDelta > 0) fInterval /= m_fAttackDelta; if(fTime > m_fAttackTimeRecent + fInterval) // 공격 간격이 넘으면.. 공격! { if(CGameProcedure::s_pProcMain->m_pMagicSkillMng->MsgSend_MagicProcess(m_iIDTarget, pSkill)) {// 스킬 패킷 보내기에 성공하면. //TRACE("%.2f\n", fTime - m_fAttackTimeRecent); } m_fAttackTimeRecent = fTime; // 최근에 공격한 시간.. } } } } else if( m_pItemPlugBasics[PLUG_POS_RIGHTHAND] && ITEM_CLASS_LAUNCHER == m_pItemPlugBasics[PLUG_POS_RIGHTHAND]->byClass ) // 투창용 아이템이면.. { __TABLE_UPC_SKILL* pSkill = s_pTbl_Skill->Find(102009); // 스킬 테이블에서 기본 활 스킬을 찾고 if(pSkill && fTime > m_fAttackTimeRecent + (pSkill->iCastTime / 10.f)) // 공격 간격이 넘으면.. 공격! { if(pTarget->IsAlive())//임시 유저가 살아 있는 상태에서만 { CGameProcedure::s_pProcMain->m_pMagicSkillMng->MsgSend_MagicProcess(m_iIDTarget, pSkill); // 스킬 패킷 보내기에 성공하면. //TRACE("%.2f\n", fTime - m_fAttackTimeRecent); m_fAttackTimeRecent = fTime; // 최근에 공격한 시간.. } } } else // 걍 공격이면.. { float fIntervalTable = 1.0f; if(m_pItemPlugBasics[PLUG_POS_RIGHTHAND] && m_pItemPlugExts[PLUG_POS_RIGHTHAND]) // 공격 간격 정의 { fIntervalTable = (m_pItemPlugBasics[PLUG_POS_RIGHTHAND]->siAttackInterval / 100.0f) * (m_pItemPlugExts[PLUG_POS_RIGHTHAND]->siAttackIntervalPercentage / 100.0f); // 100 은 1초 110 이면 1.1 초등.. 퍼센트로 간다... } float fInterval = fIntervalTable; if(m_fAttackDelta > 0) fInterval /= m_fAttackDelta; // 스킬이나 마법에 의해 변하는 공격 속도.. 1.0 이 기본이고 클수록 더 빨리 공격한다. if( fTime > m_fAttackTimeRecent + fInterval) // 공격 간격이 넘으면.. 공격! { bool bCastingNow = CGameProcedure::s_pProcMain->m_pMagicSkillMng->IsCasting(); if(false == bCastingNow) // 캐스팅 중이면 공격 패킷을 보내지 않는다. { bool bAttackable = IsAttackableTarget(pTarget); if(bAttackable) // 공격 가능.. { float fDistance = s_pPlayer->DistanceExceptRadius(pTarget); // 공격거리 CGameProcedure::s_pProcMain->MsgSend_Attack(pTarget->IDNumber(), fIntervalTable, fDistance); if(m_iSkillStep == 0 && PSA_ATTACK != m_eState && m_fFlickeringFactor == 1.0f) // 스킬을 쓰는게 아닌데 공격하지 않으면.. this->Action(PSA_ATTACK, true, pTarget); // 공격 중이아니면 공격한다.. m_fAttackTimeRecent = fTime; // 최근에 공격한 시간.. } else { if(CGameProcedure::s_pEng->ViewPoint() == VP_THIRD_PERSON) { CGameProcedure::s_pPlayer->RotateTo(pTarget); // 방향을 돌린다. float fDist = (pTarget->Position() - m_Chr.Pos()).Magnitude(); // 공격 거리를 구하고.. float fDistLimit = this->AttackableDistance(pTarget); if(fDist > fDistLimit && !m_bTargetOrPosMove) { CGameProcedure::s_pProcMain->CommandMove(MD_FOWARD, true); s_pPlayer->SetMoveTargetID(pTarget->IDNumber()); } } if(m_iSkillStep == 0 && PSA_SITDOWN != m_eState) // 스킬을 쓰는게 아닌데 앉아있는 상태가 아니면.. this->Action(PSA_BASIC, true); // 기본자세.. } } } } if(fTime == m_fAttackTimeRecent) // 공격했으면.. CGameProcedure::s_pProcMain->CommandSitDown(false, false); // 일으켜 세운다.. 앉아있는 상태에서 버그가 있다.. } } if(m_bStun) // 기절해 있으면.. { m_fStunTime -= s_fSecPerFrm; // 기절 시간 처리.. if(m_fStunTime < 0) this->StunRelease(); // 기절 풀어주기.. } if(PSA_ATTACK == m_eState || m_iSkillStep != 0) // 공격 중이거나 스킬 사용중이면.. { if(!pTarget) pTarget = TargetPointerCheck(false); // 타겟 포인터를 얻어온다.. CPlayerBase::ProcessAttack(pTarget); // 공격에 관한 루틴 처리.. 에니메이션 세팅과 충돌만 처리할뿐 패킷은 처리 안한다.. } if(m_dwMagicID != 0xffffffff) m_fCastingTime += CN3Base::s_fSecPerFrm; CPlayerBase::Tick(); // 회전, 지정된 에니메이션 Tick 및 색깔 지정 처리.. 등등.. }
void CN3FXBundleGame::Trigger(int iSourceID, int iTargetID, int iTargetJoint, int iSndID) { m_bRegion = false; CPlayerBase* pTarget = CGameProcedure::s_pProcMain->CharacterGetByID(iTargetID, false); if(!pTarget) return; CPlayerBase* pSource = CGameProcedure::s_pProcMain->CharacterGetByID(iSourceID, true); if(pSource) { if(pSource->m_pShapeExtraRef) { __Vector3 vMin = pSource->m_pShapeExtraRef->Min(); __Vector3 vMax = pSource->m_pShapeExtraRef->Max(); m_vPos = vMin + ((vMax-vMin)*0.5f); } else { const __Matrix44* pMtx = pSource->JointMatrixGet(m_iSourceJoint); if(!pMtx) m_vPos = pSource->Position(); else pSource->JointPosGet(m_iSourceJoint, m_vPos); } m_vDestPos = pSource->Position() + pSource->Direction(); } //CPlayerBase* pTarget = CGameProcedure::s_pProcMain->CharacterGetByID(iTargetID, false); if(pTarget && pTarget!=pSource) { if(m_bDependScale) { //m_vTargetScale.x = m_vTargetScale.z = pTarget->Radius() * 2.0f; //m_vTargetScale.y = pTarget->Height(); float width = pTarget->Radius() * 2.0f; if(width > pTarget->Height()) m_fTargetScale = width; else m_fTargetScale = pTarget->Height(); } if(pTarget->m_pShapeExtraRef) { __Vector3 vMin = pTarget->m_pShapeExtraRef->Min(); __Vector3 vMax = pTarget->m_pShapeExtraRef->Max(); m_vDestPos = vMin + ((vMax-vMin)*0.5f); } else { __Vector3 vMin = pTarget->Min(); __Vector3 vMax = pTarget->Max(); m_vDestPos = vMin + ((vMax-vMin)*0.5f); //m_vDestPos = pTarget->Position(); if(iTargetJoint==-1) { __Vector3 vMin = pTarget->Min(); __Vector3 vMax = pTarget->Max(); m_vDestPos = vMin + ((vMax-vMin)*0.5f); m_vDestPos.y = vMin.y; //m_vDestPos = pTarget->Position(); } else if(iTargetJoint>-1) { const __Matrix44* pMtx = pTarget->JointMatrixGet(iTargetJoint); if(!pMtx) m_vDestPos = pTarget->Position() + (pTarget->Height()*0.5f); else pTarget->JointPosGet(iTargetJoint, m_vDestPos); } } // m_vDir = pTarget->Direction(); // m_vDir.Normalize(); } m_fDistance = (m_vDestPos - m_vPos).Magnitude(); m_fHeight = m_fDistance/2.0f; m_vDir = m_vDestPos - m_vPos; m_vDir.Normalize(); if(m_bStatic) { Trigger(iSourceID, m_vDestPos, iSndID); return; } CN3FXBundle::Trigger(iSourceID, iTargetID, iTargetJoint, iSndID); }
bool CN3FXBundleGame::Tick() { if(m_dwState==FX_BUNDLE_STATE_DEAD) return false; m_fLife += CN3Base::s_fSecPerFrm; if(m_dwState==FX_BUNDLE_STATE_LIVE) { // if(m_fLife>=m_fLife0) Stop(); if(!m_bRegion) { CPlayerBase* pTarget = CGameProcedure::s_pProcMain->CharacterGetByID(m_iTargetID, false); if(pTarget && pTarget->m_pShapeExtraRef) { __Vector3 vMin = pTarget->m_pShapeExtraRef->Min(); __Vector3 vMax = pTarget->m_pShapeExtraRef->Max(); m_vDestPos = vMin + ((vMax-vMin)*0.5f); } else if(pTarget && m_iTargetJoint==-1) { __Vector3 vMin = pTarget->Min(); __Vector3 vMax = pTarget->Max(); m_vDestPos = vMin + ((vMax-vMin)*0.5f); m_vDestPos.y = vMin.y; //m_vDestPos = pTarget->Position(); } else if(pTarget && m_iTargetJoint>-1) { const __Matrix44* pMtx = pTarget->JointMatrixGet(m_iTargetJoint); if(!pMtx) m_vDestPos = pTarget->Position(); else pTarget->JointPosGet(m_iTargetJoint, m_vDestPos); } } switch(m_iMoveType) { case FX_BUNDLE_MOVE_CURVE_FIXEDTARGET: { m_vPos.x = (m_vDir*CN3Base::s_fSecPerFrm*m_fVelocity).x; m_vPos.z = (m_vDir*CN3Base::s_fSecPerFrm*m_fVelocity).z; float fAng; if(m_fDistance!=0.0f) fAng = __PI * (m_fDistance - (m_vDestPos - m_vPos).Magnitude()) / m_fDistance; else fAng = 0.0f; m_vPos.y = sin(fAng) * m_fHeight; break; } case FX_BUNDLE_MOVE_DIR_SLOW: case FX_BUNDLE_MOVE_DIR_FIXEDTARGET: { m_vPos += m_vDir*CN3Base::s_fSecPerFrm*m_fVelocity; break; } case FX_BUNDLE_MOVE_DIR_FLEXABLETARGET_RATIO: { CPlayerBase* pTarget = CGameProcedure::s_pProcMain->CharacterGetByID(m_iTargetID, false); if(!pTarget) { m_vPos += m_vDir*CN3Base::s_fSecPerFrm*m_fVelocity; break; } else { /* m_vDestPos = pTarget->Position(); const __Matrix44* pMtx = pTarget->JointMatrixGet(m_iTargetJoint); if(pMtx) pTarget->JointPosGet(m_iTargetJoint, m_vDestPos); __Vector3 vDestDir = m_vDestPos - m_vPos; vDestDir.Normalize(); __Quaternion qtRot; __Vector3 vDirAxis; float fDirAng; vDirAxis.Cross(m_vDir, vDestDir); int tmp; tmp = vDirAxis.x*10000.0f; vDirAxis.x = (float)(tmp)/10000.0f; tmp = vDirAxis.y*10000.0f; vDirAxis.y = (float)(tmp)/10000.0f; tmp = vDirAxis.z*10000.0f; vDirAxis.z = (float)(tmp)/10000.0f; if(vDirAxis.x==0.0f && vDirAxis.y==0.0f && vDirAxis.z==0.0f) vDirAxis.Set(0,1,0); fDirAng = acos((double)m_vDir.Dot(vDestDir)); if(fDirAng > __PI*s_fSecPerFrm) fDirAng = __PI*s_fSecPerFrm; else if(fDirAng < -__PI*s_fSecPerFrm) fDirAng = -__PI*s_fSecPerFrm; qtRot.RotationAxis(vDirAxis, fDirAng); __Matrix44 mtxRot = qtRot; m_vDir *= mtxRot; m_vPos += m_vDir*CN3Base::s_fSecPerFrm*m_fVelocity; float fTerrainY = s_pTerrain->GetHeight(m_vPos.x, m_vPos.z); if(m_vPos.y <= fTerrainY) m_vPos.y = fTerrainY + 0.3f; //땅을 타고 날라가라.. break; */ } //break; } case FX_BUNDLE_MOVE_DIR_FLEXABLETARGET: { CPlayerBase* pTarget = CGameProcedure::s_pProcMain->CharacterGetByID(m_iTargetID, false); if(!pTarget) { m_vPos += m_vDir*CN3Base::s_fSecPerFrm*m_fVelocity; break; } if(pTarget && pTarget->m_pShapeExtraRef) { __Vector3 vMin = pTarget->m_pShapeExtraRef->Min(); __Vector3 vMax = pTarget->m_pShapeExtraRef->Max(); m_vDestPos = vMin + ((vMax-vMin)*0.5f); } else { m_vDestPos = pTarget->Position(); const __Matrix44* pMtx = pTarget->JointMatrixGet(m_iTargetJoint); if(!pMtx) m_vDestPos = pTarget->Position(); else pTarget->JointPosGet(m_iTargetJoint, m_vDestPos); } m_vDir = m_vDestPos - m_vPos; m_vDir.Normalize(); m_vPos += m_vDir*CN3Base::s_fSecPerFrm*m_fVelocity; //float fTerrainY = s_pTerrain->GetHeight(m_vPos.x, m_vPos.z); //if(m_vPos.y <= fTerrainY) m_vPos.y = fTerrainY + 0.3f; //땅을 타고 날라가라.. break; } case FX_BUNDLE_MOVE_NONE: { //m_vDir.Set(0,0,1); m_vDir.y = 0.0f; m_vDir.Normalize(); m_vPos = m_vDestPos; if(m_iSourceID==m_iTargetID) { CPlayerBase* pSource = CGameProcedure::s_pProcMain->CharacterGetByID(m_iSourceID, false); if(pSource) { m_vDir = pSource->Direction(); m_vDir.y = 0.0f; m_vDir.Normalize(); } } break; } case FX_BUNDLE_REGION_POISON: { CN3Camera* pCamera = CGameProcedure::s_pEng->CameraGetActive(); // 활성화된 카메라 얻기.. __Vector3 vEyePos = pCamera->EyePos(); __Vector3 vEyeAt = pCamera->AtPos(); __Vector3 vEyeDir = vEyeAt - vEyePos; vEyeDir.Normalize(); m_vDir = vEyeDir; m_vPos = vEyePos + vEyeDir*CN3Base::s_CameraData.fNP*3; break; } } } if(m_dwState==FX_BUNDLE_STATE_DYING || m_dwState==FX_BUNDLE_STATE_LIVE) { if(CheckAllPartsDead() || (m_fLife0 !=0.0f && m_fLife > m_fLife0) ) { m_dwState = FX_BUNDLE_STATE_DEAD; Init(); return false; } } for(int i=0;i<MAX_FX_PART;i++) { if(m_pPart[i] && m_pPart[i]->pPart) { if(m_pPart[i]->fStartTime <= m_fLife && m_pPart[i]->pPart->m_dwState==FX_PART_STATE_READY) { m_pPart[i]->pPart->Start(); } m_pPart[i]->pPart->Tick(); } } return true; }