SKILL_RESULT cSkillManager::OnPetSkillStartSyn(MSG_SKILL_START_SYN* pmsg, ITEMBASE* pItemBase) { /// 시전자 정보가 없다면 실패 // 080602 LUJ, 스킬 발동은 플레이어만 할 수 있으므로 캐스팅한다 CPet* pOperator = ( CPet* )g_pUserTable->FindUser( pmsg->Operator ); // 080602 LUJ, 검사 구문 추가 if( ! pOperator || pOperator->GetObjectKind() != eObjectKind_Pet || pOperator->CurCastingSkillID ) { return SKILL_OPERATOR_INVALUED; } // 080410 KTH -- 일반 스킬일 경우 스킬 트리에 포함 되어있는 스킬인지 확인한다. if( pItemBase ) { ITEM_INFO* pItemInfo = ITEMMGR->GetItemInfo( pItemBase->wIconIdx ); const cSkillInfo* pSkillInfo = SKILLMGR->GetSkillInfo( pmsg->SkillIdx ); if( pSkillInfo == NULL || pItemInfo == NULL ) return SKILL_INFO_INVALUED; if( pmsg->SkillIdx / 100 != pItemInfo->SupplyValue / 100 ) return SKILL_INFO_INVALUED; } // 090226 LUJ, 스킬 검사 else { const SkillScript& skillScript = GAMERESRCMNGR->GetSkillScript( pmsg->SkillIdx ); const BOOL checkFailed = ( skillScript.mIsNeedCheck && ! pOperator->IsHaveSkill( pmsg->SkillIdx ) ); if( checkFailed ) { LogScriptHack( *pOperator, "SkillList.bin", "*pet has no skill" ); return SKILL_OPERATOR_INVALUED; } } const cSkillInfo* ptemp = GetSkillInfo( pmsg->SkillIdx ); if( ptemp == NULL ) { return SKILL_INFO_INVALUED; } cActiveSkillInfo* pSkillInfo = ( cActiveSkillInfo* )ptemp; if( pOperator->GetAbnormalStatus()->IsSilence ) { // 080616 LUJ, 침묵 중에는 물리 공격만 가능하다 if( pSkillInfo->GetKind() != SKILLKIND_PHYSIC ) { return SKILL_STATE_INVALUED; } } if( pOperator->GetAbnormalStatus()->IsBlockAttack ) { if( pSkillInfo->GetInfo().Unit == UNITKIND_PHYSIC_ATTCK ) return SKILL_STATE_INVALUED; } /// 최초 접속시 무적 상태 해제 if( pOperator->GetState() == eObjectState_Immortal ) OBJECTSTATEMGR_OBJ->EndObjectState( pOperator, eObjectState_Immortal, 0 ); /// 길드 토너먼트나 공성전에서 관람자는 스킬을 사용할 수 없다 { CObject* const ownerObject = g_pUserTable->FindUser( pOperator->GetOwnerIndex()); if(0 == ownerObject) { return SKILL_STATE_INVALUED; } else if(2 == ownerObject->GetBattleTeam()) { return SKILL_STATE_INVALUED; } } if(FALSE == pSkillInfo->IsExcutableSkillState(*pOperator, pmsg->mConsumeItem)) { return SKILL_STATE_INVALUED; } VECTOR3 TargetPos; CObject * pTargetObject = NULL; float TargetRadius; /// 타겟 설정 확인 if(GetMainTargetPos(&pmsg->MainTarget,&TargetPos, &pTargetObject) == FALSE) { /// 타겟이 없다 return SKILL_TARGET_INVALUED; } switch( pSkillInfo->GetInfo().Target ) { case eSkillTargetKind_None: { return SKILL_TARGET_INVALUED; } break; case eSkillTargetKind_OnlyOthers: { if( pTargetObject == pOperator ) { return SKILL_TARGET_INVALUED; } } break; case eSkillTargetKind_Ground: { } break; case eSkillTargetKind_OnlySelf: { if( pTargetObject != pOperator ) { return SKILL_TARGET_INVALUED; } } break; case eSkillTargetKind_AllObject: { } break; } /// 타겟 오브젝트의 크기를 구한다 if(pmsg->MainTarget.MainTargetKind == MAINTARGET::MAINTARGETKIND_POS) TargetRadius = 0; else { pTargetObject = g_pUserTable->FindUser( pmsg->MainTarget.dwMainTargetID ); TargetRadius = pTargetObject->GetRadius(); } if( pSkillInfo->IsInRange(*pOperator, TargetPos, TargetRadius) == FALSE) { if(pTargetObject) { RESULTINFO DamageInfo = {0}; DamageInfo.mSkillIndex = pSkillInfo->GetIndex(); pTargetObject->Damage(pOperator, &DamageInfo); } return SKILL_RANGE_NOTENOUGH; } if( pSkillInfo->GetKind() == SKILLKIND_ONOFF ) { BOOL destroy = FALSE; for( WORD i = 0; i < MAX_BUFF_COUNT; i++ ) { const DWORD idx = pSkillInfo->GetInfo().Buff[ i ]; if( cSkillObject* pSkill = pTargetObject->GetBuffList().GetData( idx / 100 ) ) { if( pSkill->GetSkillIdx() <= pSkillInfo->GetInfo().Buff[ i ] ) { pSkill->SetEndState(); pSkill->EndState(); destroy = TRUE; } } } if( destroy ) { return SKILL_DESTROY; } } // 080602 LUJ, 전역 스킬은 DB에서 직접 처리한 후 전송된다. 취소 등을 위해 오브젝트 ID를 직접 받아온다 const DWORD skillObjectIndex = GetNewSkillObjectID(); sSKILL_CREATE_INFO info; info.level = pSkillInfo->GetInfo().Level; info.operatorId = pOperator->GetID(); info.mainTarget = pmsg->MainTarget; info.skillDir = pmsg->SkillDir; /// 스킬 오브젝트 생성 cSkillObject* pSObj = pSkillInfo->GetSkillObject(); /// 스킬 객체 ID // 080602 LUJ, DB 업데이트 실패 시 스킬 오브젝트를 취소할 수 있도록 위에서 인덱스를 미리 받아놓도록 했다 info.skillObjectId = skillObjectIndex; if( pSkillInfo->GetInfo().Target ) { info.pos.x = TargetPos.x; info.pos.z = TargetPos.z; } else { info.pos = *CCharMove::GetPosition(pOperator); } // 090123 LUJ, 객체를 초기화한 후 타겟 검사를 수행해야한다. pSObj->Init( &info ); pSObj->SetMultiTarget( &( pmsg->TargetList ) ); pSObj->SetBattle( pOperator->GetBattleID(), pOperator->GetBattleTeam() ); pSObj->SetGridID( pOperator->GetGridID() ); /// 테이블에 등록 m_SkillObjectTable.Add( pSObj, pSObj->GetID() ); mProcessList.push_back(pSObj->GetID()); g_pServerSystem->AddSkillObject( pSObj, &info.pos ); /// 스킬 생성 성공 return SKILL_SUCCESS; }
void CPetManager::NetworkMsgParse(BYTE Protocol,void* pMsg) { switch( Protocol ) { case MP_PET_HATCH: { MSG_PET_INFO* pmsg = ( MSG_PET_INFO* )pMsg; PET_OBJECT_INFO* pObjectInfo = new PET_OBJECT_INFO; memcpy( pObjectInfo, &( pmsg->PetObjectInfo ), sizeof( PET_OBJECT_INFO ) ); mPetObjectInfoTable.Add( pObjectInfo, pObjectInfo->ItemDBIdx ); PET_INFO* pInfo = mPetInfoTable.GetData( pObjectInfo->Kind ); CItem* pItem = ITEMMGR->GetItem( pObjectInfo->ItemDBIdx ); if( !pInfo || !pItem ) return; CHATMGR->AddMsg( CTC_SYSMSG, CHATMGR->GetChatMsg(1573), pInfo->Name, pObjectInfo->SkillSlot ); pItem->ForcedUnseal(); ITEMMGR->RefreshItem( pItem ); } break; case MP_PET_EXP_NOTIFY: { HEROPET->AddExp(); } break; case MP_PET_LEVELUP_NOTIFY: { MSG_DWORD* pmsg = ( MSG_DWORD* )pMsg; CPet* pPet = ( CPet* )OBJECTMGR->GetObject( pmsg->dwData ); if( !pPet ) return; pPet->LevelUp(); APPEARANCEMGR->InitAppearance( pPet ); if( pPet == HEROPET ) { HEROPET->CalcStats(); // 081112 LYW --- PetManager : 펫이 레벨업 했을경우 잘못 출력되던 // 메시지 번호를 수정함. 1647 ->1659 (정진문) CHATMGR->AddMsg(CTC_SYSMSG, CHATMGR->GetChatMsg(1659)); } TARGETSET set; set.pTarget = pPet; EFFECTMGR->StartEffectProcess(mLevelUpEffect,pPet,&set,0,pPet->GetID()); } break; case MP_PET_LEVEL_NOTIFY: { MSG_DWORDBYTE* pmsg = ( MSG_DWORDBYTE* )pMsg; CPet* pPet = ( CPet* )OBJECTMGR->GetObject( pmsg->dwData ); if( !pPet ) return; pPet->SetLevel( pmsg->bData ); APPEARANCEMGR->InitAppearance( pPet ); if( pPet == HEROPET ) { HEROPET->CalcStats(); // 081112 LYW --- PetManager ; 펫이 레벨업 했을 경우 잘못 출력되던 메시지 번호를 수정함. // 메시지 번호를 수정함. 1647 ->1659 (정진문) CHATMGR->AddMsg(CTC_SYSMSG, CHATMGR->GetChatMsg(1659)); } } break; case MP_PET_GRADEUP_NOTIFY: { MSG_DWORDBYTE2* pmsg = ( MSG_DWORDBYTE2* )pMsg; CPet* pPet = ( CPet* )OBJECTMGR->GetObject( pmsg->dwData ); if( !pPet ) return; pPet->GradeUp(); APPEARANCEMGR->InitAppearance( pPet ); if( pPet == HEROPET ) { HEROPET->SetType( ePetType(pmsg->bData1)); HEROPET->SetSkillSlot( pmsg->bData2); HEROPET->CalcStats(); CHATMGR->AddMsg(CTC_SYSMSG, CHATMGR->GetChatMsg(1576)); CItem* pItem = ITEMMGR->GetItem( HEROPET->GetItemDBIdx() ); if( pItem ) { ITEMMGR->RefreshItem( pItem ); } } TARGETSET set; set.pTarget = pPet; EFFECTMGR->StartEffectProcess(mGradeUpEffect,pPet,&set,0,pPet->GetID()); } break; case MP_PET_FRIENDLY_SYNC: { MSG_BYTE* pmsg = ( MSG_BYTE* )pMsg; HEROPET->SetFriendly( pmsg->bData ); } break; case MP_PET_RESURRECTION_ACK: { MSG_PET_INFO* pmsg = ( MSG_PET_INFO* )pMsg; PET_OBJECT_INFO* oldinfo = mPetObjectInfoTable.GetData( pmsg->PetObjectInfo.ItemDBIdx ); if( oldinfo ) { memcpy( oldinfo, &( pmsg->PetObjectInfo ), sizeof( PET_OBJECT_INFO ) ); } CItem* pItem = ITEMMGR->GetItem( pmsg->PetObjectInfo.ItemDBIdx ); if( pItem ) { ITEMMGR->RefreshItem( pItem ); } CPetResurrectionDialog* window = GAMEIN->GetPetResurrectionDlg(); if( window && window->IsActive() ) { window->SetUsedItem( NULL ); window->SetActive( FALSE ); } QUICKMGR->RefreshQickItem(); } break; case MP_PET_LIFE_NOTIFY: { MSG_INT* pmsg = ( MSG_INT* )pMsg; if( HEROPET ) HEROPET->SetLife( HEROPET->GetLife() + pmsg->nData ); } break; case MP_PET_MAXLIFE_NOTIFY: { MSG_DWORD* pmsg = ( MSG_DWORD* )pMsg; CPet* pPet = (CPet*)OBJECTMGR->GetObject( pmsg->dwObjectID ); if( pPet ) pPet->SetMaxLife( pmsg->dwData ); } break; case MP_PET_MANA_NOTIFY: { MSG_DWORD* pmsg = ( MSG_DWORD* )pMsg; if( HEROPET ) HEROPET->SetMana( pmsg->dwData ); } break; case MP_PET_MAXMANA_NOTIFY: { MSG_DWORD* pmsg = ( MSG_DWORD* )pMsg; if( HEROPET ) HEROPET->SetMaxMana( pmsg->dwData ); } break; case MP_PET_OBJECT_INFO: { MSG_PET_INFO* pmsg = ( MSG_PET_INFO* )pMsg; PET_OBJECT_INFO* oldinfo = mPetObjectInfoTable.GetData( pmsg->PetObjectInfo.ItemDBIdx ); if( oldinfo ) { memcpy( oldinfo, &( pmsg->PetObjectInfo ), sizeof( PET_OBJECT_INFO ) ); } else { PET_OBJECT_INFO* pObjectInfo = new PET_OBJECT_INFO; memcpy( pObjectInfo, &( pmsg->PetObjectInfo ), sizeof( PET_OBJECT_INFO ) ); mPetObjectInfoTable.Add( pObjectInfo, pObjectInfo->ItemDBIdx ); } ITEMMGR->RefreshItemToolTip( pmsg->PetObjectInfo.ItemDBIdx ); // 퀵슬롯이 세팅된 후에 펫 정보가 전송된다. 따라서 사망 등의 정보가 변경되려면 재호출한다 QUICKMGR->RefreshQickItem(); } break; case MP_PET_DIE_NOTIFY: { MSG_DWORD* pmsg = ( MSG_DWORD* )pMsg; PET_OBJECT_INFO* oldinfo = mPetObjectInfoTable.GetData( pmsg->dwData ); if( oldinfo ) { oldinfo->HP = 0; oldinfo->MP = 0; oldinfo->Friendly = 0; oldinfo->State = ePetState_Die; } CItem* pItem = ITEMMGR->GetItem( pmsg->dwData ); if( pItem ) { ITEMMGR->RefreshItem( pItem ); } CHATMGR->AddMsg(CTC_SYSMSG, CHATMGR->GetChatMsg(1578)); // 081112 LYW --- PetManager : 펫이 사망하였을 경우 펫 ui를 닫도록 수정함. cDialog* pDlg = GAMEIN->GetPetUIDlg() ; if( pDlg ) { pDlg->SetActive( FALSE ) ; } // 090212 NYJ - 봉인중 죽어버리면 봉인취소 CProgressDialog* pProgressDlg = ( CProgressDialog* )WINDOWMGR->GetWindowForID( PROGRESS_DIALOG ); if(pProgressDlg && pProgressDlg->GetActionType()==CProgressDialog::eActionPetSummon) { pProgressDlg->Cancel(); } QUICKMGR->RefreshQickItem(); } break; case MP_PET_ITEM_INFO: { MSG_PET_ITEM_INFO* pmsg = ( MSG_PET_ITEM_INFO* )pMsg; CPet* pPet = ( CPet* )OBJECTMGR->GetObject( pmsg->ID ); if( pPet ) { pPet->SetWearedItem( pmsg->Item ); APPEARANCEMGR->InitAppearance( pPet ); } } break; case MP_PET_ITEM_DISCARD_ACK: { MSG_BYTE2* pmsg = ( MSG_BYTE2* )pMsg; //시간 소모로 삭제 되었다면 TRUE if( pmsg->bData2 ) { CPetWearedDialog* pDlg = GAMEIN->GetPetWearedDlg(); CItem* pItem = (pDlg) ? (CItem*)pDlg->GetIconForIdx( pmsg->bData1 ) : NULL ; if( pItem ) { CHATMGR->AddMsg( CTC_CHEAT_1, CHATMGR->GetChatMsg( 1192 ), CHATMGR->GetChatMsg( 1926 ), pItem->GetItemInfo()->ItemName ); } } GAMEIN->GetPetWearedDlg()->DeleteAck( pmsg->bData1 ); } break; case MP_PET_ITEM_MOVE_PLAYER_ACK: { MSG_PET_ITEM_MOVE_SYN* pmsg = ( MSG_PET_ITEM_MOVE_SYN* )pMsg; CInventoryExDialog* pPlayerInven = GAMEIN->GetInventoryDialog(); CStorageDialog* pPlayerStorage = GAMEIN->GetStorageDialog(); CPetWearedDialog* pPetInven = GAMEIN->GetPetWearedDlg(); CItem* pPlayerItem = NULL; const eITEMTABLE TableIdx = ITEMMGR->GetTableIdxForAbsPos( pmsg->PlayerPos ); if( TableIdx == eItemTable_Storage) { pPlayerStorage->DeleteItem( pmsg->PlayerPos, &pPlayerItem ); } else if( TableIdx == eItemTable_Inventory ) { pPlayerInven->DeleteItem( pmsg->PlayerPos, &pPlayerItem ); } else return; cIcon* pIcon = NULL; CItem* pPetItem = NULL; pPetInven->DeleteItem( pmsg->PetPos, &pIcon ); pPetItem = ( CItem* )pIcon; if( pPlayerItem ) { pPlayerItem->SetPosition( pmsg->PetPos ); pPetInven->AddItem( pmsg->PetPos, pPlayerItem ); } if( pPetItem ) { pPetItem->SetPosition( pmsg->PlayerPos ); if( TableIdx == eItemTable_Storage) { pPlayerStorage->AddItem( pPetItem ); } else if( TableIdx == eItemTable_Inventory ) { pPlayerInven->AddItem( pPetItem ); } else return; } } break; case MP_PET_ITEM_MOVE_PLAYER_NACK: { MSG_WORD* msg = (MSG_WORD*)pMsg; switch(msg->wData) { case 1: CHATMGR->AddMsg(CTC_SYSMSG, CHATMGR->GetChatMsg(1739)); break; } } break; // 090625 pdy 펫 기간제 아이템 착용처리 추가 case MP_PET_ITEM_TIMELIMT_ONEMINUTE_FROM_PETINVEN: { MSG_DWORD2* pmsg = (MSG_DWORD2*)pMsg ; ITEM_INFO* pItemInfo = NULL ; pItemInfo = ITEMMGR->GetItemInfo( pmsg->dwData1 ) ; if( !pItemInfo ) return ; POSTYPE pos = (POSTYPE)pmsg->dwData2 ; CPetWearedDialog* pDlg = GAMEIN->GetPetWearedDlg(); CItem* pItem= (pDlg) ? (CItem*)pDlg->GetIconForIdx(pos) : NULL ; const ITEMBASE* pItemBase = (pItem) ? &pItem->GetItemBaseInfo() : NULL ; if( pItemBase ) { CItem* pItem = NULL ; pItem = ITEMMGR->GetItem( pItemBase->dwDBIdx ) ; if( pItem ) { pItem->SetItemBaseInfo( *pItemBase ) ; pItem->SetLastCheckTime(gCurTime) ; pItem->SetRemainTime( 50 ) ; } } CHATMGR->AddMsg( CTC_CHEAT_1, CHATMGR->GetChatMsg( 1191 ), CHATMGR->GetChatMsg( 1926 ), pItemInfo->ItemName ) ; } break; case MP_PET_LIFE_BROAD: { const MSG_INT* const msg = (MSG_INT*)pMsg; CPet* pPet = (CPet*)OBJECTMGR->GetObject( msg->dwObjectID ); if( pPet ) { DWORD dwNewLife = pPet->GetLife() + msg->nData; pPet->SetLife( dwNewLife ); } } break; } }