#include "stdafx.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "PatternMonster.h" #include "MonsterShout.h" // ---------------------------------------------------------------------------------------------- // ¼Òȯ¼ö (¾îµå¹Î ¸í·É, ·é¿ÀÇÁ ½ºÅ³¿¡ ÀÇÇÔ) CSummonMonster::CSummonMonster() : CMonster(), m_lpMaster(NULL), m_bGuard(false) { m_bAdminCmdSummon = true; } CSummonMonster::CSummonMonster(MonsterCreateInfo& MonsterCreateInfo, CCharacter* lpMaster) : CMonster(MonsterCreateInfo, true), m_lpMaster(lpMaster), m_bGuard(false) { if (NULL != m_lpMaster) { m_CreatureStatus.m_nLevel = m_lpMaster->GetStatus().m_nLevel; m_lCurrentFrame = SUMMON_TIME; } } CSummonMonster::~CSummonMonster() { } void CSummonMonster::GuardMe(CAggresiveCreature* lpTarget, unsigned short wThreat) { if (true == m_bGuard) { AttackCmd(lpTarget, wThreat); } } void CSummonMonster::AttackCmd(CAggresiveCreature* lpTarget, unsigned short wThreat) { m_bLongRangeAttacked = true; m_Threat.AddToThreatList(lpTarget, wThreat); m_nCurrentState = CFSM::GetInstance().StateTransition(m_nCurrentState, INPUT_ID_CMD_ATTACK); } void CSummonMonster::Attacked(void) { if (true == m_bGuard) { CMonster::Attacked(); } } bool CSummonMonster::Attack(AtType attackType, unsigned char cDefenderNum, CAggresiveCreature** ppDefenders, unsigned char* cDefenderJudges, unsigned short* wDefenserMPHeal) { if (NULL == m_lpMaster) { return CMonster::Attack(attackType, cDefenderNum, ppDefenders, cDefenderJudges, wDefenserMPHeal); } unsigned char cOffencerJudge = 0; unsigned short wOffencerMPHeal = 0; unsigned short wError = PktAtAck::NO_SERVER_ERR; const int MAX_BUFFER = sizeof(PktAtAck) + AtNode::MAX_DEFENDER_NUM * sizeof(DefenserNode); char szBuffer[MAX_BUFFER]; PktAtAck* lpPktAtAck = reinterpret_cast(szBuffer); DefenserNode* lpDefenserNode = reinterpret_cast(lpPktAtAck + 1); unsigned char cDefender = 0; unsigned char cIndex = 0; for (; cIndex < cDefenderNum; ++cIndex) { if (NULL == ppDefenders[cIndex]) { continue; } if (0 == ppDefenders[cIndex]->GetStatus().m_nNowHP) { continue; } CCharacter* lpCharacter = NULL; CMonster* lpSummonee = NULL; // ŸÄÏÀÌ Ä³¸¯ÅÍÀÎ °æ¿ì if (Creature::CT_PC == Creature::GetCreatureType(ppDefenders[cDefender]->GetCID())) { lpCharacter = reinterpret_cast(ppDefenders[cDefender]); lpSummonee = lpCharacter->GetSummonee(); } else { // Ÿ°ÙÀÌ ¼Òȯ¼öÀÎ °æ¿ì if (Creature::IsSummonMonster(ppDefenders[cDefender]->GetCID())) { lpCharacter = reinterpret_cast(ppDefenders[cDefender])->GetMaster(); } } // TODO : °ø°Ý ¹æÇâÀ» ¼³Á¤ÇØÁݽôÙ. cDefenderJudges[cDefender] = ClientConstants::Judge_Front; wDefenserMPHeal[cDefender] = 0; // ´ë¹ÌÁö ¹Ý¿µ const unsigned short wDamage = ppDefenders[cDefender]->ApplyDamage(attackType, this, cOffencerJudge, cDefenderJudges[cDefender], wOffencerMPHeal, wDefenserMPHeal[cDefender], wError); // °ø°Ý ÆÐŶ ¸¸µé±â lpDefenserNode[cDefender].m_dwCharID = ppDefenders[cIndex]->GetCID(); lpDefenserNode[cDefender].m_sCurrHP = ppDefenders[cIndex]->GetStatus().m_nNowHP; lpDefenserNode[cDefender].m_sCurrMP = ppDefenders[cIndex]->GetStatus().m_nNowMP; lpDefenserNode[cDefender].m_wMaxHP = ppDefenders[cIndex]->GetStatus().m_StatusInfo.m_nMaxHP; lpDefenserNode[cDefender].m_wMaxMP = ppDefenders[cIndex]->GetStatus().m_StatusInfo.m_nMaxMP; lpDefenserNode[cDefender].m_wMPHeal = wDefenserMPHeal[cDefender]; lpDefenserNode[cDefender].m_wDamage = wDamage; lpDefenserNode[cDefender].m_cJudge = cDefenderJudges[cDefender]; if (NULL != lpCharacter) { if (NULL != lpSummonee) { lpSummonee->GuardMe(this, wDamage); } lpCharacter->CalculateEquipDurability((ClientConstants::Judge_Guard == cDefenderJudges[cDefender]) ? AtType::GUARD : AtType::DEFENCE); CGameClientDispatch* lpDispatch = lpCharacter->GetDispatcher(); if (NULL != lpDispatch) { GameClientSendPacket::SendCharAttacked(lpDispatch->GetSendStream(), this, ppDefenders[cDefender], attackType, m_MotionInfo.m_fDirection, wDamage, cDefenderJudges[cDefender], wDefenserMPHeal[cDefender], PktBase::NO_SERVER_ERR); } } ++cDefender; } if (0 == cDefender) { return true; } lpPktAtAck->m_dwCharID = m_dwCID; lpPktAtAck->m_AtType = attackType; lpPktAtAck->m_wHP = m_CreatureStatus.m_nNowHP; lpPktAtAck->m_wMP = m_CreatureStatus.m_nNowMP; lpPktAtAck->m_wMPHeal = wOffencerMPHeal; lpPktAtAck->m_cJudge = cOffencerJudge; lpPktAtAck->m_cDefenserNum = cDefender; CGameClientDispatch* lpDispatch = m_lpMaster->GetDispatcher(); if (NULL != lpDispatch) { CSendStream& SendStream = lpDispatch->GetSendStream(); if (true == SendStream.WrapCompress( szBuffer, sizeof(PktAtAck) + cDefender * sizeof(DefenserNode), CmdCharAttack, 0, wError) && PktBase::NO_SERVER_ERR == wError) { CCell* lpCell = GetCellPos().m_lpCell; if (NULL != lpCell) { lpCell->SendAttackInfo(m_dwCID, attackType, cDefender, lpDefenserNode); return true; } } } return false; } bool CSummonMonster::Dead(CAggresiveCreature* pOffencer) { if (NULL != m_lpMaster) { m_lpMaster->SetSummonee(NULL); GameClientSendPacket::SendCharSummonCmd(m_lpMaster, this, PktSummonCmd::SUC_DIE, m_dwCID); m_lpMaster = NULL; } m_dwLastBehaviorTick = m_dwLastTime = CPulse::GetInstance().GetLastTick(); m_lCurrentFrame = FPS; m_bAttacking = false; m_nCurrentState = CFSM::GetInstance().StateTransition(m_nCurrentState, INPUT_ID_ZERO_HP); if (NULL != m_CellPos.m_lpCell) { m_CellPos.m_lpCell->DeleteCreature(m_dwCID); m_CellPos.m_lpCell = NULL; } return CAggresiveCreature::Dead(pOffencer); } EnemyCheck::EnemyType CSummonMonster::IsEnemy(CCreature* lpTarget) { if (NULL == m_lpMaster) { return CMonster::IsEnemy(lpTarget); } return m_lpMaster->IsEnemy(lpTarget); } bool CSummonMonster::GetMotion(unsigned long MotionID, MotionInfo &Motion) { if (NULL == m_lpMaster) { return CMonster::GetMotion(MotionID, Motion); } if (false == CMonster::GetMotion(MotionID, Motion)) { return false; } // ¼Òȯ¼öÀÇ À̵¿ ¼Óµµ´Â ¼ÒȯÀÚ¿Í ¸ÂÃçÁØ´Ù. (¼ö½ÄÀº ÀûÁ¤·®...) if (MonsterInfo::Z3D_CA_WALK == MotionID || MonsterInfo::Z3D_CA_RUN == MotionID) { Motion.m_fVelocity = ((4.9f * (1.0f + (m_lpMaster->GetCharStatus().m_nDEX - 20) * 0.03f)) * Motion.m_dwFrame) / FPS; } return true; } // ---------------------------------------------------------------------------------------------- // ¸í¿¹ÀÇ ¼®»ó CStatue::CStatue() : CMonster(), m_dwDuration(0), m_wBonusTurn(0), m_cHPUpdateCount(0), m_dwLastAttackedTime(0), m_lpParent(NULL), m_lpLinkNPC(NULL) { } CStatue::CStatue(MonsterCreateInfo& MonsterCreateInfo, CStatue* lpParent) : CMonster(MonsterCreateInfo), m_dwDuration(0), m_wBonusTurn(0), m_cHPUpdateCount(0), m_dwLastAttackedTime(0), m_lpParent(lpParent) { m_nMovingPattern = FIXED; unsigned long dwNPCID = (MonsterCreateInfo.m_dwCID - Creature::MONSTER_BIT) | Creature::NPC_LINK_BIT; m_lpLinkNPC = CCreatureManager::GetInstance().GetNPC(dwNPCID); } CStatue::~CStatue() { } void CStatue::GiveMileage(char cGiveType) { switch (m_MonsterInfo.m_dwKID) { // 1·¹º§ case MonsterInfo::STATUE_HUMAN_COMPLETE1: case MonsterInfo::STATUE_AKHAN_COMPLETE1: // 2·¹º§ case MonsterInfo::STATUE_HUMAN_COMPLETE2: case MonsterInfo::STATUE_AKHAN_COMPLETE2: CCreatureManager::GetInstance().ProcessAllCharacter(CStatueInfo(this, true, cGiveType)); break; } } bool CStatue::RegenHPAndMP(unsigned short usAdditionalHP, unsigned short usAdditionalMP, bool bAddDefaultRegenValue) { if (false == CAggresiveCreature::RegenHPAndMP(usAdditionalHP, usAdditionalMP, bAddDefaultRegenValue)) { return false; } // ´ÙÅ© Ä«³ª¹ø ±¹°¡ ÀüÀï ¼®»ó if (SERVER_ID::STONE_WAR1 <= CServerSetup::GetInstance().GetServerZone() && CServerSetup::GetInstance().GetServerZone() <= SERVER_ID::STONE_WAR3) { // Áß°è¼­¹ö¿¡ HP ¾÷µ¥ÀÌÆ® Á¤º¸ º¸³»±â SendHPUpdate(); } /* // ½Å±ÔÁ¸ »ý¸íÃàÃâ±â else if(CServerSetup::GetInstance().GetServerZone() == SERVER_ID::ZONE9) { // Áß°è¼­¹ö¿¡ HP ¾÷µ¥ÀÌÆ® Á¤º¸ º¸³»±â SendHPUpdate(); } */ return true; } bool CStatue::Dead(CAggresiveCreature* pOffencer) { if (STATE_ID_DIE == m_nCurrentState) { return false; } unsigned short wDamage = m_CreatureStatus.m_nNowHP; m_CreatureStatus.m_nNowHP = 0; m_dwLastBehaviorTick = m_dwLastTime = CPulse::GetInstance().GetLastTick(); m_lCurrentFrame = FPS; m_bAttacking = false; m_nCurrentState = CFSM::GetInstance().StateTransition(m_nCurrentState, INPUT_ID_ZERO_HP); if (NULL == pOffencer) { // ¼®»ó ·Îµù ¿Ï·á // AttackInfo ¸¦ º¸³»¼­ ·ÎµùÁßÀÎ ¼®»óÀ» Ŭ¶óÀÌ¾ðÆ®µéÀÌ ¾ø¾Öµµ·Ï ÇØ¾ßÇÑ´Ù. AtType attackType; DefenserNode Defenser[AtNode::MAX_DEFENDER_NUM] = {0, }; attackType.m_wType = AtType::RIGHT_MELEE; Defenser[0].m_cJudge = ClientConstants::Judge_Front; Defenser[0].m_dwCharID = GetCID(); Defenser[0].m_wMaxHP = m_CreatureStatus.m_StatusInfo.m_nMaxHP; Defenser[0].m_wMaxMP = m_CreatureStatus.m_StatusInfo.m_nMaxMP; Defenser[0].m_sCurrHP = m_CreatureStatus.m_nNowHP; Defenser[0].m_sCurrMP = m_CreatureStatus.m_nNowMP; Defenser[0].m_wMPHeal = 0; Defenser[0].m_wDamage = wDamage; CCell* lpCell = m_CellPos.m_lpCell; if (lpCell) { lpCell->SendAttackInfo(0, attackType, 1, &Defenser[0]); } } if (NULL != m_CellPos.m_lpCell) { m_CellPos.m_lpCell->DeleteCreature(m_dwCID); m_CellPos.m_lpCell = NULL; } CStatue* lpNextStatue = NULL; if (NULL == pOffencer) { // ¼®»ó ·Îµù ¿Ï·á switch (m_MonsterInfo.m_dwKID) { // 1·¹º§ case MonsterInfo::STATUE_HUMAN_LOADING1: case MonsterInfo::STATUE_AKHAN_LOADING1: case MonsterInfo::BG_STATUE_HUMAN_LOADING1: case MonsterInfo::BG_STATUE_AKHAN_LOADING1: case MonsterInfo::POWER_STATUE_HUMAN_LOADING1: case MonsterInfo::POWER_STATUE_AKHAN_LOADING1: case MonsterInfo::INT_STATUE_HUMAN_LOADING1: case MonsterInfo::INT_STATUE_AKHAN_LOADING1: case MonsterInfo::EXP_STATUE_HUMAN_LOADING1: case MonsterInfo::EXP_STATUE_AKHAN_LOADING1: case MonsterInfo::WEALTH_STATUE_HUMAN_LOADING1: case MonsterInfo::WEALTH_STATUE_AKHAN_LOADING1: case MonsterInfo::LIFE_EXTRACT_HUMAN_LOADING1: case MonsterInfo::LIFE_EXTRACT_AKHAN_LOADING1: // 2·¹º§ case MonsterInfo::STATUE_HUMAN_LOADING2: case MonsterInfo::STATUE_AKHAN_LOADING2: case MonsterInfo::BG_STATUE_HUMAN_LOADING2: case MonsterInfo::BG_STATUE_AKHAN_LOADING2: case MonsterInfo::POWER_STATUE_HUMAN_LOADING2: case MonsterInfo::POWER_STATUE_AKHAN_LOADING2: case MonsterInfo::INT_STATUE_HUMAN_LOADING2: case MonsterInfo::INT_STATUE_AKHAN_LOADING2: case MonsterInfo::EXP_STATUE_HUMAN_LOADING2: case MonsterInfo::EXP_STATUE_AKHAN_LOADING2: case MonsterInfo::WEALTH_STATUE_HUMAN_LOADING2: case MonsterInfo::WEALTH_STATUE_AKHAN_LOADING2: case MonsterInfo::LIFE_EXTRACT_HUMAN_LOADING2: case MonsterInfo::LIFE_EXTRACT_AKHAN_LOADING2: lpNextStatue = GetLinkStatue(MonsterInfo::GetCompleteStatueKID(static_cast(m_MonsterInfo.m_dwKID))); break; default: // ÀÌ ·çƾÀº ¾îµå¹Î ¸í·É¿¡ ÀÇÇØ¼­¸¸ ¼öÇàµÇ¾î¾ß ÇÑ´Ù. (ÃʱâÈ­) CStatue* lpParent = (NULL == m_lpParent) ? this : m_lpParent; lpNextStatue = GetLinkStatue(static_cast(lpParent->m_MonsterInfo.m_dwKID)); break; } } else { // Àû±º¿¡ ÀÇÇØ ¼®»óÀÌ ºÎ¼­Áø °æ¿ì if (Creature::CT_PC == Creature::GetCreatureType(pOffencer->GetCID())) { CCharacter* lpCharacter = reinterpret_cast(pOffencer); lpNextStatue = GetLinkStatue(MonsterInfo::GetLoadingStatueKID(lpCharacter->GetRace(), static_cast(m_MonsterInfo.m_dwKID))); } else if (Creature::IsSummonMonster(pOffencer->GetCID())) { CSummonMonster* lpSummonMonster = reinterpret_cast(pOffencer); CCharacter* lpMaster = lpSummonMonster->GetMaster(); if (lpMaster) { lpNextStatue = GetLinkStatue(MonsterInfo::GetLoadingStatueKID(lpMaster->GetRace(), static_cast(m_MonsterInfo.m_dwKID))); } } else { ERRLOG2(g_Log, "CID:0x%08x ¼®»óÀ» ºÎ¼ø ÀÚ°¡ ij¸¯ÅͰ¡ ¾Æ´Õ´Ï´Ù. °ø°ÝÀÚCID:0x%08x", m_dwCID, pOffencer->GetCID()); lpNextStatue = GetLinkStatue(MonsterInfo::GetDefaultStatueKID(static_cast(m_MonsterInfo.m_dwKID))); } } if (NULL != lpNextStatue) { lpNextStatue->Respawn(m_dwLastTime); // ÄÁÅÙÃ÷ : ´ÙÅ© Ä«³ª¹ø ±¹°¡ ÀüÀï if (true == CServerSetup::GetInstance().UseContents(GameRYL::STONE_BATTLE)) { // 2008.07.17 ¼®»óÀüÀ϶© ¼®»óÁ¤º¸¸¦ Àü´ÞÇØ¾ßÇÑ´Ù. // ´ÙÅ© Ä«³ª¹ø ±¹°¡ ÀüÀï½Ã if (SERVER_ID::STONE_WAR1 <= CServerSetup::GetInstance().GetServerZone() && CServerSetup::GetInstance().GetServerZone() <= SERVER_ID::STONE_WAR3) { // Áß°è¼­¹ö¿¡ KID ¹× HP ¾÷µ¥ÀÌÆ® Á¤º¸ º¸³»±â lpNextStatue->SendKIDUpdate(); lpNextStatue->SendHPUpdate(true); // ¶óÁö¸Ê Ç¥½Ã Á¤º¸ º¸³»±â CCreatureManager::GetInstance().SendRealmStatueDisplayInfo(); // ¼®»ó ¸®½ºÆù Æ÷ÀÎÆ® Ãß°¡ ȤÀº »èÁ¦ unsigned long dwStatueIndex = (lpNextStatue->GetCID() & ~Creature::MONSTER_BIT) >> 16; if (lpNextStatue->EnableRespawn() && MonsterInfo::IsRaceCompleteStatueKID(lpNextStatue->GetKID())) { CCharRespawnMgr::GetInstance().AddRealmStatueRespawnPoint(dwStatueIndex, lpNextStatue->GetNation(), lpNextStatue->GetCurrentPos()); } else { CCharRespawnMgr::GetInstance().DeleteRealmStatueRespawnPoint(dwStatueIndex); } } } /* if (true == CServerSetup::GetInstance().UseContents(GameRYL::NEWZONE_ZONE9)) { // ½Å±ÔÁ¸ »ý¸í ÃàÃâ±â if (CServerSetup::GetInstance().GetServerZone() == SERVER_ID::ZONE9) { // Áß°è¼­¹ö¿¡ KID ¹× HP ¾÷µ¥ÀÌÆ® Á¤º¸ º¸³»±â lpNextStatue->SendKIDUpdate(); lpNextStatue->SendHPUpdate(true); // ¶óÁö¸Ê Ç¥½Ã Á¤º¸ º¸³»±â CCreatureManager::GetInstance().SendRealmStatueDisplayInfo(); // ½Å±ÔÁ¸ »ý¸í ÃàÃâ±â Æ÷ÀÎÆ® Ãß°¡ ȤÀº »èÁ¦ unsigned long dwStatueIndex = (lpNextStatue->GetCID() & ~Creature::MONSTER_BIT) >> 16; if (lpNextStatue->EnableRespawn() && MonsterInfo::IsRaceCompleteStatueKID(lpNextStatue->GetKID())) { CCharRespawnMgr::GetInstance().AddRealmStatueRespawnPoint(dwStatueIndex, lpNextStatue->GetNation(), lpNextStatue->GetCurrentPos()); } else { CCharRespawnMgr::GetInstance().DeleteRealmStatueRespawnPoint(dwStatueIndex); } } } */ } // ¹æ Á¤º¸ Àü¼Û if (GetMapIndex() != 0) { VirtualArea::CVirtualArea* lpVirtualArea = VirtualArea::CVirtualAreaMgr::GetInstance().GetVirtualArea(GetMapIndex()); if (NULL != lpVirtualArea && lpVirtualArea->GetVirtualType() == VirtualArea::BGSERVERMAP) { VirtualArea::CBGServerMap* lpBGServerMap = reinterpret_cast(lpVirtualArea); if (VirtualArea::STATUE == lpBGServerMap->GetMapType()) { lpBGServerMap->CalculateScore(); lpBGServerMap->SendMapInfo(); // ·Î±× ³²±â±â CCharacter* lpOffencerChar = reinterpret_cast(pOffencer); if (lpOffencerChar) { char szOffencerNation[8]; if (lpOffencerChar->GetRace() == CClass::HUMAN) strcpy(szOffencerNation, "HUMAN"); else strcpy(szOffencerNation, "AKHAN"); DETLOG7(g_Log, "Battle Server Log :: (Channel : %d, %s) - CID : 0x%08x ij¸¯ÅÍ(%s, %s)°¡ ¼®»óÀ» ºÎ¼Ì½À´Ï´Ù. (ÇöÀç Score - HM: %d AK: %d)", (lpBGServerMap->GetMapIndex() & ~VirtualArea::BGSERVERMAP), lpBGServerMap->GetMapTypeName(), lpOffencerChar->GetCID(), lpOffencerChar->GetCharacterName(), szOffencerNation, lpBGServerMap->GetMapInfo().m_wScore[CClass::HUMAN], lpBGServerMap->GetMapInfo().m_wScore[CClass::AKHAN]); } else { DETLOG4(g_Log, "Battle Server Log :: (Channel : %d, %s) - ´©±º°¡°¡ ¼®»óÀ» ºÎ¼Ì½À´Ï´Ù. (ÇöÀç Score - HM: %d AK: %d)", (lpBGServerMap->GetMapIndex() & ~VirtualArea::BGSERVERMAP), lpBGServerMap->GetMapTypeName(), lpBGServerMap->GetMapInfo().m_wScore[CClass::HUMAN], lpBGServerMap->GetMapInfo().m_wScore[CClass::AKHAN]); } } } } return CAggresiveCreature::Dead(pOffencer); } bool CStatue::Rest(void) { if (STATE_ID_DIE == m_nCurrentState) { return false; } m_wBonusTurn = 0; m_CreatureStatus.m_nNowHP = 0; m_dwLastBehaviorTick = m_dwLastTime = CPulse::GetInstance().GetLastTick(); m_lCurrentFrame = FPS; m_bAttacking = false; m_nCurrentState = CFSM::GetInstance().StateTransition(m_nCurrentState, INPUT_ID_ZERO_HP); if (NULL != m_CellPos.m_lpCell) { m_CellPos.m_lpCell->DeleteCreature(m_dwCID); m_CellPos.m_lpCell = NULL; } return CAggresiveCreature::Dead(NULL); } EnemyCheck::EnemyType CStatue::IsEnemy(CCreature* lpTarget) { return CMonster::IsEnemy(lpTarget); } bool CStatue::CreateLinkStatue(unsigned short wKind) { // Ãʱ⠻óŰ¡ Á߸³ÀÌ ¾Æ´Ñ ¼®»óµéÀ» À§ÇÑ Ã³¸® // ex) Ãʱ⠻óŰ¡ ÈÞ¸Õ ¼®»óÀ̶ó¸é ÈÞ¸Õ ¼®»óÀ» ¸¸µé ŸÀֿ̹¡ Á߸³ ¼®»óÀ» ¸¸µç´Ù. if (m_MonsterInfo.m_dwKID == wKind) { if (0 != GetMapIndex()) { wKind = MonsterInfo::BG_STATUE_NEUTRALITY1; } else { // 1·¹º§ if (MonsterInfo::STATUE_NEUTRALITY1 <= wKind && MonsterInfo::STATUE_AKHAN_COMPLETE1 >= wKind) { wKind = MonsterInfo::STATUE_NEUTRALITY1; } else if (MonsterInfo::POWER_STATUE_NEUTRALITY1 <= wKind && MonsterInfo::POWER_STATUE_AKHAN_COMPLETE1 >= wKind) { wKind = MonsterInfo::POWER_STATUE_NEUTRALITY1; } else if (MonsterInfo::INT_STATUE_NEUTRALITY1 <= wKind && MonsterInfo::INT_STATUE_AKHAN_COMPLETE1 >= wKind) { wKind = MonsterInfo::INT_STATUE_NEUTRALITY1; } else if (MonsterInfo::EXP_STATUE_NEUTRALITY1 <= wKind && MonsterInfo::EXP_STATUE_AKHAN_COMPLETE1 >= wKind) { wKind = MonsterInfo::EXP_STATUE_NEUTRALITY1; } else if (MonsterInfo::WEALTH_STATUE_NEUTRALITY1 <= wKind && MonsterInfo::WEALTH_STATUE_AKHAN_COMPLETE1 >= wKind) { wKind = MonsterInfo::WEALTH_STATUE_NEUTRALITY1; } else if (MonsterInfo::LIFE_EXTRACT_NEUTRALITY1 <= wKind && MonsterInfo::LIFE_EXTRACT_AKHAN_COMPLETE1 >= wKind) { wKind = MonsterInfo::LIFE_EXTRACT_NEUTRALITY1; } // 2·¹º§ else if (MonsterInfo::STATUE_NEUTRALITY2 <= wKind && MonsterInfo::STATUE_AKHAN_COMPLETE2 >= wKind) { wKind = MonsterInfo::STATUE_NEUTRALITY2; } else if (MonsterInfo::POWER_STATUE_NEUTRALITY2 <= wKind && MonsterInfo::POWER_STATUE_AKHAN_COMPLETE2 >= wKind) { wKind = MonsterInfo::POWER_STATUE_NEUTRALITY2; } else if (MonsterInfo::INT_STATUE_NEUTRALITY2 <= wKind && MonsterInfo::INT_STATUE_AKHAN_COMPLETE2 >= wKind) { wKind = MonsterInfo::INT_STATUE_NEUTRALITY2; } else if (MonsterInfo::EXP_STATUE_NEUTRALITY2 <= wKind && MonsterInfo::EXP_STATUE_AKHAN_COMPLETE2 >= wKind) { wKind = MonsterInfo::EXP_STATUE_NEUTRALITY2; } else if (MonsterInfo::WEALTH_STATUE_NEUTRALITY2 <= wKind && MonsterInfo::WEALTH_STATUE_AKHAN_COMPLETE2 >= wKind) { wKind = MonsterInfo::WEALTH_STATUE_NEUTRALITY2; } else if (MonsterInfo::LIFE_EXTRACT_NEUTRALITY2 <= wKind && MonsterInfo::LIFE_EXTRACT_AKHAN_COMPLETE2 >= wKind) { wKind = MonsterInfo::LIFE_EXTRACT_NEUTRALITY2; } } } CMonster::MonsterCreateInfo tempInfo; tempInfo.m_dwCID = (m_dwCID & ~Creature::MONSTER_KIND_BIT) | wKind; // ÀÌ¹Ì Á¸ÀçÇÏ´ÂÁö üũ if (0 != GetMapIndex()) { VirtualArea::CVirtualArea* lpVirtualArea = VirtualArea::CVirtualAreaMgr::GetInstance().GetVirtualArea(GetMapIndex()); if (lpVirtualArea) { CVirtualMonsterMgr* lpVirtualMonsterMgr = lpVirtualArea->GetMonsterManager(); if (lpVirtualMonsterMgr && NULL != lpVirtualMonsterMgr->GetCreature(tempInfo.m_dwCID)) { ERRLOG0(g_Log, "¼®»ó »ý¼º¿¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù."); return false; } } } else { if (NULL != CCreatureManager::GetInstance().GetCreature(tempInfo.m_dwCID)) { ERRLOG0(g_Log, "¼®»ó »ý¼º¿¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù."); return false; } } tempInfo.m_nKID = wKind; tempInfo.m_Pos = m_OriginalPosition; CStatue* lpStatue = new CStatue(tempInfo, this); if (NULL == lpStatue) { ERRLOG0(g_Log, "¼®»ó »ý¼º¿¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù."); return false; } lpStatue->SetMapIndex(GetMapIndex()); if (false == lpStatue->InitMonster(tempInfo.m_Pos, true)) { ERRLOG0(g_Log, "¼®»ó »ý¼º¿¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù."); return false; } // ¸ó½ºÅÍ Ãß°¡ if (0 != GetMapIndex()) { VirtualArea::CVirtualArea* lpVirtualArea = VirtualArea::CVirtualAreaMgr::GetInstance().GetVirtualArea(GetMapIndex()); if (lpVirtualArea) { CVirtualMonsterMgr* lpVirtualMonsterMgr = lpVirtualArea->GetMonsterManager(); if (lpVirtualMonsterMgr) lpVirtualMonsterMgr->AddMonster(lpStatue); } } else { CCreatureManager::GetInstance().AddCreature(lpStatue); } return true; } CStatue* CStatue::GetLinkStatue(unsigned short wKind) { CStatue* lpParent = (NULL == m_lpParent) ? this : m_lpParent; if (0 != GetMapIndex()) { VirtualArea::CVirtualArea* lpVirtualArea = VirtualArea::CVirtualAreaMgr::GetInstance().GetVirtualArea(GetMapIndex()); if (lpVirtualArea) { CVirtualMonsterMgr* lpVirtualMonsterMgr = lpVirtualArea->GetMonsterManager(); if (lpVirtualMonsterMgr) { return reinterpret_cast(lpVirtualMonsterMgr->GetMonster( (lpParent->GetCID() & ~Creature::MONSTER_KIND_BIT) | wKind)); } } } else { return reinterpret_cast(CCreatureManager::GetInstance().GetMonster( (lpParent->GetCID() & ~Creature::MONSTER_KIND_BIT) | wKind)); } return NULL; } Item::CItem* CStatue::SellToCharacter(CCharacter *lpCustomer, unsigned short wKindItem, TakeType takeType, Item::CItem* lpRequestItem, unsigned long &dwPrice, unsigned short wCouponID, unsigned short &usError) { if (NULL != m_lpLinkNPC) { unsigned short wError = 0; return m_lpLinkNPC->SellToCharacter(lpCustomer, wKindItem, takeType, lpRequestItem, dwPrice, wCouponID, wError); usError = wError; } return NULL; } bool CStatue::SendKIDUpdate() { GET_SINGLE_DISPATCH(lpDBAgentDispatch, CDBAgentDispatch, CDBAgentDispatch::GetDispatchTable()); if (0 != lpDBAgentDispatch) { CSendStream& SendStream = lpDBAgentDispatch->GetSendStream(); char* lpBuffer = SendStream.GetBuffer(sizeof(PktStatueCmd) + sizeof(StatueInfo)); if (NULL != lpBuffer) { PktStatueCmd* lpPktStatueCmd = reinterpret_cast(lpBuffer); StatueInfo* lpStatueInfo = reinterpret_cast(lpPktStatueCmd + 1); lpPktStatueCmd->m_wSubCmd = PktStatueCmd::CMD_UPDATE_KID; lpPktStatueCmd->m_dwValue = CServerSetup::GetInstance().GetServerChannel(); lpPktStatueCmd->m_wSize = sizeof(StatueInfo); lpStatueInfo->m_dwIndex = (GetCID() & ~Creature::MONSTER_BIT) >> 16; lpStatueInfo->m_wKID = GetKID(); lpStatueInfo->m_dwLostHP = 0; return SendStream.WrapCrypt(sizeof(PktStatueCmd) + sizeof(StatueInfo), CmdStatueCmd, 0, 0); } } return false; } bool CStatue::SendHPUpdate(bool bForce) { ++m_cHPUpdateCount; if (m_cHPUpdateCount >= MAX_HP_UPDATE_COUNT || bForce) { m_cHPUpdateCount = 0; GET_SINGLE_DISPATCH(lpDBAgentDispatch, CDBAgentDispatch, CDBAgentDispatch::GetDispatchTable()); if (0 != lpDBAgentDispatch) { CSendStream& SendStream = lpDBAgentDispatch->GetSendStream(); char* lpBuffer = SendStream.GetBuffer(sizeof(PktStatueCmd) + sizeof(StatueInfo)); if (NULL != lpBuffer) { PktStatueCmd* lpPktStatueCmd = reinterpret_cast(lpBuffer); StatueInfo* lpStatueInfo = reinterpret_cast(lpPktStatueCmd + 1); lpPktStatueCmd->m_wSubCmd = PktStatueCmd::CMD_UPDATE_LOST_HP; lpPktStatueCmd->m_dwValue = CServerSetup::GetInstance().GetServerChannel(); lpPktStatueCmd->m_wSize = sizeof(StatueInfo); lpStatueInfo->m_dwIndex = (GetCID() & ~Creature::MONSTER_BIT) >> 16; lpStatueInfo->m_wKID = 0; lpStatueInfo->m_dwLostHP = GetStatus().m_StatusInfo.m_nMaxHP - GetStatus().m_nNowHP; return SendStream.WrapCrypt(sizeof(PktStatueCmd) + sizeof(StatueInfo), CmdStatueCmd, 0, 0); } else { return false; } } else { return false; } } return true; } void CStatue::SendAttacked() { unsigned long dwNowTime = timeGetTime(); if (dwNowTime - m_dwLastAttackedTime >= STATUE_ATTACKED_TIME) { m_dwLastAttackedTime = dwNowTime; unsigned long dwIndex = (GetCID() & ~Creature::MONSTER_BIT) >> 16; // ¶óÁö¸Ê Ç¥½Ã Á¤º¸ º¸³»±â CCreatureManager::GetInstance().SendRealmStatueDisplayInfo(dwIndex, true); } } CStatueInfo::CStatueInfo(CStatue* lpStatue, bool bBonusTurn, char cGiveType) : m_lpStatue(lpStatue), m_bBonusTurn(bBonusTurn), m_cGiveType(cGiveType) { } bool CStatueInfo::operator () (CCharacter* lpCharacter) { if (NULL != lpCharacter) { if (lpCharacter->GetMapIndex() != m_lpStatue->GetMapIndex()) { return false; } char cAddMileage = 1; // if(SERVER_ID::STONE_WAR2 == CServerSetup::GetInstance().GetServerZone()) // cAddMileage = 5; // else if(SERVER_ID::STONE_WAR3 == CServerSetup::GetInstance().GetServerZone()) // cAddMileage = 10; PktStatueInfo pktSI; pktSI.m_dwMileage = 0; pktSI.m_wHumanNum = CCreatureManager::GetInstance().GetCharacterNum(CClass::HUMAN); pktSI.m_wAkhanNum = CCreatureManager::GetInstance().GetCharacterNum(CClass::AKHAN); pktSI.m_wNowHP = m_lpStatue->GetStatus().m_nNowHP; pktSI.m_wKID = static_cast(m_lpStatue->GetCID() & Creature::MONSTER_KIND_BIT); pktSI.m_cState = m_lpStatue->GetCurrentState(); pktSI.m_cIndex = static_cast(m_lpStatue->GetSerialNumber()); if (true == m_bBonusTurn) { if(m_cGiveType == 0) // ±âÁ¸¹æ½Ä °ú°Å ZONE3¹ø¿¡¼­ ÁøÇàÇß´ø ¹èƲ±×¶ó¿îµå Çü½Ä { const unsigned char cBonusTurn = CCreatureManager::GetInstance().GetBonusTurn(lpCharacter->GetMapIndex()); if (0 != lpCharacter->GetStatus().m_nNowHP && 0 != m_lpStatue->GetStatus().m_nNowHP && static_cast(lpCharacter->GetRace()) == cBonusTurn && m_lpStatue->GetCurrentPos().GetDistance(lpCharacter->GetCurrentPos()) < CStatue::BONUS_DISTANCE) { lpCharacter->SetMileage(lpCharacter->GetMileage() + CStatue::BONUS_MILEAGE); pktSI.m_dwMileage = lpCharacter->GetMileage(); } } else { // ÇØ´ç¼®»óÀÌ ¾î´ÀÁ¾Á·²¨³Ä.. unsigned char cBonusTurn = CClass::MAX_RACE; switch (m_lpStatue->GetKID()) { case MonsterInfo::STATUE_HUMAN_COMPLETE1: cAddMileage = 1; cBonusTurn = CClass::HUMAN; break; case MonsterInfo::STATUE_HUMAN_COMPLETE2: cAddMileage = 1; cBonusTurn = CClass::HUMAN; break; case MonsterInfo::STATUE_AKHAN_COMPLETE1: cAddMileage = 1; cBonusTurn = CClass::AKHAN; break; case MonsterInfo::STATUE_AKHAN_COMPLETE2: cAddMileage = 1; cBonusTurn = CClass::AKHAN; break; } if (0 != lpCharacter->GetStatus().m_nNowHP && 0 != m_lpStatue->GetStatus().m_nNowHP && static_cast(lpCharacter->GetRace()) == cBonusTurn) { lpCharacter->SetMileage(lpCharacter->GetMileage() + cAddMileage ); pktSI.m_dwMileage = lpCharacter->GetMileage(); } } } CGameClientDispatch* lpDispatch = lpCharacter->GetDispatcher(); if (NULL != lpDispatch) { char* szPacket = reinterpret_cast(&pktSI); if (PacketWrap::WrapCrypt(szPacket, sizeof(PktStatueInfo), CmdStatueInfo, 0, 0)) { return lpDispatch->GetSendStream().PutBuffer(szPacket, sizeof(PktStatueInfo), CmdStatueInfo); } } } return false; } CBlessMileageInfo::CBlessMileageInfo(char cBlessType) : m_cBlessType(cBlessType) { m_cAddMileage = 1; if(SERVER_ID::STONE_WAR2 == CServerSetup::GetInstance().GetServerZone()) m_cAddMileage = 5; else if(SERVER_ID::STONE_WAR3 == CServerSetup::GetInstance().GetServerZone()) m_cAddMileage = 10; } bool CBlessMileageInfo::operator () (CCharacter* lpCharacter) { if (NULL != lpCharacter) { PktStatueInfo pktSI; pktSI.m_dwMileage = 0; pktSI.m_wHumanNum = CCreatureManager::GetInstance().GetCharacterNum(CClass::HUMAN); pktSI.m_wAkhanNum = CCreatureManager::GetInstance().GetCharacterNum(CClass::AKHAN); pktSI.m_wNowHP = 0; pktSI.m_wKID = 0; pktSI.m_cState = 0; pktSI.m_cIndex = 0; if (0 != lpCharacter->GetStatus().m_nNowHP) { lpCharacter->SetMileage(lpCharacter->GetMileage() + m_cAddMileage); pktSI.m_dwMileage = lpCharacter->GetMileage(); } CGameClientDispatch* lpDispatch = lpCharacter->GetDispatcher(); if (NULL != lpDispatch) { char* szPacket = reinterpret_cast(&pktSI); if (PacketWrap::WrapCrypt(szPacket, sizeof(PktStatueInfo), CmdStatueInfo, 0, 0)) { return lpDispatch->GetSendStream().PutBuffer(szPacket, sizeof(PktStatueInfo), CmdStatueInfo); } } } return false; } // ------------------------------------------------------------------------------------- // ¿ÀºêÁ§Æ® ¸ó½ºÅÍ (²É, ³ª¹«, ¹ö¼¸·ù) CGatherMonster::CGatherMonster() : CMonster() { } CGatherMonster::CGatherMonster(MonsterCreateInfo& MonsterCreate, bool bAdminCmdSummon) : CMonster(MonsterCreate, bAdminCmdSummon) { } CGatherMonster::~CGatherMonster() { } // ------------------------------------------------------------------------------------- // ¿ÀºêÁ§Æ® ¸ó½ºÅÍ (²É, ³ª¹«, ¹ö¼¸·ù) CObjectMonster::CObjectMonster() : CMonster() { } CObjectMonster::CObjectMonster(MonsterCreateInfo& MonsterCreate, bool bAdminCmdSummon) : CMonster(MonsterCreate, bAdminCmdSummon) { } CObjectMonster::~CObjectMonster() { } // ------------------------------------------------------------------------------------- // ½ºÅ³ »ç¿ë ¸ó½ºÅÍ CSkillMonster::CSkillMonster() : CMonster(), m_cConsumeMPCount(0), m_bCasting(false), m_dwTargetCID(0), m_cSkillPattern(0), m_nCastingCount(0) { std::fill_n(m_lastCastTime, int(MAX_SKILL_PATTERN), 0); ZeroMemory(&m_attackType, sizeof(AtType)); } CSkillMonster::CSkillMonster(MonsterCreateInfo& MonsterCreate, bool bAdminCmdSummon) : CMonster(MonsterCreate, bAdminCmdSummon), m_cConsumeMPCount(0), m_bCasting(false), m_dwTargetCID(0), m_cSkillPattern(0), m_nCastingCount(0) { std::fill_n(m_lastCastTime, int(MAX_SKILL_PATTERN), 0); ZeroMemory(&m_attackType, sizeof(AtType)); } CSkillMonster::~CSkillMonster() { } bool CSkillMonster::Dead(CAggresiveCreature* pOffencer) { m_bCasting = false; const char* szCharacterName = 0; if (0 != pOffencer && Creature::CT_PC == Creature::GetCreatureType(pOffencer->GetCID())) { szCharacterName = static_cast(pOffencer)->GetCharacterName(); } CMonsterShout::GetInstance().Shout(m_dwCID, m_MonsterInfo.m_dwKID, static_cast(m_CurrentPos.m_fPointX), static_cast(m_CurrentPos.m_fPointZ), CMonsterShout::DEAD, szCharacterName, 0); return CMonster::Dead(pOffencer); } LONG CSkillMonster::SendMove(unsigned short nAniNum) { // edith 2009.07.16 ¸ó½ºÅÍ´Â ½ºÅ³ ij½ºÆÃ Áß¿¡´Â À̵¿ÇÏÁö ¸¶¶ó. // if(m_bCasting) // return 0; return CMonster::SendMove(nAniNum); } bool CSkillMonster::Attack(AtType attackType, unsigned char cDefenderNum, CAggresiveCreature** ppDefenders, unsigned char* cDefenderJudges, unsigned short* wDefenderMPHeal) { if (m_CreatureStatus.m_nNowHP == 0) { ERRLOG1(g_Log, "CID:0x%08x Á×Àº ¸ó½ºÅͰ¡ °ø°ÝÇÏ·Á°í ÇÏ¿´½À´Ï´Ù.", m_dwCID); return false; } if (cDefenderNum > AtNode::MAX_DEFENDER_NUM) { ERRLOG2(g_Log, "CID:0x%08x ¸ó½ºÅͰ¡ °ø°ÝÇÒ ¶§, ¹æ¾îÀÚÀÇ ¼ýÀÚ°¡ ÃÖ´ë ¹æ¾îÀÚ ¼ýÀÚ¸¦ ³Ñ¾ú½À´Ï´Ù. ¹æ¾îÀÚ¼ö : %d", m_dwCID, cDefenderNum); cDefenderNum = AtNode::MAX_DEFENDER_NUM; } if (0 == (attackType.m_wType & AtType::SKILL_BIT) && 0 == cDefenderNum) { ERRLOG0(g_Log, "½ºÅ³ÀÌ ¾Æ´Ñ ÀÏ¹Ý °ø°ÝÀº, ¹Ýµå½Ã Ÿ°ÙÀÌ ÀÖÀ» °æ¿ì¿¡¸¸ ¼­¹ö·Î º¸³»¾ß ÇÕ´Ï´Ù."); return false; } if (0 != (attackType.m_wType & AtType::SKILL_BIT)) { const Skill::ProtoType* pSkillProtoType = CSkillMgr::GetInstance().GetSkillProtoType(attackType.m_wType); if (NULL == pSkillProtoType) { ERRLOG2(g_Log, "CID:0x%08x Á¸ÀçÇÏÁö ¾Ê´Â ½ºÅ³ ¾ÆÀ̵ðÀÔ´Ï´Ù. Skill ID:0x%04x", m_dwCID, attackType.m_wType); return false; } } unsigned char cOffencerJudge = 0; unsigned short wOffencerMPHeal = 0; unsigned short wError = PktAtAck::NO_SERVER_ERR; m_cConsumeMPCount = std::min(cDefenderNum, unsigned char(AtNode::MAX_MONSTER_DEFENDER_NUM)); unsigned char cDefender = 0; unsigned char cIndex = 0; // MON_TODO : by Vincent - 2004 : 2 : 25 DefenserNode Defenser[AtNode::MAX_DEFENDER_NUM]; // ------------ // ¸ó½ºÅÍ ¿ÜÄ¡±â ¶§¹®¿¡ ³ÖÀ½. unsigned int nCriticalCount = 0; CCharacter* lpDefendShoutCharacter = 0; for (; cIndex < cDefenderNum; ++cIndex) { // MP ¼Ò¸ð ŸÀֱ̹îÁöÀÇ Ä«¿îÆ® (¹üÀ§ ¸¶¹ýÀº ÇÑ ¹ø¸¸ MP ¼Ò¸ð) --m_cConsumeMPCount; if (NULL == ppDefenders[cIndex]) { continue; } if (0 == ppDefenders[cIndex]->GetStatus().m_nNowHP) { continue; } // TODO : °ø°Ý ¹æÇâÀ» ¼³Á¤ÇØÁݽôÙ. cDefenderJudges[cDefender] = ClientConstants::Judge_Front; wDefenderMPHeal[cDefender] = 0; const unsigned short nPrevHP = ppDefenders[cIndex]->GetStatus().m_nNowHP; const unsigned short nPrevMP = ppDefenders[cIndex]->GetStatus().m_nNowMP; const unsigned short wPrevAttackerHP = m_CreatureStatus.m_nNowHP; // ´ë¹ÌÁö ¹Ý¿µ const unsigned short wDamage = ppDefenders[cIndex]->ApplyDamage(attackType, this, cOffencerJudge, cDefenderJudges[cDefender], wOffencerMPHeal, wDefenderMPHeal[cDefender], wError); if (cDefenderJudges[cDefender] == ClientConstants::Judge_Critical) { ++nCriticalCount; } const unsigned short nNowHP = ppDefenders[cIndex]->GetStatus().m_nNowHP; const unsigned short nNowMP = ppDefenders[cIndex]->GetStatus().m_nNowMP; // ½ºÅ³¿¡ ÀÇÇÑ ÀÚ»ì ¹æÁö if (0 == m_CreatureStatus.m_nNowHP) { m_CreatureStatus.m_nNowHP = wPrevAttackerHP; wError = PktAtAck::FAIL_SUICIDE; break; } else { if (Creature::CT_PC == Creature::GetCreatureType(ppDefenders[cIndex]->GetCID())) { // ¹æ¾îÀÚ°¡ ij¸¯ÅÍÀÎ °æ¿ì CCharacter* lpDefendCharacter = (CCharacter *)ppDefenders[cIndex]; if (0 == lpDefendShoutCharacter || 0 == (rand() % 3)) { lpDefendShoutCharacter = lpDefendCharacter; } CMonster* lpSummonee = lpDefendCharacter->GetSummonee(); if (NULL != lpSummonee) { lpSummonee->GuardMe(this, wDamage); } lpDefendCharacter->CalculateEquipDurability((ClientConstants::Judge_Guard == cDefenderJudges[cDefender]) ? AtType::GUARD : AtType::DEFENCE); CGameClientDispatch* lpDispatch = lpDefendCharacter->GetDispatcher(); if (NULL != lpDispatch) { GameClientSendPacket::SendCharAttacked(lpDispatch->GetSendStream(), this, lpDefendCharacter, attackType, m_MotionInfo.m_fDirection, wDamage, cDefenderJudges[cDefender], wDefenderMPHeal[cDefender], PktBase::NO_SERVER_ERR); } } } Defenser[cDefender].m_cJudge = cDefenderJudges[cDefender]; Defenser[cDefender].m_dwCharID = ppDefenders[cDefender]->GetCID(); Defenser[cDefender].m_wMaxHP = ppDefenders[cDefender]->GetStatus().m_StatusInfo.m_nMaxHP; Defenser[cDefender].m_wMaxMP = ppDefenders[cDefender]->GetStatus().m_StatusInfo.m_nMaxMP; Defenser[cDefender].m_sCurrHP = ppDefenders[cDefender]->GetStatus().m_nNowHP; Defenser[cDefender].m_sCurrMP = ppDefenders[cDefender]->GetStatus().m_nNowMP; Defenser[cDefender].m_wMPHeal = wDefenderMPHeal[cDefender]; Defenser[cDefender].m_wDamage = wDamage; ++cDefender; } // ¿ÜÄ¡±â °Ë»ç CMonsterShout::Behavior eBehavior = CMonsterShout::NORMAL_ATTACK; unsigned short usShoutSkill_ID = 0; if (0 != (attackType.m_wType & AtType::SKILL_BIT)) { if (0 == cDefender) { Skill::CFunctions::ConsumeMP(attackType, this, 0); } eBehavior = CMonsterShout::SKILL_ATTACK; usShoutSkill_ID = attackType.m_wType; } else if (0 < nCriticalCount) { eBehavior = CMonsterShout::CRITICAL_ATTACK; } const char* szName = 0; if (0 != lpDefendShoutCharacter) { szName = lpDefendShoutCharacter->GetCharacterName(); } // ¿ÜÄ¡±â °Ë»öÇØ¼­ ¿Üħ. À̸§Àº, °ø°ÝÇÏ´Â °æ¿ìÀ̹ǷΠ¸Â´Â ³Ñ ¾Æ¹«³ÑÀ̳ª ÇÑ³Ñ Àâ¾Æ¼­ ±×³Ñ À̸§À» ÁØ´Ù. CMonsterShout::GetInstance().Shout(m_dwCID, m_MonsterInfo.m_dwKID, static_cast(m_CurrentPos.m_fPointX), static_cast(m_CurrentPos.m_fPointZ), eBehavior, szName, usShoutSkill_ID); // MON_TODO : by Vincent - 2004 : 2 : 25 CCell* lpCell = m_CellPos.m_lpCell; if (lpCell) { lpCell->SendAttackInfo(GetCID(), attackType, cDefender, &Defenser[0]); } // ------------ return true; } bool CSkillMonster::UseSkill(AtType attackType, CAggresiveCreature** ppDefenders, char cSkillPattern) { if (NULL == ppDefenders[0]) { return false; } // ½ºÅ³ ¾ò±â const Skill::ProtoType* pThisSkill = CSkillMgr::GetInstance().GetSkillProtoType(attackType.m_wType); if (NULL == pThisSkill) { ERRLOG2(g_Log, "CID:0x%08x Á¸ÀçÇÏÁö ¾Ê´Â ½ºÅ³ ¾ÆÀ̵ðÀÔ´Ï´Ù. Skill ID:0x%04x", m_dwCID, attackType.m_wType); return false; } char cTargetType = Skill::Target::ENEMY; unsigned char cSkillLockCount = m_MonsterInfo.m_cSkillLevel / CSkillMgr::MAX_SKILL_LEVEL; unsigned char cSkillLevel = m_MonsterInfo.m_cSkillLevel % CSkillMgr::MAX_SKILL_LEVEL; if (cSkillLockCount >= CSkillMgr::MAX_SKILL_LOCKCOUNT - 1) { cSkillLockCount = CSkillMgr::MAX_SKILL_LOCKCOUNT - 2; } if (cSkillLockCount > 0 && cSkillLevel < CSkillMonster::USE_SKILL_MIN_LEVEL) { --cSkillLockCount; cSkillLevel = CSkillMonster::USE_SKILL_LEVEL; } unsigned short useMP = pThisSkill[cSkillLockCount].m_StartMP + pThisSkill[cSkillLockCount].m_LockMP + (pThisSkill[cSkillLockCount].m_LevelMP + pThisSkill[cSkillLockCount].m_LockMP) * cSkillLevel ; unsigned long dwCurrentTime = timeGetTime(); unsigned long dwCoolDownTime = pThisSkill[cSkillLockCount].m_dwCoolDownTime; if (pThisSkill->m_bIsClassSkill) dwCoolDownTime = pThisSkill[0].m_dwCoolDownTime; // ½ºÅ³À» »ç¿ëÇÒ¼ö ¾ø´Â »óȲÀÎÁö üũ if (m_CreatureStatus.m_nNowMP < useMP || dwCurrentTime - m_lastCastTime[cSkillPattern] < dwCoolDownTime || Math::Random::ComplexRandom(100) > m_MonsterInfo.m_wSkillUseRate) { return false; } // ½ºÅ³ °Å¸® üũ unsigned char cDefenderNum = 1; unsigned char nDefenserJudges[AtNode::MAX_DEFENDER_NUM]; unsigned short wDefenserMPHeal[AtNode::MAX_DEFENDER_NUM]; CAggresiveCreature* pTarget = ppDefenders[0]; if (NULL != pTarget) { float fSquareTargetDistance = (m_CurrentPos.m_fPointX - pTarget->GetCurrentPos().m_fPointX) * (m_CurrentPos.m_fPointX - pTarget->GetCurrentPos().m_fPointX) + (m_CurrentPos.m_fPointZ - pTarget->GetCurrentPos().m_fPointZ) * (m_CurrentPos.m_fPointZ - pTarget->GetCurrentPos().m_fPointZ); float fSquareEffectDistance = (pThisSkill[cSkillLockCount].m_fMaxRange + Skill::ERROR_OF_DISTANCE) * (pThisSkill[cSkillLockCount].m_fMaxRange + Skill::ERROR_OF_DISTANCE); if (fSquareTargetDistance > fSquareEffectDistance) { return false; } // ½ºÅ³ ´ë»ó ¼³Á¤ if (pThisSkill->m_eTargetType == Skill::Target::FRIEND || pThisSkill->m_eTargetType == Skill::Target::DEAD_FRIEND || pThisSkill->m_eTargetType == Skill::Target::FRIEND_EXCEPT_SELF || pThisSkill->m_eTargetType == Skill::Target::FRIEND_OBJECT || pThisSkill->m_eTargetType == Skill::Target::PARTY || pThisSkill->m_eTargetType == Skill::Target::SUMMON) { cTargetType = Skill::Target::FRIEND; } } // TODO : °ø°ÝÇÏ´Â ¹æÇâÀ» ¼³Á¤ÇսôÙ. (ÇöÀç´Â ¹«Á¶°Ç Á¤¸é) short nMaxDefenderNum = AtNode::MAX_DEFENDER_NUM; std::fill_n(&nDefenserJudges[0], nMaxDefenderNum, ClientConstants::Judge_Front); std::fill_n(&wDefenserMPHeal[0], nMaxDefenderNum, 0); float fDir = CalcDir2D(GetCurrentPos().m_fPointX, GetCurrentPos().m_fPointZ, pTarget->GetCurrentPos().m_fPointX, pTarget->GetCurrentPos().m_fPointZ); // ij½ºÆÃ ŸÀÔÀ̸é, ij½ºÆ® ¸ðµå·Î º¯È¯Çϰí, ³ª¸ÓÁö´Â ¹Ù·Î »ç¿ëÇÑ´Ù. if (pThisSkill->m_eSkillType == Skill::Type::CAST) { m_bCasting = true; m_attackType = attackType; m_dwTargetCID = ppDefenders[0]->GetCID(); m_cSkillPattern = cSkillPattern; // edith 2009.08.06 ½ºÅ³ °ø°Ý½Ã À̵¿ÇÏÁö ¾Ê°Ô Çϱâ SendMove(1); return true; } // ½ºÅ³ »ç¿ëÇÑ ½Ã°£À» ÀúÀå m_lastCastTime[cSkillPattern] = dwCurrentTime; // MON_TODO : ½ºÅ³ »ç¿ë Á¤º¸¸¦ º¸³»ÁØ´Ù. CCell* lpCell = m_CellPos.m_lpCell; if (lpCell) { CastObject castObject; castObject.m_wTypeID = attackType.m_wType; castObject.m_DstPos.fPointX = ppDefenders[0]->GetCurrentPos().m_fPointX * 100.f; castObject.m_DstPos.fPointY = ppDefenders[0]->GetCurrentPos().m_fPointY * 100.f; castObject.m_DstPos.fPointZ = ppDefenders[0]->GetCurrentPos().m_fPointZ * 100.f; castObject.m_cObjectLevel = attackType.m_cSkillLockCount; if (pThisSkill->m_bIsClassSkill) castObject.m_cObjectLevel = 0; castObject.m_dwTargetID = ppDefenders[0]->GetCID(); castObject.m_cObjectType = 6; const Skill::ProtoType* lpSkillProtoType = CSkillMgr::GetInstance().GetSkillProtoType(attackType.m_wType); if (NULL == lpSkillProtoType) { ERRLOG2(g_Log, "CID:0x%08x Á¸ÀçÇÏÁö ¾Ê´Â ½ºÅ³ ¾ÆÀ̵ðÀÔ´Ï´Ù. Skill ID:0x%04x", castObject.m_dwTargetID, attackType.m_wType); return 0; } else { switch (lpSkillProtoType->m_usSkill_ID) { case 0x8104 : castObject.m_cObjectType = 11; break; case 0x9104 : castObject.m_cObjectType = 31; break; case 0x8603 : castObject.m_cObjectType = 12; break; case 0x8702 : castObject.m_cObjectType = 20; break; case 0x9802 : castObject.m_cObjectType = 34; break; } } // edith 2009.08.06 ¸ó½ºÅͰ¡ ½ºÅ³¾µ¶§ ½ºÅ³ÀÇ ÀÌÆÑÆ®¸¦ Ŭ¶óÀÌ¾ðÆ®¿¡¼­ ¶ç¿öÁÖ±â À§ÇÑ ºÎºÐ. lpCell->SendCastObjectInfo(GetCID(), ppDefenders[0]->GetCID(), castObject); } // ¹üÀ§ ¸¶¹ýÀ̶ó¸é... if (0 != pThisSkill[cSkillLockCount].m_fEffectExtent) { if (Skill::Target::PARTY == pThisSkill[cSkillLockCount].m_eTargetType) { // ÆÄƼ ¸¶¹ýÀ̶ó¸é CParty* lpParty = ppDefenders[0]->GetParty(); if (NULL != lpParty) { return lpParty->Attack(attackType, ppDefenders, nDefenserJudges, this, pThisSkill[attackType.m_cSkillLockCount].m_fEffectExtent, cTargetType); } } else { // ÀÏ¹Ý ¹üÀ§ ¸¶¹ý return CAggresiveCreature::MultiAttack(attackType, cDefenderNum, ppDefenders, nDefenserJudges, GetCurrentPos(), fDir, pThisSkill[cSkillLockCount].m_fMaxRange + Skill::ERROR_OF_DISTANCE, m_MonsterInfo.m_fAttackAngle, cTargetType); } } // »ç¿ëÇÏ´Â ½ºÅ³ÀÇ Á¾·ù¿¡ µû¶ó¼­ Attack È£Ãâ ÇÔ¼ö¸¦ ´Þ¸®ÇÑ´Ù. // Enchant ºÎ¿© ¸¶¹ýÀÇ °æ¿ì´Â ÇÑ¸í¿¡°Ô¸¸ »ç¿ëÇÑ´Ù. return Attack(attackType, cDefenderNum, ppDefenders, nDefenserJudges, wDefenserMPHeal); } bool CSkillMonster::UseCastedSkill(void) { CAggresiveCreature* pTarget = reinterpret_cast(CCreatureManager::GetInstance().GetCreature(m_dwTargetCID)); if (NULL == pTarget) return false; if (pTarget->GetMapIndex() != GetMapIndex()) return false; // ½ºÅ³ ¾ò±â const Skill::ProtoType* pThisSkill = CSkillMgr::GetInstance().GetSkillProtoType(m_attackType.m_wType); if (NULL == pThisSkill) { ERRLOG2(g_Log, "CID:0x%08x Á¸ÀçÇÏÁö ¾Ê´Â ½ºÅ³ ¾ÆÀ̵ðÀÔ´Ï´Ù. Skill ID:0x%04x", m_dwCID, m_attackType.m_wType); return false; } char cTargetType = Skill::Target::ENEMY; unsigned char cSkillLockCount = m_MonsterInfo.m_cSkillLevel / 6; unsigned char cSkillLevel = m_MonsterInfo.m_cSkillLevel % 6; // 100% È®·ü·Î ½ºÅ³À» »ç¿ëÇÑ °ÍÀ̱⠶§¹®¿¡.. ij½ºÆ® ŸÀÓÀ» ¼ÂÆÃÇϰí, ¸¶¹ý »ç¿ë È®·üÀº °Ë»çÇÏÁö ¾Ê´Â´Ù. m_lastCastTime[m_cSkillPattern] = timeGetTime(); unsigned char cDefenderNum = 1; unsigned char nDefenserJudges[AtNode::MAX_DEFENDER_NUM]; unsigned short wDefenserMPHeal[AtNode::MAX_DEFENDER_NUM]; CAggresiveCreature* ppDefenders[AtNode::MAX_DEFENDER_NUM] = {0, }; ppDefenders[0] = pTarget; // ½ºÅ³ °Å¸® üũ if (NULL != pTarget) { float fSquareTargetDistance = (m_CurrentPos.m_fPointX - pTarget->GetCurrentPos().m_fPointX) * (m_CurrentPos.m_fPointX - pTarget->GetCurrentPos().m_fPointX) + (m_CurrentPos.m_fPointZ - pTarget->GetCurrentPos().m_fPointZ) * (m_CurrentPos.m_fPointZ - pTarget->GetCurrentPos().m_fPointZ); float fSquareEffectDistance = (pThisSkill[cSkillLockCount].m_fMaxRange + Skill::ERROR_OF_DISTANCE) * (pThisSkill[cSkillLockCount].m_fMaxRange + Skill::ERROR_OF_DISTANCE); if (fSquareTargetDistance > fSquareEffectDistance) { return false; } // ½ºÅ³ ´ë»ó ¼³Á¤ if (pThisSkill->m_eTargetType == Skill::Target::FRIEND || pThisSkill->m_eTargetType == Skill::Target::DEAD_FRIEND || pThisSkill->m_eTargetType == Skill::Target::FRIEND_EXCEPT_SELF || pThisSkill->m_eTargetType == Skill::Target::FRIEND_OBJECT || pThisSkill->m_eTargetType == Skill::Target::PARTY || pThisSkill->m_eTargetType == Skill::Target::SUMMON) { cTargetType = Skill::Target::FRIEND; } } // TODO : °ø°ÝÇÏ´Â ¹æÇâÀ» ¼³Á¤ÇսôÙ. (ÇöÀç´Â ¹«Á¶°Ç Á¤¸é) short nMaxDefenderNum = AtNode::MAX_DEFENDER_NUM; std::fill_n(&nDefenserJudges[0], nMaxDefenderNum, ClientConstants::Judge_Front); std::fill_n(&wDefenserMPHeal[0], nMaxDefenderNum, 0); float fDir = CalcDir2D(GetCurrentPos().m_fPointX, GetCurrentPos().m_fPointZ, pTarget->GetCurrentPos().m_fPointX, pTarget->GetCurrentPos().m_fPointZ); // MON_TODO : ½ºÅ³ »ç¿ë Á¤º¸¸¦ º¸³»ÁØ´Ù. CCell* lpCell = m_CellPos.m_lpCell; if (lpCell) { CastObject castObject; castObject.m_wTypeID = m_attackType.m_wType; castObject.m_DstPos.fPointX = pTarget->GetCurrentPos().m_fPointX * 100.f; castObject.m_DstPos.fPointY = pTarget->GetCurrentPos().m_fPointY * 100.f; castObject.m_DstPos.fPointZ = pTarget->GetCurrentPos().m_fPointZ * 100.f; // castObject.m_cObjectType = 0; // castObject.m_cObjectLevel = cSkillLockCount; // castObject.m_dwTargetID = pTarget->GetCID(); // castObject.m_cObjectType = 7; castObject.m_cObjectType = 6; castObject.m_cObjectLevel = m_attackType.m_cSkillLockCount; if (pThisSkill->m_bIsClassSkill) castObject.m_cObjectLevel = 0; castObject.m_dwTargetID = pTarget->GetCID(); lpCell->SendCastObjectInfo(GetCID(), pTarget->GetCID(), castObject); } // ¹üÀ§ ¸¶¹ýÀ̶ó¸é... if (0 != pThisSkill[cSkillLockCount].m_fEffectExtent) { if (Skill::Target::PARTY == pThisSkill[cSkillLockCount].m_eTargetType) { // ÆÄƼ ¸¶¹ýÀ̶ó¸é CParty* lpParty = ppDefenders[0]->GetParty(); if (NULL != lpParty) { return lpParty->Attack(m_attackType, ppDefenders, nDefenserJudges, this, pThisSkill[m_attackType.m_cSkillLockCount].m_fEffectExtent, cTargetType); } } else { // ÀÏ¹Ý ¹üÀ§ ¸¶¹ý return CAggresiveCreature::MultiAttack(m_attackType, cDefenderNum, ppDefenders, nDefenserJudges, GetCurrentPos(), fDir, pThisSkill[cSkillLockCount].m_fMaxRange + Skill::ERROR_OF_DISTANCE, m_MonsterInfo.m_fAttackAngle, cTargetType); } } // »ç¿ëÇÏ´Â ½ºÅ³ÀÇ Á¾·ù¿¡ µû¶ó¼­ Attack È£Ãâ ÇÔ¼ö¸¦ ´Þ¸®ÇÑ´Ù. // Enchant ºÎ¿© ¸¶¹ýÀÇ °æ¿ì´Â ÇÑ¸í¿¡°Ô¸¸ »ç¿ëÇÑ´Ù. return Attack(m_attackType, cDefenderNum, ppDefenders, nDefenserJudges, wDefenserMPHeal); } float CSkillMonster::CalculateDistance(CAggresiveCreature* pTarget) { if (NULL == pTarget) return 0; float fSquareTargetDistance = (m_CurrentPos.m_fPointX - pTarget->GetCurrentPos().m_fPointX) * (m_CurrentPos.m_fPointX - pTarget->GetCurrentPos().m_fPointX) + (m_CurrentPos.m_fPointZ - pTarget->GetCurrentPos().m_fPointZ) * (m_CurrentPos.m_fPointZ - pTarget->GetCurrentPos().m_fPointZ); return sqrtf(fSquareTargetDistance); } struct CompareLevel { typedef std::vector TargetVector; bool operator () (const TargetVector::value_type& lhs, const TargetVector::value_type& rhs) const { return lhs->GetStatus().m_nLevel > rhs->GetStatus().m_nLevel; } }; CAggresiveCreature* CSkillMonster::FindHighestLVMember() { if (NULL == m_pParty) return NULL; // ÆÄƼ ¸â¹ö¸¦ µÇÁ®º»´Ù. CMonsterParty* lpParty = reinterpret_cast(m_pParty); // ÇØ´ç ¸ó½ºÅ͸¦ ã¾Æ¼­ ÀúÀåÇØµÑ º¤ÅÍ std::vector targetVector; targetVector.clear(); targetVector.reserve(10); for (int i=0; iGetMemberNum(); ++ i) { // ¸â¹ö ¸ó½ºÅÍ ¾ò¾î¿Â±â CMonster* lpMonster = lpParty->GetMember(i); // °Å¸® üũ float fSquareTargetDistance = (m_CurrentPos.m_fPointX - lpMonster->GetCurrentPos().m_fPointX) * (m_CurrentPos.m_fPointX - lpMonster->GetCurrentPos().m_fPointX) + (m_CurrentPos.m_fPointZ - lpMonster->GetCurrentPos().m_fPointZ) * (m_CurrentPos.m_fPointZ - lpMonster->GetCurrentPos().m_fPointZ); if (fSquareTargetDistance <= CCell::CELL_DISTANCE) { targetVector.push_back(lpMonster); } } // ÇÑ¸íµµ ¾ø´Ù¸é... if (targetVector.size() == 0) { return NULL; } // ÇØ´ç ÆÐÅÏ¿¡ ¼±ÅÃµÈ ¸ó½ºÅÍ Áß¿¡¼­ ÃÖ°í ·¹º§ÀÇ ¸ó½ºÅ͸¦ ¸®ÅÏÇÑ´Ù. std::sort(targetVector.begin(), targetVector.end(), CompareLevel()); return targetVector[0]; } CAggresiveCreature* CSkillMonster::FindHighestLVMember(const AtType& attackType) { if (NULL == m_pParty) { if (true == GetEnchantInfo().GetFlag(m_MonsterInfo.m_cEnchantSpellType)) { return NULL; } return this; } // ½ºÅ³ ¾ò±â const Skill::ProtoType* pThisSkill = CSkillMgr::GetInstance().GetSkillProtoType(attackType.m_wType); if (NULL == pThisSkill) { ERRLOG2(g_Log, "CID:0x%08x Á¸ÀçÇÏÁö ¾Ê´Â ½ºÅ³ ¾ÆÀ̵ðÀÔ´Ï´Ù. Skill ID:0x%04x", m_dwCID, attackType.m_wType); return NULL; } // ÆÄƼ ¸â¹ö¸¦ µÇÁ®º»´Ù. CMonsterParty* lpParty = reinterpret_cast(m_pParty); // ½ºÅ³ À¯È¿ °Å¸® float fSquareEffectDistance = (pThisSkill[attackType.m_cSkillLockCount].m_fMaxRange + Skill::ERROR_OF_DISTANCE) * (pThisSkill[attackType.m_cSkillLockCount].m_fMaxRange + Skill::ERROR_OF_DISTANCE); // ÇØ´ç ¸ó½ºÅ͸¦ ã¾Æ¼­ ÀúÀåÇØµÑ º¤ÅÍ std::vector targetVector; targetVector.clear(); for (int i=0; iGetMemberNum(); ++ i) { // ¸â¹ö ¸ó½ºÅÍ ¾ò¾î¿Â±â CMonster* lpMonster = lpParty->GetMember(i); // NULL À̰ųª ÀÌ¹Ì ÇØ´ç ½ºÅ³ÀÌ ºÎ¿©µÈ »óŶó¸é ´ÙÀ½À¸·Î.. if (NULL == lpMonster || true == lpMonster->GetEnchantInfo().GetFlag(m_MonsterInfo.m_cEnchantSpellType)) { continue; } // °Å¸® üũ float fSquareTargetDistance = (m_CurrentPos.m_fPointX - lpMonster->GetCurrentPos().m_fPointX) * (m_CurrentPos.m_fPointX - lpMonster->GetCurrentPos().m_fPointX) + (m_CurrentPos.m_fPointZ - lpMonster->GetCurrentPos().m_fPointZ) * (m_CurrentPos.m_fPointZ - lpMonster->GetCurrentPos().m_fPointZ); if (fSquareTargetDistance <= fSquareEffectDistance) { targetVector.push_back(lpMonster); } } // ÇÑ¸íµµ ¾ø´Ù¸é... if (targetVector.size() == 0) { return NULL; } // ÇØ´ç ÆÐÅÏ¿¡ ¼±ÅÃµÈ ¸ó½ºÅÍ Áß¿¡¼­ ÃÖ°í ·¹º§ÀÇ ¸ó½ºÅ͸¦ ¸®ÅÏÇÑ´Ù. std::sort(targetVector.begin(), targetVector.end(), CompareLevel()); return targetVector[0]; } struct CompareHP { typedef std::vector TargetVector; bool operator () (const TargetVector::value_type& lhs, const TargetVector::value_type& rhs) const { return lhs->GetStatus().m_nNowHP < rhs->GetStatus().m_nNowHP; } }; CAggresiveCreature* CSkillMonster::FindLowestHPMember(const AtType& attackType, bool bRegin, float fRemainHP) { if (NULL == m_pParty) { if (GetStatus().m_StatusInfo.m_nMaxHP * fRemainHP >= GetStatus().m_nNowHP) return this; return NULL; } // ½ºÅ³ ¾ò±â const Skill::ProtoType* pThisSkill = CSkillMgr::GetInstance().GetSkillProtoType(attackType.m_wType); if (NULL == pThisSkill) { ERRLOG2(g_Log, "CID:0x%08x Á¸ÀçÇÏÁö ¾Ê´Â ½ºÅ³ ¾ÆÀ̵ðÀÔ´Ï´Ù. Skill ID:0x%04x", m_dwCID, attackType.m_wType); return NULL; } // ÆÄƼ ¸â¹ö¸¦ µÇÁ®º»´Ù. CMonsterParty* lpParty = reinterpret_cast(m_pParty); // ½ºÅ³ À¯È¿ °Å¸® float fSquareEffectDistance = (pThisSkill[attackType.m_cSkillLockCount].m_fMaxRange + Skill::ERROR_OF_DISTANCE) * (pThisSkill[attackType.m_cSkillLockCount].m_fMaxRange + Skill::ERROR_OF_DISTANCE); // ÇØ´ç ¸ó½ºÅ͸¦ ã¾Æ¼­ ÀúÀåÇØµÑ º¤ÅÍ std::vector targetVector; targetVector.clear(); for (int i=0; iGetMemberNum(); ++ i) { // ¸â¹ö ¸ó½ºÅÍ ¾ò¾î¿Â±â CMonster* lpMonster = lpParty->GetMember(i); // NULL ÀÌ¸é ´ÙÀ½À¸·Î.. if (NULL == lpMonster) { continue; } // HP°¡ üũ if (lpMonster->GetStatus().m_StatusInfo.m_nMaxHP * fRemainHP >= lpMonster->GetStatus().m_nNowHP) { if (bRegin) { // °Å¸® üũ float fSquareTargetDistance = (m_CurrentPos.m_fPointX - lpMonster->GetCurrentPos().m_fPointX) * (m_CurrentPos.m_fPointX - lpMonster->GetCurrentPos().m_fPointX) + (m_CurrentPos.m_fPointZ - lpMonster->GetCurrentPos().m_fPointZ) * (m_CurrentPos.m_fPointZ - lpMonster->GetCurrentPos().m_fPointZ); if (fSquareTargetDistance > fSquareEffectDistance) continue; } targetVector.push_back(lpMonster); } } // ÇÑ¸íµµ ¾ø´Ù¸é... if (targetVector.size() == 0) { return NULL; } // ÇØ´ç ÆÐÅÏ¿¡ ¼±ÅÃµÈ ¸ó½ºÅÍ Áß¿¡¼­ ÃÖÀú HP º°·Î sort ÇÑ´Ù. std::sort(targetVector.begin(), targetVector.end(), CompareHP()); return targetVector[0]; } CAggresiveCreature* CSkillMonster::FindEnemy(const AtType& attackType, unsigned char cType1, unsigned char cType2) { // ½ºÅ³ ¾ò±â const Skill::ProtoType* pThisSkill = CSkillMgr::GetInstance().GetSkillProtoType(attackType.m_wType); if (NULL == pThisSkill) { ERRLOG2(g_Log, "CID:0x%08x Á¸ÀçÇÏÁö ¾Ê´Â ½ºÅ³ ¾ÆÀ̵ðÀÔ´Ï´Ù. Skill ID:0x%04x", m_dwCID, attackType.m_wType); return NULL; } // ÀûÀÇ CID Set À» ¸¸µç´Ù. CMonsterParty::PartyTargetSet targetSet; targetSet.clear(); if (m_pParty) { // ÆÄƼ ¸â¹öÀÇ ÀûÀ» Set ¿¡ ³Ö´Â´Ù. CMonsterParty* lpParty = reinterpret_cast(m_pParty); targetSet = lpParty->GetPartyTargetSet(); } // ¿ø·¡ Ÿ°Ù ¶ÇÇÑ ÀûÀÇ Set ¿¡ ³Ö´Â´Ù. if (m_lpTarget) targetSet.insert(m_lpTarget->GetCID()); // ½ºÅ³ À¯È¿ °Å¸® float fSquareEffectDistance = (pThisSkill[attackType.m_cSkillLockCount].m_fMaxRange + Skill::ERROR_OF_DISTANCE) * (pThisSkill[attackType.m_cSkillLockCount].m_fMaxRange + Skill::ERROR_OF_DISTANCE); CMonsterParty::PartyTargetSet::iterator pos = targetSet.begin(); CMonsterParty::PartyTargetSet::iterator end = targetSet.end(); CAggresiveCreature* lpTarget = NULL; while (pos != end) { // ½ºÅ³ À¯È¿ ¹üÀ§ ³»ÀÇ ÀûÀ» ã´Â´Ù. CAggresiveCreature* lpCreature = CCreatureManager::GetInstance().GetAggresiveCreature(*pos); if (NULL == lpCreature || EnemyCheck::EC_ENEMY != IsEnemy(lpCreature)) { ++pos; continue; } if (NULL == lpTarget) { lpTarget = lpCreature; ++pos; continue; } // ÆÐÅÏ Å¸ÀÔ¿¡ ¸Â´Â Ÿ°ÙÀ» ã´Â´Ù. switch (cType1) { case TYPE_LV: { if (TYPE_HIGHEST == cType2 && lpTarget->GetStatus().m_nLevel < lpCreature->GetStatus().m_nLevel) lpTarget = lpCreature; else if (TYPE_LOWEST == cType2 && lpTarget->GetStatus().m_nLevel > lpCreature->GetStatus().m_nLevel) lpTarget = lpCreature; } break; case TYPE_HP: { if (TYPE_HIGHEST == cType2 && lpTarget->GetStatus().m_nNowHP < lpCreature->GetStatus().m_nNowHP) lpTarget = lpCreature; else if (TYPE_LOWEST == cType2 && lpTarget->GetStatus().m_nNowHP > lpCreature->GetStatus().m_nNowHP) lpTarget = lpCreature; } break; } ++pos; } return lpTarget; } // ------------------------------------------------------------------------------------- // ¸ó½ºÅÍ Å¸ÀÔ (µðÆæ´õ) CDefenderMonster::CDefenderMonster() : CSkillMonster() { } CDefenderMonster::CDefenderMonster(MonsterCreateInfo& MonsterCreate, bool bAdminCmdSummon) : CSkillMonster(MonsterCreate, bAdminCmdSummon) { } CDefenderMonster::~CDefenderMonster() { } bool CDefenderMonster::SkillAttack(void) { unsigned char cSkillLockCount = m_MonsterInfo.m_cSkillLevel / CSkillMgr::MAX_SKILL_LEVEL; unsigned char cSkillLevel = m_MonsterInfo.m_cSkillLevel % CSkillMgr::MAX_SKILL_LEVEL; if (cSkillLockCount >= CSkillMgr::MAX_SKILL_LOCKCOUNT - 1) { cSkillLockCount = CSkillMgr::MAX_SKILL_LOCKCOUNT - 2; } if (cSkillLockCount > 0 && cSkillLevel < CSkillMonster::USE_SKILL_MIN_LEVEL) { --cSkillLockCount; cSkillLevel = CSkillMonster::USE_SKILL_LEVEL; } // ¸¶¹ýÀ» ¾µ¼ö ¾ø´Â.. m_nSkillLevel ÀÌ 0 ÀÎ ³à¼®ÀÌ´Ù. if (0 == cSkillLockCount && 0 == cSkillLevel) { //ERRLOG1(g_Log, "CID:0x%08x ¸¶¹ýÀ» ¾µ¼ö ¾ø´Â ³à¼®ÀÔ´Ï´Ù. ¸ó½ºÅÍÀÇ ½ºÅ³·¹º§ÀÌ 0 À¸·Î ¼³Á¤µÇ¾î ÀÖ½À´Ï´Ù.", m_dwCID); return false; } enum { FIRST_PATTERN=0, SECOND_PATTERN=1, THIRD_PATTERN=2, FOURTH_PATTERN=3, MAX_PATTERN = 4 }; int nSelectPattern = FIRST_PATTERN; CAggresiveCreature* ppAggresiveCreature[AtNode::MAX_DEFENDER_NUM] = {0, }; AtType attackType; attackType.m_cSkillLockCount = cSkillLockCount; attackType.m_cSkillLevel = cSkillLevel; char nSkillPattern = 0; while (nSelectPattern < MAX_PATTERN) { switch (nSelectPattern) { case FIRST_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // B B D : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ ÀûÀÌ ÀÚ½ÅÀ¸·ÎºÎÅÍ 5m ÀÌ»ó ¸Ö¾îÁú ¶§ // : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ Àû¿¡°Ô // : D ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î ³Ñ±ä´Ù. if (0 == m_MonsterInfo.m_wSkillID[D_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = D_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[D_SKILL]; if (CalculateDistance(m_lpTarget) < 5.f) { ++nSelectPattern; continue; } ppAggresiveCreature[0] = m_lpTarget; } break; case SECOND_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // E A C : Àڽſ¡°Ô ºÎ¿© ¸¶¹ýÀÌ °É·ÁÁ® ÀÖÁö ¾ÊÀ» ¶§ // : Àڽſ¡°Ô // : C ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø°Å³ª, ÀÌ¹Ì ºÎ¿© ¸¶¹ýÀÌ °É·Á ÀÖ´Â »óŶó¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î ³Ñ±ä´Ù. if (0 == m_MonsterInfo.m_wSkillID[C_SKILL] || true == GetEnchantInfo().GetFlag(m_MonsterInfo.m_cEnchantSpellType)) { ++nSelectPattern; continue; } nSkillPattern = C_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[C_SKILL]; ppAggresiveCreature[0] = this; } break; case THIRD_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // C C B : ±×·ì¿¡ ¼ÓÇØÀÖ´Â ¾Æ±ºÁß Çϳª¶óµµ HP°¡ 50% ÀÌÇϰ¡ µÇ¾úÀ» ¶§ // : °¡Àå ³·Àº HP¸¦ °¡Áö°í ÀÖ´Â ¾Æ±º // : B ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[B_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = B_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[B_SKILL]; ppAggresiveCreature[0] = FindLowestHPMember(attackType, true); if (NULL == ppAggresiveCreature[0]) { ++nSelectPattern; continue; } } break; case FOURTH_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // A B A : ½ºÅ³ »ç¿ë °¡´É MP ÀÜ¿©·® ÀÖÀ½ / ´ë»óÀÌ ½ºÅ³ »ç¿ë °¡´É ¹üÀ§¿¡ ÀÖÀ» ¶§ // : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ Àû¿¡°Ô // : A ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[A_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = A_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[A_SKILL]; ppAggresiveCreature[0] = m_lpTarget; } break; default: { ERRLOG1(g_Log, "CID:0x%08x ¾ø´Â ÆÐÅÏÀÌ ³Ñ¾î¿Ô½À´Ï´Ù.", m_dwCID); return false; } } // ½ºÅ³ »ç¿ë (ij½ºÆÃ ŸÀÔÀÎ °æ¿ì¿¡´Â »ç¿ëÇÒ¼ö ÀÖ´ÂÁö¸¸ üũÇÏ°Ô µÈ´Ù.) if (true == UseSkill(attackType, ppAggresiveCreature, nSkillPattern)) { return true; } else { ++nSelectPattern; } } return false; } // ------------------------------------------------------------------------------------- // ¸ó½ºÅÍ Å¸ÀÔ (¿ö¸®¾î) CWarriorMonster::CWarriorMonster() : CSkillMonster() { } CWarriorMonster::CWarriorMonster(MonsterCreateInfo& MonsterCreate, bool bAdminCmdSummon) : CSkillMonster(MonsterCreate, bAdminCmdSummon) { } CWarriorMonster::~CWarriorMonster() { } bool CWarriorMonster::SkillAttack(void) { unsigned char cSkillLockCount = m_MonsterInfo.m_cSkillLevel / CSkillMgr::MAX_SKILL_LEVEL; unsigned char cSkillLevel = m_MonsterInfo.m_cSkillLevel % CSkillMgr::MAX_SKILL_LEVEL; if (cSkillLockCount >= CSkillMgr::MAX_SKILL_LOCKCOUNT - 1) { cSkillLockCount = CSkillMgr::MAX_SKILL_LOCKCOUNT - 2; } if (cSkillLockCount > 0 && cSkillLevel < CSkillMonster::USE_SKILL_MIN_LEVEL) { --cSkillLockCount; cSkillLevel = CSkillMonster::USE_SKILL_LEVEL; } // ¸¶¹ýÀ» ¾µ¼ö ¾ø´Â.. m_nSkillLevel ÀÌ 0 ÀÎ ³à¼®ÀÌ´Ù. if (0 == cSkillLockCount && 0 == cSkillLevel) { //ERRLOG1(g_Log, "CID:0x%08x ¸¶¹ýÀ» ¾µ¼ö ¾ø´Â ³à¼®ÀÔ´Ï´Ù. ¸ó½ºÅÍÀÇ ½ºÅ³·¹º§ÀÌ 0 À¸·Î ¼³Á¤µÇ¾î ÀÖ½À´Ï´Ù.", m_dwCID); return false; } enum { FIRST_PATTERN=0, SECOND_PATTERN=1, THIRD_PATTERN=2, FOURTH_PATTERN=3, MAX_PATTERN = 4 }; int nSelectPattern = FIRST_PATTERN; CAggresiveCreature* ppAggresiveCreature[AtNode::MAX_DEFENDER_NUM] = {0, }; AtType attackType; attackType.m_cSkillLockCount = cSkillLockCount; attackType.m_cSkillLevel = cSkillLevel; char nSkillPattern = 0; while (nSelectPattern < MAX_PATTERN) { switch (nSelectPattern) { case FIRST_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // B B D : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ ÀûÀÌ ÀÚ½ÅÀ¸·ÎºÎÅÍ 5m ÀÌ»ó ¸Ö¾îÁú ¶§ // : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ Àû¿¡°Ô // : D ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î ³Ñ±ä´Ù. if (0 == m_MonsterInfo.m_wSkillID[D_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = D_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[D_SKILL]; if (CalculateDistance(m_lpTarget) < 5.f) { ++nSelectPattern; continue; } ppAggresiveCreature[0] = m_lpTarget; } break; case SECOND_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // E A C : Àڽſ¡°Ô ºÎ¿© ¸¶¹ýÀÌ °É·ÁÁ® ÀÖÁö ¾ÊÀ» ¶§ // : Àڽſ¡°Ô // : C ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø°Å³ª, ÀÌ¹Ì ºÎ¿© ¸¶¹ýÀÌ °É·Á ÀÖ´Â »óŶó¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î ³Ñ±ä´Ù. if (0 == m_MonsterInfo.m_wSkillID[C_SKILL] || true == GetEnchantInfo().GetFlag(m_MonsterInfo.m_cEnchantSpellType)) { ++nSelectPattern; continue; } nSkillPattern = C_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[C_SKILL]; ppAggresiveCreature[0] = this; } break; case THIRD_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // C C B : ±×·ì¿¡ ¼ÓÇØÀÖ´Â ¾Æ±ºÁß Çϳª¶óµµ HP°¡ 50% ÀÌÇϰ¡ µÇ¾úÀ» ¶§ // : °¡Àå ³·Àº HP¸¦ °¡Áö°í ÀÖ´Â ¾Æ±º // : B ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[B_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = B_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[B_SKILL]; ppAggresiveCreature[0] = FindLowestHPMember(attackType, true); if (NULL == ppAggresiveCreature[0]) { ++nSelectPattern; continue; } } break; case FOURTH_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // C B A : ±×·ì¿¡ ¼ÓÇØÀÖ´Â ¾Æ±ºÁß Çϳª¶óµµ HP°¡ 50% ÀÌÇϰ¡ µÇ¾úÀ» ¶§ // : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ Àû // : A ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[A_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = A_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[A_SKILL]; ppAggresiveCreature[0] = m_lpTarget; } break; default: { ERRLOG1(g_Log, "CID:0x%08x ¾ø´Â ÆÐÅÏÀÌ ³Ñ¾î¿Ô½À´Ï´Ù.", m_dwCID); return false; } } // ½ºÅ³ »ç¿ë (ij½ºÆÃ ŸÀÔÀÎ °æ¿ì¿¡´Â »ç¿ëÇÒ¼ö ÀÖ´ÂÁö¸¸ üũÇÏ°Ô µÈ´Ù.) if (true == UseSkill(attackType, ppAggresiveCreature, nSkillPattern)) { return true; } else { ++nSelectPattern; } } return false; } // ------------------------------------------------------------------------------------- // ¸ó½ºÅÍ Å¸ÀÔ (¾îÄݶóÀÌÆ®) CAcolyteMonster::CAcolyteMonster() : CSkillMonster() { m_wDefaultSearchRange = ACOLYTE_SEARCH_RANGE; } CAcolyteMonster::CAcolyteMonster(MonsterCreateInfo& MonsterCreate, bool bAdminCmdSummon) : CSkillMonster(MonsterCreate, bAdminCmdSummon) { m_wDefaultSearchRange = ACOLYTE_SEARCH_RANGE; } CAcolyteMonster::~CAcolyteMonster() { } bool CAcolyteMonster::SkillAttack(void) { unsigned char cSkillLockCount = m_MonsterInfo.m_cSkillLevel / CSkillMgr::MAX_SKILL_LEVEL; unsigned char cSkillLevel = m_MonsterInfo.m_cSkillLevel % CSkillMgr::MAX_SKILL_LEVEL; if (cSkillLockCount >= CSkillMgr::MAX_SKILL_LOCKCOUNT - 1) { cSkillLockCount = CSkillMgr::MAX_SKILL_LOCKCOUNT - 2; } if (cSkillLockCount > 0 && cSkillLevel < CSkillMonster::USE_SKILL_MIN_LEVEL) { --cSkillLockCount; cSkillLevel = CSkillMonster::USE_SKILL_LEVEL; } // ¸¶¹ýÀ» ¾µ¼ö ¾ø´Â.. m_nSkillLevel ÀÌ 0 ÀÎ ³à¼®ÀÌ´Ù. if (0 == cSkillLockCount && 0 == cSkillLevel) { //ERRLOG1(g_Log, "CID:0x%08x ¸¶¹ýÀ» ¾µ¼ö ¾ø´Â ³à¼®ÀÔ´Ï´Ù. ¸ó½ºÅÍÀÇ ½ºÅ³·¹º§ÀÌ 0 À¸·Î ¼³Á¤µÇ¾î ÀÖ½À´Ï´Ù.", m_dwCID); return false; } enum { FIRST_PATTERN=0, SECOND_PATTERN=1, THIRD_PATTERN=2, FOURTH_PATTERN=3, MAX_PATTERN = 4 }; int nSelectPattern = FIRST_PATTERN; CAggresiveCreature* ppAggresiveCreature[AtNode::MAX_DEFENDER_NUM] = {0, }; AtType attackType; attackType.m_cSkillLockCount = cSkillLockCount; attackType.m_cSkillLevel = cSkillLevel; char nSkillPattern = 0; while (nSelectPattern < MAX_PATTERN) { switch (nSelectPattern) { case FIRST_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // C C B : ±×·ì¿¡ ¼ÓÇØÀÖ´Â ¾Æ±ºÁß Çϳª¶óµµ HP°¡ 50% ÀÌÇϰ¡ µÇ¾úÀ» ¶§ // : °¡Àå ³·Àº HP¸¦ °¡Áö°í ÀÖ´Â ¾Æ±º // : B ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[B_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = B_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[B_SKILL]; ppAggresiveCreature[0] = FindLowestHPMember(attackType, true); if (NULL == ppAggresiveCreature[0]) { ++nSelectPattern; continue; } } break; case SECOND_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // D C D : ±×·ì¿¡ ¼ÓÇØ ÀÖ´Â ¾Æ±ºÁß Çϳª¶óµµ HP°¡ 70% ÀÌÇϰ¡ µÇ¾úÀ» ¶§ // : °¡Àå ³·Àº HP¸¦ °¡Áö°í ÀÖ´Â ¾Æ±º // : D ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[D_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = D_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[D_SKILL]; ppAggresiveCreature[0] = FindLowestHPMember(attackType, true, 0.7f); if (NULL == ppAggresiveCreature[0]) { ++nSelectPattern; continue; } } break; case THIRD_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // A B A : ½ºÅ³ »ç¿ë °¡´É MP ÀÜ¿©·® ÀÖÀ½ / ´ë»óÀÌ ½ºÅ³ »ç¿ë °¡´É ¹üÀ§¿¡ ÀÖÀ» ¶§ // : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ Àû¿¡°Ô // : A ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[A_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = A_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[A_SKILL]; ppAggresiveCreature[0] = m_lpTarget; } break; case FOURTH_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // A J C : ½ºÅ³ »ç¿ë °¡´É MP ÀÜ¿©·® ÀÖÀ½ / ´ë»óÀÌ ½ºÅ³ »ç¿ë °¡´É ¹üÀ§¿¡ ÀÖÀ» ¶§ // : ºÎ¿© ½ºÅ³ÀÌ °É·ÁÀÖÁö ¾ÊÀº ¾Æ±º Áß °¡Àå ³ôÀº LV // : C ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[C_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = C_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[C_SKILL]; // ÇØ´ç ±â¼úÀÇ °Å¸® ¾È¿¡ ÀÖ´Â ÃÖ°í ·¹º§ÀÇ ÇØ´ç ¸ó½ºÅ͸¦ ¸®ÅÏÇØÁØ´Ù. // ÇØ´ç ºÎ¿© ½ºÅ³ÀÇ ½ºÆçÀÌ ÀÌ¹Ì °É·ÁÀÖ´Â ³à¼®À» Á¦¿ÜÇϰí ã¾Æ¼­ ³Ñ°ÜÁØ´Ù. ppAggresiveCreature[0] = FindHighestLVMember(attackType); // ÇÑ¸íµµ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î if (NULL == ppAggresiveCreature[0]) { ++nSelectPattern; continue; } } break; default: { ERRLOG1(g_Log, "CID:0x%08x ¾ø´Â ÆÐÅÏÀÌ ³Ñ¾î¿Ô½À´Ï´Ù.", m_dwCID); return false; } } // ½ºÅ³ »ç¿ë (ij½ºÆÃ ŸÀÔÀÎ °æ¿ì¿¡´Â »ç¿ëÇÒ¼ö ÀÖ´ÂÁö¸¸ üũÇÏ°Ô µÈ´Ù.) if (true == UseSkill(attackType, ppAggresiveCreature, nSkillPattern)) { return true; } else { ++nSelectPattern; } } return false; } // ------------------------------------------------------------------------------------- // ¸ó½ºÅÍ Å¸ÀÔ (¸ÞÀÌÁö) CMageMonster::CMageMonster() : CSkillMonster() { m_wDefaultSearchRange = MAGE_SEARCH_RANGE; } CMageMonster::CMageMonster(MonsterCreateInfo& MonsterCreate, bool bAdminCmdSummon) : CSkillMonster(MonsterCreate, bAdminCmdSummon) { m_wDefaultSearchRange = MAGE_SEARCH_RANGE; } CMageMonster::~CMageMonster() { } bool CMageMonster::SkillAttack(void) { unsigned char cSkillLockCount = m_MonsterInfo.m_cSkillLevel / CSkillMgr::MAX_SKILL_LEVEL; unsigned char cSkillLevel = m_MonsterInfo.m_cSkillLevel % CSkillMgr::MAX_SKILL_LEVEL; if (cSkillLockCount >= CSkillMgr::MAX_SKILL_LOCKCOUNT - 1) { cSkillLockCount = CSkillMgr::MAX_SKILL_LOCKCOUNT - 2; } if (cSkillLockCount > 0 && cSkillLevel < CSkillMonster::USE_SKILL_MIN_LEVEL) { --cSkillLockCount; cSkillLevel = CSkillMonster::USE_SKILL_LEVEL; } // ¸¶¹ýÀ» ¾µ¼ö ¾ø´Â.. m_nSkillLevel ÀÌ 0 ÀÎ ³à¼®ÀÌ´Ù. if (0 == cSkillLockCount && 0 == cSkillLevel) { //ERRLOG1(g_Log, "CID:0x%08x ¸¶¹ýÀ» ¾µ¼ö ¾ø´Â ³à¼®ÀÔ´Ï´Ù. ¸ó½ºÅÍÀÇ ½ºÅ³·¹º§ÀÌ 0 À¸·Î ¼³Á¤µÇ¾î ÀÖ½À´Ï´Ù.", m_dwCID); return false; } enum { FIRST_PATTERN=0, SECOND_PATTERN=1, THIRD_PATTERN=2, FOURTH_PATTERN=3, MAX_PATTERN = 4 }; int nSelectPattern = FIRST_PATTERN; CAggresiveCreature* ppAggresiveCreature[AtNode::MAX_DEFENDER_NUM] = {0, }; AtType attackType; attackType.m_cSkillLockCount = cSkillLockCount; attackType.m_cSkillLevel = cSkillLevel; char nSkillPattern = 0; while (nSelectPattern < MAX_PATTERN) { switch (nSelectPattern) { case FIRST_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // F A B : ÀÚ½ÅÀÇ MP°¡ 30% ÀÌÇϰ¡ µÇ¾úÀ» ¶§ // : Àڽſ¡°Ô // : B ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø°Å³ª, ÀÌ¹Ì ºÎ¿© ¸¶¹ýÀÌ °É·Á ÀÖ´Â »óŶó¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î ³Ñ±ä´Ù. if (0 == m_MonsterInfo.m_wSkillID[B_SKILL] || m_CreatureStatus.m_nNowMP > m_CreatureStatus.m_StatusInfo.m_nMaxMP * 0.3f) { ++nSelectPattern; continue; } nSkillPattern = B_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[B_SKILL]; ppAggresiveCreature[0] = this; } break; case SECOND_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // E A C : Àڽſ¡°Ô ºÎ¿© ¸¶¹ýÀÌ °É·ÁÁ® ÀÖÁö ¾ÊÀ» ¶§ // : Àڽſ¡°Ô // : C ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø°Å³ª, ÀÌ¹Ì ºÎ¿© ¸¶¹ýÀÌ °É·Á ÀÖ´Â »óŶó¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î ³Ñ±ä´Ù. if (0 == m_MonsterInfo.m_wSkillID[C_SKILL] || true == GetEnchantInfo().GetFlag(m_MonsterInfo.m_cEnchantSpellType)) { ++nSelectPattern; continue; } nSkillPattern = C_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[C_SKILL]; ppAggresiveCreature[0] = this; } break; case THIRD_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // A F A : ½ºÅ³ »ç¿ë °¡´É MP ÀÜ¿©·® ÀÖÀ½ / ´ë»óÀÌ ½ºÅ³ »ç¿ë °¡´É ¹üÀ§¿¡ ÀÖÀ» ¶§ // : °¡Àå ³·Àº HP¸¦ °¡Áö°í ÀÖ´Â Àû // : A ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[A_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = A_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[A_SKILL]; ppAggresiveCreature[0] = FindEnemy(attackType, TYPE_HP, TYPE_LOWEST); if (NULL == ppAggresiveCreature[0]) { ++nSelectPattern; continue; } } break; case FOURTH_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // A F D : ½ºÅ³ »ç¿ë °¡´É MP ÀÜ¿©·® ÀÖÀ½ / ´ë»óÀÌ ½ºÅ³ »ç¿ë °¡´É ¹üÀ§¿¡ ÀÖÀ» ¶§ // : °¡Àå ³·Àº HP¸¦ °¡Áö°í ÀÖ´Â Àû // : D ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[D_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = D_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[D_SKILL]; ppAggresiveCreature[0] = FindEnemy(attackType, TYPE_HP, TYPE_LOWEST); if (NULL == ppAggresiveCreature[0]) { ++nSelectPattern; continue; } } break; default: { ERRLOG1(g_Log, "CID:0x%08x ¾ø´Â ÆÐÅÏÀÌ ³Ñ¾î¿Ô½À´Ï´Ù.", m_dwCID); return false; } } // ½ºÅ³ »ç¿ë (ij½ºÆÃ ŸÀÔÀÎ °æ¿ì¿¡´Â »ç¿ëÇÒ¼ö ÀÖ´ÂÁö¸¸ üũÇÏ°Ô µÈ´Ù.) if (true == UseSkill(attackType, ppAggresiveCreature, nSkillPattern)) { return true; } else { ++nSelectPattern; } } return false; } // ------------------------------------------------------------------------------------- // ¸ó½ºÅÍ Å¸ÀÔ (º¸½º) CBossMonster::CBossMonster() : CSkillMonster() { m_wDefaultSearchRange = BOSS_SEARCH_RANGE; } CBossMonster::CBossMonster(MonsterCreateInfo& MonsterCreate, bool bAdminCmdSummon) : CSkillMonster(MonsterCreate, bAdminCmdSummon) { m_wDefaultSearchRange = BOSS_SEARCH_RANGE; } CBossMonster::~CBossMonster() { } bool CBossMonster::SkillAttack(void) { unsigned char cSkillLockCount = m_MonsterInfo.m_cSkillLevel / CSkillMgr::MAX_SKILL_LEVEL; unsigned char cSkillLevel = m_MonsterInfo.m_cSkillLevel % CSkillMgr::MAX_SKILL_LEVEL; if (cSkillLockCount >= CSkillMgr::MAX_SKILL_LOCKCOUNT - 1) { cSkillLockCount = CSkillMgr::MAX_SKILL_LOCKCOUNT - 2; } if (cSkillLockCount > 0 && cSkillLevel < CSkillMonster::USE_SKILL_MIN_LEVEL) { --cSkillLockCount; cSkillLevel = CSkillMonster::USE_SKILL_LEVEL; } // ¸¶¹ýÀ» ¾µ¼ö ¾ø´Â.. m_nSkillLevel ÀÌ 0 ÀÎ ³à¼®ÀÌ´Ù. if (0 == cSkillLockCount && 0 == cSkillLevel) { //ERRLOG1(g_Log, "CID:0x%08x ¸¶¹ýÀ» ¾µ¼ö ¾ø´Â ³à¼®ÀÔ´Ï´Ù. ¸ó½ºÅÍÀÇ ½ºÅ³·¹º§ÀÌ 0 À¸·Î ¼³Á¤µÇ¾î ÀÖ½À´Ï´Ù.", m_dwCID); return false; } enum { FIRST_PATTERN=0, SECOND_PATTERN=1, THIRD_PATTERN=2, FOURTH_PATTERN=3, FIFTH_PATTERN=4, MAX_PATTERN = 5 }; int nSelectPattern = FIRST_PATTERN; CAggresiveCreature* ppAggresiveCreature[AtNode::MAX_DEFENDER_NUM] = {0, }; AtType attackType; attackType.m_cSkillLockCount = cSkillLockCount; attackType.m_cSkillLevel = cSkillLevel; char nSkillPattern = 0; while (nSelectPattern < MAX_PATTERN) { switch (nSelectPattern) { case FIRST_PATTERN: { // ÀüÅõ°¡ ½ÃÀ۵Ǹé Boss ÀÇ Ã¦Æ® ½ºÅ³À» ¹ßµ¿ // ½ºÅ³ÀÌ ¾ø°Å³ª, ÀÌ¹Ì Ã¦Æ® ½ºÅ³À» ¹ßµ¿ÇÑ »óŸé.. ´ÙÀ½ ÆÐÅÏÀ¸·Î ³Ñ±ä´Ù. if (0 == m_MonsterInfo.m_wSkillID[BOSS_CHANT_SKILL] || true == GetEnchantInfo().GetFlag(m_MonsterInfo.m_cChantSpellType)) { ++nSelectPattern; continue; } nSkillPattern = BOSS_CHANT_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[BOSS_CHANT_SKILL]; ppAggresiveCreature[0] = this; } break; case SECOND_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // A F A : ½ºÅ³ »ç¿ë °¡´É MP ÀÜ¿©·® ÀÖÀ½ / ´ë»óÀÌ ½ºÅ³ »ç¿ë °¡´É ¹üÀ§¿¡ ÀÖÀ» ¶§ // : °¡Àå ³·Àº HP¸¦ °¡Áö°í ÀÖ´Â Àû // : A ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[A_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = A_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[A_SKILL]; ppAggresiveCreature[0] = FindEnemy(attackType, TYPE_HP, TYPE_LOWEST); if (NULL == ppAggresiveCreature[0]) { ++nSelectPattern; continue; } } break; case THIRD_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // D A B : ±×·ì¿¡ ¼ÓÇØ ÀÖ´Â ¾Æ±ºÁß Çϳª¶óµµ HP°¡ 70% ÀÌÇϰ¡ µÇ¾úÀ» ¶§ // : Àڽſ¡°Ô // : B ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[B_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = B_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[B_SKILL]; ppAggresiveCreature[0] = FindLowestHPMember(attackType, true, 0.7f); if (NULL == ppAggresiveCreature[0]) { ++nSelectPattern; continue; } ppAggresiveCreature[0] = this; } break; case FOURTH_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // B B C : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ ÀûÀÌ ÀÚ½ÅÀ¸·ÎºÎÅÍ 5m ÀÌ»ó ¸Ö¾îÁú ¶§ // : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ Àû¿¡°Ô // : C ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î ³Ñ±ä´Ù. if (0 == m_MonsterInfo.m_wSkillID[C_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = C_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[C_SKILL]; if (CalculateDistance(m_lpTarget) < 5.f) { ++nSelectPattern; continue; } ppAggresiveCreature[0] = m_lpTarget; } break; case FIFTH_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // C B D : ±×·ì¿¡ ¼ÓÇØÀÖ´Â ¾Æ±ºÁß Çϳª¶óµµ HP°¡ 50% ÀÌÇϰ¡ µÇ¾úÀ» ¶§ // : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ Àû // : D ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[D_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = D_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[D_SKILL]; ppAggresiveCreature[0] = FindLowestHPMember(attackType, true); if (NULL == ppAggresiveCreature[0]) { ++nSelectPattern; continue; } ppAggresiveCreature[0] = m_lpTarget; } break; default: { ERRLOG1(g_Log, "CID:0x%08x ¾ø´Â ÆÐÅÏÀÌ ³Ñ¾î¿Ô½À´Ï´Ù.", m_dwCID); return false; } } // ½ºÅ³ »ç¿ë (ij½ºÆÃ ŸÀÔÀÎ °æ¿ì¿¡´Â »ç¿ëÇÒ¼ö ÀÖ´ÂÁö¸¸ üũÇÏ°Ô µÈ´Ù.) if (true == UseSkill(attackType, ppAggresiveCreature, nSkillPattern)) { return true; } else { ++nSelectPattern; } } return false; } // ------------------------------------------------------------------------------------- // ¸ó½ºÅÍ Å¸ÀÔ (Ä¡ÇÁ) CChiefMonster::CChiefMonster() : CSkillMonster() { m_wDefaultSearchRange = CHIEF_SEARCH_RANGE; } CChiefMonster::CChiefMonster(MonsterCreateInfo& MonsterCreate, bool bAdminCmdSummon) : CSkillMonster(MonsterCreate, bAdminCmdSummon) { m_wDefaultSearchRange = CHIEF_SEARCH_RANGE; } CChiefMonster::~CChiefMonster() { } bool CChiefMonster::SkillAttack(void) { unsigned char cSkillLockCount = m_MonsterInfo.m_cSkillLevel / CSkillMgr::MAX_SKILL_LEVEL; unsigned char cSkillLevel = m_MonsterInfo.m_cSkillLevel % CSkillMgr::MAX_SKILL_LEVEL; if (cSkillLockCount >= CSkillMgr::MAX_SKILL_LOCKCOUNT - 1) { cSkillLockCount = CSkillMgr::MAX_SKILL_LOCKCOUNT - 2; } if (cSkillLockCount > 0 && cSkillLevel < CSkillMonster::USE_SKILL_MIN_LEVEL) { --cSkillLockCount; cSkillLevel = CSkillMonster::USE_SKILL_LEVEL; } // ¸¶¹ýÀ» ¾µ¼ö ¾ø´Â.. m_nSkillLevel ÀÌ 0 ÀÎ ³à¼®ÀÌ´Ù. if (0 == cSkillLockCount && 0 == cSkillLevel) { //ERRLOG1(g_Log, "CID:0x%08x ¸¶¹ýÀ» ¾µ¼ö ¾ø´Â ³à¼®ÀÔ´Ï´Ù. ¸ó½ºÅÍÀÇ ½ºÅ³·¹º§ÀÌ 0 À¸·Î ¼³Á¤µÇ¾î ÀÖ½À´Ï´Ù.", m_dwCID); return false; } enum { FIRST_PATTERN=0, SECOND_PATTERN=1, THIRD_PATTERN=2, FOURTH_PATTERN=3, FIFTH_PATTERN=4, MAX_PATTERN = 5 }; int nSelectPattern = FIRST_PATTERN; CAggresiveCreature* ppAggresiveCreature[AtNode::MAX_DEFENDER_NUM] = {0, }; AtType attackType; attackType.m_cSkillLockCount = cSkillLockCount; attackType.m_cSkillLevel = cSkillLevel; char nSkillPattern = 0; while (nSelectPattern < MAX_PATTERN) { switch (nSelectPattern) { case FIRST_PATTERN: { // ÀüÅõ°¡ ½ÃÀ۵Ǹé Boss ÀÇ Ã¦Æ® ½ºÅ³À» ¹ßµ¿ // ½ºÅ³ÀÌ ¾ø°Å³ª, ÀÌ¹Ì Ã¦Æ® ½ºÅ³À» ¹ßµ¿ÇÑ »óŸé.. ´ÙÀ½ ÆÐÅÏÀ¸·Î ³Ñ±ä´Ù. if (0 == m_MonsterInfo.m_wSkillID[BOSS_CHANT_SKILL] || true == GetEnchantInfo().GetFlag(m_MonsterInfo.m_cChantSpellType)) { ++nSelectPattern; continue; } nSkillPattern = BOSS_CHANT_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[BOSS_CHANT_SKILL]; ppAggresiveCreature[0] = this; } break; case SECOND_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // E A C : Àڽſ¡°Ô ºÎ¿© ¸¶¹ýÀÌ °É·ÁÁ® ÀÖÁö ¾ÊÀ» ¶§ // : Àڽſ¡°Ô // : C ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø°Å³ª, ÀÌ¹Ì ºÎ¿© ¸¶¹ýÀÌ °É·Á ÀÖ´Â »óŶó¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î ³Ñ±ä´Ù. if (0 == m_MonsterInfo.m_wSkillID[C_SKILL] || true == GetEnchantInfo().GetFlag(m_MonsterInfo.m_cEnchantSpellType)) { ++nSelectPattern; continue; } nSkillPattern = C_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[C_SKILL]; ppAggresiveCreature[0] = this; } break; case THIRD_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // C C B : ±×·ì¿¡ ¼ÓÇØÀÖ´Â ¾Æ±ºÁß Çϳª¶óµµ HP°¡ 50% ÀÌÇϰ¡ µÇ¾úÀ» ¶§ // : °¡Àå ³·Àº HP¸¦ °¡Áö°í ÀÖ´Â ¾Æ±º // : B ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[B_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = B_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[B_SKILL]; ppAggresiveCreature[0] = FindLowestHPMember(attackType, true); if (NULL == ppAggresiveCreature[0]) { ++nSelectPattern; continue; } } break; case FOURTH_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // A B A : ½ºÅ³ »ç¿ë °¡´É MP ÀÜ¿©·® ÀÖÀ½ / ´ë»óÀÌ ½ºÅ³ »ç¿ë °¡´É ¹üÀ§¿¡ ÀÖÀ» ¶§ // : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ Àû¿¡°Ô // : A ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[A_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = A_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[A_SKILL]; ppAggresiveCreature[0] = m_lpTarget; } break; case FIFTH_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // A B D : ½ºÅ³ »ç¿ë °¡´É MP ÀÜ¿©·® ÀÖÀ½ / ´ë»óÀÌ ½ºÅ³ »ç¿ë °¡´É ¹üÀ§¿¡ ÀÖÀ» ¶§ // : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ Àû¿¡°Ô // : D ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[D_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = D_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[D_SKILL]; ppAggresiveCreature[0] = m_lpTarget; } break; default: { ERRLOG1(g_Log, "CID:0x%08x ¾ø´Â ÆÐÅÏÀÌ ³Ñ¾î¿Ô½À´Ï´Ù.", m_dwCID); return false; } } // ½ºÅ³ »ç¿ë (ij½ºÆÃ ŸÀÔÀÎ °æ¿ì¿¡´Â »ç¿ëÇÒ¼ö ÀÖ´ÂÁö¸¸ üũÇÏ°Ô µÈ´Ù.) if (true == UseSkill(attackType, ppAggresiveCreature, nSkillPattern)) { return true; } else { ++nSelectPattern; } } return false; } // ------------------------------------------------------------------------------------- // ¸ó½ºÅÍ Å¸ÀÔ (³×ÀÓµå) CNamedMonster::CNamedMonster() : CSkillMonster() { m_wDefaultSearchRange = NAMED_SEARCH_RANGE; } CNamedMonster::CNamedMonster(MonsterCreateInfo& MonsterCreate, bool bAdminCmdSummon) : CSkillMonster(MonsterCreate, bAdminCmdSummon) { m_RespawnPosition = MonsterCreate.m_Pos; if (!bAdminCmdSummon && m_wRespawnArea > 0) { MonsterCreate.m_Pos.m_fPointX += static_cast(Math::Random::SimpleRandom(GetTickCount(), m_wRespawnArea*2) - m_wRespawnArea); MonsterCreate.m_Pos.m_fPointZ += static_cast(Math::Random::SimpleRandom(GetTickCount(), m_wRespawnArea*2) - m_wRespawnArea); } m_OriginalPosition = MonsterCreate.m_Pos; m_wDefaultSearchRange = NAMED_SEARCH_RANGE; } CNamedMonster::~CNamedMonster() { } void CNamedMonster::Respawn(unsigned long dwTick) { m_OriginalPosition = m_RespawnPosition; if(m_wRespawnArea > 0) { float randomValue = static_cast(Math::Random::ComplexRandom(m_wRespawnArea*2)); m_OriginalPosition.m_fPointX += randomValue - m_wRespawnArea; randomValue = static_cast(Math::Random::ComplexRandom(m_wRespawnArea*2)); m_OriginalPosition.m_fPointZ += randomValue - m_wRespawnArea; } InitMonster(m_OriginalPosition); m_nCurrentState = STATE_ID_NORMAL; // ¸®½ºÆù½Ã ¿ÜÄ¡±â. CMonsterShout::GetInstance().Shout(m_dwCID, m_MonsterInfo.m_dwKID, static_cast(m_CurrentPos.m_fPointX), static_cast(m_CurrentPos.m_fPointZ), CMonsterShout::RESPAWN, 0, 0); // ÆÄƼ¿¡ Ãß°¡ CParty* lpParty = CPartyMgr::GetInstance().GetParty(GetPID()); if (NULL != lpParty) { SetParty(lpParty); lpParty->Join(GetCID(), 0, NULL, GetMapIndex()); } } bool CNamedMonster::SkillAttack(void) { unsigned char cSkillLockCount = m_MonsterInfo.m_cSkillLevel / CSkillMgr::MAX_SKILL_LEVEL; unsigned char cSkillLevel = m_MonsterInfo.m_cSkillLevel % CSkillMgr::MAX_SKILL_LEVEL; if (cSkillLockCount >= CSkillMgr::MAX_SKILL_LOCKCOUNT - 1) { cSkillLockCount = CSkillMgr::MAX_SKILL_LOCKCOUNT - 2; } if (cSkillLockCount > 0 && cSkillLevel < CSkillMonster::USE_SKILL_MIN_LEVEL) { --cSkillLockCount; cSkillLevel = CSkillMonster::USE_SKILL_LEVEL; } // ¸¶¹ýÀ» ¾µ¼ö ¾ø´Â.. m_nSkillLevel ÀÌ 0 ÀÎ ³à¼®ÀÌ´Ù. if (0 == cSkillLockCount && 0 == cSkillLevel) return false; enum { FIRST_PATTERN=0, SECOND_PATTERN=1, THIRD_PATTERN=2, FOURTH_PATTERN=3, FIFTH_PATTERN=4, MAX_PATTERN = 5 }; int nSelectPattern = FIRST_PATTERN; CAggresiveCreature* ppAggresiveCreature[AtNode::MAX_DEFENDER_NUM] = {0, }; AtType attackType; attackType.m_cSkillLockCount = cSkillLockCount; attackType.m_cSkillLevel = cSkillLevel; char nSkillPattern = 0; while (nSelectPattern < MAX_PATTERN) { switch (nSelectPattern) { case FIRST_PATTERN: { // ÀüÅõ°¡ ½ÃÀ۵Ǹé Boss ÀÇ Ã¦Æ® ½ºÅ³À» ¹ßµ¿ // ½ºÅ³ÀÌ ¾ø°Å³ª, ÀÌ¹Ì Ã¦Æ® ½ºÅ³À» ¹ßµ¿ÇÑ »óŸé.. ´ÙÀ½ ÆÐÅÏÀ¸·Î ³Ñ±ä´Ù. if (0 == m_MonsterInfo.m_wSkillID[BOSS_CHANT_SKILL] || true == GetEnchantInfo().GetFlag(m_MonsterInfo.m_cChantSpellType)) { ++nSelectPattern; continue; } nSkillPattern = BOSS_CHANT_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[BOSS_CHANT_SKILL]; ppAggresiveCreature[0] = this; } break; case SECOND_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // C B A : ±×·ì¿¡ ¼ÓÇØÀÖ´Â ¾Æ±ºÁß Çϳª¶óµµ HP°¡ 50% ÀÌÇϰ¡ µÇ¾úÀ» ¶§ // : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ Àû // : A ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[A_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = A_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[A_SKILL]; ppAggresiveCreature[0] = FindLowestHPMember(attackType, true); if (NULL == ppAggresiveCreature[0]) { ++nSelectPattern; continue; } ppAggresiveCreature[0] = m_lpTarget; } break; case THIRD_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // D A B : ±×·ì¿¡ ¼ÓÇØ ÀÖ´Â ¾Æ±ºÁß Çϳª¶óµµ HP°¡ 70% ÀÌÇϰ¡ µÇ¾úÀ» ¶§ // : Àڽſ¡°Ô // : B ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[B_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = B_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[B_SKILL]; ppAggresiveCreature[0] = FindLowestHPMember(attackType, true, 0.7f); if (NULL == ppAggresiveCreature[0]) { ++nSelectPattern; continue; } ppAggresiveCreature[0] = this; } break; case FOURTH_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // E A C : Àڽſ¡°Ô ºÎ¿© ¸¶¹ýÀÌ °É·ÁÁ® ÀÖÁö ¾ÊÀ» ¶§ // : Àڽſ¡°Ô // : C ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø°Å³ª, ÀÌ¹Ì ºÎ¿© ¸¶¹ýÀÌ °É·Á ÀÖ´Â »óŶó¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î ³Ñ±ä´Ù. if (0 == m_MonsterInfo.m_wSkillID[C_SKILL] || true == GetEnchantInfo().GetFlag(m_MonsterInfo.m_cEnchantSpellType)) { ++nSelectPattern; continue; } nSkillPattern = C_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[C_SKILL]; ppAggresiveCreature[0] = this; } break; case FIFTH_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // A B D : ½ºÅ³ »ç¿ë °¡´É MP ÀÜ¿©·® ÀÖÀ½ / ´ë»óÀÌ ½ºÅ³ »ç¿ë °¡´É ¹üÀ§¿¡ ÀÖÀ» ¶§ // : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ Àû¿¡°Ô // : D ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[D_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = D_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[D_SKILL]; ppAggresiveCreature[0] = m_lpTarget; } break; default: { ERRLOG1(g_Log, "CID:0x%08x ¾ø´Â ÆÐÅÏÀÌ ³Ñ¾î¿Ô½À´Ï´Ù.", m_dwCID); return false; } } // ½ºÅ³ »ç¿ë (ij½ºÆÃ ŸÀÔÀÎ °æ¿ì¿¡´Â »ç¿ëÇÒ¼ö ÀÖ´ÂÁö¸¸ üũÇÏ°Ô µÈ´Ù.) if (true == UseSkill(attackType, ppAggresiveCreature, nSkillPattern)) { const char* szTargetName = 0; if (0 != ppAggresiveCreature[0] && Creature::CT_PC == Creature::GetCreatureType(ppAggresiveCreature[0]->GetCID())) { szTargetName = static_cast(ppAggresiveCreature[0])->GetCharacterName(); } // ½ºÅ³ »ç¿ë½Ã ¿ÜÄ¡±â CMonsterShout::GetInstance().Shout(m_dwCID, m_MonsterInfo.m_dwKID, static_cast(m_CurrentPos.m_fPointX), static_cast(m_CurrentPos.m_fPointZ), CMonsterShout::SKILL_ATTACK, szTargetName, attackType.m_wType); return true; } else { ++nSelectPattern; } } return false; } // ------------------------------------------------------------------------------------- // ¸ó½ºÅÍ Å¸ÀÔ (°æºñº´) CGuardMonster::CGuardMonster() : CSkillMonster() { m_wDefaultSearchRange = GUARD_SEARCH_RANGE; } CGuardMonster::CGuardMonster(MonsterCreateInfo& MonsterCreate, bool bAdminCmdSummon) : CSkillMonster(MonsterCreate, bAdminCmdSummon) { } CGuardMonster::~CGuardMonster() { } void CGuardMonster::SearchPlayer() { // TODO : ÇØ»óµµ Á¶ÀýÀ» ÅëÇØ float °è»êÀ» ¾ø¾Öº¸ÀÚ. if (NULL == m_CellPos.m_lpCell) { ERRLOG1(g_Log, "CID:0X%08 ¸ó½ºÅͰ¡ ¼¿ ¹üÀ§ ¹Û¿¡ ÀÖ½À´Ï´Ù.", m_dwCID); return; } CCell* pCell = NULL; CCharacter* pTempTarget = NULL; CCharacter* pCurrentTarget = NULL; const float fSquareSearchRange = (float)(m_wSearchRange * m_wSearchRange); for (int nCellCount = 0; nCellCount < CCell::CONNECT_NUM; ++nCellCount) { pCell = m_CellPos.m_lpCell->GetConnectCell(nCellCount); if (NULL == pCell || false == pCell->IsCharacter()) { continue; } pTempTarget = pCell->GetFirstCharacter(); while (NULL != pTempTarget) { if (pTempTarget->GetStatus().m_nNowHP > 0 && false == pTempTarget->IsRideArms() && EnemyCheck::EC_ENEMY == IsEnemy(pTempTarget)) { if (false == pTempTarget->GetEnchantInfo().GetFlag(Skill::SpellID::Stealth) && false == pTempTarget->GetEnchantInfo().GetFlag(Skill::SpellID::Invincible) && false == pTempTarget->GetEnchantInfo().GetFlag(Skill::SpellID::Hide)) { const float fDX = pTempTarget->GetCurrentPos().m_fPointX - GetCurrentPos().m_fPointX; const float fDZ = pTempTarget->GetCurrentPos().m_fPointZ - GetCurrentPos().m_fPointZ; const float fDistance = (fDX * fDX) + (fDZ * fDZ); if (fDistance < fSquareSearchRange) { pCurrentTarget = pTempTarget; break; } } } pTempTarget = pCell->GetNextCharacter(); } } if (NULL != pCurrentTarget) { m_Threat.AddToThreatList(pCurrentTarget, 1); m_nCurrentState = CFSM::GetInstance().StateTransition(m_nCurrentState, INPUT_ID_SEEN_PLAYER); } } bool CGuardMonster::SkillAttack(void) { unsigned char cSkillLockCount = m_MonsterInfo.m_cSkillLevel / CSkillMgr::MAX_SKILL_LEVEL; unsigned char cSkillLevel = m_MonsterInfo.m_cSkillLevel % CSkillMgr::MAX_SKILL_LEVEL; if (cSkillLockCount >= CSkillMgr::MAX_SKILL_LOCKCOUNT - 1) { cSkillLockCount = CSkillMgr::MAX_SKILL_LOCKCOUNT - 2; } if (cSkillLockCount > 0 && cSkillLevel < CSkillMonster::USE_SKILL_MIN_LEVEL) { --cSkillLockCount; cSkillLevel = CSkillMonster::USE_SKILL_LEVEL; } // ¸¶¹ýÀ» ¾µ¼ö ¾ø´Â.. m_nSkillLevel ÀÌ 0 ÀÎ ³à¼®ÀÌ´Ù. if (0 == cSkillLockCount && 0 == cSkillLevel) { //ERRLOG1(g_Log, "CID:0x%08x ¸¶¹ýÀ» ¾µ¼ö ¾ø´Â ³à¼®ÀÔ´Ï´Ù. ¸ó½ºÅÍÀÇ ½ºÅ³·¹º§ÀÌ 0 À¸·Î ¼³Á¤µÇ¾î ÀÖ½À´Ï´Ù.", m_dwCID); return false; } enum { FIRST_PATTERN=0, SECOND_PATTERN=1, THIRD_PATTERN=2, FOURTH_PATTERN=3, MAX_PATTERN = 4 }; int nSelectPattern = FIRST_PATTERN; CAggresiveCreature* ppAggresiveCreature[AtNode::MAX_DEFENDER_NUM] = {0, }; AtType attackType; attackType.m_cSkillLockCount = cSkillLockCount; attackType.m_cSkillLevel = cSkillLevel; char nSkillPattern = 0; while (nSelectPattern < MAX_PATTERN) { switch (nSelectPattern) { case FIRST_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // B B D : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ ÀûÀÌ ÀÚ½ÅÀ¸·ÎºÎÅÍ 5m ÀÌ»ó ¸Ö¾îÁú ¶§ // : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ Àû¿¡°Ô // : D ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î ³Ñ±ä´Ù. if (0 == m_MonsterInfo.m_wSkillID[D_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = D_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[D_SKILL]; if (CalculateDistance(m_lpTarget) < 5.f) { ++nSelectPattern; continue; } ppAggresiveCreature[0] = m_lpTarget; } break; case SECOND_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // E A C : Àڽſ¡°Ô ºÎ¿© ¸¶¹ýÀÌ °É·ÁÁ® ÀÖÁö ¾ÊÀ» ¶§ // : Àڽſ¡°Ô // : C ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø°Å³ª, ÀÌ¹Ì ºÎ¿© ¸¶¹ýÀÌ °É·Á ÀÖ´Â »óŶó¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î ³Ñ±ä´Ù. if (0 == m_MonsterInfo.m_wSkillID[C_SKILL] || true == GetEnchantInfo().GetFlag(m_MonsterInfo.m_cEnchantSpellType)) { ++nSelectPattern; continue; } nSkillPattern = C_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[C_SKILL]; ppAggresiveCreature[0] = this; } break; case THIRD_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // C C B : ±×·ì¿¡ ¼ÓÇØÀÖ´Â ¾Æ±ºÁß Çϳª¶óµµ HP°¡ 50% ÀÌÇϰ¡ µÇ¾úÀ» ¶§ // : °¡Àå ³·Àº HP¸¦ °¡Áö°í ÀÖ´Â ¾Æ±º // : B ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[B_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = B_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[B_SKILL]; ppAggresiveCreature[0] = FindLowestHPMember(attackType, true); if (NULL == ppAggresiveCreature[0]) { ++nSelectPattern; continue; } } break; case FOURTH_PATTERN: { // Á¶°Ç ´ë»ó Çൿ // A B A : ½ºÅ³ »ç¿ë °¡´É MP ÀÜ¿©·® ÀÖÀ½ / ´ë»óÀÌ ½ºÅ³ »ç¿ë °¡´É ¹üÀ§¿¡ ÀÖÀ» ¶§ // : Àڽſ¡°Ô °¡Àå À§ÇùÀûÀÎ Àû¿¡°Ô // : A ½ºÅ³ »ç¿ë // ½ºÅ³ÀÌ ¾ø´Ù¸é.. ´ÙÀ½ ÆÐÅÏÀ¸·Î.. if (0 == m_MonsterInfo.m_wSkillID[A_SKILL]) { ++nSelectPattern; continue; } nSkillPattern = A_SKILL; attackType.m_wType = m_MonsterInfo.m_wSkillID[A_SKILL]; ppAggresiveCreature[0] = m_lpTarget; } break; default: { ERRLOG1(g_Log, "CID:0x%08x ¾ø´Â ÆÐÅÏÀÌ ³Ñ¾î¿Ô½À´Ï´Ù.", m_dwCID); return false; } } // ½ºÅ³ »ç¿ë (ij½ºÆÃ ŸÀÔÀÎ °æ¿ì¿¡´Â »ç¿ëÇÒ¼ö ÀÖ´ÂÁö¸¸ üũÇÏ°Ô µÈ´Ù.) if (true == UseSkill(attackType, ppAggresiveCreature, nSkillPattern)) { return true; } else { ++nSelectPattern; } } return false; }