Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
	}
}