#include "StdAfx.h" #include "Character.h" #include "SceneManager.h" #include "ObjectManager.h" #include "PlayerInputMgr.h" #include "Effect/EffectManager.h" #include "Utils/ClientUtils.h" #include "AudioInterface.h" #include "Avatar.h" #include "Skill/SkillManager.h" #include "ResourceManager.h" #include "State/StateIdle.h" #include "State/StateMove.h" #include "State/StateMoutMove.h" #include "State/StateAttack.h" #include "ItemManager.h" #include "Effect/WaterEffect.h" #include "Effect/NumberFont.h" #include "PathFinder.h" #include "ClientApp.h" #include "Effect/DecalManager.h" #include "Skill/SpellProcess.h" #include "Aura.h" #include "Console.h" #include "Utils/Soundid.h" #include "ui/UISystem.h" #include "ui/UIItemSystem.h" #include "ui/UIShowPlayer.h" #include "ui/UIGamePlay.h" #include "ui/UIIndex.h" #include "Network/PacketBuilder.h" #include "ui/SocialitySystem.h" #include "NetWork/NetworkManager.h" //聊天显示时间 #define MAX_CHAT_TIME (2.5f) #define MAX_BUBBF_TIME (1.5f) #define MAX_STEP (0.5f) #define MIN_WALK_NORMAL (0.7f) #define GRAVITY (NiPoint3(0.f, 0.f, -12.f)) #define MAX_ITERATIONS 4 #define SCALE_EXTENT (0.01f) #define SCALE_RATE (0.1f) static const NiPoint3 extent(EXTENT); IStateProxy* CCharacter::sm_StateProxys[STATE_MAX]; IStateProxy* CCharacter::GetStateInstance(State eState) { return GetStateProxy(eState); } // 不同的类别相同状态的代理可能不一样. IStateProxy* CCharacter::GetStateProxy(State StateID) { switch(StateID) { case STATE_IDLE: return StateIdle::Instance(); case STATE_ACTIONIDLE: return StateActionIdle::Instance(); case STATE_MOVE: return StateMove::Instance(); case STATE_MOUNT_IDLE: return StateMountMove::Instance(); case STATE_DEATH: return StateDeath::Instance(); case STATE_NORMAL_ATTACK: return StateAttack::Instance(); default: break; } return NULL; } //IStateProxy* CCharacter::GetCurStateProxy() //{ // NIASSERT( GetCurState() < STATE_MAX); // static BOOL ClassStateInited = FALSE; // if (!ClassStateInited) // { // for (UINT i = STATE_UNKNOWN ; i < STATE_MAX; i++) // { // CCharacter::sm_StateProxys[i] = GetStateProxy((State)i); // } // ClassStateInited = TRUE; // } // return CCharacter::sm_StateProxys[GetCurState()]; //} BOOL CCharacter::IsStateActorActive() { // 如果状态角色没有激活,则不再进行状态更新. //if (IsDead()) //{ // return FALSE; //} // sth??? return TRUE; } CCharacter::CCharacter(void) { m_bIsDead = false; m_PathFinder = NULL; m_TargetObjectID = 0; m_MoveState = CMS_RUN; m_AttackAnimEnded = FALSE; m_fChatTime = 0.f; m_NextPoint = NiPoint3::ZERO; m_eWaterLevel = WL_NONE; m_uiLastWaterEffect = 0; m_bPathMove = false; m_pStateData = NULL; m_bForceFly = false; // character physics param // { m_kInitVel = NiPoint3(0.0f, 0.0f, 0.0f); m_kInternelVel = m_kInitVel; m_ePhysics = PHYS_Walking; m_LastOrient = NiPoint3(0.0f, 0.0f, 0.0f); m_LastPoint = NiPoint3(0.0f, 0.0f, 0.0f); // } // jump param // { m_iJumpState = EJS_NONE; m_fWaterLine = 1.5f; m_speedScale = 1.f; m_fGravityScale = 1.f; m_ptGravity = GRAVITY; // } m_pkMoveSeq = 0; m_bIsWait = false; m_bInWater = false; m_fWaterHeight = -NI_INFINITY; m_fWaitAnimTime = 0.0f; memset(&m_stMoveInfo, 0, sizeof(MovementInfo)); m_bRebuild = false; m_iDelay = 0; m_uiPathMoveFlag = 0; m_bStopAttack = true; m_pAttackInst[0] = 0; m_pAttackInst[1] = 0; m_bAttackPrepare = false; m_iAttackUpdate = 0; m_bIsInWorld = false; m_fAccSpeed = 0.0f; m_bEnablePhys = false; m_SelState = false; m_UnitFlag = 0; m_iSpecialState = -1; m_uiArenaMapID = 0; m_strMoutSitAction = "sit01"; m_pkMountCreature = NULL; m_pkMountFoot = NULL; m_pkMountHead = NULL; for (unsigned int ui = 0; ui < MAX_AURAS; ui++) m_pkAura[ui] = 0; m_fDesirdAngle = 0.0f; m_fFaceingAngle = 0.f; m_fTurnAccSpeed = 0.0f; m_spVoice[0] = 0; m_spVoice[1] = 0; m_fModleScale = 0.f; m_scaleTime = 0.f; laststormstate = false; mbIsTargetTarget = false; m_bFlying = false; m_bPhyFly = true; m_spAttackEffect = NULL; m_bneedUpdateSwimAni = false; m_spNameRef = NULL; m_bNeedDoAnim = false; m_stTelePortPara.ReSet(); m_fbackStrikeSpeed = 10.f; m_bisStrikeBack = false; m_bisForcePull = false; m_fUsedTime = 0.f; m_fLmtTime = 0.3f; m_iStrickBackCount = 0; m_bisStuned = false; m_bisSYMount = false; m_kCamera = NiPoint3::ZERO; } CCharacter::~CCharacter(void) { if (m_pStateData) { NiDelete m_pStateData; m_pStateData = NULL; } for (unsigned int ui = 0; ui < 2; ui++) { if (m_pAttackInst[ui]) { delete m_pAttackInst[ui]; m_pAttackInst[ui] = NULL; } } for (unsigned int ui = 0; ui < MAX_AURAS; ui++) { delete m_pkAura[ui]; m_pkAura[ui] = 0; } if(m_spAttackEffect) { EffectMgr->DeleteCComboAttackEffect(this->GetGUID()); NiDelete m_spAttackEffect; m_spAttackEffect = NULL; } if(m_pkMountFoot) { m_pkMountFoot->m_pkMountHead = NULL; m_pkMountFoot = NULL; } if(m_pkMountHead) { m_pkMountHead->m_pkMountFoot = NULL; m_pkMountHead = NULL; } if(m_pkMountCreature) { NiDelete m_pkMountCreature; m_pkMountCreature = NULL; } m_spVoice[1] = 0; m_spVoice[0] = 0; } void CCharacter::OnCreate(ByteBuffer* data, ui8 update_flags) { CGameObject::OnCreate(data, update_flags); m_pAttackInst[0] = NiNew NormalAttackInstance(this); m_pAttackInst[1] = NiNew SpellInstance(this); for (unsigned int ui = 0; ui < MAX_AURAS; ui++) { m_pkAura[ui] = NiNew AuraEffect; if (m_pkAura[ui]) m_pkAura[ui]->SetOwner(this); } ui32 entryid = GetUInt32Value(OBJECT_FIELD_ENTRY); CCreatureNameDB::stCNDB cndb; ItemMgr->GetCreatureTitleName(entryid, m_titleName); if (ItemMgr->GetCNDB(entryid, cndb)) { SoundDB::soundfile sf; g_pkSoundFiles->GetSoundFile(cndb.sound_run, sf); if ( sf.filename.length() ) { m_strRunSound = "sound/char/" + sf.filename + ".wav"; } } //ItemMgr->GetCreatureName(entryid, m_titleName); SetDesiredAngle(m_positionO, true); m_spVoice[0] = NiNew ALAudioSource(AudioSource::TYPE_3D); m_spVoice[1] = NiNew ALAudioSource(AudioSource::TYPE_3D); if (m_spVoice[0]) { m_spVoice[0]->SetMinMaxDistance(5.0f, 60.0f); m_spVoice[0]->SetGain(1.0f); } m_spAttackEffect = NiNew CComboAttackEffect; if(m_spAttackEffect && m_spAttackEffect->Initialise()) m_spAttackEffect->SetOwner(this); m_spNameRef = new sNameRecode; m_spNameRef->stName.bShowMask = true; m_spNameRef->stName.bGM = false; } void CCharacter::PostOnCreate() { CGameObject::PostOnCreate(); } void CCharacter::UpdateMountMode() { float fTime = SYState()->ClientApp->GetAccumTime(); if(IsMountCreature()) { m_pkMountCreature->UpdateTransformbyChar(this); NiPoint3 kPos; NiNode* pkPetNode = m_pkMountCreature->GetPetNode(); if(pkPetNode == NULL) return; kPos = pkPetNode->GetWorldTranslate(); NiAVObject* pkAVObject = GetSceneNode()->GetObjectByName("Bip01"); if(pkAVObject == NULL) return; NiPoint3 distance = pkAVObject->GetTranslate(); kPos -= pkAVObject->GetTranslate()*GetFloatValue(OBJECT_FIELD_SCALE_X); GetSceneNode()->SetTranslate(kPos); } else if(IsMountByPlayer()) { GetSceneNode()->Update(0.0f, false); m_pkMountHead->UpdateTransformbyChar(this); NiPoint3 kPos; NiNode* pkPetNode = GetPetNode(); if(pkPetNode == NULL) return; kPos = pkPetNode->GetWorldTranslate(); if(m_pkMountHead->GetSceneNode() == NULL) return; NiAVObject* pkAVObject = m_pkMountHead->GetSceneNode()->GetObjectByName("Bip01"); if(pkAVObject == NULL) return; kPos -= pkAVObject->GetTranslate()*GetFloatValue(OBJECT_FIELD_SCALE_X); m_pkMountHead->GetSceneNode()->SetTranslate(kPos); //UpdateAnimObj(0.0f); m_pkMountHead->UpdateAnimObj(0.0f); } else if(IsMountPlayer()) { UpdateTransformbyChar(m_pkMountFoot); NiPoint3 kPos; NiNode* pkPetNode = m_pkMountFoot->GetPetNode(); if(pkPetNode == NULL) return; kPos = pkPetNode->GetWorldTranslate(); NiAVObject* pkAVObject = GetSceneNode()->GetObjectByName("Bip01"); if(pkAVObject == NULL) return; kPos -= pkAVObject->GetTranslate()*m_pkMountFoot->GetFloatValue(OBJECT_FIELD_SCALE_X); GetSceneNode()->SetTranslate(kPos); UpdateAnimObj(0.0f); } } void CCharacter::Update(float dt) { float fTime = SYState()->ClientApp->GetAccumTime(); DWORD dwTime = float2int32(fTime * 1000.0f); UpdateCharacterLOD(); SYStateActorBase::UpdateState(fTime, dt); if (IsInWorld()) UpdatePhysics(dt); if(m_bAUpdate) { UpdateSpecialState(dt); PendingUpdate(); } if (!IsMountPlayer() || this == ObjectMgr->GetLocalPlayer()) { UpdateAnimObj(dt); } if(m_spAttackEffect && m_spAttackEffect->IsNeedUpdate()) m_spAttackEffect->UpdateEffect(fTime, dt); /*if( fabs( m_fWaterLine - 1.5f ) < 0.0001f ) {*/ /*NiAVObject* pkObj = NULL; pkObj= GetSceneNode()->GetObjectByName("Dummy02"); if( pkObj ) { NiPoint3 niptChest = pkObj->GetTranslate(); m_fWaterLine = fabs(niptChest.z - 0.6); }*/ //} UpdateEvents(); UpdateChatText(dt); UpdateDamages(dt); CheckInWater(); UpdataAura(dt); /*int bPlaying = 0; std::vector::iterator itSpell; for ( itSpell = m_vPlayingSpell.begin(); itSpell != m_vPlayingSpell.end(); ++itSpell ) { SpellInstance* pPlayingSpell = *itSpell; if ( pPlayingSpell ) { if ( pPlayingSpell->Update( dt )) { pPlayingSpell->Reset(); NiDelete pPlayingSpell; *itSpell = NULL; } else { bPlaying++; } } } if ( !bPlaying && ( m_vPlayingSpell.size() > 0 ) ) { m_vPlayingSpell.clear(); }*/ } void CCharacter::UpdateAnimObj(float dt) { CAnimObject::Update(dt); CGameObject::Update(dt); } void CCharacter::UpdatePhysics(float fDelta) { } void CCharacter::UpdateEvents() { if ( IsActorLoaded() ) { const NiTObjectArray& aTextkeys = GetTextKeys(); for (unsigned int ui = 0; ui < aTextkeys.GetSize(); ui++) { const NiFixedString& kStr = aTextkeys.GetAt(ui); if ( kStr.Equals("leftfoot") || kStr.Equals("rightfoot") ) { std::string strFileName; char filepath[64]; switch ( m_eWaterLevel ) { case WL_NONE: strFileName = "footstep.wav"; break; case WL_STANDING_WATER: strFileName = "FootStepsInWater.wav"; break; } if ( !m_spVoice[1] ) { m_spVoice[1] = NiNew ALAudioSource(AudioSource::TYPE_3D); } GetSceneNode()->AttachChild(m_spVoice[1]); m_spVoice[1]->SetMinMaxDistance(5.0f, 50.0f); m_spVoice[1]->SetGain(1.f); /* if ( GetGameObjectType() == GOT_CREATURE ) { if ( m_strRunSound.length() ) { sprintf( filepath, "%s", m_strRunSound.c_str() ); } else continue; } else*/ sprintf( filepath, "Sound/%s", strFileName.c_str() ); const char* pOldname = m_spVoice[1]->GetFilename(); if ( pOldname && !strcmp( pOldname, filepath)) { m_spVoice[1]->Play(); } else SYState()->IAudio->PlaySound(m_spVoice[1], filepath); } if ( kStr.Equals("bossdragon _leftfront") || kStr.Equals("bossdragon _rightfront") ) { std::string strFileName; char filepath[64]; strFileName = "FootstepsBoss.wav"; if ( !m_spVoice[1] ) { m_spVoice[1] = NiNew ALAudioSource(AudioSource::TYPE_3D); } GetSceneNode()->AttachChild(m_spVoice[1]); m_spVoice[1]->SetMinMaxDistance(5.0f, 100.0f); m_spVoice[1]->SetGain(3.f); sprintf( filepath, "Sound/%s", strFileName.c_str() ); const char* pOldname = m_spVoice[1]->GetFilename(); if ( pOldname && !strcmp( pOldname, filepath)) { m_spVoice[1]->Play(); } else SYState()->IAudio->PlaySound(m_spVoice[1], filepath); ObjectMgr->GetLocalPlayer()->GetCamera().Shaking( 0.2, 0.3, 0.2 ); } /*if (kStr.Equals("rightfoot")) { GetSceneNode()->AttachChild(m_spVoice[1]); m_spVoice[1]->SetMinMaxDistance(5.0f, 50.0f); m_spVoice[1]->SetGain(1.f); SYState()->IAudio->PlaySound(m_spVoice[1], "Sound/footstep.wav"); }*/ } } } void CCharacter::UpdateSpecialState(float dt) { float fFacing = GetFacing(); //float fMoveAngle = GetDesiredAngle(); float fMoveAngle = 0.f; if ( ( isMount() || IsJumping() ) && IsMoving() && !( GetMovementFlags()&MOVEFLAG_MOVE_BACKWARD ) ) { fMoveAngle = GetDesiredAngle(); } /*else if ( GetMovementFlags()&MOVEFLAG_MOVE_FORWARD ) { fMoveAngle = GetFacingAngle(); if ( GetMovementFlags()&MOVEFLAG_STRAFE_LEFT ) { fMoveAngle += NI_PI/4; } if ( GetMovementFlags()&MOVEFLAG_STRAFE_RIGHT ) { fMoveAngle -= NI_PI/4; } }*/ else { fMoveAngle = GetFacingAngle(); } while (fFacing > NI_TWO_PI) fFacing -= NI_TWO_PI; while (fFacing < 0) fFacing += NI_TWO_PI; while (fMoveAngle > NI_TWO_PI) fMoveAngle -= NI_TWO_PI; while (fMoveAngle < 0) fMoveAngle += NI_TWO_PI; if (fabs(fFacing - fMoveAngle)>0.001 /* && !( GetMovementFlags()&MOVEFLAG_MOVE_BACKWARD ) */) { float fFromAngle = fFacing; float fToAngle = fMoveAngle; float fLeftTurn, fRightTurn; fLeftTurn = fFromAngle - fToAngle; if (fLeftTurn < 0) { fLeftTurn = NI_TWO_PI + fLeftTurn; } fRightTurn = NI_TWO_PI - fLeftTurn; m_fTurnAccSpeed += dt * 1.33f; float fDelta = NI_TWO_PI * dt + m_fTurnAccSpeed; float fNewAngle = fFromAngle; if (fLeftTurn < fRightTurn) { if (fLeftTurn < fDelta) { fNewAngle = fToAngle; m_fTurnAccSpeed = 0.0f; } else { fNewAngle = fFromAngle - fDelta; } } else { if (fRightTurn < fDelta) { fNewAngle = fToAngle; m_fTurnAccSpeed = 0.0f; } else { fNewAngle = fFromAngle + fDelta; } } while (fNewAngle > NI_TWO_PI) fNewAngle -= NI_TWO_PI; while (fNewAngle < 0) fNewAngle += NI_TWO_PI; SetFacing(fNewAngle); } } void CCharacter::UpdateDamages(float fTime) { if (m_DamageResults.empty()) { return; } std::vector::iterator it = m_DamageResults.begin(); while (it != m_DamageResults.end()) { DamageResult& Damage = *it; ProcessDamage(Damage); Damage.Time += fTime; if ( Damage.TotalTime >= 0.0f && Damage.Time >= Damage.TotalTime) { it = m_DamageResults.erase(it); }else { ++it; } } } void CCharacter::ProcessDamage(const DamageResult& Result) { if (Result.SpellId != INVALID_SPELL_ID) { SpellTemplate* pSpellTemplate = SYState()->SkillMgr->GetSpellTemplate(Result.SpellId); if (pSpellTemplate) { // 当前不传入攻击者ID. //pSpellTemplate->Damage(NULL, this); } } } void CCharacter::UpdateChatText(float dt) { if( m_fChatTime > 0.f ) { m_fChatTime -= dt/**2*/; } } void CCharacter::SetChatText(const std::string& strText) { m_strChatText = strText; m_fChatTime = MAX_CHAT_TIME; } void CCharacter::SetWorldTransform(const NiPoint3& kPos, const NiPoint3& kDir) { SetRotate(kDir); SetPosition(kPos); } void CCharacter::SetDirectionTo(const NiPoint3& Target) { NiPoint3 kDir( Target ); kDir -= GetPosition(); kDir.Unitize(); float fZ = NiATan2(-kDir.y, kDir.x) - NI_PI/2; if( fZ < 0.f ) fZ += NI_TWO_PI; if( fZ > NI_TWO_PI ) fZ -= NI_TWO_PI; if( GetFacingAngle() != fZ ) SetDesiredAngle(fZ); } BOOL CCharacter::MoveTo(const NiPoint3& Target, UINT Flag, bool findpath /*= true*/) { if (!m_bPathMove && GetCurPostureState() == STATE_MOVE) return FALSE; // 这里不要做寻路 //if (findpath) //{ // // Test // if(!m_PathFinder) // m_PathFinder = new CPathFinder; // //m_PathFinder->GeneratePath((int)GetPosition().x, (int)GetPosition().y, (int)Target.x, (int)Target.y); // m_PathFinder->GeneratePathWP((int)GetPosition().x, (int)GetPosition().y, (int)GetPosition().z, (int)Target.x, (int)Target.y, (int)Target.z); // m_MoveDestPos = m_PathFinder->GetNextPathPoint(); //} //else { m_MoveDestPos = Target; NiPoint3 ptDir = Target - GetPosition(); m_LastOrient = ptDir; m_LastOrient.Unitize(); } /*if( GetCurPostureState() != STATE_MOVE ) SetNextState(STATE_MOVE, CUR_TIME);*/ if (isMount() && GetCurPostureState() != STATE_MOUNT_MOVE) { SetNextState(STATE_MOUNT_MOVE, CUR_TIME); if (IsMountCreature()) { GetMountCreature()->SetNextState(STATE_MOUNT_MOVE, CUR_TIME); } } else if( !isMount() && GetCurPostureState() != STATE_MOVE) { SetNextState(STATE_MOVE, CUR_TIME); } //StartForward(); //PathMoveStart(m_MoveDestPos, Flag); return TRUE; } void CCharacter::Teleport(NiPoint3& transPos, float fOrientation) { /*if( IsLocalPlayer() ) { MSG_C2S::stMove_Teleport_Ack stTeleAck; stTeleAck.guid = GetGUID(); NetworkMgr->SendPacket(stTeleAck); }*/ StopMove(); SetNextState(STATE_IDLE, CUR_TIME); //transPos.z = CMap::Get()->GetHeight(transPos.x, transPos.y); m_stTelePortPara.bTelePort = true; m_stTelePortPara.ptTelePos.x = transPos.x; m_stTelePortPara.ptTelePos.y = transPos.y; m_stTelePortPara.ptTelePos.z = transPos.z; m_stTelePortPara.fTeleAngle = fOrientation; //float h = CMap::Get()->GetHeight(transPos.x, transPos.y); //if( h > transPos.z ) // transPos.z = h; //SetPosition(transPos); //SetRotate(NiPoint3(0, 0, fOrientation)); //SetDesiredAngle( fOrientation ); } void CCharacter::ToNewWorld() { } void CCharacter::StopMove() { if( m_bisStrikeBack && !IsDead() ) return; if ( m_bisStrikeBack && IsDead() ) { if( m_bisStrikeBack && IsLocalPlayer() ) { if ( m_iStrickBackCount < 0 ) { m_iStrickBackCount = 0; } while ( m_iStrickBackCount ) { SYState()->LocalPlayerInput->UnlockInput(); m_iStrickBackCount--; } ((CPlayerLocal*)this)->m_bAutoRun = false; } m_bisStrikeBack = false; } // 间接递归, baisc test:Character::IsPathMove if (IsPathMove()) { PathMoveEnd(); } /*if ( GetMovementFlags() & MOVEFLAG_MOVE_BACKWARD ) { float fangle = GetDesiredAngle(); SetDesiredAngle( fangle + NI_PI ); }*/ StopVertical(); StopHorizontal(); } float CCharacter::GetMoveSpeed() const { if ( m_bisStrikeBack ) { return m_fbackStrikeSpeed; } if( GetMoveState() == CMS_RUN || GetMoveState() == CMS_STORM || GetMoveState() == CMS_MOUNTRUN) { if ( GetMovementFlags() & MOVEFLAG_MOVE_BACKWARD ) { return m_backWalkSpeed*m_speedScale; } return m_runSpeed*m_speedScale; } else if (GetMoveState() == CMS_RUSH) { return m_rushSpeed; } return m_walkSpeed; } void CCharacter::PathMoveStart(const NiPoint3& pos, UINT uiFlag) { m_MoveDestPos = pos; m_bPathMove = true; m_kPathMoveDir = m_MoveDestPos - GetPosition(); m_kPathMoveDir.Unitize(); m_kPathMoveDir.z = 0.0f; float fZ = NiATan2(-m_kPathMoveDir.y, m_kPathMoveDir.x) - NI_PI/2; while( fZ < 0.f ) fZ += NI_TWO_PI; while( fZ > NI_TWO_PI ) fZ -= NI_TWO_PI; if( GetDesiredAngle() != fZ ) { SetDesiredAngle(fZ); } m_uiPathMoveFlag = uiFlag; } void CCharacter::PathMoveEnd() { m_bPathMove = false; m_kPathMoveDir = NiPoint3::ZERO; m_uiPathMoveFlag = 0; if(m_PathFinder) { m_PathFinder->ClearPathPoint(); } } void CCharacter::PathMoveUpdate(float fTimeDelta) { if( m_bPathMove ) { NiPoint3 kNewVec = GetPosition() - m_MoveDestPos; kNewVec.z = 0; kNewVec.Unitize(); NiPoint3 kOldVec = -m_kPathMoveDir; if (kOldVec.Dot(kNewVec) <= 0.0f) { if ( m_PathFinder) { if ( m_PathFinder->IsPathPointEmpty() ) { PathMoveEnd(); return; } m_MoveDestPos = m_PathFinder->GetNextPathPoint(); PathMoveStart(m_MoveDestPos, m_uiPathMoveFlag); SetDirectionTo(m_MoveDestPos); } else { NiPoint3 cp = this->GetPosition(); NiPoint3 s, e; float tarz; s = NiPoint3(cp.x, cp.y, cp.z + 5.0f); e = NiPoint3(cp.x, cp.y, cp.z - 5.0f); ResultList collList; if (CMap::Get()->MultiCollideBox(s, e, NiPoint3(0.1f, 0.1f, 0.1f), collList)) tarz = s.z + (e.z-s.z)*collList[0].fTime; //tarz = s.z * collList[0].fTime + e.z * (1 - collList[0].fTime); cp.z = tarz; SetPosition(cp); PathMoveEnd(); } } } } void CCharacter::UpdateDirection(float fTimeDelta) { NiPoint3 kDir = GetRotate(); kDir.z += m_kMove.yaw*fTimeDelta; while( kDir.z > float(NI_PI*2) ) kDir.z -= float(NI_PI*2); while( kDir.z < 0.f ) kDir.z += float(NI_PI*2); SetRotate(kDir); } void CCharacter::BeginAttack(SYObjID dwTargetObjectID) { m_targetList.Clear(); m_targetList.AddEntry(dwTargetObjectID); if (GetCurActionState() != STATE_NORMAL_ATTACK && GetCurActionState() != STATE_SKILL_ATTACK) { NormalAttackInstance* pkNAI = (NormalAttackInstance*)GetAttackInst(0); if (pkNAI && !pkNAI->IsSpellAttack()) { pkNAI->BeginAttack(m_targetList); } ForceStateChange(STATE_NORMAL_ATTACK, CUR_TIME); } m_bStopAttack = false; } void CCharacter::AttackUpdate(const ui64& victim_guid) { m_targetList.Clear(); m_targetList.AddEntry(victim_guid); if (GetCurActionState() != STATE_NORMAL_ATTACK && GetCurActionState() != STATE_SKILL_ATTACK) { ForceStateChange(STATE_NORMAL_ATTACK, CUR_TIME); NormalAttackInstance* pkNAI = (NormalAttackInstance*)GetAttackInst(0); if (pkNAI && !pkNAI->IsSpellAttack()) { pkNAI->SetBow(); pkNAI->BeginAttack(m_targetList); } } m_iAttackUpdate++; } void CCharacter::EndAttack() { m_bStopAttack = true; } bool CCharacter::IsSpellCast(SpellID spellID) { return m_pAttackInst[1]->IsSpellCast(spellID); } void CCharacter::SpellCast(SpellID spellID, ui32 castTime, const SpellCastTargets& spellCastTarget) { if (castTime < 0) return; SpellTemplate* Template = SYState()->SkillMgr->GetSpellTemplate(spellID); if (Template == NULL) { return; } m_pAttackInst[1]->BeginCast(spellID, castTime, spellCastTarget); } void CCharacter::SpellDelay(ui32 uiDelay) { m_pAttackInst[1]->CastDelay(uiDelay); } void CCharacter::TunnelDelay(ui32 uiDelay) { m_pAttackInst[1]->TunnelDelay(uiDelay); } void CCharacter::SpellGo(SpellID spellID, const vector& vTargetHit, const SpellCastTargets& sepllCastTarget) { m_pAttackInst[1]->BeginMagic(spellID, vTargetHit, sepllCastTarget); /*SpellInstance* pIns = m_pAttackInst[1]; m_vPlayingSpell.push_back( pIns ); m_pAttackInst[1] = NULL; m_pAttackInst[1] = NiNew SpellInstance(this);*/ } void CCharacter::SpellTunnel(SpellID spellID, float castTime ) { m_pAttackInst[1]->BeginTunnel(spellID, castTime ); } void CCharacter::EndTunnel() { m_pAttackInst[1]->EndTunnel(); } void CCharacter::SpellFailure(uint32 spellid, uint8 uiErrorCode) { std::string strMediaName; bool bInterRupted = false; switch (uiErrorCode) { case SPELL_FAILED_LINE_OF_SIGHT: { if ( IsLocalPlayer()) { strMediaName = "Sound/SpellError/SpellErrorLineOfSight.wav"; } bInterRupted = true; } break; case SPELL_FAILED_UNIT_NOT_INFRONT: { if ( IsLocalPlayer()) { strMediaName = "Sound/SpellError/SpellErrorNotInFront.ogg"; } bInterRupted = true; } break; case SPELL_FAILED_OUT_OF_RANGE: case SPELL_FAILED_MOVING: case SPELL_FAILED_INTERRUPTED: case SPELL_FAILED_INTERRUPTED_COMBAT: case SPELL_FAILED_TARGETS_DEAD: case SPELL_FAILED_STUNNED: case SPELL_FAILED_NO_POWER: case SPELL_FAILED_SILENCED: case SPELL_FAILED_ROOTED: case SPELL_FAILED_FLEEING: case SPELL_FAILED_CASTER_DEAD: case SPELL_FAILED_TOO_CLOSE: case SPELL_FAILED_PACIFIED: case SPELL_FAILED_FIZZLE: case SPELL_FAILED_TOO_NEAR: case SPELL_FAILED_NOT_INFRONT: case SPELL_FAILED_NOT_SHAPESHIFT: case SPELL_FAILED_ONLY_MOUNTED: case SPELL_FAILED_TARGET_FRIENDLY: case SPELL_FAILED_TARGET_NOT_DEAD: case SPELL_FAILED_BAD_TARGETS: case SPELL_FAILED_NOT_BEHIND: case SPELL_FAILED_NOT_MOUNTED: case SPELL_FAILED_TARGET_ENEMY: case SPELL_FAILED_NOT_ON_MOUNTED: case SPELL_FAILED_CANTUSE_IN_SHAPESHIFT: case SPELL_FAILED_CANTUSE_IN_MOUNT: case SPELL_FAILED_CANTUSE_IN_COMBAT: case SPELL_FAILED_LOWLEVEL: { bInterRupted = true; } break; case SPELL_FAILED_NOT_READY: case SPELL_FAILED_SPELL_IN_PROGRESS: break; } if ( bInterRupted ) { m_pAttackInst[1]->SpellFailure(spellid, uiErrorCode); } if ( strMediaName.length() > 0 ) { SYState()->IAudio->PlayUiSound(strMediaName.c_str(), NiPoint3::ZERO, 1.5f, 1 ); } } void CCharacter::SpellDamage() { } void CCharacter::AddTarget(SYObjID id) { m_targetList.AddEntry(id); } void CCharacter::AddTarget(const NiPoint3& kPos, float fRadius) { m_targetList.AddEntry(kPos, fRadius); } #define OVERCLIP 1.1f void ClipPlane( const NiPoint3& in, const NiPoint3& normal, NiPoint3& out) { float backoff = in.Dot(normal); if( backoff < 0.f ) { backoff *= OVERCLIP; } else { backoff *= (1 / OVERCLIP); } out = in - backoff*normal; } const char* GetPhysStateDesc(EPhysics ePhysState) { switch (ePhysState) { case PHYS_None: return "PHYS_None"; case PHYS_Walking: return "PHYS_Walking"; case PHYS_Falling: return "PHYS_Falling"; case PHYS_Swimming: return "PHYS_Swimming"; case PHYS_Flying: return "PHYS_Flying"; case PHYS_Rotating: return "PHYS_Rotating"; case PHYS_Projectile: return "PHYS_Projectile"; case PHYS_Interpolating: return "PHYS_Interpolating"; case PHYS_MovingBrush: return "PHYS_MovingBrush"; case PHYS_Spider: return "PHYS_Spider"; case PHYS_Trailer: return "PHYS_Trailer"; case PHYS_Ladder: return "PHYS_Ladder"; case PHYS_RootMotion: return "PHYS_RootMotion"; } return "error"; } static EPhysics ePhysState = PHYS_None; void CCharacter::BeginCharPhys() { } void CCharacter::EndCharPhys() { if (this == ObjectMgr->GetLocalPlayer()) { if (ePhysState != m_ePhysics) { ePhysState = m_ePhysics; } } } float CCharacter::GetZInitVelocity() const { return 11.f; } bool CCharacter::CalcMoveVelocity(NiPoint3& vVelocity, float fOrient, bool bUpVel /*= false*/) { NiMatrix3 kRotate; kRotate.MakeZRotation(fOrient); return CalcMoveVelocity(vVelocity, bUpVel, &kRotate); } bool CCharacter::CalcMoveVelocity(NiPoint3& vVelocity, bool bUpVel /*= false*/, NiMatrix3* pkRotMat/*=0*/) { if (this->GetMovementFlags() == MOVEFLAG_MOVE_STOP) return false; if (!(this->GetMovementFlags() & (MOVEFLAG_MOVING_MASK | MOVEFLAG_TURNING_MASK | MOVEFLAG_STRAFING_MASK)) && this->GetMovementFlags() & MOVEFLAG_JUMPING) { vVelocity = NiPoint3(0, 0, GetZInitVelocity()); return true; } if (!pkRotMat) { float fSn, fCs; NiSinCos(GetDesiredAngle(), fSn, fCs); vVelocity = NiPoint3(-fSn, -fCs, 0); if ( m_ePhysics == PHYS_Flying || m_ePhysics == PHYS_Swimming ) { if ( m_kCamera.Length() != 0 && GetMoveState() != CMS_RUSH ) { m_kCamera.Unitize(); NiPoint3 Orient( m_kCamera.x, m_kCamera.y, 0 ); float vlength = Orient.Length(); if ( vlength ) { if ( m_kCamera.z != 0.f ) { vVelocity.z = NiSqr(1.f - vlength*vlength)*(m_kCamera.z/NiAbs(m_kCamera.z)); } } else { vVelocity.z = m_kCamera.z; } if ( vVelocity.z > 1.f ) { vVelocity.z = 1.f; } if ( vVelocity.z < - 1.f ) { vVelocity.z = - 1.f; } //vVelocity = m_kCamera; /*float ftan = 0.f; float zoff = 0.f; float offsetx = fSn; float offsety = fCs; float camex = fabs( m_kCamera.x ); float camey = fabs( m_kCamera.y ); if( camex ) { ftan = m_kCamera.z / camex; zoff = ftan * fabs( offsetx ); } else if( camey ) { ftan = m_kCamera.z / camey; zoff = ftan * fabs( offsety ); } else if ( ( !camey ) && ( !camex ) ) { vVelocity.x = 0; vVelocity.y = 0; if ( m_kCamera.z > 0 ) { zoff = 0.2f; } if ( m_kCamera.z < 0 ) { zoff = -0.2f; } ftan = 1.f; } if ( ftan > 0 || ftan < -0.4f) { vVelocity.z = zoff; if ( vVelocity.z > 1.0f ) { vVelocity.z = 1.0f; } if ( vVelocity.z < -1.0f ) { vVelocity.z = -1.0f; } } if ( m_fzupDistans ) { vVelocity.x = 0; vVelocity.y = 0; }*/ } else { /*NiPoint3 Orient( m_LastOrient.x, m_LastOrient.y, 0 ); float vlength = Orient.Length(); if ( vlength ) { if ( m_LastOrient.z != 0.f ) { vVelocity.z = NiSqr(1.f - vlength*vlength)*(m_LastOrient.z/NiAbs(m_LastOrient.z)); } } else { vVelocity.z = m_LastOrient.z; }*/ vVelocity = m_LastOrient; if ( vVelocity.z > 1.f ) { vVelocity.z = 1.f; } if ( vVelocity.z < - 1.f ) { vVelocity.z = - 1.f; } } } } else { pkRotMat->GetCol(1, vVelocity); vVelocity = -vVelocity; } vVelocity.x *= (GetMoveSpeed() + m_fAccSpeed*m_speedScale); vVelocity.y *= (GetMoveSpeed() + m_fAccSpeed*m_speedScale); vVelocity.z *= (GetMoveSpeed() + m_fAccSpeed*m_speedScale); if (GetMovementFlags() & MOVEFLAG_JUMPING) { if ( m_bisStrikeBack) { vVelocity.z = 3.f; } else vVelocity.z = GetZInitVelocity(); } if ( GetMovementFlags() & MOVEFLAG_PITCH_UP ) { if( !( GetMovementFlags() & MOVEFLAG_MOVING_MASK ) &&!( GetMovementFlags() & MOVEFLAG_STRAFING_MASK )) { vVelocity.x = 0.f; vVelocity.y = 0.f; } vVelocity.z = 25.0f; } if ( GetMovementFlags() & MOVEFLAG_PITCH_DOWN ) { if( !( GetMovementFlags() & MOVEFLAG_MOVING_MASK )&&!( GetMovementFlags() & MOVEFLAG_STRAFING_MASK ) ) { vVelocity.x = 0.f; vVelocity.y = 0.f; } vVelocity.z = 4.0f; } return true; } void CCharacter::PerformPhysics(float fTimeDelta) { BeginCharPhys(); StartNewPhysics(fTimeDelta, 0); EndCharPhys(); } void CCharacter::UpdatePullMove( float dt ) { NiPoint3 ptCur = GetPosition(); if ( m_fUsedTime >= m_fLmtTime ) { SetPosition( m_ptPullTargrt ); } else { NiPoint3 ptNext = ptCur + ( m_ptPullTargrt - ptCur)*dt/( m_fLmtTime - m_fUsedTime ); SetPosition( ptNext ); m_fUsedTime += dt; } NiPoint3 ptOffset = ( ptCur - m_ptPullTargrt ); float dis = ptOffset.Length(); if ( dis <= 0.0001 ) { m_bisForcePull = false; m_fUsedTime = 0.f; m_ptPullTargrt = GetPosition(); } } bool CCharacter::UpdateMoveTransform(float fTime, float fTimeDelta, float& fT) { NiPoint3 ptNewPos; float newOrient = this->GetFacing(); float fRetRatio = 0.0f; NiPoint3 ptCurPos = m_kPosition;//this->GetPosition(); NiPoint3 ptDesiredPos = NiPoint3(m_stMoveInfo.x, m_stMoveInfo.y, m_stMoveInfo.z); NiPoint3 transDir = ptDesiredPos - ptCurPos; float fLen = transDir.Unitize(); float fFrameMoveLength = fTimeDelta * GetMoveSpeed(); NIASSERT(fFrameMoveLength >= 0.0f); if ( fLen <= fFrameMoveLength) { SetPosition(ptDesiredPos); fT = fRetRatio; return true; } ptNewPos = ptCurPos + transDir * fFrameMoveLength; newOrient = m_stMoveInfo.orientation; fRetRatio = fFrameMoveLength/fLen; fT = fRetRatio; this->SetPosition(ptNewPos); this->SetDesiredAngle(newOrient); return false; } void CCharacter::StartNewPhysics(float fTimeDelta, int iIterations) { if( fTimeDelta < 0.0003f ) return; CMap* pkMap = CMap::Get(); if( !pkMap || !pkMap->IsLoaded() ) return; m_speedScale = 1.f; switch(m_ePhysics) { case PHYS_Walking: { PhysWalking(fTimeDelta, iIterations); break; } case PHYS_Falling: PhysFalling(fTimeDelta, iIterations); break; case PHYS_Swimming: { PhysSwimming(fTimeDelta, iIterations); break; } case PHYS_Flying: { PhysFlying(fTimeDelta, iIterations); break; } } } void CCharacter::SetPhysics(EPhysics ePhys) { if ( m_ePhysics != ePhys && m_ePhysics == PHYS_Swimming ) { EndSwimming(); } if ( (m_ePhysics == PHYS_Falling) && (ePhys == PHYS_Walking) ) { if ( m_kInternelVel.z < -24.f ) { if ( IsLocalPlayer() ) { PacketBuilder->SendFallSpeed( -m_kInternelVel.z ); } CSceneEffect* pEffect = (CSceneEffect*)EffectMgr->CreateSceneEffect( "Effect_joy_100730.nif",true, true, false, 1 ); if ( isMount() ) { pEffect->SetEffScale(0.5f); } else pEffect->SetEffScale(0.3f); //NiPoint3 ptEffect( MsgRecv.x, MsgRecv.y, MsgRecv.z); pEffect->AttachToScene( GetPosition() ); std::string filepath; if ( !m_spVoice[0] ) { m_spVoice[0] = NiNew ALAudioSource(AudioSource::TYPE_3D); } GetSceneNode()->AttachChild(m_spVoice[0]); m_spVoice[0]->SetMinMaxDistance(5.0f, 60.0f); m_spVoice[0]->SetGain(1.f); if (GetGender() ) { filepath = "Sound/MaleFall.wav"; } else { filepath = "Sound/FemaleFall.wav"; } const char* pOldname = m_spVoice[0]->GetFilename(); if ( pOldname && !strcmp( pOldname, filepath.c_str())) { m_spVoice[0]->Play(); } else SYState()->IAudio->PlaySound(m_spVoice[0], filepath.c_str()); /* GetSceneNode()->AttachChild(m_spVoice[0]); m_spVoice[0]->SetMinMaxDistance(5.0f, 50.0f); m_spVoice[0]->SetGain(1.f); if (GetGender() ) { SYState()->IAudio->PlaySound(m_spVoice[0], "Sound/MaleFall.wav"); } else SYState()->IAudio->PlaySound(m_spVoice[0], "Sound/FemaleFall.wav");*/ } } m_ePhysics = ePhys; switch(m_ePhysics) { case PHYS_Walking: { } break; case PHYS_Swimming: { StartSwimming(); } break; case PHYS_Falling: { } break; case PHYS_Flying: { } break; } } EWaterLevel CCharacter::CheckInWater() { NiPoint3 ptCurPos = this->GetPosition(); CMap* pkMap = CMap::Get(); if(pkMap == NULL) return WL_NONE; m_bInWater = pkMap->GetWaterHeight(ptCurPos.x, ptCurPos.y, m_fWaterHeight); if (m_bInWater) { if( m_fWaterHeight < ptCurPos.z ) { m_eWaterLevel = WL_NONE; } else if( m_fWaterHeight < ptCurPos.z + m_fWaterLine*m_fModleScale ) { m_eWaterLevel = WL_STANDING_WATER; } else { //处于游泳状态 m_eWaterLevel = WL_UNDER_WATER; } } else { m_eWaterLevel = WL_NONE; } return m_eWaterLevel; } #define SWIMMING_BUOYANCY 0.6f float CCharacter::GetBuoyancy() const { return 1.0f; } void CCharacter::PhysFlying(float fTimeDelta, int iIterations) { CMap* pkMap = CMap::Get(); m_kInternelVel = NiPoint3::ZERO; bool bret = CalcMoveVelocity(m_kInternelVel); // reset NiPoint3 kOldLocation = m_kPosition; NiPoint3 start = kOldLocation; float fTimeRemaining = fTimeDelta; // NiPoint3 kDesireMove = m_kInternelVel; NiPoint3 kDesireDir = m_kInternelVel; kDesireDir.Unitize(); NiPoint3 delta; Result result; while( fTimeRemaining > 0.f && iIterations < MAX_ITERATIONS ) { if ( !IsFlying() ) { SetPhysics( PHYS_Walking ); StartNewPhysics(fTimeRemaining, iIterations); return; } ++iIterations; float fTimeTick = (fTimeRemaining > 0.05f) ? NiMin(0.05f, fTimeRemaining * 0.5f) : fTimeRemaining; fTimeRemaining -= fTimeTick; delta = fTimeTick * m_kInternelVel; if( NiAbs(delta.x) < 0.0001 && NiAbs(delta.y) < 0.0001 && NiAbs(delta.z) < 0.0001 ) { fTimeRemaining = 0.f; } else { /*NiPoint3 zDelta( 0.f,0.f, 1.f ); Result zResult; pkMap->MoveObject(start, zDelta, extent, zResult); if( result.fTime < 1.f ) { if ( IsLocalPlayer()) { SetPhyFly(false); SetPhysics(PHYS_Walking); StartNewPhysics(fTimeRemaining, iIterations); return; } }*/ pkMap->MoveObject(start, delta, extent, result); if( result.fTime < 1.f ) { // collision horizon if (result.pkCollObject == 0) { StepUp(start, kDesireDir, delta * (1.f - result.fTime), result); if ( IsLocalPlayer()) { SetPhyFly(false); SetPhysics(PHYS_Walking); StartNewPhysics(fTimeRemaining, iIterations); } } //SetPhyFly(false); } } //drop to floor /*NiPoint3 down(0.f, 0.f, 0.f ); pkMap->MoveObject(start, down, extent, result);*/ } start = CheckMoveable(kOldLocation, start, false); //start.z -= extent.z; if ( start.z > 750 ) { start.z = 750; } SetPosition(start); m_kInternelVel = (start - kOldLocation)/fTimeDelta; } void CCharacter::PhysSwimming(float fTimeDelta, int iIterations) { //NiPoint3 kOldLocation = m_kPosition;//GetPosition(); //NiPoint3 start = kOldLocation; //float fRemaining = fTimeDelta; //fRemaining -= fTimeDelta; //SetPosition(start); //if (fRemaining > 0.0f) //{ // float fBuoyancy = GetBuoyancy(); // if ( fBuoyancy < SWIMMING_BUOYANCY) // { // SetPhysics(PHYS_Falling); // StartNewPhysics(fRemaining, iIterations); // } //} CMap* pkMap = CMap::Get(); m_kInternelVel = NiPoint3::ZERO; bool bret = CalcMoveVelocity(m_kInternelVel); // reset NiPoint3 kOldLocation = m_kPosition; NiPoint3 start = kOldLocation; float fTimeRemaining = fTimeDelta; // NiPoint3 kDesireMove = m_kInternelVel; NiPoint3 kDesireDir = m_kInternelVel; kDesireDir.Unitize(); NiPoint3 delta; Result result; while( fTimeRemaining > 0.f && iIterations < MAX_ITERATIONS ) { ++iIterations; float fTimeTick = (fTimeRemaining > 0.05f) ? NiMin(0.05f, fTimeRemaining * 0.5f) : fTimeRemaining; fTimeRemaining -= fTimeTick; float scale = 1.0f; if( GetMoveState() != CMS_RUSH ) { scale = 0.5f; } delta = fTimeTick * m_kInternelVel * scale; if( NiAbs(delta.x) < 0.0001 && NiAbs(delta.y) < 0.0001 && NiAbs(delta.z) < 0.0001 ) { fTimeRemaining = 0.f; } else { pkMap->MoveObject(start, delta, extent, result); if( result.fTime < 1.f ) { // collision horizon if (result.pkCollObject != 0) { } StepUp(start, kDesireDir, delta * (1.f - result.fTime), result); } } //drop to floor /*NiPoint3 down(0.f, 0.f, 0.f ); pkMap->MoveObject(start, down, extent, result);*/ if( result.fTime > 1.f ) { start = CheckMoveable(kOldLocation, start, false); //start.z -= extent.z; SetPosition(start); m_kInternelVel = (start - kOldLocation)/fTimeDelta; m_kInternelVel.z = 0.f; SetPhysics(PHYS_Falling); StartNewPhysics(fTimeRemaining, iIterations); return; } else { if ( CheckInWater() != EWaterLevel::WL_UNDER_WATER ) { /* start = CheckMoveable(kOldLocation, start, false); start.z -= extent.z; SetPosition(start); m_kInternelVel = (start - kOldLocation)/fTimeDelta;*/ if ( CheckInWater() != EWaterLevel::WL_UNDER_WATER ) { SetPhysics( PHYS_Walking ); StartNewPhysics(fTimeRemaining, iIterations); return; } } } } //float ftan = 0.f; //float zoff = 0.f; //float offsetx = start.x - kOldLocation.x; //float offsety = start.y - kOldLocation.y; //float camex = fabs( m_kCamera.x ); //float camey = fabs( m_kCamera.y ); //if( camex ) //{ // ftan = m_kCamera.z / camex; // zoff = ftan * fabs( offsetx ); //} //else if( camey ) //{ // ftan = m_kCamera.z / camey; // zoff = ftan * fabs( offsety ); //} //else if ( ( !camey ) && ( !camex ) ) //{ // zoff = 0.2f; //} //if ( zoff > 0.2f ) //{ // zoff = 0.2f; //} //if ( zoff < -0.2f ) //{ // zoff = -0.2f; //} //if ( fabs( ftan ) > 0.8f ) //{ // start.z += zoff; //} NiPoint3 vLanding = CheckMoveable(kOldLocation, start, false); if ( vLanding.z == start.z ) { start = vLanding; if ( m_kCamera.z < -0.0001f ) { float ang = NiACos( fabs(m_kCamera.z) / m_kCamera.Length()); if( ang > NI_PI/3.f && ang < NI_PI/2.f && !( GetMovementFlags()&MOVEFLAG_PITCH_DOWN ) ) { start.z = kOldLocation.z; } } if ( m_fWaterHeight - start.z < m_fWaterLine*m_fModleScale ) { start.z = m_fWaterHeight - m_fWaterLine*m_fModleScale; } } else { start = vLanding; } //start.z -= extent.z; if ( start.z - kOldLocation.z > 0.4 ) { start.z = kOldLocation.z + 0.4; } SetPosition(start); m_kInternelVel = (start - kOldLocation)/fTimeDelta; } void CCharacter::StepUp(NiPoint3& start, const NiPoint3& kDesireDir, NiPoint3 delta, Result& result) { CMap* pkMap = CMap::Get(); NiPoint3 down(0.f, 0.f, -MAX_STEP); if ( IsFlying() || (CheckInWater() == WL_UNDER_WATER) ) { down.z = 0.f; } if( NiAbs( result.kNormal.z ) < MIN_WALK_NORMAL ) { NiPoint3 oldstart = start; Result oldResult = result; // step up - treat as vertical wall start.z += MAX_STEP; pkMap->MoveObject(start, delta, extent, result); if(result.fTime > 0.f) { pkMap->MoveObject(start, down, extent, result); if( result.fTime < 1.f && NiAbs( result.kNormal.z ) < MIN_WALK_NORMAL ) { start = oldstart; result = oldResult; } } else { start = oldstart; result = oldResult; } } else if( result.kNormal.z >= MIN_WALK_NORMAL ) { // walkable slope - slide up it float dist = delta.Length()*1.3f; //需要保持xy平面方向不变 pkMap->MoveObject(start, delta + NiPoint3(0.f, 0.f, dist*result.kNormal.z), extent, result); if( result.fTime < 1.f && NiAbs( result.kNormal.z ) < MIN_WALK_NORMAL ) { NiPoint3 oldstart = start; Result oldresult = result; start.z += MAX_STEP; pkMap->MoveObject(start, delta, extent, result); pkMap->MoveObject(start, down, extent, result); if( result.fTime < 1.f && NiAbs( result.kNormal.z ) < MIN_WALK_NORMAL ) { start = oldstart; result = oldresult; } } } NiPoint3 n1, n2, n3, n4; if( result.fTime < 1.f ) { n1 = result.kNormal; //adjust and try again result.kNormal.z = 0.f; // treat barrier as vertical; result.kNormal.Unitize(); NiPoint3 kOriginalDelta = delta; NiPoint3 kOriginalNormal = result.kNormal; ClipPlane(delta, result.kNormal, delta); delta *= (1.f - result.fTime); if( delta.Dot(kOriginalDelta) >= 0.f ) { pkMap->MoveObject(start, delta, extent, result); n2 = result.kNormal; if( result.fTime < 1.f ) { //two wall adjust if( kOriginalNormal.Dot(result.kNormal) <= 0.f ) //90 or less corner, so use cross product for dir { NiPoint3 newDir = result.kNormal.UnitCross(kOriginalNormal); delta = delta.Dot(newDir) * newDir * (1.f - result.fTime); if( kDesireDir.Dot(delta) < 0.f ) delta = -delta; } else //adjust to new wall { ClipPlane(delta, result.kNormal, delta); delta *= (1.f - result.fTime); if( kDesireDir.Dot(delta) < 0.f ) delta = NiPoint3(0.f, 0.f, 0.f); } pkMap->MoveObject(start, delta, extent, result); } } } } //Walking, copy from unreal2 void CCharacter::PhysWalking(float fTimeDelta, int iIterations) { CMap* pkMap = CMap::Get(); m_kInternelVel = NiPoint3::ZERO; m_speedScale = 1.f; if ( CheckInWater() == WL_STANDING_WATER && ( GetMoveState() != CMS_RUSH ) ) { NiPoint3 ptCurPos = this->GetPosition(); m_speedScale = NiAbs( 0.7f * ( m_fWaterLine*m_fModleScale- ( m_fWaterHeight - ptCurPos.z ))/(m_fWaterLine*m_fModleScale) + 0.3f ); } bool bret = CalcMoveVelocity(m_kInternelVel); // reset NiPoint3 kOldLocation = m_kPosition; kOldLocation.z += extent.z; NiPoint3 start = kOldLocation; float fTimeRemaining = fTimeDelta; // NiPoint3 kDesireMove = m_kInternelVel; NiPoint3 kDesireDir = m_kInternelVel; kDesireDir.Unitize(); NiPoint3 delta; Result result; while( fTimeRemaining > 0.f && iIterations < MAX_ITERATIONS ) { if ( IsFlying() ) { SetPhysics(PHYS_Flying ); StartNewPhysics(fTimeRemaining, iIterations); return; } ++iIterations; float fTimeTick = (fTimeRemaining > 0.05f) ? NiMin(0.05f, fTimeRemaining * 0.5f) : fTimeRemaining; fTimeRemaining -= fTimeTick; delta = fTimeTick * m_kInternelVel; if( NiAbs(delta.x) < 0.0001 && NiAbs(delta.y) < 0.0001 && NiAbs(delta.z) < 0.0001 ) { fTimeRemaining = 0.f; } else { pkMap->MoveObject(start, delta, extent, result); if( result.fTime < 1.f ) { // collision horizon if (result.pkCollObject != 0) { } StepUp(start, kDesireDir, delta * (1.f - result.fTime), result); } } //drop to floor NiPoint3 down(0.f, 0.f, -MAX_STEP); pkMap->MoveObject(start, down, extent, result); if( result.fTime < 1.f ) { if( result.kNormal.z < MIN_WALK_NORMAL ) { // slide down slope NiPoint3 slide(0.f, 0.f, -MAX_STEP*0.2f); ClipPlane(slide, result.kNormal, slide); pkMap->MoveObject(start, slide, extent, result); } if ( CheckInWater() == WL_UNDER_WATER ) { start = CheckMoveable(kOldLocation, start, false); start.z = m_fWaterHeight - m_fWaterLine*m_fModleScale; SetPosition(start); m_kInternelVel = (start - kOldLocation)/fTimeDelta; SetPhysics(PHYS_Swimming ); StartNewPhysics(fTimeRemaining, iIterations); return; } } else { start = CheckMoveable(kOldLocation, start, false); start.z -= extent.z; SetPosition(start); m_kInternelVel = (start - kOldLocation)/fTimeDelta; m_kInternelVel.z = 0.f; SetPhysics(PHYS_Falling); StartNewPhysics(fTimeRemaining, iIterations); /*if ( !isMount() ) { ForceStateChange( STATE_FALLING, CUR_TIME ); }*/ return; } //if ( m_NextPoint != NiPoint3::ZERO ) //{ // if (!IsFlying() || (CheckInWater() != WL_UNDER_WATER)) // { // m_NextPoint.z = start.z; // } // NiPoint3 ptoff = m_NextPoint - start; // bool bEnd = false; // if ( ptoff.Length() < 0.0001f ) // { // bEnd = true; // } // else // { // ptoff.Unitize(); // ptoff.z = 0.0f; // float fZ = NiATan2(-ptoff.y, ptoff.x) - NI_PI/2; // while( fZ < 0.f ) // fZ += NI_TWO_PI; // while( fZ > NI_TWO_PI ) // fZ -= NI_TWO_PI; // if((fabs(fZ - GetDesiredAngle()) > 0.001f )) // bEnd = true; // } // if ( bEnd ) // { // break; // } //} } start = CheckMoveable(kOldLocation, start, false); start.z -= extent.z; SetPosition(start); m_kInternelVel = (start - kOldLocation)/fTimeDelta; } NiPoint3 CCharacter::NewFallVelocity(const NiPoint3& kVelocity, const NiPoint3& kAcceleration, float fTimeTick) const { return kVelocity + fTimeTick * kAcceleration * 2.f; } //Falling, copy from unreal2 void CCharacter::PhysFalling(float fTimeDelta, int iIterations) { CMap* pkMap = CMap::Get(); float fTimeRemaining = fTimeDelta; NiPoint3 start = m_kPosition; start.z += extent.z; NiPoint3 kOldLocation; NiPoint3 kAdjusted; Result result; if(m_kInternelVel.z < -100.f) { kAdjusted = m_kInternelVel*fTimeDelta; pkMap->MoveObject(start, kAdjusted, extent, result); if(result.fTime == 0.f) { SetPhysics(PHYS_Walking); start = CheckMoveable(m_kPosition, start, true); start.z -= extent.z; SetPosition(start); return; } } while( fTimeRemaining > 0.f && iIterations < MAX_ITERATIONS ) { if ( CheckInWater() == WL_UNDER_WATER ) { if ( IsJumping() ) { EndJump(); } SetPhysics(PHYS_Swimming ); StartNewPhysics(fTimeRemaining, iIterations); start.z = m_fWaterHeight - m_fWaterLine*m_fModleScale; SetPosition( start ); return; } if ( IsFlying() ) { SetPhysics(PHYS_Flying ); StartNewPhysics(fTimeRemaining, iIterations); return; } iIterations++; float fTimeTick = (fTimeRemaining > 0.05f) ? NiMin(0.05f, fTimeRemaining * 0.5f) : fTimeRemaining; fTimeRemaining -= fTimeTick; m_kInternelVel = NewFallVelocity(m_kInternelVel, m_ptGravity*m_fGravityScale, fTimeTick); kAdjusted = m_kInternelVel*fTimeTick; kOldLocation = start; pkMap->MoveObject(start, kAdjusted, extent, result); if( result.fTime < 1.f ) { bool bCanSwim = false; if (bCanSwim) { // 进水了 float fBuoyancy = GetBuoyancy(); if ( fBuoyancy >= SWIMMING_BUOYANCY) { SetPhysics(PHYS_Swimming); StartNewPhysics(fTimeRemaining, iIterations); SYState()->IAudio->PlaySound( "Sound/EnterWater.wav", NiPoint3::ZERO, 1.f, 1 ); return; } } if( result.kNormal.z >= MIN_WALK_NORMAL || (result.fTime - 0.f) < 0.001f ) { fTimeRemaining = fTimeTick * (1.f - result.fTime); //if( result.fTime > 0.1f && result.fTime * fTimeTick > 0.003f ) // m_kInternelVel = (start - kOldLocation)/(result.fTime * fTimeTick); SetPhysics(PHYS_Walking); start = CheckMoveable(m_kPosition, start, true); start.z -= extent.z; SetPosition(start); StartNewPhysics(fTimeRemaining, iIterations); return; } else { NiPoint3 kOldNormal = result.kNormal; NiPoint3 delta; ClipPlane(kAdjusted, result.kNormal, delta); delta *= (1.f - result.fTime); if( delta.Dot(kAdjusted) >= 0.f ) { pkMap->MoveObject(start, delta, extent, result); if( result.fTime < 1.f ) //hit second wall { if( result.kNormal.z >= MIN_WALK_NORMAL ) { SetPhysics(PHYS_Walking); start = CheckMoveable(m_kPosition, start, true); start.z -= extent.z; SetPosition(start); return; } NiPoint3 kDesiredDir = kAdjusted; kDesiredDir.Unitize(); if( kOldNormal.Dot(result.kNormal) <= 0.f ) //90 or less corner, so use cross product for dir { NiPoint3 kNewDir = result.kNormal.UnitCross(kOldNormal); delta = delta.Dot(kNewDir)*(1.f - result.fTime)*kNewDir; if( kDesiredDir.Dot(delta) < 0.f ) delta = -delta; } else { ClipPlane(delta, result.kNormal, delta); delta *= (1.f - result.fTime); if( delta.Dot(kDesiredDir) <= 0.f ) delta = NiPoint3(0.f, 0.f, 0.f); } pkMap->MoveObject(start, delta, extent, result); if(result.kNormal.z >= MIN_WALK_NORMAL ) { SetPhysics(PHYS_Walking); start = CheckMoveable(m_kPosition, start, true); start.z -= extent.z; SetPosition(start); return; } if( result.fTime < 1.f ) { ClipPlane(delta, result.kNormal, delta); delta *= (1.f - result.fTime); pkMap->MoveObject(start, delta, extent, result); if( result.kNormal.z >= MIN_WALK_NORMAL ) { SetPhysics(PHYS_Walking); start = CheckMoveable(m_kPosition, start, true); start.z -= extent.z; SetPosition(start); return; } } } } } } float fOldZ = m_kInternelVel.z; m_kInternelVel = (start - kOldLocation)/fTimeTick; m_kInternelVel.z = fOldZ; } start = CheckMoveable(m_kPosition, start, true); start.z -= extent.z; SetPosition(start); } //检查可移动性 NiPoint3 CCharacter::CheckMoveable(const NiPoint3& kFrom, const NiPoint3& kTo, bool bJump) const { CMap* pkMap = CMap::Get(); NIASSERT(pkMap); NiPoint3 kPos; bool isFly = IsFlying(); if(pkMap->GetGridInfo(kTo.x, kTo.y, isFly )) { kPos = kTo; } else if(!bJump) { kPos = kFrom; } else { NiPoint3 kStart = kFrom; NiPoint3 kEnd = kFrom; kEnd.z = kTo.z; Result kResult; pkMap->MoveObject(kStart, kEnd - kStart, EXTENT, kResult); kPos.x = kFrom.x; kPos.y = kFrom.y; kPos.z = kStart.z; } float h; if(!pkMap->GetHeight(kPos.x, kPos.y, h)) return kFrom; if(kPos.z < h) kPos.z = h; return kPos; } BOOL CCharacter::IsStuned() { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); } BOOL CCharacter::IsIceBlock() { return (GetUInt32Value(UNIT_FIELD_ICE_BLOCK) > 0); } BOOL CCharacter::IsSleep() { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SLEEP); // } BOOL CCharacter::IsRoot() { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_ROOT); //UNIT_FLAG_ROOT } BOOL CCharacter::IsFrozen() { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FROZEN); //UNIT_FLAG_FROZEN } BOOL CCharacter::IsSilenced() { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED); //UNIT_FLAG_SILENCED } BOOL CCharacter::IsConfused() { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); //UNIT_FLAG_CONFUSED } BOOL CCharacter::IsFleeing() { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); //UNIT_FLAG_FLEEING } bool CCharacter::IsFlying() const { if ( (GetMoveState() == CMS_RUSH) && ((m_ePhysics == PHYS_Falling) || (m_ePhysics == PHYS_Flying)) ) { return true; } if ( m_bForceFly ) { return true; } if ( !CMap::Get() ) { return false; } CPlayerInputMgr* inputmgr = SYState()->LocalPlayerInput; if ( inputmgr && inputmgr->IsUseMouseMove() ) { return false; } switch( CMap::Get()->GetMapId() ) { case 10: case 20: case 21: case 24: case 25: case 6: case 53: case 7: break; default: return false; } return ( m_bPhyFly && m_bFlying ); } void CCharacter::EndOfSequence(NiActorManager* pkManager, NiActorManager::SequenceID eSequenceID, float fCurrentTime, float fEventTime) { CAnimObject::EndOfSequence(pkManager, eSequenceID, fCurrentTime, fEventTime); } void CCharacter::UpdateCharacterLOD() { } void CCharacter::SetTargetObjectID(SYObjID dwTargetObjectID) { m_TargetObjectID = dwTargetObjectID; } int CCharacter::RequestDamageID() { return 0; } CCharacter* CCharacter::GetTargetObject() { SYObjID guid = GetTargetObjectID(); return (CCharacter*)ObjectMgr->GetObject(guid); } BOOL CCharacter::CanBeenAttack() { if (GetHP() <= 0 ) { return FALSE; } if (GetCurActionState() == STATE_DEATH) { return FALSE; } return TRUE; } void CCharacter::StopAttack() { ; } bool CCharacter::Draw(CCullingProcess* pkCuller) { if(CAnimObject::Draw(pkCuller)) { NiCamera* pkCamera = pkCuller->GetCamera(); //显示姓名 DrawName(pkCamera); //显示场景聊天 DrawChatText(pkCamera); DrawWaterEffect(); return true; } return false; } bool CCharacter::CanMove() { if (GetCurPostureState() == STATE_DEATH || GetCurPostureState() == STATE_FALLING || GetCurPostureState() == STATE_CONSTRAINT || GetPhsyicState() == PHYS_Falling) return false; if (IsStuned() || IsSleep() || IsFrozen() || IsIceBlock() /*|| IsRoot() || IsFleeing()*/) { // temp StopMove(); return false; } // if( isType(TYPE_PLAYER) && IsFleeing() ) // { // StopMove(); // return false; // } return true; } void CCharacter::SetAccSpeed(float fAccSpeed) { m_fAccSpeed = fAccSpeed; } bool CCharacter::IsHostile(CCharacter* pChar) { CPlayerLocal* pkLocalPlayer = (CPlayerLocal*)ObjectMgr->GetLocalPlayer(); if (pkLocalPlayer->IsInArena()) return true; uint32 ffaA = 0; uint32 ffaB = 0; CCreature* pCreatureA =NULL; CCreature* pCreatureB =NULL; CPlayer* pPlayerA = NULL; CPlayer* pPlayerB =NULL; if (GetGameObjectType() == GOT_CREATURE && !((CCreature*)this)->IsPet()) { pCreatureA = ((CCreature*)this); ffaA = GetUInt32Value(UNIT_FIELD_FFA); } else if (isType(TYPE_PLAYER)) { pPlayerA = ((CPlayer*)this); ffaA = GetUInt32Value(UNIT_FIELD_FFA); } if (pChar->GetGameObjectType() == GOT_CREATURE&& !((CCreature*)pChar)->IsPet()) { pCreatureB = ((CCreature*)pChar); ffaB = pChar->GetUInt32Value(UNIT_FIELD_FFA); } else if (pChar->isType(TYPE_PLAYER)) { pPlayerB = ((CPlayer*)pChar); ffaB = pChar->GetUInt32Value(UNIT_FIELD_FFA); } if ((pChar->isType(TYPE_PLAYER) || (pChar->GetGameObjectType() == GOT_CREATURE&& !((CCreature*)pChar)->IsPet())) && (isType(TYPE_PLAYER) ||(GetGameObjectType() == GOT_CREATURE && !((CCreature*)this)->IsPet()))) { if (ffaA && ffaB) { if (pPlayerA && pPlayerB) { if (ffaA == 1 && ffaB == 1) { uint32 groupid_a = pChar->GetUInt32Value( PLAYER_FIELD_GROUP_ID ); uint32 groupid_b = this->GetUInt32Value( PLAYER_FIELD_GROUP_ID ); if( groupid_a > 0 ) return groupid_a != groupid_b; else return true; } else if (ffaA == 2 || ffaB == 2) { return false; } } if( ((ffaA >10 && ffaA < 14) || (ffaB > 10 && ffaB < 14))) { if (ffaA != ffaB) return true; else return false; } if( ffaA >= 21 && ffaA <= 22 && ffaB >= 21 && ffaB <= 22 ) return ffaA != ffaB; if (ffaA == 11 || ffaB == 11) { return false; } if (pPlayerA && pPlayerB) { if (GetUInt32Value( PLAYER_GUILDID) == pChar->GetUInt32Value( PLAYER_FIELD_HOSTILE_GUILDID)) return true; } } } if (isType(TYPE_PLAYER) && pChar->GetGameObjectType() == GOT_CREATURE) { if (((CCreature*)pChar)->IsPet()) //宠物 { return false ; } ffaA = GetUInt32Value(UNIT_FIELD_FFA); if (ffaA == 11) return false; } else if (GetGameObjectType() == GOT_CREATURE && pChar->isType(TYPE_PLAYER)) { if (((CCreature*)this)->IsPet()) //宠物 { return false ; } } // if (pChar->isType(TYPE_PLAYER) && isType(TYPE_PLAYER)) // { // uint32 ffaA = GetUInt32Value(UNIT_FIELD_FFA); // uint32 ffaB = pChar->GetUInt32Value(UNIT_FIELD_FFA); // if( ffaA == 1 && ffaB == 1 ) // { // uint32 groupid_a = pChar->GetUInt32Value( PLAYER_FIELD_GROUP_ID ); // uint32 groupid_b = this->GetUInt32Value( PLAYER_FIELD_GROUP_ID ); // if( groupid_a > 0 ) // return groupid_a != groupid_b; // else // return true; // } // if( ((ffaA >10 && ffaA < 14) || (ffaB > 10 && ffaB < 14))) // { // if (ffaA != ffaB) // return true; // else // return false; // } // if( ffaA >= 21 && ffaA <= 22 && ffaB >= 21 && ffaB <= 22 ) // return ffaA != ffaB; //} //else //if (isType(TYPE_PLAYER) && pChar->GetGameObjectType() == GOT_CREATURE) //{ // if (((CCreature*)pChar)->IsPet()) //宠物 // { // return false ; // } // uint32 ffaA = GetUInt32Value(UNIT_FIELD_FFA); // if (ffaA == 11) // return false; //} //else //if (GetGameObjectType() == GOT_CREATURE && pChar->isType(TYPE_PLAYER)) //{ // if (((CCreature*)this)->IsPet()) //宠物 // { // return false ; // } // uint32 ffaA = pChar->GetUInt32Value(UNIT_FIELD_FFA); // if (ffaA == 11) // return false; //} //else //if (GetGameObjectType() == GOT_CREATURE && pChar->GetGameObjectType() == GOT_CREATURE && !((CCreature*)pChar)->IsPet() && !((CCreature*)this)->IsPet() ) //{ // uint32 ffaA = GetUInt32Value(UNIT_FIELD_FFA); // uint32 ffaB = pChar->GetUInt32Value(UNIT_FIELD_FFA); // if( ffaA == 1 && ffaB == 1 ) // { // uint32 groupid_a = pChar->GetUInt32Value( PLAYER_FIELD_GROUP_ID ); // uint32 groupid_b = this->GetUInt32Value( PLAYER_FIELD_GROUP_ID ); // if( groupid_a > 0 ) // return groupid_a != groupid_b; // else // return true; // } // if( ((ffaA >10 && ffaA < 14) || (ffaB > 10 && ffaB < 14))) // { // if (ffaA != ffaB) // return true; // else // return false; // } // if( ffaA >= 21 && ffaA <= 22 && ffaB >= 21 && ffaB <= 22 ) // return ffaA != ffaB; //} //if (pChar->GetGameObjectType() == GOT_PLAYER && GetGameObjectType() == GOT_PLAYER && // pChar->GetUInt32Value( PLAYER_GUILDID) != 0 && // GetUInt32Value( PLAYER_GUILDID) != 0) //{ // if (GetUInt32Value( PLAYER_GUILDID) == pChar->GetUInt32Value( PLAYER_FIELD_HOSTILE_GUILDID)) // return true; //} uint32 myfaction = GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE); uint32 hisfaction = pChar->GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE); if( myfaction == hisfaction ) return false; if( hisfaction == 1000 || myfaction == 1000 || hisfaction == 10000 || myfaction == 10000 ) return false; if( hisfaction == 30000 || myfaction == 30000 ) return false; if( myfaction >= 1 && myfaction <= 3 && hisfaction >= 1 && hisfaction <= 3 ) return false; return true; } bool CCharacter::IsFriendly(CCharacter* pChar) { CPlayerLocal* pkLocalPlayer = (CPlayerLocal*)ObjectMgr->GetLocalPlayer(); if (pkLocalPlayer && pkLocalPlayer->IsInArena()) return false; if (this == pChar) return true; //if(IsLocalPlayer() && GetUInt32Value( UNIT_FIELD_FFA)) // return false; //if(pChar->IsLocalPlayer() && pChar->GetUInt32Value( UNIT_FIELD_FFA)) // return false; uint32 myfaction = GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE); uint32 hisfaction = pChar->GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE); if( hisfaction == 30000 || myfaction == 30000 ) return true; CPlayer* pPlayerA = NULL; CPlayer* pPlayerB = NULL; CCreature* pCreatureA = NULL; CCreature* pCreatureB = NULL; uint32 ffaA = 0; uint32 ffaB = 0; if (pChar->isType(TYPE_PLAYER)) { pPlayerB = ((CPlayer*)pChar); ffaB = pChar->GetUInt32Value(UNIT_FIELD_FFA); } else if (pChar->GetGameObjectType() == GOT_CREATURE && !((CCreature*)pChar)->IsPet()) { ffaB = pChar->GetInt32Value(UNIT_FIELD_FFA); pCreatureB = ((CCreature*)pChar); } if (isType(TYPE_PLAYER)) { ffaA = GetInt32Value(UNIT_FIELD_FFA); pPlayerA = ((CPlayer*)this); } else if (GetGameObjectType()== GOT_CREATURE && !((CCreature*)this)->IsPet()) { ffaA = GetInt32Value(UNIT_FIELD_FFA); pCreatureA = ((CCreature*)this); } if (ffaA && ffaB) { if (pPlayerA && pPlayerB) { if (ffaA == 1 && ffaB == 1) { uint32 groupid_a = pPlayerA->GetUInt32Value( PLAYER_FIELD_GROUP_ID ); uint32 groupid_b = pPlayerB->GetUInt32Value( PLAYER_FIELD_GROUP_ID ); if( groupid_a > 0 ) return groupid_a == groupid_b; else return false; } } if (ffaA == 2 || ffaB == 2) return true; if( ((ffaA >10 && ffaA < 14) || (ffaB > 10 && ffaB < 14))) { if (ffaA != ffaB) return false; else return true; } if( ffaA >= 21 && ffaA <= 22 && ffaB >= 21 && ffaB <= 22 ) return ffaA == ffaB; if (pPlayerA && pPlayerB) { uint32 myguid = this->GetUInt32Value(PLAYER_GUILDID); uint32 myhostguid = this->GetUInt32Value(PLAYER_FIELD_HOSTILE_GUILDID); uint32 hisguid = pChar->GetUInt32Value(PLAYER_GUILDID); uint32 hishostguid = pChar->GetUInt32Value(PLAYER_FIELD_HOSTILE_GUILDID); if(myguid && myguid == hishostguid) return false; if(hisguid && hisguid == myhostguid) return false; } } if (isType(TYPE_PLAYER) && pChar->GetGameObjectType() == GOT_CREATURE) { if (((CCreature*)pChar)->IsPet()) //宠物 { return true ; } ffaA = GetUInt32Value(UNIT_FIELD_FFA); if (ffaA == 11 && hisfaction > 3) return true; } else if (GetGameObjectType() == GOT_CREATURE && pChar->isType(TYPE_PLAYER)) { if (((CCreature*)this)->IsPet()) //宠物 { return true ; } ffaA = pChar->GetUInt32Value(UNIT_FIELD_FFA); if (ffaA == 11 && myfaction > 3) return true; } // if (pChar->isType(TYPE_PLAYER) && isType(TYPE_PLAYER)) // { // uint32 ffaA = GetUInt32Value(UNIT_FIELD_FFA); // uint32 ffaB = pChar->GetUInt32Value(UNIT_FIELD_FFA); // //if( ffaA == 1 && ffaB == 1 ) // // return false; // if( ffaA == 1 && ffaB == 1 ) // { // uint32 groupid_a = pChar->GetUInt32Value( PLAYER_FIELD_GROUP_ID ); // uint32 groupid_b = this->GetUInt32Value( PLAYER_FIELD_GROUP_ID ); // if( groupid_a > 0 ) // return groupid_a == groupid_b; // else // return false; // } // if (ffaA == 2 || ffaB == 2) // return true; // if( ((ffaA >10 && ffaA < 14) || (ffaB > 10 && ffaB < 14))) // { // if (ffaA != ffaB) // return false; // else // return true; // } // if( ffaA >= 21 && ffaA <= 22 && ffaB >= 21 && ffaB <= 22 ) // return ffaA == ffaB; // uint32 myguid = this->GetUInt32Value(PLAYER_GUILDID); // uint32 myhostguid = this->GetUInt32Value(PLAYER_FIELD_HOSTILE_GUILDID); // uint32 hisguid = pChar->GetUInt32Value(PLAYER_GUILDID); // uint32 hishostguid = pChar->GetUInt32Value(PLAYER_FIELD_HOSTILE_GUILDID); // if(myguid && myguid == hishostguid) // return false; // if(hisguid && hisguid == myhostguid) // return false; // } //else //if (isType(TYPE_PLAYER) && pChar->GetGameObjectType() == GOT_CREATURE) //{ // if (((CCreature*)pChar)->IsPet()) //宠物 // { // return true ; // } // uint32 ffaA = GetUInt32Value(UNIT_FIELD_FFA); // if (ffaA == 11 && hisfaction > 3) // return true; //} //else //if (GetGameObjectType() == GOT_CREATURE && pChar->isType(TYPE_PLAYER)) //{ // if (((CCreature*)this)->IsPet()) //宠物 // { // return true ; // } // uint32 ffaA = pChar->GetUInt32Value(UNIT_FIELD_FFA); // if (ffaA == 11 && myfaction > 3) // return true; //} //else if (GetGameObjectType() == GOT_CREATURE && pChar->GetGameObjectType() == GOT_CREATURE && !((CCreature*)pChar)->IsPet() && !((CCreature*)this)->IsPet() ) //{ // uint32 ffaA = GetUInt32Value(UNIT_FIELD_FFA); // uint32 ffaB = pChar->GetUInt32Value(UNIT_FIELD_FFA); // if (ffaA == 2 || ffaB == 2) // return true; // if( ((ffaA >10 && ffaA < 14) || (ffaB > 10 && ffaB < 14))) // { // if (ffaA != ffaB) // return false; // else // return true; // } // if( ffaA >= 21 && ffaA <= 22 && ffaB >= 21 && ffaB <= 22 ) // return ffaA == ffaB; //} if( myfaction == hisfaction ) return true; if( hisfaction == 10000 || myfaction == 10000 ) return true; if( hisfaction == 1000 || myfaction == 1000) return false; if( myfaction >= 1 && myfaction <= 3 && hisfaction >= 1 && hisfaction <= 3 ) return true; return false; } bool CCharacter::IsTarget(CCharacter* pChar) { if (!pChar) return false; return pChar->GetGUID() == GetUInt64Value(UNIT_FIELD_TARGET); } void CCharacter::EnterArena(ui32 mapID) { m_uiArenaMapID = mapID; } void CCharacter::LeaveArena() { m_uiArenaMapID = 0; } bool CCharacter::IsInArena() { if (!m_uiArenaMapID) return false; if (CMap::Get()->GetMapId() != m_uiArenaMapID) { return false; } return true; } void GetShowStatic(CCharacter* who, unsigned int* uiColor, bool* IsShowHpBar, float* distance) { CPlayerLocal* pkLocalPlayer = (CPlayerLocal*)ObjectMgr->GetLocalPlayer(); if(pkLocalPlayer == who) *uiColor = D3DCOLOR_ARGB(200, 255, 255, 255); else if(who->IsFriendly(pkLocalPlayer)) *uiColor = D3DCOLOR_ARGB(200, 0, 255, 0); else if(who->IsDead()) *uiColor = D3DCOLOR_ARGB(200, 153, 153, 153); else if( who->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_COMBAT) || ( who->GetGameObjectType() == GOT_CREATURE&&!((CCreature*)who)->IsPet()&&who->GetUInt32Value( UNIT_FIELD_FFA) != 0)) { *uiColor = D3DCOLOR_ARGB(200, 253, 102, 0); *IsShowHpBar = true; } else if(who->IsHostile(pkLocalPlayer)) { *uiColor = D3DCOLOR_ARGB(200, 253, 102, 0); *IsShowHpBar = true; } else *uiColor = D3DCOLOR_ARGB(200, 255, 255, 0); NiPoint3 dist( who->GetPosition() ); dist -= pkLocalPlayer->GetCamera().GetTranslate(); *distance = dist.Length(); } void CCharacter::DrawName(const NiCamera* Camera) { if(!m_spNameRef) return; NiPoint3 kPos( GetSceneNode()->GetTranslate() ); kPos.z += m_kNamePosOffset; WorldPtToUIPt(kPos, Camera); unsigned int uiColor; bool IsShowHPBar = false; float dist = 0.f; GetShowStatic(this, &uiColor, &IsShowHPBar, &dist); m_spNameRef->type = GOT_CREATURE; CharName* NewName = &m_spNameRef->stName; NewName->Class = 0; NewName->ffa = 0; NewName->zodiac = 0; UINT mask = 8; if(SocialitySys && !SocialitySys->GetTeamSysPtr()->GetTargetIcon(&mask, GetGUID(), GetInt32Value(OBJECT_FIELD_UNIQUE_ID))) { mask = 8; } NewName->GroupMask = mask; EffectMgr->AddCharName(m_spNameRef, kPos, GetName(), m_titleName.c_str(), NULL, NULL, uiColor, dist, IsShowHPBar, ObjectMgr->GetLocalPlayer()->GetTargetObjectID() == GetGUID()); #ifdef _DEBUG DrawStateDesc(kPos); #endif // } #ifdef _DEBUG void CCharacter::DrawStateDesc(const NiPoint3& kPos) { char szBuffer[256]; State eMovementState = GetCurPostureState(); State eActionState = GetCurActionState(); IStateProxy* pkMInst = GetStateInstance(eMovementState); IStateProxy* pkAInst = GetStateInstance(eActionState); NIASSERT(pkMInst && pkAInst); sprintf(szBuffer, "%s||%s", pkMInst->GetStateDesc(), pkAInst->GetStateDesc()); EffectMgr->AddSceneText(kPos, szBuffer, D3DCOLOR_ARGB(255, 255, 255, 255)); } #endif // void CCharacter::DrawChatText(const NiCamera* Camera) { if( m_fChatTime > 0.f ) { float addoffset = 0.f; if (m_spNameRef && (m_spNameRef->stName.bShowName || m_spNameRef->stName.ShowHp)) { addoffset = 0.7f; } NiPoint3 pos = GetPosition(); pos.z += m_kNamePosOffset + addoffset; WorldPtToUIPt(pos, Camera); unsigned int uiAlpha = unsigned int((m_fChatTime / MAX_CHAT_TIME)*255.f); EffectMgr->AddChatText(pos, m_strChatText.c_str(), D3DCOLOR_ARGB(uiAlpha, 0, 255, 0)); } } void CCharacter::DrawWaterEffect() { //water effect if( m_eWaterLevel != WL_NONE ) { NiPoint3 pos = GetPosition(); pos.z = m_fWaterHeight; if(GetCurPostureState() == STATE_MOVE) { if(SYState()->CurTime - m_uiLastWaterEffect >= unsigned int(MAX_WAKE_LIFE/6*1000)) { m_uiLastWaterEffect = SYState()->CurTime; CWaterEffect::AddEffect(pos, GetMatrixRotate(), CWaterEffect::ET_WAKE); } } else { if( SYState()->CurTime - m_uiLastWaterEffect >= unsigned int(MAX_SPLASH_LIFE*1000) ) { m_uiLastWaterEffect = SYState()->CurTime; CWaterEffect::AddEffect(pos, GetMatrixRotate(), CWaterEffect::ET_SPLASH); } } } } ////////////////////////////////////////////////////////////////////////// // // 网络消息 // ////////////////////////////////////////////////////////////////////////// void CCharacter::OnDeath(bool bDeadNow) { m_bIsDead = true; GetAttackInst(0)->Reset(); GetAttackInst(1)->Reset(); m_kInternelVel = NiPoint3::ZERO; //SetUInt32Value(UNIT_FIELD_HEALTH, 0); //SetUInt32Value(UNIT_FIELD_POWER1, 0); //ForceStateChange(STATE_ACTIONIDLE, CUR_TIME); ULOG("%s TO BE DEAD Now", GetName()); bool Succes = ForceStateChange(STATE_DEATH, CUR_TIME); if (!Succes) { ULOG("%sTo Be Dead Faild", GetName()); } if(!bDeadNow) { SetCurAnimation("death", 1.0, 0, TRUE); AnimationID AnimID = GetAnimationIDByName("death"); if(AnimID == NiActorManager::INVALID_SEQUENCE_ID) { return; } NiControllerSequence* pkCurSeq = m_spActorManager->GetSequence(m_uiCurrAnimID); float t = pkCurSeq->GetLength(); pkCurSeq->SetBeginKeyTime(t); } else { ALAudioSource* pkSound = GetSoundInst(); if (pkSound){ char soundfile[64]; if (GetGameObjectType() == GOT_CREATURE) { ui32 entryid = GetUInt32Value(OBJECT_FIELD_ENTRY); CCreatureNameDB::stCNDB cndb; if (!ItemMgr->GetCNDB(entryid, cndb)) return; if (cndb.sound_death != 0 /*&& cndb.sound_attack2 != 0*/) { SoundDB::soundfile sf; if ( g_pkSoundFiles->GetSoundFile(cndb.sound_death, sf)) { _snprintf(soundfile, 64, "sound/char/%s.wav", sf.filename.c_str()); GetSceneNode()->AttachChild(pkSound); pkSound->SetMinMaxDistance(1.0f, 60.0f); pkSound->SetGain(1.0f); SYState()->IAudio->PlaySound(pkSound, soundfile); } } } else if (GetAsPlayer()) { std::string soundfiles[3][2] = {"js_death05", "js_death06", "js_death03", "js_death04", "js_death01", "js_death02"}; CPlayer* lp = (CPlayer*)this; uint8 race = lp->GetRace(); uint8 gender = lp->GetGender(); std::string sf = soundfiles[race-1][1-gender]; _snprintf(soundfile, 64, "sound/char/%s.wav", sf.c_str()); GetSceneNode()->AttachChild(pkSound); pkSound->SetMinMaxDistance(1.0f, 60.0f); pkSound->SetGain(2.0f); SYState()->IAudio->PlaySound(pkSound, soundfile); } } } //SetUInt32Value(UNIT_FIELD_HEALTH, 0); /*SetDeathAnimation(); */ } void CCharacter::OnAlive() { m_bIsDead = false; ResetMovementFlags(); // 重置状态 ResetState(); SetPhysics(PHYS_Walking); // SetNextState(STATE_IDLE,CUR_TIME); //ObjectMgr->GetPlayer(); /*if ( GetGameObjectType() == GOT_PLAYER ) { SYState()->IAudio->PlaySound("Sound\\Effect\\relive.wav", GetPosition()); }*/ } void CCharacter::OnActorLoaded(NiActorManager* pkActorManager) { CAnimObject::OnActorLoaded(pkActorManager); if (IsInWorld() && IsDead()) OnDeath(false); for (int index = UNIT_FIELD_AURA ; index <= UNIT_FIELD_AURA_55 ; index++) { if(GetUInt32Value(index)) { ui32 localid = m_AuraInfo[index - UNIT_FIELD_AURA].SpellId; ui32 spellid = GetUInt32Value(index); if(spellid){ uint32 cdtspell,cdtinscrease; if(g_pkSpellInfo->GetSpellCDTIncrease(spellid, cdtspell, cdtinscrease)){ m_increasespellcdt[cdtspell] = cdtinscrease; } }else{ m_increasespellcdt.erase(spellid); } BOOL bUpdateMask = (spellid != 0)?TRUE:FALSE; if (bUpdateMask){ m_pkAura[index - UNIT_FIELD_AURA]->Start(spellid); }else{ if (localid != 0){ m_pkAura[index - UNIT_FIELD_AURA]->Over(); m_AuraInfo[index - UNIT_FIELD_AURA].AuraTime = 0.0f; } } } } /*for (int index = UNIT_FIELD_AURA ; index <= UNIT_FIELD_AURA_55 ; index++) { if(GetUInt32Value(index)) { ui32 localid = m_AuraInfo[index - UNIT_FIELD_AURA].SpellId; ui32 spellid = GetUInt32Value(index); if(spellid){ uint32 cdtspell,cdtinscrease; if(g_pkSpellInfo->GetSpellCDTIncrease(spellid, cdtspell, cdtinscrease)){ m_increasespellcdt[cdtspell] = cdtinscrease; } }else{ m_increasespellcdt.erase(spellid); } BOOL bUpdateMask = (spellid != 0)?TRUE:FALSE; if (bUpdateMask){ m_pkAura[index - UNIT_FIELD_AURA]->Start(spellid); }else{ if (localid != 0){ m_pkAura[index - UNIT_FIELD_AURA]->Over(); m_AuraInfo[index - UNIT_FIELD_AURA].AuraTime = 0.0f; } } } }*/ } void CCharacter::BubbleUpEffectNumber( int Number, int affectType /*= 0*/,ui32 SubType /*= 0*/, const WCHAR* extraOutput /*= NULL*/ , ui32 SubType2) { NiColorA color; static NiColorA sBubColors[BUBBLE_MAX] = { NiColorA(1.0f, 1.0f, 1.0f, 1.0f), NiColorA(1.0f, 1.0f, 0.0f, 1.0f), NiColorA(0.0f, 1.0f, 0.0f, 1.0f), NiColorA(0.0f, 0.0f, 1.0f, 1.0f), NiColorA(0.0f, 1.0f, 0.0f, 1.0f), NiColorA(1.0f, 1.0f, 0.0f, 1.0f), NiColorA(1.0f, 1.0f, 0.0f, 1.0f) }; color = sBubColors[affectType]; if (affectType == BUBBLE_HEADTEXT) { if (SubType == 0) { color = NiColorA(1.f, 211.f / 255.f, 3.f / 255.f, 1.f); }else { color = NiColorA(0.f, 1.f, 0.f, 1.f); } } affectType = affectType % BUBBLE_MAX; EffectMgr->BubbleUpEffectNumber(m_spAttackEffect, affectType, SubType, Number, color, MAX_BUBBF_TIME, extraOutput, SubType2); } const char* CCharacter::GetBaseAnimationName(ECHAR_ANIM_GROUP eAnimGroup, int nIndex) { switch(eAnimGroup) { case CAG_IDLE: switch (nIndex) { case 0: return "stand"; case 1: return "swim_wait"; default: return "stand"; } case CAG_STUNNED: { return "stun01"; } case CAG_MOUT_IDLE: { //return "sit01"; return m_strMoutSitAction.c_str(); } case CAG_WAIT: switch (nIndex) { case 0: return "wait"; case 1: return "swim_wait"; default: return "wait"; } case CAG_RUN: switch (nIndex) { case 0: return "walk"; case 1: return "run"; case 2: return "Action_100003210"; case 3: return "swim"; default: return "run"; } case CAG_WALK: return "walk"; case CAG_DEAD: switch (nIndex) { case 0: return "death"; case 1: return "swim_death"; default: return "death"; } case CAG_JUMP_UP: if(nIndex == 2) { //return "sit01"; return m_strMoutSitAction.c_str(); } else { return "jump_start"; } case CAG_JUMP_ON: if(nIndex == 2) { //return "sit01"; return m_strMoutSitAction.c_str(); } else { return "jump_fly"; } case CAG_JUMP_DOWN: if(nIndex == 2) { //return "sit01"; return m_strMoutSitAction.c_str(); } else { return "jump_fall"; } case CAG_JUMP_RUN: if(nIndex == 2) { //return "sit01"; return m_strMoutSitAction.c_str(); } else { return "jump_fall_run"; } case CAG_MOUNTRUN: //return "sit01"; return m_strMoutSitAction.c_str(); default: break; } return NULL; } const char* CCharacter::GetClassAnimationName(ECHAR_ANIM_GROUP eAnimGroup, int nIndex) { return NULL; } void CCharacter::StartForward(bool bAutoRun) { //m_stMoveInfo.flags &= ~MOVEFLAG_MOVING_MASK; if ( !(m_stMoveInfo.flags & MOVEFLAG_MOVE_FORWARD) ) { m_stMoveInfo.flags |= MOVEFLAG_MOVE_FORWARD; SetNeedUpdateSwimAnim( true ); } } void CCharacter::StopForward() { //m_stMoveInfo.flags &= ~MOVEFLAG_MOVE_FORWARD; if ( (m_stMoveInfo.flags & MOVEFLAG_MOVE_FORWARD) ) { m_stMoveInfo.flags &= ~MOVEFLAG_MOVE_FORWARD; SetNeedUpdateSwimAnim( true ); } //SetNeedUpdateSwimAnim( true ); } void CCharacter::StartBackward() { //m_stMoveInfo.flags &= ~MOVEFLAG_MOVING_MASK; if ( !(m_stMoveInfo.flags & MOVEFLAG_MOVE_BACKWARD) ) { m_stMoveInfo.flags |= MOVEFLAG_MOVE_BACKWARD; SetNeedUpdateSwimAnim( true ); } } void CCharacter::StartSwimming() { uint32 idSpell = 0; if ( isMount() ) { if( GetMountSpell( idSpell )) { PacketBuilder->SendCancelAura(idSpell); } } if ( GetShapeSpell( idSpell ) ) { PacketBuilder->SendCancelAura(idSpell); } if ( IsMoving() ) { SetMoveAnimation( GetMoveState() ); } } void CCharacter::EndSwimming() { if ( !IsJumping() && IsMoving() ) { SetMoveAnimation( GetMoveState() ); } } void CCharacter::StartFlyUp() { //m_stMoveInfo.flags &= ~MOVEFLAG_MOVING_MASK; m_stMoveInfo.flags |= MOVEFLAG_PITCH_UP; } void CCharacter::StopFlyUp() { //m_stMoveInfo.flags &= ~MOVEFLAG_MOVING_MASK; m_stMoveInfo.flags &= ~MOVEFLAG_PITCH_UP; } void CCharacter::StartSwimUp() { //m_stMoveInfo.flags &= ~MOVEFLAG_MOVING_MASK; m_stMoveInfo.flags |= MOVEFLAG_PITCH_DOWN; /*if ( !(m_stMoveInfo.flags & MOVEFLAG_PITCH_DOWN) ) { m_stMoveInfo.flags |= MOVEFLAG_PITCH_DOWN; SetNeedUpdateSwimAnim( true ); }*/ } void CCharacter::StopSwimUp() { //m_stMoveInfo.flags &= ~MOVEFLAG_MOVING_MASK; //m_stMoveInfo.flags &= ~MOVEFLAG_PITCH_DOWN; if ( (m_stMoveInfo.flags & MOVEFLAG_PITCH_DOWN) ) { m_stMoveInfo.flags &= ~MOVEFLAG_PITCH_DOWN; //SetNeedUpdateSwimAnim( true ); } } void CCharacter::StopBackward() { //m_stMoveInfo.flags &= ~MOVEFLAG_MOVE_BACKWARD; if ( (m_stMoveInfo.flags & MOVEFLAG_MOVE_BACKWARD) ) { m_stMoveInfo.flags &= ~MOVEFLAG_MOVE_BACKWARD; SetNeedUpdateSwimAnim( true ); } //SetNeedUpdateSwimAnim( true ); } void CCharacter::StopVertical() { m_stMoveInfo.flags &= ~(MOVEFLAG_MOVING_MASK | MOVEFLAG_TURNING_MASK ); } void CCharacter::StartLeft() { //m_stMoveInfo.flags &= ~MOVEFLAG_STRAFING_MASK; //m_stMoveInfo.flags |= MOVEFLAG_STRAFE_LEFT; if ( !(m_stMoveInfo.flags & MOVEFLAG_STRAFE_LEFT) ) { m_stMoveInfo.flags |= MOVEFLAG_STRAFE_LEFT; SetNeedUpdateSwimAnim( true ); } } void CCharacter::StopLeft() { //m_stMoveInfo.flags &= ~MOVEFLAG_STRAFE_LEFT; if ( (m_stMoveInfo.flags & MOVEFLAG_STRAFE_LEFT) ) { m_stMoveInfo.flags &= ~MOVEFLAG_STRAFE_LEFT; /*float fangle = GetDesiredAngle(); SetDesiredAngle( fangle + NI_PI/2.f );*/ SetNeedUpdateSwimAnim( true ); } //SetNeedUpdateSwimAnim( true ); } void CCharacter::StartRight() { //m_stMoveInfo.flags &= ~MOVEFLAG_STRAFING_MASK; //m_stMoveInfo.flags |= MOVEFLAG_STRAFE_RIGHT; if ( !(m_stMoveInfo.flags & MOVEFLAG_STRAFE_RIGHT) ) { m_stMoveInfo.flags |= MOVEFLAG_STRAFE_RIGHT; SetNeedUpdateSwimAnim( true ); } } void CCharacter::StopRight() { //m_stMoveInfo.flags &= ~MOVEFLAG_STRAFE_RIGHT; if ( (m_stMoveInfo.flags & MOVEFLAG_STRAFE_RIGHT) ) { m_stMoveInfo.flags &= ~MOVEFLAG_STRAFE_RIGHT; /*SetNeedUpdateSwimAnim( true ); float fangle = GetDesiredAngle(); SetDesiredAngle( fangle - NI_PI/2.f );*/ } //SetNeedUpdateSwimAnim( true ); } void CCharacter::StopHorizontal() { m_stMoveInfo.flags &= ~MOVEFLAG_STRAFING_MASK; } void CCharacter::StartTurnLeft() { m_stMoveInfo.flags &= ~(MOVEFLAG_STRAFING_MASK | MOVEFLAG_TURNING_MASK); m_stMoveInfo.flags |= MOVEFLAG_TURN_LEFT; } void CCharacter::StartTurnRight() { m_stMoveInfo.flags &= ~(MOVEFLAG_STRAFING_MASK | MOVEFLAG_TURNING_MASK); m_stMoveInfo.flags |= MOVEFLAG_TURN_RIGHT; } void CCharacter::StopTurn() { m_stMoveInfo.flags &= ~MOVEFLAG_TURNING_MASK; } bool CCharacter::StartJump(bool bPhys, bool bSyncPos /*= false*/, NiPoint3* pkVelocity) { bool bret = false; NiPoint3 vInitVelocity; if (pkVelocity == NULL) { bret = CalcMoveVelocity(vInitVelocity, true); } else { vInitVelocity = *pkVelocity; } if (bSyncPos) { SetPosition(NiPoint3(m_stMoveInfo.x, m_stMoveInfo.y, m_stMoveInfo.z)); } //设置物理状态 if (!SetJumpPhysState(vInitVelocity)) return false; SetJumpState(EJS_START); return true; } void CCharacter::EndJump() { SetJumpState(EJS_NONE); if( m_bisStrikeBack && IsLocalPlayer() ) { if ( m_iStrickBackCount < 0 ) { m_iStrickBackCount = 0; } while ( m_iStrickBackCount ) { SYState()->LocalPlayerInput->UnlockInput(); m_iStrickBackCount--; } ((CPlayerLocal*)this)->m_bAutoRun = false; } m_bisStrikeBack = false; } void CCharacter::OnJumpInputEvent() { } bool CCharacter::SetJumpPhysState(const NiPoint3& vInitVelocity) { // if( m_ePhysics == PHYS_Walking ) { SetPhysics(PHYS_Falling); m_kInitVel = vInitVelocity; m_kInternelVel = m_kInitVel; // return true; // } return true; } void CCharacter::SetFacing(float rot) { SetRotate(NiPoint3(0.f, 0.f, rot)); } void CCharacter::PrepareMovementInfo() { } NiAVObject* CCharacter::GetWeaponNode() { if (m_spSceneNode) { // TODO: 是不是所有的武器都会在右手? NiAVObject* pRightHand = m_spSceneNode->GetObjectByName("RightHand_Node"); NIASSERT(pRightHand); NiNode* pRHNode = NiDynamicCast(NiNode, pRightHand); NIASSERT(pRHNode); return pRHNode; } return NULL; } void CCharacter::ApplyAura(ui32 spellid, ui8 slot) { SpellTemplate* pkSpell = SYState()->SkillMgr->GetSpellTemplate(spellid); NIASSERT(pkSpell); if (!pkSpell) return; // pkSpell->ApplyEffect(NULL, this); } void CCharacter::EnablePhys(bool bEnable) { m_bEnablePhys = bEnable; } float CCharacter::GetDesiredAngle() const { return m_fDesirdAngle; } float CCharacter::GetFacingAngle() const { return m_fFaceingAngle; } void CCharacter::SetDesiredAngle(float fAngle, bool bForce /*= false*/) { float fOffset = NI_PI/2.f; float dir = 0.f; float isback = 0.f; if ( m_stMoveInfo.flags & MOVEFLAG_MOVE_FORWARD ) { fOffset = fOffset/2.f; } if ( m_stMoveInfo.flags & MOVEFLAG_MOVE_BACKWARD ) { fOffset = -fOffset/2.f; isback = 1.f; } if ( m_stMoveInfo.flags & MOVEFLAG_STRAFE_RIGHT ) { dir = -1.f; } if ( m_stMoveInfo.flags & MOVEFLAG_STRAFE_LEFT ) { dir = 1.f; } if ( ( m_stMoveInfo.flags & MOVEFLAG_MOVE_BACKWARD ) && IsMoving() ) { dir = 0.f; } m_fFaceingAngle = fAngle + fOffset*dir + isback*NI_PI; m_fDesirdAngle = fAngle; while( m_fFaceingAngle >= NI_TWO_PI ) { m_fFaceingAngle -= NI_TWO_PI; } while( m_fDesirdAngle >= NI_TWO_PI ) { m_fDesirdAngle -= NI_TWO_PI; } if (bForce) { SetFacing(m_fFaceingAngle); } } void CCharacter::SetServerAngle( float serverAngle ) { float fOffset = NI_PI/2.f; float dir = 0.f; float isback = 0.f; if ( m_stMoveInfo.flags & MOVEFLAG_MOVE_FORWARD ) { fOffset = fOffset/2.f; } if ( m_stMoveInfo.flags & MOVEFLAG_MOVE_BACKWARD ) { fOffset = -fOffset/2.f; isback = 1.f; } if ( m_stMoveInfo.flags & MOVEFLAG_STRAFE_RIGHT ) { dir = 1.f; } if ( m_stMoveInfo.flags & MOVEFLAG_STRAFE_LEFT ) { dir = -1.f; } if ( ( m_stMoveInfo.flags & MOVEFLAG_MOVE_BACKWARD ) && IsMoving() ) { dir = 0.f; } m_fDesirdAngle = serverAngle + fOffset*dir + isback*NI_PI; m_fFaceingAngle = serverAngle; while( m_fFaceingAngle >= NI_TWO_PI ) { m_fFaceingAngle -= NI_TWO_PI; } while( m_fDesirdAngle >= NI_TWO_PI ) { m_fDesirdAngle -= NI_TWO_PI; } while( m_fFaceingAngle < 0 ) { m_fFaceingAngle += NI_TWO_PI; } while( m_fDesirdAngle < 0 ) { m_fDesirdAngle += NI_TWO_PI; } } void CCharacter::OnValueChanged(class UpdateMask* mask) { //CGameObject::OnValueChanged(mask); CPlayerLocal* plocal = ObjectMgr->GetLocalPlayer(); for (int index = UNIT_FIELD_AURA ; index <= UNIT_FIELD_AURA_55 ; index++) { if(mask->GetBit(index)) { ui32 localid = m_AuraInfo[index - UNIT_FIELD_AURA].SpellId; ui32 spellid = GetUInt32Value(index); m_AuraInfo[index - UNIT_FIELD_AURA].SpellId = spellid; m_AuraInfo[index - UNIT_FIELD_AURA].UpdateMsk = spellid?true:false; if(IsActorLoaded()) { if(spellid){ uint32 cdtspell,cdtinscrease; if(g_pkSpellInfo->GetSpellCDTIncrease(spellid, cdtspell, cdtinscrease)){ m_increasespellcdt[cdtspell] = cdtinscrease; } }else{ m_increasespellcdt.erase(spellid); } BOOL bUpdateMask = (spellid != 0)?TRUE:FALSE; if (bUpdateMask){ m_pkAura[index - UNIT_FIELD_AURA]->Start(spellid); }else{ if (localid != 0){ m_pkAura[index - UNIT_FIELD_AURA]->Over(); m_AuraInfo[index - UNIT_FIELD_AURA].AuraTime = 0.0f; } } } } } if(mask->GetBit(UNIT_FIELD_TARGET)) { CPlayerInputMgr * InputMgr = SYState()->LocalPlayerInput; ui64 Targetguid = GetUInt64Value(UNIT_FIELD_TARGET); SetTargetObjectID(Targetguid); if(this == plocal) { TeamShow->SetTargetGUID(Targetguid); InputMgr->SetDecal(Targetguid); CCharacter* pChar = (CCharacter*)ObjectMgr->GetObject(Targetguid); if (pChar) TeamShow->SetTargetTarget(pChar->GetUInt64Value(UNIT_FIELD_TARGET)); else TeamShow->SetTargetTarget(0); UControl* pSpellProcessBar = UInGame::GetFrame(FRAME_IG_TARGETCASTBAR); if(pSpellProcessBar){ pSpellProcessBar->SetVisible(FALSE); } } else if (plocal->IsTarget(this)/*||(!plocal->GetUInt64Value(UNIT_FIELD_TARGET) && !Targetguid)*/) { TeamShow->SetTargetTarget(GetUInt64Value(UNIT_FIELD_TARGET)); } } if(mask->GetBit(OBJECT_FIELD_SCALE_X)) { /*float scale = GetFloatValue(OBJECT_FIELD_SCALE_X); SetModleScale(scale);*/ //m_bInScale = true; } if (plocal && mbIsTargetTarget) { CCharacter* pChar = plocal->GetTargetObject(); if(pChar && pChar->IsTarget(this)){ if (mask->GetBit(UNIT_FIELD_HEALTH)) { TeamShow->SetTargetTargetField(FIELD_TARGETTARGET_HP,GetUInt32Value(UNIT_FIELD_HEALTH)); } if (mask->GetBit(UNIT_FIELD_MAXHEALTH)) { TeamShow->SetTargetTargetField(FIELD_TARGETTARGET_MAXHP,GetUInt32Value(UNIT_FIELD_MAXHEALTH)); } if (mask->GetBit(UNIT_FIELD_POWER1)) { TeamShow->SetTargetTargetField(FIELD_TARGETTARGET_MP,GetUInt32Value(UNIT_FIELD_POWER1)); } if (mask->GetBit(UNIT_FIELD_MAXPOWER1)) { TeamShow->SetTargetTargetField(FIELD_TARGETTARGET_MAXMP,GetUInt32Value(UNIT_FIELD_MAXPOWER1)); } } } if(m_spNameRef) { CharName* NewName = &m_spNameRef->stName; if (mask->GetBit(UNIT_FIELD_HEALTH)) { NewName->hp = GetUInt32Value(UNIT_FIELD_HEALTH); } if (mask->GetBit(UNIT_FIELD_MAXHEALTH)) { NewName->Maxhp = GetUInt32Value(UNIT_FIELD_MAXHEALTH); } if (mask->GetBit(UNIT_FIELD_LEVEL)) { NewName->Level = GetUInt32Value(UNIT_FIELD_LEVEL); } if (mask->GetBit(UNIT_FIELD_BYTES_0)) { NewName->Class = GetByte(UNIT_FIELD_BYTES_0,1); } } if( mask->GetBit(UNIT_FIELD_HEALTH) || mask->GetBit(UNIT_FIELD_POWER1) || mask->GetBit(UNIT_FIELD_MAXHEALTH) || mask->GetBit(UNIT_FIELD_MAXPOWER1) || mask->GetBit(UNIT_FIELD_LEVEL)) { TeamShow->UpdateTarget(GetGUID()); } if (mask->GetBit(UNIT_FIELD_FACTIONTEMPLATE) || mask->GetBit(PLAYER_FIELD_GROUP_ID) || mask->GetBit(UNIT_FIELD_FFA)) { if (IsLocalPlayer()) { if (TeamShow->GetTargetID() == GetUInt64Value(UNIT_FIELD_TARGET)) TeamShow->UpdateTargetUI(); } else if (TeamShow->GetTargetID() == GetGUID()) { TeamShow->UpdateTargetUI(); CPlayerInputMgr * InputMgr = SYState()->LocalPlayerInput; if (InputMgr) InputMgr->SetDecal(plocal->GetTargetObjectID()); } } if ( mask->GetBit( PLAYER_FIELD_GRAVITY_RATE ) ) { m_fGravityScale = GetFloatValue(PLAYER_FIELD_GRAVITY_RATE); if ( m_fGravityScale < 0.f ) { m_fGravityScale = 0.f; } } } void CCharacter::SetTargetTarget(bool btemp) { mbIsTargetTarget = btemp; UControl* pSpellProcessBar = UInGame::GetFrame(FRAME_IG_TARGETTARGETCASTBAR); if(pSpellProcessBar) { pSpellProcessBar->SetVisible(FALSE); } } void CCharacter::SetAuraDuringTime(int slot, float time, float maxtime) { if (slot < 0 || slot >= MAX_AURAS) return; m_AuraInfo[slot].AuraTime = time; m_AuraInfo[slot].MaxAuraTime = maxtime; } void CCharacter::SetAuraLevel(int slot, int level) { if (slot < 0 || slot >= MAX_AURAS) return; m_AuraInfo[slot].level = level; } bool CCharacter::GetMountSpell(ui32& spellId) { for (int i = 0 ; i < MAX_AURAS ; ++i) { if( g_pkSpellInfo->IsMountSpell( m_AuraInfo[i].SpellId ) ) { spellId = m_AuraInfo[i].SpellId; return true; } } return false; } bool CCharacter::GetShapeSpell(ui32& spellId) { for (int i = 0 ; i < MAX_AURAS ; ++i) { if( g_pkSpellInfo->IsShapeSpell( m_AuraInfo[i].SpellId ) ) { spellId = m_AuraInfo[i].SpellId; return true; } } return false; } bool CCharacter::IsAuraInChar(ui32 spellId) { for (int i = 0 ; i < MAX_AURAS ; ++i) { if( spellId == m_AuraInfo[i].SpellId) { return true; } } return false; } CCharacter::AuraInfo * CCharacter::GetAura(int slot) { return (m_AuraInfo + slot); } void CCharacter::UpdataAura(float dt) { for (int i = 0 ; i < MAX_AURAS ; ++i) { if ( m_AuraInfo[i].UpdateMsk ) { m_AuraInfo[i].AuraTime -= dt; if ( m_AuraInfo[i].AuraTime < 0.0f ) { m_AuraInfo[i].AuraTime = 0.0f; } } } } void CCharacter::UpdateTransformbyChar(CCharacter* pkChar) { //float scale = pkChar->GetFloatValue(OBJECT_FIELD_SCALE_X); float scale = pkChar->GetFloatValue(OBJECT_FIELD_SCALE_X); float curscale = GetModelScale(); if ( ( scale -curscale) > 0.01f || ( scale -curscale ) < -0.01f ) { float momentscale = curscale; if ( m_fModleScale < 0.001f ) { momentscale = scale; } else { float scaletimes = 1.f + SCALE_EXTENT; if ( (scale -curscale) < -0.01f ) { scaletimes = 1.f - SCALE_EXTENT; } momentscale = curscale*scaletimes; if ( scaletimes > 1.f && momentscale > scale ) { momentscale = scale; } if ( scaletimes < 1.f && momentscale < scale ) { momentscale = scale; } if(momentscale < 0.01f) momentscale = 1.f; } this->SetModleScale(momentscale); GetSceneNode()->SetScale(momentscale); } GetSceneNode()->SetTranslate(pkChar->GetPhyPosition()); GetSceneNode()->SetRotate(pkChar->GetSceneNode()->GetRotate()); GetSceneNode()->Update(0.0f, false); m_scaleTime = 0.f; } void CCharacter::SetModleScale(float modle) { if(modle == m_fModleScale) return; m_fModleScale = modle; NiAVObject* pkNameOffset = GetSceneNode()->GetObjectByName("Dummy02"); if(pkNameOffset) { m_kNamePosOffset = pkNameOffset->GetTranslate().z * m_fModleScale; } } NiNode* CCharacter::GetPetNode() { if(GetSceneNode()) { return NiDynamicCast(NiNode,(GetSceneNode()->GetObjectByName("Pet_Node01"))); } return NULL; } BOOL CCharacter::SetMoveAnimation(UINT Flags, BOOL bForceStart) { return FALSE; } BOOL CCharacter::SetJumpAnimation(int iJumpState, bool bAnimLoop) { BOOL bForceStart = FALSE; //CAG_JUMP_UP, CAG_JUMP_ON, CAG_JUMP_DOWN, CAG_RUN ECHAR_ANIM_GROUP eJumpAnim; if (iJumpState == EJS_START) { eJumpAnim = CAG_JUMP_UP; bForceStart = TRUE; } else if (iJumpState == EJS_FALLING) { eJumpAnim = CAG_JUMP_ON; bForceStart = TRUE; } else if (iJumpState == EJS_LANDING) { if (IsMoving()) eJumpAnim = CAG_JUMP_RUN; else eJumpAnim = CAG_JUMP_DOWN; bForceStart = FALSE; } else{ NIASSERT(0); return FALSE; } NiFixedString strAnim = GetBaseAnimationName(eJumpAnim, GetMoveState()); AnimationID animID = GetAnimationIDByName(strAnim); return (SetCurAnimation(animID, 1, bAnimLoop, bForceStart, 1) != NULL); } BOOL CCharacter::SetAttackPrepare() { SetAttackAnimation(true); SetAttackPrepare(true); return TRUE; } BOOL CCharacter::SetCombatPrepareAnimation(int iType) { const char* szCombatPrepareAnimName = GetBaseAnimationName((ECHAR_ANIM_GROUP)iType, 0); AnimationID animID = GetAnimationIDByName(szCombatPrepareAnimName); NiControllerSequence* Seq = SetCurAnimation(szCombatPrepareAnimName); if (Seq) { NiTimeController::CycleType CT = Seq->GetCycleType(); if (CT == NiTimeController::CLAMP) { Seq->SetCycleType(NiTimeController::LOOP); } } else { return FALSE; } return TRUE; } BOOL CCharacter::SetIdleAnimation(int iType) { if ( m_bisStuned ) { AnimationID animID = GetAnimationIDByName("stun01"); if ( animID == m_uiCurrAnimID ) { return TRUE; } else iType = CAG_STUNNED; } BOOL bForceStart = FALSE; int iPriority = -1; AnimationID animID = NiActorManager::INVALID_SEQUENCE_ID; int AnimIndex = 0; if ( CheckInWater() == WL_UNDER_WATER ) { //水里话 设置动作融合 iPriority = 2; AnimIndex = 1; } const char* szIdleAnimName = GetBaseAnimationName((ECHAR_ANIM_GROUP)iType, AnimIndex); float fCurTime = SYState()->ClientApp->GetAccumTime(); if (iType == CAG_WAIT && GetWaitSeqNum() > 0 ) { char szWaitAnim[256]; if ( GetGameObjectType() == GOT_CREATURE ) { int i = NiRand()%GetWaitSeqNum(); if ( i == 0 ) _snprintf(szWaitAnim, 256, "%s", szIdleAnimName); else _snprintf(szWaitAnim, 256, "%s%d", szIdleAnimName, i + 1); } else { int i = NiRand()%GetWaitSeqNum(); _snprintf(szWaitAnim, 256, "%s%02d", szIdleAnimName, i + 1); ui32 entry = GetUInt32Value(UNIT_FIELD_FORMDISPLAYID); if(entry) { _snprintf(szWaitAnim, 256, "wait"); OnDisplayedWaitSound(entry); } } animID = GetAnimationIDByName(szWaitAnim); } else { animID = GetAnimationIDByName(szIdleAnimName); } NiControllerSequence* Seq = SetCurAnimation(animID, 1.0, TRUE,bForceStart, iPriority); return (Seq != NULL); } void CCharacter::OnDisplayedWaitSound(ui32 entry) { ALAudioSource* pkSound = GetSoundInst(); if (pkSound){ char soundfile[64]; CCreatureNameDB::stCNDB cndb; if (!ItemMgr->GetCNDB(entry, cndb)) return; if (cndb.sound_stand != 0 ) { SoundDB::soundfile sf; if ( g_pkSoundFiles->GetSoundFile(cndb.sound_stand, sf)) { _snprintf(soundfile, 64, "sound/char/%s.wav", sf.filename.c_str()); GetSceneNode()->AttachChild(pkSound); pkSound->SetMinMaxDistance(5.0f, 80.0f); pkSound->SetGain(1.0f); SYState()->IAudio->PlaySound(pkSound, soundfile); } } } } INT CCharacter::MakeAttackSerial() const { INT Serial = NiRand()%/*ATK_SERIAL_MAX*/100; if(Serial<35) Serial = 0; else if(Serial < 70) Serial = 1; else Serial = 2; return Serial; } BOOL CCharacter::SetAttackAnimation(bool bPrepare /*= false*/) { UINT Serial = (UINT)MakeAttackSerial(); AnimationID AtkAnim = NiActorManager::INVALID_SEQUENCE_ID; if (bPrepare) { NiFixedString strAnimName = GetBaseAnimationName(CAG_COMBATPREPARE); AtkAnim = GetAnimationIDByName(strAnimName); } else { AtkAnim = GetNormalAttackAnimation(Serial); } if (AtkAnim == NiActorManager::INVALID_SEQUENCE_ID) return FALSE; DeactivateAllLayerAnims(); const uint32& baseAttackTime = GetUInt32Value(UNIT_FIELD_BASEATTACKTIME); NiControllerSequence* Seq = ActivateAnimation(AtkAnim, 2, 1, 0.1f, NiKFMTool::SYNC_SEQUENCE_ID_NONE, false, true, true); if (Seq) { Seq->SetFrequency(1.0f); Seq->SetCycleType(NiTimeController::CLAMP); float fLength = Seq->GetLength(); float fScale = fLength/(baseAttackTime*0.001f); if (fScale > 1.0f) Seq->SetFrequency(1.f/fScale); } return TRUE; } void CCharacter::ProcessJumpState(bool bSyncPos /*= false*/, NiPoint3* pkInitVelocity /*= NULL*/) { if ( GetMoveState() == CMS_RUSH ) { EndJump(); } BOOL bRet = FALSE; int iJumpState = GetJumpState(); BOOL bStorm = this->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STORM); if (bStorm) { if ( iJumpState == EJS_NONE ) { if ( !StartJump(true, bSyncPos, pkInitVelocity)) { SetJumpState(EJS_LANDING); return; } } ResetJumpingFlag(); return; } float fCurTime = SYState()->ClientApp->GetAccumTime(); if ( iJumpState == EJS_NONE ) { bRet = SetJumpAnimation(EJS_START); NIASSERT(bRet); if ( !StartJump(true, bSyncPos, pkInitVelocity)) { SetJumpState(EJS_NONE); return; } ResetJumpingFlag(); } else { if ( IsCurAnimEndInTime(fCurTime) && iJumpState == EJS_START) { bRet = SetJumpAnimation(EJS_FALLING, true); SetJumpState(EJS_FALLING); } if ( GetPhsyicState() != PHYS_Falling && iJumpState == EJS_FALLING) { SetJumpState(EJS_LANDING); SetJumpAnimation(EJS_LANDING); if( m_bisStrikeBack ) { m_stMoveInfo.flags &= ~MOVEFLAG_MOTION_MASK; m_kInternelVel.x = 0.f; m_kInternelVel.y = 0.f; } if ( CheckInWater() == WL_NONE ) { SYState()->IAudio->PlaySound( "Sound/footStep.wav", NiPoint3::ZERO, 2.f, 1 ); } if ( CheckInWater() == WL_STANDING_WATER ) { SYState()->IAudio->PlaySound( "Sound/FootStepsInWater.wav", NiPoint3::ZERO, 1.f, 1 ); } } if ( GetJumpState() == EJS_LANDING) { if ( IsCurAnimEndInTime(fCurTime)) { if (IsMoving() ) { BOOL bRet2 = SetMoveAnimation(GetMoveState(), FALSE); } EndJump(); } } if ( CheckInWater() == WL_UNDER_WATER ) { SYState()->IAudio->PlaySound( "Sound/EnterWater.wav", NiPoint3::ZERO, 1.f, 1 ); } } } char* CCharacter::GetHeadImageFile(CCharacter* pChar) { if (!pChar) return NULL; static char strFile[256]; NiSprintf(strFile,256,"Data\\UI\\Icon\\Monster\\Icon_%d.png" ,pChar->GetUInt32Value(OBJECT_FIELD_ENTRY)); return strFile; }