Beispiel #1
0
void CAISocket::RecvNpcRegionUpdate(Packet & pkt)
{
	uint16 sNpcID;
	float fX, fY, fZ;

	pkt >> sNpcID >> fX >> fY >> fZ;

	CNpc * pNpc = g_pMain->GetNpcPtr(sNpcID);
	if (pNpc == nullptr)
		return;

	pNpc->SetPosition(fX, fY, fZ);
	pNpc->RegisterRegion();
}
void CUser::ClientEvent(uint16 sNpcID)
{
	// Ensure AI's loaded
	if (!g_pMain->m_bPointCheckFlag
		|| isDead())
		return;

	int32 iEventID = 0;
	CNpc *pNpc = g_pMain->GetNpcPtr(sNpcID);
	if (pNpc == nullptr
		|| !isInRange(pNpc, MAX_NPC_RANGE))
		return;

	m_sEventNid = sNpcID;
	m_sEventSid = pNpc->GetProtoID(); // For convenience purposes with Lua scripts.

	// Aww.
	if (pNpc->GetType() == NPC_KISS)
	{
		KissUser();
		return;
	}

	FastGuard lock(g_pMain->m_questNpcLock);
	QuestNpcList::iterator itr = g_pMain->m_QuestNpcList.find(pNpc->GetProtoID());
	if (itr == g_pMain->m_QuestNpcList.end())
		return;

	// Copy it. We should really lock the list, but nevermind.
	QuestHelperList & pList = itr->second;
	_QUEST_HELPER * pHelper = nullptr;
	foreach(itr, pList)
	{
		if ((*itr) == nullptr
			|| (*itr)->sEventDataIndex
			|| (*itr)->bEventStatus
			|| ((*itr)->bNation != 3 && (*itr)->bNation != GetNation())
			|| ((*itr)->bClass != 5 && !JobGroupCheck((*itr)->bClass)))
			continue;

		pHelper = (*itr);
		break;
	}

	if (pHelper == nullptr)
		return;

	QuestV2RunEvent(pHelper, pHelper->nEventTriggerIndex);
}
void CFishingManager::Fishing_Ready_Ack(void* pMsg)
{
	MSG_DWORD4* pmsg = (MSG_DWORD4*)pMsg;

	CObject* pObject = OBJECTMGR->GetObject(pmsg->dwObjectID);
	if(!pObject)
		return;

	if(pObject == HERO)
	{
		if(0==pmsg->dwData1 || 0==pmsg->dwData3 || 0==pmsg->dwData4)
			return;

		SetFishingStartTime(gCurTime);
		SetFishingPlace(pmsg->dwData1);

		m_fGaugeStartPos = (float)pmsg->dwData2/100.0f;
		m_dwProcessTime = pmsg->dwData3;
		m_nRepeatCount = pmsg->dwData4;

		LONG maxValue = 0;
		cGuageBar* pGaugeBar = GAMEIN->GetFishingGaugeDlg()->GetFishingGB();
		if(pGaugeBar)
			maxValue = pGaugeBar->GetMaxValue();

		m_fGaugeBarSpeed = ((float)m_nRepeatCount * maxValue) / (float)m_dwProcessTime;
		m_dwUpdateTime = (m_dwProcessTime / m_nRepeatCount) / maxValue;

		m_bActive = TRUE;
	}
	else
	{
		CNpc* pNpc = (CNpc*)OBJECTMGR->GetObject(pmsg->dwData1);
		if(pNpc)
		{
			// 방향전환
			VECTOR3 pos;
			pNpc->GetPosition(&pos);
			MOVEMGR->SetLookatPos(pObject,&pos,0,gCurTime);
		}
	}


	OBJECTSTATEMGR->StartObjectState(pObject, eObjectState_Fishing);
	OBJECTEFFECTDESC desc( FindEffectNum("char_m_fishing_swing_A.beff") );

	pObject->RemoveObjectEffect( FISHING_START_EFFECT );
	pObject->AddObjectEffect( FISHING_START_EFFECT, &desc, 1 );
}
Beispiel #4
0
// TO-DO: Remove this. NPCs don't just randomly die, it would make sense to do this as a result of the cause, not just because.
void CAISocket::RecvNpcDead(Packet & pkt)
{
	CNpc * pNpc;
	Unit * pAttacker;
	uint16 nid, attackerID;
	pkt >> nid >> attackerID;

	pNpc = g_pMain->GetNpcPtr(nid);
	if (pNpc == nullptr
		|| pNpc->GetMap() == nullptr)
		return;

	pAttacker = g_pMain->GetUnitPtr(attackerID);
	pNpc->OnDeath(pAttacker);
}
Beispiel #5
0
void CUser::HealAreaCheck(int rx, int rz)
{
	MAP* pMap = GetMap();
	if (pMap == NULL) return;
	// 자신의 region에 있는 NpcArray을 먼저 검색하여,, 가까운 거리에 Monster가 있는지를 판단..
	if(rx < 0 || rz < 0 || rx > pMap->GetXRegionMax() || rz > pMap->GetZRegionMax())	{
		TRACE("#### CUser-HealAreaCheck() Fail : [nid=%d, name=%s], nRX=%d, nRZ=%d #####\n", m_iUserId, m_strUserID, rx, rz);
		return;
	}

	float fRadius = 10.0f;				// 30m

	__Vector3 vStart, vEnd;
	CNpc* pNpc = NULL ;      // Pointer initialization!
	float fDis = 0.0f;
	vStart.Set(m_curx, (float)0, m_curz);
	int send_index=0, result = 1, count = 0; 

	EnterCriticalSection( &g_region_critical );
	CRegion *pRegion = &pMap->m_ppRegion[rx][rz];
	int total_mon = pRegion->m_RegionNpcArray.GetSize();
	int *pNpcIDList = new int[total_mon];
	foreach_stlmap (itr, pRegion->m_RegionNpcArray)
		pNpcIDList[count++] = *itr->second;

	LeaveCriticalSection( &g_region_critical );

	for(int i = 0 ; i < total_mon; i++ ) {
		int nid = pNpcIDList[i];
		if( nid < NPC_BAND ) continue;
		pNpc = (CNpc*)g_pMain->m_arNpc.GetData(nid - NPC_BAND);

		if( pNpc != NULL && pNpc->m_NpcState != NPC_DEAD)	{
			if( m_bNation == pNpc->m_byGroup ) continue;
			vEnd.Set(pNpc->m_fCurX, pNpc->m_fCurY, pNpc->m_fCurZ); 
			fDis = pNpc->GetDistance(vStart, vEnd);

			if(fDis <= fRadius)	{	// NPC가 반경안에 있을 경우...
				pNpc->ChangeTarget(1004, this);
			}	
		}
	}

	if (pNpcIDList)
		delete [] pNpcIDList;
}
CNpc* CRoomEvent::GetNpcPtr( int sid )
{
	if (m_mapRoomNpcArray.IsEmpty())	
	{
		TRACE("### RoomEvent-GetNpcPtr() : monster empty ###\n");
		return nullptr;
	}

	foreach_stlmap (itr, m_mapRoomNpcArray)
	{
		CNpc *pNpc = g_pMain->GetNpcPtr(itr->first);
		if (pNpc == nullptr
			|| pNpc->GetProtoID() != sid)
			continue;

		return pNpc;
	}
Beispiel #7
0
void CAISocket::RecvNpcInOut(char* pBuf)
{
	int index = 0, nid = 0, nType = 0;
	float fx = 0.0f, fz=0.0f, fy=0.0f;

	nType = GetByte( pBuf, index );
	nid = GetShort(pBuf, index);
	fx = Getfloat( pBuf, index );
	fz = Getfloat( pBuf, index );
	fy = Getfloat( pBuf, index );

	if(nid >= NPC_BAND)		{
		CNpc* pNpc = m_pMain->m_arNpcArray.GetData(nid);
		if(!pNpc)	return;
		pNpc->NpcInOut( nType, fx, fz, fy );
	}
}
Beispiel #8
0
void CUser::Attack(int sid, int tid)
{
	CNpc* pNpc = m_pMain->m_arNpc.GetData(tid-NPC_BAND);
	if(pNpc == NULL)	return;
	if(pNpc->m_NpcState == NPC_DEAD) return;
	if(pNpc->m_iHP == 0) return;

/*	if(pNpc->m_tNpcType == NPCTYPE_GUARD)					// 경비병이면 타겟을 해당 유저로
	{
		pNpc->m_Target.id = m_iUserId + USER_BAND;
		pNpc->m_Target.x = m_curx;
		pNpc->m_Target.y = m_cury;
		pNpc->m_Target.failCount = 0;
		pNpc->Attack(m_pIocport);
	//	return;
	}	*/

	int nDefence = 0, nFinalDamage = 0;
	// NPC 방어값 
	nDefence = pNpc->GetDefense();

	// 명중이면 //Damage 처리 ----------------------------------------------------------------//
	nFinalDamage = GetDamage(tid);
	if( m_pMain->m_byTestMode )		nFinalDamage = 3000;	// sungyong test
		
	// Calculate Target HP	 -------------------------------------------------------//
	short sOldNpcHP = pNpc->m_iHP;

	if(pNpc->SetDamage(0, nFinalDamage, m_strUserID, m_iUserId + USER_BAND, m_pIocport) == FALSE)
	{
		// Npc가 죽은 경우,,
		pNpc->SendExpToUserList(); // 경험치 분배!!
		pNpc->SendDead(m_pIocport);
		SendAttackSuccess(tid, ATTACK_TARGET_DEAD, nFinalDamage, pNpc->m_iHP);

	//	CheckMaxValue(m_dwXP, 1);		// 몹이 죽을때만 1 증가!	
	//	SendXP();
	}
	else
	{
		// 공격 결과 전송
		SendAttackSuccess(tid, ATTACK_SUCCESS, nFinalDamage, pNpc->m_iHP);
	}
	//	m_dwLastAttackTime = GetTickCount();
}
uint8 CMagicProcess::ExecuteType2(int magicid, int tid, int data1, int data2, int data3)
{
	Packet result(AG_MAGIC_ATTACK_RESULT, uint8(MAGIC_EFFECTING));
	int damage = m_pSrcUser->GetDamage(tid, magicid);;
	uint8 bResult = 1;
	
	result << magicid << m_pSrcUser->m_iUserId << tid << data1;

	if (damage > 0){
		CNpc* pNpc = nullptr ;      // Pointer initialization!
		pNpc = g_pMain->m_arNpc.GetData(tid-NPC_BAND);
		if(pNpc == nullptr || pNpc->m_NpcState == NPC_DEAD || pNpc->m_iHP == 0)	{
			bResult = 0;
			goto packet_send;
		}

		if (!pNpc->SetDamage(magicid, damage, m_pSrcUser->m_strUserID, m_pSrcUser->m_iUserId + USER_BAND))
		{
			result	<< int16(bResult) << data3 << int16(0) << int16(0) << int16(0)
					<< int16(damage == 0 ? -104 : 0);
			g_pMain->Send(&result);

			pNpc->SendExpToUserList(); // 경험치 분배!!
			pNpc->SendDead();
			m_pSrcUser->SendAttackSuccess(tid, MAGIC_ATTACK_TARGET_DEAD, damage, pNpc->m_iHP);
			//m_pSrcUser->SendAttackSuccess(tid, ATTACK_TARGET_DEAD, damage, pNpc->m_iHP);

			return bResult;
		}
		else	{
			// 공격 결과 전송
			m_pSrcUser->SendAttackSuccess(tid, ATTACK_SUCCESS, damage, pNpc->m_iHP);
		}
	}
//	else
//		result = 0;

packet_send:
	// this is a little redundant but leaving it in just in case order is intended
	// this should all be removed eventually anyway...
	result	<< int16(bResult) << data3 << int16(0) << int16(0) << int16(0)
			<< int16(damage == 0 ? -104 : 0);
	g_pMain->Send(&result);
	return bResult;
}
uint8 CMagicProcess::ExecuteType1(int magicid, int tid, int data1, int data2, int data3, uint8 sequence)   // Applied to an attack skill using a weapon.
{	
	int damage = 0;
	uint8 bResult = 1;     // Variable initialization. result == 1 : success, 0 : fail
	_MAGIC_TABLE* pMagic = g_pMain->m_MagictableArray.GetData( magicid );   // Get main magic table.
	if( !pMagic ) return 0; 

	damage = m_pSrcUser->GetDamage(tid, magicid);  // Get damage points of enemy.	
// 	if(damage <= 0)	damage = 1;
	//TRACE("magictype1 ,, magicid=%d, damage=%d\n", magicid, damage);

//	if (damage > 0) {
		CNpc* pNpc = nullptr ;      // Pointer initialization!
		pNpc = g_pMain->m_arNpc.GetData(tid-NPC_BAND);
		if(pNpc == nullptr || pNpc->m_NpcState == NPC_DEAD || pNpc->m_iHP == 0)	{
			bResult = 0;
			goto packet_send;
		}

		if(pNpc->SetDamage(magicid, damage, m_pSrcUser->m_strUserID, m_pSrcUser->m_iUserId + USER_BAND) == false)	{
			// Npc가 죽은 경우,,
			pNpc->SendExpToUserList(); // 경험치 분배!!
			pNpc->SendDead();
			//m_pSrcUser->SendAttackSuccess(tid, MAGIC_ATTACK_TARGET_DEAD, 0, pNpc->m_iHP);
			m_pSrcUser->SendAttackSuccess(tid, ATTACK_TARGET_DEAD, damage, pNpc->m_iHP);
		}
		else	{
			// 공격 결과 전송
			m_pSrcUser->SendAttackSuccess(tid, ATTACK_SUCCESS, damage, pNpc->m_iHP);
		}

packet_send:
	if (pMagic->bType[1] == 0 || pMagic->bType[1] == 1)
	{
		Packet result(AG_MAGIC_ATTACK_RESULT, uint8(MAGIC_EFFECTING));
		result	<< magicid
				<< m_pSrcUser->m_iUserId << int16(tid) 
				<< int16(data1) << uint8(bResult) << int16(data3)
				<< int16(0) << int16(0) << int16(0)
				<< int16(damage == 0 ? -104 : 0);
		g_pMain->Send(&result);	
	}

	return bResult;
}
	bool OnGS2C_LookInfoNpc(struct pk::GS2C_LookInfoNpc *value)
	{
		if ( !gMap )
		{
			return false;
		}

		CNpc* pNPC = CNpc::create();
		if ( pNPC )
		{
			pNPC->SetId(value->id);
			//pNPC->SetDataID(value->npc_data_id);
			pNPC->SetDataID(1000000);

			pNPC->EnterMap(gMap,value->x,value->y);
		}

		return true;
	}
Beispiel #12
0
BOOL CServerDlg::CreateNpcThread()
{
    m_TotalNPC = m_sMapEventNpc;
    m_CurrentNPC = 0;
    m_CurrentNPCError = 0;

    LOAD_TABLE_ERROR_ONLY(CNpcPosSet, &m_GameDB, NULL, false);

    int step = 0, nThreadNumber = 0;
    CNpcThread* pNpcThread = NULL;
    DWORD id;

    foreach_stlmap (itr, m_arNpc)
    {
        if (step == 0)
            pNpcThread = new CNpcThread;

        CNpc *pNpc = pNpcThread->m_pNpc[step] = itr->second;
        pNpc->m_sThreadNumber = nThreadNumber;
        pNpc->Init();

        ++step;

        if( step == NPC_NUM )
        {
            pNpcThread->m_sThreadNumber = nThreadNumber++;
            pNpcThread->m_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&NpcThreadProc, &(pNpcThread->m_ThreadInfo), CREATE_SUSPENDED, &id);
            m_arNpcThread.push_back( pNpcThread );
            step = 0;
        }
    }
    if( step != 0 )
    {
        pNpcThread->m_sThreadNumber = nThreadNumber++;
        pNpcThread->m_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&NpcThreadProc, &(pNpcThread->m_ThreadInfo), CREATE_SUSPENDED, &id);
        m_arNpcThread.push_back( pNpcThread );
    }

    m_hZoneEventThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&ZoneEventThreadProc, (LPVOID)(this), CREATE_SUSPENDED, &id);
    printf("[Monster Init - %d, threads=%d]\n", m_TotalNPC, m_arNpcThread.size());
    return TRUE;
}
Beispiel #13
0
void CAISocket::RecvMagicAttackResult(Packet & pkt)
{
	uint32 magicid;
	uint16 sid, tid;
	uint8 byCommand; 

	/* 
		This is all so redundant...
		When everything's switched over to pass in Packets
		we can just pass it through directly!
		As it is now.. we still need a length (which we can hardcode, but meh)
	*/
	pkt >> byCommand >> magicid >> sid >> tid;

	pkt.SetOpcode(WIZ_MAGIC_PROCESS);
	if (byCommand == MAGIC_CASTING
		|| (byCommand == MAGIC_EFFECTING && sid >= NPC_BAND && tid >= NPC_BAND))
	{
		CNpc *pNpc = g_pMain->m_arNpcArray.GetData(sid);
		if (!pNpc)
			return;

		pNpc->SendToRegion(&pkt);
	}
	else if (byCommand == MAGIC_EFFECTING)
	{
		if (sid >= USER_BAND && sid < NPC_BAND)
		{
			CUser *pUser = g_pMain->GetUserPtr(sid);
			if (pUser == NULL || pUser->isDead())
				return;

			pUser->SendToRegion(&pkt);
			return;
		}

		// If we're an NPC, casting a skill (rather, it's finished casting) on a player...
		pkt.rpos(0);
		m_MagicProcess.MagicPacket(pkt);
	}
	
}
Beispiel #14
0
void CAISocket::RecvNpcMoveResult(Packet & pkt)
{
	uint8 flag;			// 01(INFO_MODIFY), 02(INFO_DELETE)	
	uint16 sNid;
	float fX, fY, fZ, fSecForMetor;
	pkt >> flag >> sNid >> fX >> fZ >> fY >> fSecForMetor;

	CNpc * pNpc = g_pMain->GetNpcPtr(sNid);
	if (pNpc == nullptr)
		return;

	if (pNpc->isDead())
	{
		Packet result(AG_NPC_HP_REQ);
		result << sNid << pNpc->m_iHP;
		Send(&result);
	}

	pNpc->MoveResult(fX, fY, fZ, fSecForMetor);
}
void CGameSocket::RecvNpcHpChange(Packet & pkt)
{
	int16 nid, sAttackerID;
	int32 nHP, nAmount;
	pkt >> nid >> sAttackerID >> nHP >> nAmount;
	CNpc * pNpc = g_pMain->m_arNpc.GetData(nid);
	if (pNpc == nullptr)
		return;

	if (nAmount < 0)
	{
		pNpc->SetDamage(0, -nAmount, sAttackerID, 1);
	}
	else
	{		
		pNpc->m_iHP += nAmount;
		if (pNpc->m_iHP > pNpc->m_iMaxHP)
			pNpc->m_iHP = pNpc->m_iMaxHP;
	}
}
void CGameSocket::RecvBattleEvent(char* pBuf)
{
	int index = 0, i=0;
	int nType = 0, nEvent = 0;
	CNpc* pNpc = NULL;

	nType = GetByte(pBuf,index);
	nEvent = GetByte(pBuf,index);

	if( nEvent == BATTLEZONE_OPEN )	{
		m_pMain->m_sKillKarusNpc = 0;
		m_pMain->m_sKillElmoNpc = 0;
		m_pMain->m_byBattleEvent = BATTLEZONE_OPEN;
		TRACE("----> RecvBattleEvent : Battle zone Open \n");
	}
	else if( nEvent == BATTLEZONE_CLOSE )	{
		m_pMain->m_sKillKarusNpc = 0;
		m_pMain->m_sKillElmoNpc = 0;
		m_pMain->m_byBattleEvent = BATTLEZONE_CLOSE;
		TRACE("<---- RecvBattleEvent : Battle zone Close \n");
		m_pMain->ResetBattleZone();
	}

	int nSize = m_pMain->m_arNpc.GetSize();

	for( i = 0; i < nSize; i++)	{
		pNpc = m_pMain->m_arNpc.GetData( i );
		if( !pNpc ) continue;
		if( pNpc->m_tNpcType > 10 && (pNpc->m_byGroup == KARUS_ZONE || pNpc->m_byGroup == ELMORAD_ZONE) )	{	// npc에만 적용되고, 국가에 소속된 npc
			if( nEvent == BATTLEZONE_OPEN )	{		// 전쟁 이벤트 시작 (npc의 능력치 다운)
				pNpc->ChangeAbility( BATTLEZONE_OPEN );
			}
			else if( nEvent == BATTLEZONE_CLOSE )	{	// 전쟁 이벤트 끝 (npc의 능력치 회복)	
				pNpc->ChangeAbility( BATTLEZONE_CLOSE );
			}
		}
	}

	
}
Beispiel #17
0
void CUser::Attack(int sid, int tid)
{
    CNpc* pNpc = g_pMain->m_arNpc.GetData(tid-NPC_BAND);
    if(pNpc == nullptr)	return;
    if(pNpc->m_NpcState == NPC_DEAD) return;
    if(pNpc->m_iHP == 0) return;

    /*	if(pNpc->m_proto->m_tNpcType == NPCTYPE_GUARD)					// 경비병이면 타겟을 해당 유저로
    	{
    		pNpc->m_Target.id = m_iUserId + USER_BAND;
    		pNpc->m_Target.x = m_curx;
    		pNpc->m_Target.y = m_cury;
    		pNpc->m_Target.failCount = 0;
    		pNpc->Attack();
    	//	return;
    	}	*/

    int nDefence = 0, nFinalDamage = 0;
    // NPC 방어값
    nDefence = pNpc->GetDefense();

    // 명중이면 //Damage 처리 ----------------------------------------------------------------//
    nFinalDamage = GetDamage(tid);

    // Calculate Target HP	 -------------------------------------------------------//
    short sOldNpcHP = pNpc->m_iHP;

    if(pNpc->SetDamage(0, nFinalDamage, m_strUserID, m_iUserId + USER_BAND) == false)
    {
        // Npc가 죽은 경우,,
        pNpc->SendExpToUserList(); // 경험치 분배!!
        pNpc->SendDead();
        SendAttackSuccess(tid, ATTACK_TARGET_DEAD, nFinalDamage, pNpc->m_iHP);
    }
    else
    {
        // 공격 결과 전송
        SendAttackSuccess(tid, ATTACK_SUCCESS, nFinalDamage, pNpc->m_iHP);
    }
}
Beispiel #18
0
void CGameSocket::RecvNpcHpChange(Packet & pkt)
{
	int16 nid, sAttackerID;
	int32 nHP, nAmount;
	uint8 attributeType = AttributeNone;

	pkt >> nid >> sAttackerID >> nHP >> nAmount >> attributeType;
	CNpc * pNpc = g_pMain->GetNpcPtr(nid);
	if (pNpc == nullptr)
		return;

	if (nAmount < 0)
	{
		pNpc->RecvAttackReq(-nAmount, sAttackerID, (AttributeType) attributeType);
	}
	else
	{		
		pNpc->m_iHP += nAmount;
		if (pNpc->m_iHP > pNpc->m_iMaxHP)
			pNpc->m_iHP = pNpc->m_iMaxHP;
	}
}
Beispiel #19
0
void CAISocket::RecvNpcAttack(Packet & pkt)
{
	CNpc * pAttacker;
	Unit * pTarget;
	uint16 sAttackerID, sTargetID;
	int16 sDamage;
	uint8 bResult = ATTACK_FAIL;

	pkt >> sAttackerID >> sTargetID;

	pAttacker = g_pMain->GetNpcPtr(sAttackerID);
	pTarget = g_pMain->GetUnitPtr(sTargetID);

	if (pAttacker == nullptr
		|| pAttacker->isPlayer()
		|| pTarget == nullptr
		|| pAttacker->isDead()
		|| pTarget->isDead())
		return;

	// TO-DO: Wrap this up into its own virtual method
	sDamage = pAttacker->GetDamage(pTarget);
	if (sDamage > 0)
	{
		pTarget->HpChange(-(sDamage), pAttacker);
		if (pTarget->isDead())
			bResult = ATTACK_TARGET_DEAD;
		else
			bResult = ATTACK_SUCCESS;

		// Every hit takes a little of the defender's armour durability.
		if (pTarget->isPlayer())
			TO_USER(pTarget)->ItemWoreOut(DEFENCE, sDamage);
	}

	Packet result(WIZ_ATTACK, uint8(DIRECT_ATTACK));
	result << bResult << sAttackerID << sTargetID;
	pAttacker->SendToRegion(&result);
}
Beispiel #20
0
bool CServerDlg::CreateNpcThread()
{
	m_TotalNPC = m_sMapEventNpc;
	m_CurrentNPC = 0;

	LOAD_TABLE_ERROR_ONLY(CNpcPosSet, &m_GameDB, nullptr, false);
			
	foreach_stlmap (itr, g_arZone)
	{
		CNpcThread * pNpcThread = new CNpcThread;
		m_arNpcThread.push_back(pNpcThread);

		foreach_stlmap (npcItr, m_arNpc)
		{
			if (npcItr->second->m_bCurZone != itr->first)
				continue;

			CNpc * pNpc = npcItr->second;
			pNpc->Init();
			pNpcThread->m_pNpcs.insert(pNpc);
		}
	}
Beispiel #21
0
void CAISocket::InitEventMonster(int index)
{
	int count = index;
	if( count < 0 || count > NPC_BAND )	{
		TRACE("### InitEventMonster index Fail = %d ###\n", index);
		return;
	}

	int max_eventmop = count+EVENT_MONSTER;
	for( int i=count; i<max_eventmop; i++ )	{
		CNpc* pNpc = new CNpc();
		pNpc->m_sNid = i+NPC_BAND;
		//TRACE("InitEventMonster : uid = %d\n", pNpc->m_sNid);
		if (!g_pMain->m_arNpcArray.PutData(pNpc->GetID(), pNpc))
		{
			TRACE("Npc PutData Fail - %d\n", pNpc->GetID());
			pNpc->DecRef();
		}	
	}

	count = g_pMain->m_arNpcArray.GetSize();
	TRACE("TotalMonster = %d\n", count);
}
Beispiel #22
0
/**
* @brief	Executes the death action.
*
* @param	pKiller	The killer.
*/
void CNpc::OnDeath(Unit *pKiller)
{
	if (m_NpcState == NPC_DEAD)
		return;

	ASSERT(GetMap() != nullptr);
	ASSERT(GetRegion() != nullptr);

	m_NpcState = NPC_DEAD;

	if (m_byObjectType == SPECIAL_OBJECT)
	{
		_OBJECT_EVENT *pEvent = GetMap()->GetObjectEvent(GetProtoID());
		if (pEvent != nullptr)
			pEvent->byLife = 0;
	}

	Unit::OnDeath(pKiller);

	CNpc * pNpc = TO_NPC(this);
	CUser * pUser = TO_USER(pKiller);

	if (pNpc != nullptr && pUser != nullptr)
	{
		if (pNpc->isMonster() && pUser->isPlayer())
		{
			if (pNpc->m_sSid == 700 || pNpc->m_sSid == 750)
			{
				if (pUser->CheckExistEvent(STARTER_SEED_QUEST, 0) || pUser->CheckExistEvent(STARTER_SEED_QUEST, 1))
					pUser->SaveEvent(STARTER_SEED_QUEST, 2);
			}
		}
	}

	GetRegion()->Remove(TO_NPC(this));
	SetRegion();
}
Beispiel #23
0
bool CServerDlg::CreateNpcThread()
{
	m_TotalNPC = m_sMapEventNpc;
	m_CurrentNPC = 0;

	LOAD_TABLE_ERROR_ONLY(CNpcPosSet, &m_GameDB, nullptr, false);

	FastGuard lock(m_eventThreadLock);
	foreach_stlmap (itr, g_arZone)
	{
		CNpcThread * pNpcThread = new CNpcThread();
		m_arNpcThread.insert(make_pair(itr->first, pNpcThread));
		m_arEventNpcThread.insert(make_pair(itr->first, new CNpcThread()));

		foreach_stlmap (npcItr, m_arNpc)
		{
			if (npcItr->second->GetZoneID() != itr->first)
				continue;

			CNpc * pNpc = npcItr->second;
			pNpc->Init();
			pNpcThread->m_pNpcs.insert(pNpc);
		}
	}
Beispiel #24
0
void CAISocket::RecvNpcDead(char* pBuf)
{
	int index = 0, send_index = 0;
	int nid = 0;
	char send_buff[256];
	_OBJECT_EVENT* pEvent = NULL;

	nid = GetShort(pBuf,index);


	if(nid >= NPC_BAND)		{
		CNpc* pNpc = m_pMain->m_arNpcArray.GetData(nid);
		if(!pNpc)	return;

		C3DMap* pMap = pNpc->GetMap();
		if (pMap == NULL)
			return;

		if( pNpc->m_byObjectType == SPECIAL_OBJECT )	{
			pEvent = pMap->GetObjectEvent( pNpc->m_sSid );
			if( pEvent )	pEvent->byLife = 0;
		}

		//pNpc->NpcInOut( NPC_OUT );
		//TRACE("RecvNpcDead - (%d,%s)\n", pNpc->m_sNid, pNpc->m_strName);

		pMap->RegionNpcRemove(pNpc->m_sRegion_X, pNpc->m_sRegion_Z, nid);
		//TRACE("--- RecvNpcDead : Npc를 Region에서 삭제처리.. ,, zone=%d, region_x=%d, y=%d\n", pNpc->m_sZoneIndex, pNpc->m_sRegion_X, pNpc->m_sRegion_Z);

		SetByte( send_buff, WIZ_DEAD, send_index );
		SetShort( send_buff, nid, send_index );
		m_pMain->Send_Region(send_buff, send_index, pNpc->GetMap(), pNpc->m_sRegion_X, pNpc->m_sRegion_Z, NULL, false);

		pNpc->m_sRegion_X = 0;		pNpc->m_sRegion_Z = 0;
	}
}
Beispiel #25
0
bool CLevel::loadNW(CString& pFileName)
{
	CStringList levelData;
	CString version;
	char* dataFile = getDataFile(pFileName.text());
	if(!strlen(dataFile))
		return false;

	if(!levelData.load(dataFile))
		return false;

	if(levelData.count() < 1)
		return false;

	version = levelData[0];
	modTime = getFileModTime(dataFile);
	fileName = pFileName;
	if(version == "GLEVNW01" || version == "GSERVL01")
	{
		for(int i = 1; i < levelData.count(); i ++)
		{
			CStringList words;
			words.load(levelData[i].text(), " ");
			if(words.count() <= 0)
				continue;
			if(words[0] == "BOARD")
			{
				if(words.count() <= 5)
					continue;

				int x = atoi(words[1].text());
				int y = atoi(words[2].text());
				int w = atoi(words[3].text());
				CString& data = words[5];
				if(x >= 0 && x <= 64 && y >= 0 && y <= 64 && w > 0 && x + w <= 64)
				{
					if(data.length() >= w*2)
					{
						for(int ii = x; ii < x + w; ii++)
						{
							char left = data.readChar();
							char top = data.readChar();
							short tile = base64.find(left) << 6;
							tile += base64.find(top);
							tiles[ii + y*64] = tile;
						}
					}
				}
			} else if(words[0] == "LINK")
			{
				if(words.count() <= 7)
					continue;
				if(strlen(getDataFile(words[1].text())))
				{
					links.add(new CLink(words[1], atoi(words[2].text()), atoi(words[3].text()),
						atoi(words[4].text()), atoi(words[5].text()), words[6], words[7]));
				}
			} else if(words[0] == "CHEST")
			{
				if(words.count() <= 4)
					continue;
				for(int ii = 0; ii < itemcount; ii++)
				{
					if(words[3] == itemNames[ii])
					{
						chests.add(new CChest(atoi(words[1].text()), atoi(words[2].text()),
							atoi(words[4].text()), ii));
						break;
					}
				}

			} else if(words[0] == "NPC")
			{
				if(words.count() <= 3)
					continue;
				CString image, code, code2;
				float x, y;
				if(words[1] != "-")
					image = words[1];

				x = (float)atof(words[2].text());
				y = (float)atof(words[3].text());
				for(i++; i < levelData.count() && levelData[i] != "NPCEND"; i++)
					code << levelData[i] << "\xa7";

				// Create the new NPC.  Do this before parsing the join commands.
				// The CNpc constructor will remove all comments.
				CNpc* jnpc = new CNpc( image, code, x, y, this, true );

				// Now filter out the join commands.
				CStringList npcData;
				npcData.load( jnpc->clientCode.text(), "\xa7" );
				for ( int j = 0; j < npcData.count(); ++j )
					code2 << processNpcLine( npcData[j] ) << "\xa7";
				jnpc->clientCode = code2;

				// Now, add all the joined files to the code.
				if ( joinList.count() > 0 )
				{
					CString* file = 0;
					while ( (file = (CString*)joinList[0]) != 0 )
					{
						// Load the source file into memory.
						CString dataFile = getDataFile(file->text());
						if(dataFile.length())
						{
							// Append to the end of the script.
							CString retVal;
							retVal.load(dataFile.text());
							retVal.replaceAll("\r\n", "\xa7");
							retVal.replaceAll("\n", "\xa7");
							jnpc->clientCode << retVal << "\xa7";
						}
						delete (CString*)joinList[0];
						joinList.remove(0);
					}
				}
				joinList.clear();

				npcs.add( jnpc );
			} else if(words[0] == "BADDY")
			{
				if(words.count() <= 3)
					continue;
				int x = atoi(words[1].text());
				int y = atoi(words[2].text());
				int type = atoi(words[3].text());

				CBaddy* baddy = new CBaddy(x, y, type);
				int baddyId = createBaddyId(baddy);
				baddy->id = baddyId;
				for(i++; i < levelData.count() && levelData[i] != "BADDYEND"; i++)
					baddy->verses.add(levelData[i].text());
				if(baddies.count() < 50)
					baddies.add(baddy);
				else delete baddy;
			} else if(words[0] == "SIGN")
			{
				if(words.count() <= 2)
					continue;

				CString sign;
				int x = atoi(words[1].text());
				int y = atoi(words[2].text());
				sign.writeChar(x+32);
				sign.writeChar(y+32);

				for (i++; i < levelData.count() && levelData[i] != "SIGNEND"; i++)
					sign << getSignCode(CString() << levelData[i] << "\n");
				signs.add(sign);
			} else if(words[0] == "REPLACENPC")
			{
				int npcId = atoi(words[1].text());
				CNpc* npc = (CNpc*)npcs[npcId];
				if(npc == NULL)
					continue;

				for(i++; i < levelData.count() && levelData[i] != "REPLACENPCEND"; i++)
					npc->setProps((CPacket&)levelData[i]);
			}
		}
	} else return false;

	return true;
}
//	Npc Thread 를 만든다.
BOOL CServerDlg::CreateNpcThread()
{
    BOOL	bMoveNext	= TRUE;
    int		nSerial		= m_sMapEventNpc;
    int		nPathSerial = 1;
    int		nNpcCount	= 0;
    int		i=0, j=0;
    int nRandom = 0, nServerNum = 0;
    double  dbSpeed = 0;

    m_TotalNPC = 0;			// DB에 있는 수
    m_CurrentNPC = 0;
    m_CurrentNPCError = 0;

    CNpcTable*	pNpcTable = NULL;
    CRoomEvent* pRoom = NULL;

    CNpcPosSet NpcPosSet;

    char szPath[500];
    char szX[5];
    char szZ[5];

    float fRandom_X = 0.0f;
    float fRandom_Z = 0.0f;

    int nMonsterNumber = 0;

    try
    {
        if(NpcPosSet.IsOpen()) NpcPosSet.Close();
        if(!NpcPosSet.Open())	{
            AfxMessageBox(_T("MONSTER_POS DB Open Fail!"));
            return FALSE;
        }
        if(NpcPosSet.IsBOF())	{
            AfxMessageBox(_T("MONSTER_POS DB Empty!"));
            return FALSE;
        }

        NpcPosSet.MoveFirst();

        while(!NpcPosSet.IsEOF())	{
            nMonsterNumber = NpcPosSet.m_NumNPC;
            //if( NpcPosSet.m_ZoneID == 101 )	{	// 테스트를 위해서,,
            //	nMonsterNumber = 1;
            //if(nMonsterNumber > 4)	{
            //	nMonsterNumber = nMonsterNumber / 4;
            //}
            //}
            nServerNum = 0;
            nServerNum = GetServerNumber( NpcPosSet.m_ZoneID );

            if( m_byZone == nServerNum || m_byZone == UNIFY_ZONE)	{
                for(j=0; j<nMonsterNumber; j++)		{
                    CNpc*		pNpc		= new CNpc();

                    pNpc->m_byMoveType = NpcPosSet.m_ActType;
                    pNpc->m_byInitMoveType = NpcPosSet.m_ActType;

                    bool bMonster = (NpcPosSet.m_ActType < 100);
                    if (bMonster)
                        pNpcTable = m_arMonTable.GetData(NpcPosSet.m_NpcID);
                    else
                    {
                        pNpc->m_byMoveType = NpcPosSet.m_ActType - 100;
                        //pNpc->m_byInitMoveType = NpcPosSet.m_ActType - 100;
                        pNpcTable = m_arNpcTable.GetData(NpcPosSet.m_NpcID);
                    }

                    if (pNpcTable == NULL)
                    {
                        char buff[128] = {0};
                        sprintf(buff, "NPC %d not found in %s table.", pNpc->m_sNid, bMonster ? "K_MONSTER" : "K_NPC");
                        AfxMessageBox(buff);
                        delete pNpc;
                        return FALSE;
                    }

                    pNpc->Load(nSerial++, pNpcTable);
                    pNpc->m_byBattlePos = 0;

                    if(pNpc->m_byMoveType >= 2)	{
                        pNpc->m_byBattlePos = myrand( 1, 3 );
                        pNpc->m_byPathCount = nPathSerial++;
                    }

                    pNpc->InitPos();

                    if( bMoveNext )	{
                        bMoveNext = FALSE;
                        nNpcCount = NpcPosSet.m_NumNPC;
                    }

                    //////// MONSTER POS ////////////////////////////////////////
                    pNpc->m_bCurZone = NpcPosSet.m_ZoneID;

                    // map에 몬스터의 위치를 랜덤하게 위치시킨다.. (테스트 용 : 수정-DB에서 읽어오는데로 몬 위치 결정)
                    nRandom = abs(NpcPosSet.m_LeftX - NpcPosSet.m_RightX);
                    if(nRandom <= 1)
                        fRandom_X = (float)NpcPosSet.m_LeftX;
                    else	{
                        if(NpcPosSet.m_LeftX < NpcPosSet.m_RightX)
                            fRandom_X = (float)myrand(NpcPosSet.m_LeftX, NpcPosSet.m_RightX);
                        else
                            fRandom_X = (float)myrand(NpcPosSet.m_RightX, NpcPosSet.m_LeftX);
                    }
                    nRandom = abs(NpcPosSet.m_TopZ - NpcPosSet.m_BottomZ);
                    if(nRandom <= 1)
                        fRandom_Z = (float)NpcPosSet.m_TopZ;
                    else	{
                        if(NpcPosSet.m_TopZ < NpcPosSet.m_BottomZ)
                            fRandom_Z = (float)myrand(NpcPosSet.m_TopZ, NpcPosSet.m_BottomZ);
                        else
                            fRandom_Z = (float)myrand(NpcPosSet.m_BottomZ, NpcPosSet.m_TopZ);
                    }

                    pNpc->m_fCurX	= fRandom_X;
                    pNpc->m_fCurY	= 0;
                    pNpc->m_fCurZ	= fRandom_Z;

                    pNpc->m_sRegenTime		= NpcPosSet.m_RegTime * 1000;	// 초(DB)단위-> 밀리세컨드로
                    pNpc->m_byDirection = NpcPosSet.m_byDirection;
                    pNpc->m_sMaxPathCount = NpcPosSet.m_DotCnt;

                    if( pNpc->m_byMoveType >= 2 && NpcPosSet.m_DotCnt == 0 )	{
                        pNpc->m_byMoveType = 1;
                        TRACE("##### ServerDlg:CreateNpcThread - Path type Error :  nid=%d, sid=%d, name=%s, acttype=%d, path=%d #####\n", pNpc->m_sNid+NPC_BAND, pNpc->m_proto->m_sSid, pNpc->m_proto->m_strName, pNpc->m_byMoveType, pNpc->m_sMaxPathCount);
                    }

                    int index = 0;
                    strcpy_s(szPath, sizeof(szPath), NpcPosSet.m_path);

                    if(NpcPosSet.m_DotCnt != 0)	{
                        for(int l = 0; l<NpcPosSet.m_DotCnt; l++)	{
                            memset(szX, 0x00, 5);
                            memset(szZ, 0x00, 5);
                            GetString(szX, szPath, 4, index);
                            GetString(szZ, szPath, 4, index);
                            pNpc->m_PathList.pPattenPos[l].x = atoi(szX);
                            pNpc->m_PathList.pPattenPos[l].z = atoi(szZ);
                            //	TRACE(" l=%d, x=%d, z=%d\n", l, pNpc->m_PathList.pPattenPos[l].x, pNpc->m_PathList.pPattenPos[l].z);
                        }
                    }

                    //pNpc->m_byType			= NpcPosSet.m_byType;

                    pNpc->m_tItemPer		= pNpcTable->m_tItemPer;	// NPC Type
                    pNpc->m_tDnPer			= pNpcTable->m_tDnPer;	// NPC Type

                    pNpc->m_nInitMinX = pNpc->m_nLimitMinX		= NpcPosSet.m_LeftX;
                    pNpc->m_nInitMinY = pNpc->m_nLimitMinZ		= NpcPosSet.m_TopZ;
                    pNpc->m_nInitMaxX = pNpc->m_nLimitMaxX		= NpcPosSet.m_RightX;
                    pNpc->m_nInitMaxY = pNpc->m_nLimitMaxZ		= NpcPosSet.m_BottomZ;
                    // dungeon work
                    pNpc->m_byDungeonFamily	= NpcPosSet.m_DungeonFamily;
                    pNpc->m_bySpecialType	= NpcPosSet.m_SpecialType;
                    pNpc->m_byRegenType		= NpcPosSet.m_RegenType;
                    pNpc->m_byTrapNumber    = NpcPosSet.m_TrapNumber;

                    if( pNpc->m_byDungeonFamily > 0 )	{
                        pNpc->m_nLimitMinX = NpcPosSet.m_LimitMinX;
                        pNpc->m_nLimitMinZ = NpcPosSet.m_LimitMinZ;
                        pNpc->m_nLimitMaxX = NpcPosSet.m_LimitMaxX;
                        pNpc->m_nLimitMaxZ = NpcPosSet.m_LimitMaxZ;
                    }

                    pNpc->m_pZone = GetZoneByID(pNpc->m_bCurZone);
                    if (pNpc->GetMap() == NULL)		{
                        AfxMessageBox("Error : CServerDlg,, Invaild zone Index!!");
                        delete pNpc;
                        return FALSE;
                    }

                    if( !m_arNpc.PutData( pNpc->m_sNid, pNpc) )		{
                        TRACE("Npc PutData Fail - %d\n", pNpc->m_sNid);
                        delete pNpc;
                        pNpc = NULL;
                        continue;
                    }

                    pNpc->SetUid(pNpc->m_fCurX, pNpc->m_fCurZ, pNpc->m_sNid + NPC_BAND);

                    //
                    if (pNpc->GetMap()->m_byRoomEvent > 0 && pNpc->m_byDungeonFamily > 0 )	{
                        pRoom = pNpc->GetMap()->m_arRoomEventArray.GetData( pNpc->m_byDungeonFamily );
                        if (pRoom == NULL)
                        {
                            TRACE("Error : CServerDlg,, Map Room Npc Fail!! : nid=%d, sid=%d, name=%s, fam=%d, zone=%d\n", pNpc->m_sNid+NPC_BAND, pNpc->m_proto->m_sSid, pNpc->m_proto->m_strName, pNpc->m_byDungeonFamily, pNpc->m_bCurZone);
                            AfxMessageBox("Error : CServerDlg,, Map Room Npc Fail!!");
                            delete pNpc;
                            return FALSE;
                        }

                        int *pInt = new int;
                        *pInt = pNpc->m_sNid;
                        if( !pRoom->m_mapRoomNpcArray.PutData( pNpc->m_sNid, pInt ) )	{
                            TRACE("### Map - Room Array MonsterNid Fail : nid=%d, sid=%d ###\n", pNpc->m_sNid, pNpc->m_proto->m_sSid);
                        }
                    }


                    m_TotalNPC = nSerial;

                    if(--nNpcCount > 0) continue;

                    bMoveNext = TRUE;
                    nNpcCount = 0;

                }
            }

            nPathSerial = 1;
            NpcPosSet.MoveNext();
        }

        NpcPosSet.Close();
    }
    catch(CDBException* e)
    {
        e->ReportError();
        e->Delete();

        return FALSE;
    }

    int step = 0, nThreadNumber = 0;
    CNpcThread* pNpcThread = NULL;

    foreach_stlmap (itr, m_arNpc)
    {
        if (step == 0)
            pNpcThread = new CNpcThread;

        CNpc *pNpc = pNpcThread->m_pNpc[step] = itr->second;
        pNpc->m_sThreadNumber = nThreadNumber;
        pNpc->Init();

        ++step;

        if( step == NPC_NUM )
        {
            pNpcThread->m_sThreadNumber = nThreadNumber++;
            pNpcThread->m_pThread = AfxBeginThread(NpcThreadProc, &(pNpcThread->m_ThreadInfo), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
            m_arNpcThread.push_back( pNpcThread );
            step = 0;
        }
    }
    if( step != 0 )
    {
        pNpcThread->m_sThreadNumber = nThreadNumber++;
        pNpcThread->m_pThread = AfxBeginThread(NpcThreadProc, &(pNpcThread->m_ThreadInfo), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
        m_arNpcThread.push_back( pNpcThread );
    }

    m_pZoneEventThread = AfxBeginThread(ZoneEventThreadProc, (LPVOID)(this), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);

    //TRACE("m_TotalNPC = %d \n", m_TotalNPC);
    AddToList("[Monster Init - %d, threads=%d]", m_TotalNPC, m_arNpcThread.size());
    return TRUE;
}
Beispiel #27
0
void cCookManager::Cook_Syn(void* pMsg)
{
	WORD wResult = eCookError_None;
	MSG_COOK_SYN* pmsg = (MSG_COOK_SYN*)pMsg;
	CPlayer* pPlayer = (CPlayer*)g_pUserTable->FindUser(pmsg->dwObjectID);
	
	if(pPlayer)
	{
		// 스피드핵 체크
		if(0 < pPlayer->GetLastCookTime())
		{
			wResult=eCookError_InvaildState;
			goto COOK_NACK;
		}

		// 요리도구확인
		WORD wCookUtilLevel = CheckCookUtil(pPlayer);
		if(!wCookUtilLevel)
		{
			wResult=eCookError_InvaildUtil;			
			goto COOK_NACK;
		}

		// 레시피확인
		stRecipeInfo* pRecipe = GetRecipeInfo(pmsg->dwRecipeIdx);
		if(!pRecipe)
		{
			wResult=eCookError_InvaildRecipe;
			goto COOK_NACK;
		}

		// 요리도구-레시피 레벨확인
		if(wCookUtilLevel<eCOOKLEVEL3 && wCookUtilLevel<COOKMGR->GetCookLevelFromRecipe(pRecipe->dwRecipeIdx))
		{
			wResult=eCookError_LowerUtil;
			goto COOK_NACK;
		}

		// 모닥불확인
		CNpc* pFire = (CNpc*)g_pUserTable->FindUser(pmsg->dwFireNpcIdx);
		if(!pFire || eObjectKind_Npc!=pFire->GetObjectKind())
		{
			wResult=eCookError_InvaildFire;
			goto COOK_NACK;
		}

		// 제작수량확인
		if(pmsg->wMakeNum<1 || 99<pmsg->wMakeNum)
		{
			wResult=eCookError_InvaildMakeNum;
			goto COOK_NACK;
		}

		// 거리제한
		VECTOR3 vHeroPos, vPlacePos;
		pPlayer->GetPosition(&vHeroPos) ;
		pFire->GetPosition(&vPlacePos);
		float fDistance = CalcDistanceXZ(&vHeroPos, &vPlacePos);
		if(MAX_COOKING_DISTANCE < fDistance)
		{
			wResult = eCookError_OverDistance;
			goto COOK_NACK;
		}

		CItemSlot* pInvenSlot = pPlayer->GetSlot(eItemTable_Inventory);
		if(0 == ITEMMGR->GetTotalEmptySlotNum(pInvenSlot, pPlayer))
		{
			wResult = eCookError_InvenFull;
			goto COOK_NACK;
		}

		// 요리재료확인 및 소모
		if(!CheckIngredients(pPlayer, pRecipe, pmsg->wMakeNum))
		{
			wResult = eCookError_NeedIngredient;
			goto COOK_NACK;
		}

		// 숙련도확인 및 증가
		WORD wCookCount = pPlayer->GetCookCount(); 
		WORD wAddPoint = 0;
		if(pPlayer->GetCookLevel() == GetCookLevelFromRecipe(pRecipe->dwRecipeIdx))
		{
			WORD wExpertPointMin = (WORD)pRecipe->dwExpertPointMin;
			WORD wExpertPointMax = (WORD)pRecipe->dwExpertPointMax;
			if(pPlayer->GetCookCount() < wExpertPointMin)
			{
				wResult = eCookError_LowerExpertPoint;
				goto COOK_NACK;
			}
			
			if(wExpertPointMax < wCookCount)
				wAddPoint = 0;
			else if(wExpertPointMax <= wCookCount+pmsg->wMakeNum)
				wAddPoint = wExpertPointMax - wCookCount;
			else
				wAddPoint = pmsg->wMakeNum;

			if(wCookCount+wAddPoint < COOKMGR->GetMaxCookCount(pPlayer->GetCookLevel()))
				pPlayer->SetCookCount(wCookCount + wAddPoint);
			else
				pPlayer->SetCookCount(COOKMGR->GetMaxCookCount(pPlayer->GetCookLevel()));
		}

		Cooking_Update(pPlayer);
		Cooking_Log(pPlayer->GetID(), eCookingLog_CookCount, pRecipe->dwRecipeIdx, wCookCount, wAddPoint, pPlayer->GetCookCount());

		DWORD* pPlayerIdx = new DWORD;
		if(pPlayerIdx)
		{
			*pPlayerIdx = pPlayer->GetID();
			pPlayer->SetLastCookTime(gCurTime);
			m_CookerList.Add(pPlayerIdx, *pPlayerIdx);
		}

		MSG_DWORD2 msgAck;
		msgAck.Category = MP_COOK;
		msgAck.Protocol = MP_COOK_ACK;
		msgAck.dwObjectID = pPlayer->GetID();
		msgAck.dwData1 = pRecipe->dwRecipeIdx;
		msgAck.dwData2 = pmsg->wMakeNum;
		pPlayer->SendMsg(&msgAck, sizeof(msgAck));

		MSG_DWORD4 msg;
		msg.Category = MP_COOK;
		msg.Protocol = MP_COOK_STATE;
		msg.dwObjectID = pPlayer->GetID();
		msg.dwData1 = pPlayer->GetCookLevel();
		msg.dwData2 = pPlayer->GetCookCount();
		msg.dwData3 = pPlayer->GetEatCount();
		msg.dwData4 = pPlayer->GetFireCount();
		pPlayer->SendMsg(&msg, sizeof(msg));

		return;
	}


COOK_NACK:
	MSG_DWORD msg;
	msg.Category = MP_COOK;
	msg.Protocol = MP_COOK_NACK;
	msg.dwObjectID = pPlayer->GetID();
	msg.dwData = wResult;
	PACKEDDATA_OBJ->QuickSend( pPlayer, &msg, sizeof( msg ) );
}
Beispiel #28
0
BOOL  CRoomEvent::RunEvent( int event_num )
{
	CNpc* pNpc = NULL;
	int nOption_1 = 0, nOption_2 = 0;
	BOOL bRetValue = FALSE;
	switch( event_num )	{
	case 1:					// 다른 몬스터의 출현
		nOption_1 = m_Exec[ m_byLogicNumber-1 ].sOption_1;
		pNpc = GetNpcPtr( nOption_1 );
		if( pNpc )	{
			pNpc->m_byChangeType = 3;	// 몬스터 출현해주세여...
			pNpc->SetLive( &m_pMain->m_Iocport );
		}
		else	{
			TRACE("### RunEvent Error : 몬스터 출현 할 수 없당 = %d, logic=%d ###\n", nOption_1, m_byLogicNumber);
		}
		if( m_byCheck == m_byLogicNumber )	{	// 방이 클리어
			return TRUE;
		}
		else		m_byLogicNumber++;

		break;
	case 2:					// 문이 열림
		nOption_1 = m_Exec[ m_byLogicNumber-1 ].sOption_1;
		pNpc = GetNpcPtr( nOption_1 );
		if( pNpc )	{
			
		}
		else	{
			TRACE("### RunEvent Error : 문 담당 몬스터 출현 할 수 없당 = %d, logic=%d ###\n", nOption_1, m_byLogicNumber);
		}

		//wsprintf(notify, "** 알림 : [%d] 문이 열립니다 **", m_sRoomNumber);
		//m_pMain->SendSystemMsg( notify, PUBLIC_CHAT, SEND_ALL);

		if( m_byCheck == m_byLogicNumber )	{	// 방이 클리어
			return TRUE;
		}
		else		m_byLogicNumber++;

		break;
	case 3:					// 다른 몬스터로 변환
		if( m_byCheck == m_byLogicNumber )	{	// 방이 클리어
			return TRUE;
		}
		break;
	case 4:					// 특정몬스터 옵션2의 마리수만큼 출현
		nOption_1 = m_Exec[ m_byLogicNumber-1 ].sOption_1;
		nOption_2 = m_Exec[ m_byLogicNumber-1 ].sOption_2;
		bRetValue = CheckMonsterCount( nOption_1, nOption_2, 2 );

		//wsprintf(notify, "** 알림 : [%d, %d] 몬스터 출현 **", nOption_1, nOption_2);
		//m_pMain->SendSystemMsg( notify, PUBLIC_CHAT, SEND_ALL);

		if( m_byCheck == m_byLogicNumber )	{	// 방이 클리어
			return TRUE;
		}
		else		m_byLogicNumber++;
		break;
	case 100:					// 특정몬스터 옵션2의 마리수만큼 출현
		nOption_1 = m_Exec[ m_byLogicNumber-1 ].sOption_1;
		nOption_2 = m_Exec[ m_byLogicNumber-1 ].sOption_2;

		TRACE("RunEvent - room=%d, option1=%d, option2=%d\n", m_sRoomNumber, nOption_1, nOption_2);
		if( nOption_1 != 0 )	{
			EndEventSay( nOption_1, nOption_2 );
		}
		if( m_byCheck == m_byLogicNumber )	{	// 방이 클리어
			return TRUE;
		}
		else		m_byLogicNumber++;
		break;
	default:
		TRACE("### RunEvent Fail :: event number = %d ###\n", event_num);
		break;
	}

	return FALSE;
}
Beispiel #29
0
void CAISocket::RecvNpcInfoAll(Packet & pkt)
{
	uint8 bCount = pkt.read<uint8>(); // max of 20

	pkt.SByte();
	for (int i = 0; i < bCount; i++)
	{
		uint8 bDirection;
		std::string strName;

		CNpc* pNpc = new CNpc();
		pNpc->Initialize();

		pkt >> pNpc->m_NpcState >> pNpc->m_sNid >> pNpc->m_sSid >> pNpc->m_sPid >> pNpc->m_sSize >> pNpc->m_iWeapon_1 >> pNpc->m_iWeapon_2
			>> pNpc->m_bZone >> strName >> pNpc->m_bNation >> pNpc->m_bLevel
			>> pNpc->m_curx >> pNpc->m_curz >> pNpc->m_cury >> bDirection
			>> pNpc->m_tNpcType >> pNpc->m_iSellingGroup >> pNpc->m_iMaxHP >> pNpc->m_iHP >> pNpc->m_byGateOpen
			>> pNpc->m_fTotalHitrate >> pNpc->m_fTotalEvasionrate 
			>> pNpc->m_sTotalAc >> pNpc->m_sTotalHit 
			>> pNpc->m_byObjectType
			>> pNpc->m_byTrapNumber >> pNpc->m_bMonster
			>> pNpc->m_sFireR >> pNpc->m_sColdR >> pNpc->m_sLightningR
			>> pNpc->m_sMagicR >> pNpc->m_sDiseaseR >> pNpc->m_sPoisonR;

		if (strName.empty())
			strName = "<the spawn with no name>";

		if (strName.length() > MAX_NPC_SIZE)
		{
			pNpc->DecRef();
			continue;
		}

		pNpc->m_pMap = g_pMain->GetZoneByID(pNpc->GetZoneID());
		if (pNpc->GetMap() == nullptr)
		{
			pNpc->DecRef();
			continue;
		}

		//TRACE("Recv --> NpcUserInfo : uid = %d, x=%f, z=%f.. \n", nid, fPosX, fPosZ);
		pNpc->m_strName = strName;

		pNpc->m_byDirection = bDirection;
		pNpc->SetRegion(pNpc->GetNewRegionX(), pNpc->GetNewRegionZ());

		if (pNpc->m_byObjectType == SPECIAL_OBJECT)
		{
			_OBJECT_EVENT* pEvent = pNpc->GetMap()->GetObjectEvent(pNpc->m_sSid);
			if (pEvent != nullptr)
				pEvent->byLife = 1;
		}

		//	TRACE("Recv --> NpcUserInfoAll : uid=%d, sid=%d, name=%s, x=%f, z=%f. gate=%d, objecttype=%d \n", nid, sPid, szName, fPosX, fPosZ, byGateOpen, byObjectType);

		if (!g_pMain->m_arNpcArray.PutData(pNpc->GetID(), pNpc))
		{
			TRACE("Npc PutData Fail - %d\n", pNpc->GetID());
			pNpc->DecRef();
			continue;
		}

		if (pNpc->m_NpcState == NPC_DEAD)
		{
			TRACE("Recv --> NpcUserInfoAll : nid=%d, sid=%d, name=%s\n", pNpc->GetID(), pNpc->m_sSid, strName.c_str());
			continue;
		}

		pNpc->SendInOut(INOUT_IN, pNpc->GetX(), pNpc->GetZ(), pNpc->GetY());
	}
}
Beispiel #30
0
void CAISocket::RecvNpcInfo(Packet & pkt)
{
	std::string strName;
	uint8 Mode, byDirection;
	uint16 sNid;
	bool bCreated = false;

	pkt.SByte();
	pkt >> Mode >> sNid;

	CNpc *pNpc = g_pMain->GetNpcPtr(sNid);
	if (pNpc == nullptr)
	{
		pNpc = new CNpc();
		pNpc->m_sNid = sNid;
		bCreated = true;
	}

	pkt >> pNpc->m_sSid >> pNpc->m_sPid >> pNpc->m_sSize >> pNpc->m_iWeapon_1 >> pNpc->m_iWeapon_2
		>> pNpc->m_bZone >> strName >> pNpc->m_bNation >> pNpc->m_bLevel
		>> pNpc->m_curx >> pNpc->m_curz >> pNpc->m_cury >> byDirection
		>> pNpc->m_tNpcType >> pNpc->m_iSellingGroup >> pNpc->m_iMaxHP >> pNpc->m_iHP >> pNpc->m_byGateOpen
		>> pNpc->m_fTotalHitrate >> pNpc->m_fTotalEvasionrate 
		>> pNpc->m_sTotalAc >> pNpc->m_sTotalHit 
		>> pNpc->m_byObjectType
		>> pNpc->m_byTrapNumber >> pNpc->m_bMonster
		>> pNpc->m_sFireR >> pNpc->m_sColdR >> pNpc->m_sLightningR
		>> pNpc->m_sMagicR >> pNpc->m_sDiseaseR >> pNpc->m_sPoisonR;

	if (strName.empty() || strName.length() > MAX_NPC_SIZE)
	{
		pNpc->DecRef();
		return;
	}

	pNpc->m_NpcState = Mode;
	pNpc->m_byDirection = byDirection;
	pNpc->m_strName = strName;

	pNpc->m_pMap = g_pMain->GetZoneByID(pNpc->GetZoneID());
	if (pNpc->GetMap() == nullptr)
	{
		pNpc->DecRef();
		return;
	}

	pNpc->RegisterRegion();

	if (pNpc->m_byObjectType == SPECIAL_OBJECT)
	{
		_OBJECT_EVENT *pEvent = pNpc->GetMap()->GetObjectEvent( pNpc->m_sSid );
		if (pEvent != nullptr)
			pEvent->byLife = 1;
	}

	if (bCreated)
		g_pMain->m_arNpcArray.PutData(pNpc->GetID(), pNpc);

	if (pNpc->m_NpcState == NPC_DEAD)
	{
		TRACE("RecvNpcInfo - dead monster nid=%d, name=%s\n", pNpc->GetID(), pNpc->GetName().c_str());
		return;
	}

	pNpc->SendInOut(INOUT_IN, pNpc->GetX(), pNpc->GetZ(), pNpc->GetY());
}