CWarMap::CWarMap(long lMapIndex, const TGuildWarInfo & r_info, TWarMapInfo * pkWarMapInfo, DWORD dwGuildID1, DWORD dwGuildID2) { m_kMapInfo = *pkWarMapInfo; m_kMapInfo.lMapIndex = lMapIndex; memcpy(&m_WarInfo, &r_info, sizeof(TGuildWarInfo)); m_TeamData[0].Initialize(); m_TeamData[0].dwID = dwGuildID1; m_TeamData[0].pkGuild = CGuildManager::instance().TouchGuild(dwGuildID1); m_TeamData[1].Initialize(); m_TeamData[1].dwID = dwGuildID2; m_TeamData[1].pkGuild = CGuildManager::instance().TouchGuild(dwGuildID2); m_iObserverCount = 0; war_map_info* info = AllocEventInfo<war_map_info>(); info->pWarMap = this; SetBeginEvent(event_create(war_begin_event, info, PASSES_PER_SEC(60))); m_pkEndEvent = NULL; m_pkTimeoutEvent = NULL; m_pkResetFlagEvent = NULL; m_bTimeout = false; m_dwStartTime = get_dword_time(); m_bEnded = false; if (GetType() == WAR_MAP_TYPE_FLAG) { AddFlagBase(0); AddFlagBase(1); AddFlag(0); AddFlag(1); } }
void CParty::HealParty() { // XXX DELETEME 클라이언트 완료될때까지 { return; } if (!m_bPartyHealReady) return; TMemberMap::iterator it; LPCHARACTER l = GetLeaderCharacter(); for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { if (!it->second.pCharacter) continue; LPCHARACTER ch = it->second.pCharacter; if (DISTANCE_APPROX(l->GetX()-ch->GetX(), l->GetY()-ch->GetY()) < PARTY_DEFAULT_RANGE) { ch->PointChange(POINT_HP, ch->GetMaxHP()-ch->GetHP()); ch->PointChange(POINT_SP, ch->GetMaxSP()-ch->GetSP()); } } m_bPartyHealReady = false; m_dwPartyHealTime = get_dword_time(); }
void CParty::Destroy() { sys_log(2, "Party::Destroy"); // PC가 만든 파티면 파티매니저에 맵에서 PID를 삭제해야 한다. if (m_bPCParty) { for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it) CPartyManager::instance().SetPartyMember(it->first, NULL); } event_cancel(&m_eventUpdate); RemoveBonus(); TMemberMap::iterator it = m_memberMap.begin(); DWORD dwTime = get_dword_time(); while (it != m_memberMap.end()) { TMember & rMember = it->second; ++it; if (rMember.pCharacter) { if (rMember.pCharacter->GetDesc()) { TPacketGCPartyRemove p; p.header = HEADER_GC_PARTY_REMOVE; p.pid = rMember.pCharacter->GetPlayerID(); rMember.pCharacter->GetDesc()->Packet(&p, sizeof(p)); rMember.pCharacter->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티가 해산 되었습니다.")); } else { // NPC일 경우 일정 시간 후 전투 중이 아닐 때 사라지게 하는 이벤트를 시작시킨다. rMember.pCharacter->SetLastAttacked(dwTime); rMember.pCharacter->StartDestroyWhenIdleEvent(); } rMember.pCharacter->SetParty(NULL); } } m_memberMap.clear(); m_itNextOwner = m_memberMap.begin(); if (m_pkDungeon_for_Only_party != NULL) { m_pkDungeon_for_Only_party->SetPartyNull(); m_pkDungeon_for_Only_party = NULL; } }
void CParty::Destroy() { sys_log(2, "Party::Destroy"); // PC°Ў ёёµз ЖДЖјёй ЖДЖјёЕґПАъїЎ ёКїЎј PIDё¦ »иБ¦ЗШѕЯ ЗСґЩ. if (m_bPCParty) { for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it) CPartyManager::instance().SetPartyMember(it->first, NULL); } event_cancel(&m_eventUpdate); RemoveBonus(); TMemberMap::iterator it = m_memberMap.begin(); DWORD dwTime = get_dword_time(); while (it != m_memberMap.end()) { TMember & rMember = it->second; ++it; if (rMember.pCharacter) { if (rMember.pCharacter->GetDesc()) { TPacketGCPartyRemove p; p.header = HEADER_GC_PARTY_REMOVE; p.pid = rMember.pCharacter->GetPlayerID(); rMember.pCharacter->GetDesc()->Packet(&p, sizeof(p)); rMember.pCharacter->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ЖДЖј> ЖДЖј°Ў ЗШ»к µЗѕъЅАґПґЩ.")); } else { // NPCАП °жїм АПБ¤ ЅГ°Ј ИД АьЕх БЯАМ ѕЖґТ ¶§ »з¶уБц°Ф ЗПґВ АМєҐЖ®ё¦ ЅГАЫЅГЕІґЩ. rMember.pCharacter->SetLastAttacked(dwTime); rMember.pCharacter->StartDestroyWhenIdleEvent(); } rMember.pCharacter->SetParty(NULL); } } m_memberMap.clear(); m_itNextOwner = m_memberMap.begin(); if (m_pkDungeon_for_Only_party != NULL) { m_pkDungeon_for_Only_party->SetPartyNull(); m_pkDungeon_for_Only_party = NULL; } }
bool CWarMap::CheckScore() { if (m_bEnded) return true; // 30초 이후 부터 확인한다. if (get_dword_time() - m_dwStartTime < 30000) return false; // 점수가 같으면 체크하지 않는다. if (m_TeamData[0].iScore == m_TeamData[1].iScore) return false; int iEndScore = m_WarInfo.iEndScore; if (test_server) iEndScore /= 10; DWORD dwWinner; DWORD dwLoser; if (m_TeamData[0].iScore >= iEndScore) { dwWinner = m_TeamData[0].dwID; dwLoser = m_TeamData[1].dwID; } else if (m_TeamData[1].iScore >= iEndScore) { dwWinner = m_TeamData[1].dwID; dwLoser = m_TeamData[0].dwID; } else return false; int iRewardGold = 0; if (dwWinner == m_TeamData[0].dwID) iRewardGold = GetRewardGold(0); else if (dwWinner == m_TeamData[1].dwID) iRewardGold = GetRewardGold(1); sys_log(0, "WarMap::CheckScore end score %d guild1 %u score guild2 %d %u score %d winner %u reward %d", iEndScore, m_TeamData[0].dwID, m_TeamData[0].iScore, m_TeamData[1].dwID, m_TeamData[1].iScore, dwWinner, iRewardGold); CGuildManager::instance().RequestWarOver(dwWinner, dwLoser, dwWinner, iRewardGold); return true; }
void DESC_MANAGER::ProcessExpiredLoginKey() { DWORD dwCurrentTime = get_dword_time(); std::map<DWORD, CLoginKey *>::iterator it, it2; it = m_map_pkLoginKey.begin(); while (it != m_map_pkLoginKey.end()) { it2 = it++; if (it2->second->m_dwExpireTime == 0) continue; if (dwCurrentTime - it2->second->m_dwExpireTime > 60000) { M2_DELETE(it2->second); m_map_pkLoginKey.erase(it2); } } }
bool CHARACTER::UpdateAffect() { // affect_event 에서 처리할 일은 아니지만, 1초짜리 이벤트에서 처리하는 것이 // 이것 뿐이라 여기서 물약 처리를 한다. if (GetPoint(POINT_HP_RECOVERY) > 0) { if (GetMaxHP() <= GetHP()) { PointChange(POINT_HP_RECOVERY, -GetPoint(POINT_HP_RECOVERY)); } else { int iVal = 0; if (LC_IsYMIR()) { iVal = MIN(GetPoint(POINT_HP_RECOVERY), GetMaxHP() * 9 / 100); } else { iVal = MIN(GetPoint(POINT_HP_RECOVERY), GetMaxHP() * 7 / 100); } PointChange(POINT_HP, iVal); PointChange(POINT_HP_RECOVERY, -iVal); } } if (GetPoint(POINT_SP_RECOVERY) > 0) { if (GetMaxSP() <= GetSP()) PointChange(POINT_SP_RECOVERY, -GetPoint(POINT_SP_RECOVERY)); else { int iVal; if (!g_iUseLocale) iVal = MIN(GetPoint(POINT_SP_RECOVERY), GetMaxSP() * 7 / 100); else iVal = MIN(GetPoint(POINT_SP_RECOVERY), GetMaxSP() * 7 / 100); PointChange(POINT_SP, iVal); PointChange(POINT_SP_RECOVERY, -iVal); } } if (GetPoint(POINT_HP_RECOVER_CONTINUE) > 0) { PointChange(POINT_HP, GetPoint(POINT_HP_RECOVER_CONTINUE)); } if (GetPoint(POINT_SP_RECOVER_CONTINUE) > 0) { PointChange(POINT_SP, GetPoint(POINT_SP_RECOVER_CONTINUE)); } AutoRecoveryItemProcess( AFFECT_AUTO_HP_RECOVERY ); AutoRecoveryItemProcess( AFFECT_AUTO_SP_RECOVERY ); // 스테미나 회복 if (GetMaxStamina() > GetStamina()) { int iSec = (get_dword_time() - GetStopTime()) / 3000; if (iSec) PointChange(POINT_STAMINA, GetMaxStamina()/1); } // ProcessAffect는 affect가 없으면 true를 리턴한다. if (ProcessAffect()) if (GetPoint(POINT_HP_RECOVERY) == 0 && GetPoint(POINT_SP_RECOVERY) == 0 && GetStamina() == GetMaxStamina()) { m_pkAffectEvent = NULL; return false; } return true; }
void CParty::Update() { sys_log(1, "PARTY::Update"); LPCHARACTER l = GetLeaderCharacter(); if (!l) return; TMemberMap::iterator it; int iNearMember = 0; bool bResendAll = false; for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { LPCHARACTER ch = it->second.pCharacter; it->second.bNear = false; if (!ch) continue; if (l->GetDungeon()) it->second.bNear = l->GetDungeon() == ch->GetDungeon(); else it->second.bNear = (DISTANCE_APPROX(l->GetX()-ch->GetX(), l->GetY()-ch->GetY()) < PARTY_DEFAULT_RANGE); if (it->second.bNear) { ++iNearMember; //sys_log(0,"NEAR %s", ch->GetName()); } } if (iNearMember <= 1 && !l->GetDungeon()) { for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) it->second.bNear = false; iNearMember = 0; } if (iNearMember != m_iCountNearPartyMember) { m_iCountNearPartyMember = iNearMember; bResendAll = true; } m_iLeadership = l->GetLeadershipSkillLevel(); int iNewExpBonus = ComputePartyBonusExpPercent(); m_iAttBonus = ComputePartyBonusAttackGrade(); m_iDefBonus = ComputePartyBonusDefenseGrade(); if (m_iExpBonus != iNewExpBonus) { bResendAll = true; m_iExpBonus = iNewExpBonus; } bool bLongTimeExpBonusChanged = false; // 파티 결성 후 충분한 시간이 지나면 경험치 보너스를 받는다. if (!m_iLongTimeExpBonus && (get_dword_time() - m_dwPartyStartTime > PARTY_ENOUGH_MINUTE_FOR_EXP_BONUS * 60 * 1000 / (g_iUseLocale?1:2))) { bLongTimeExpBonusChanged = true; m_iLongTimeExpBonus = 5; bResendAll = true; } for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { LPCHARACTER ch = it->second.pCharacter; if (!ch) continue; if (bLongTimeExpBonusChanged && ch->GetDesc()) ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("파티의 협동력이 높아져 지금부터 추가 경험치 보너스를 받습니다.")); bool bNear = it->second.bNear; ComputeRolePoint(ch, it->second.bRole, bNear); if (bNear) { if (!bResendAll) SendPartyInfoOneToAll(ch); } } // PARTY_ROLE_LIMIT_LEVEL_BUG_FIX m_anMaxRole[PARTY_ROLE_ATTACKER] = m_iLeadership >= 10 ? 1 : 0; m_anMaxRole[PARTY_ROLE_HASTE] = m_iLeadership >= 20 ? 1 : 0; m_anMaxRole[PARTY_ROLE_TANKER] = m_iLeadership >= 20 ? 1 : 0; m_anMaxRole[PARTY_ROLE_BUFFER] = m_iLeadership >= 25 ? 1 : 0; m_anMaxRole[PARTY_ROLE_SKILL_MASTER] = m_iLeadership >= 35 ? 1 : 0; m_anMaxRole[PARTY_ROLE_DEFENDER] = m_iLeadership >= 40 ? 1 : 0; m_anMaxRole[PARTY_ROLE_ATTACKER] += m_iLeadership >= 40 ? 1 : 0; // END_OF_PARTY_ROLE_LIMIT_LEVEL_BUG_FIX // Party Heal Update if (!m_bPartyHealReady) { if (!m_bCanUsePartyHeal && m_iLeadership >= 18) m_dwPartyHealTime = get_dword_time(); m_bCanUsePartyHeal = m_iLeadership >= 18; // 통솔력 18 이상은 힐을 사용할 수 있음. // 통솔력 40이상은 파티 힐 쿨타임이 적다. DWORD PartyHealCoolTime = (m_iLeadership >= 40) ? PARTY_HEAL_COOLTIME_SHORT * 60 * 1000 : PARTY_HEAL_COOLTIME_LONG * 60 * 1000; if (m_bCanUsePartyHeal) { if (get_dword_time() > m_dwPartyHealTime + PartyHealCoolTime) { m_bPartyHealReady = true; // send heal ready if (0) // XXX DELETEME 클라이언트 완료될때까지 if (GetLeaderCharacter()) GetLeaderCharacter()->ChatPacket(CHAT_TYPE_COMMAND, "PartyHealReady"); } } } if (bResendAll) { for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it) if (it->second.pCharacter) SendPartyInfoOneToAll(it->second.pCharacter); } }
int idle() { static struct timeval pta = { 0, 0 }; static int process_time_count = 0; struct timeval now; if (pta.tv_sec == 0) gettimeofday(&pta, (struct timezone *) 0); int passed_pulses; if (!(passed_pulses = thecore_idle())) return 0; assert(passed_pulses > 0); DWORD t; while (passed_pulses--) { heartbeat(thecore_heart, ++thecore_heart->pulse); // To reduce the possibility of abort() in checkpointing thecore_tick(); } t = get_dword_time(); CHARACTER_MANAGER::instance().Update(thecore_heart->pulse); db_clientdesc->Update(t); s_dwProfiler[PROF_CHR_UPDATE] += (get_dword_time() - t); t = get_dword_time(); if (!io_loop(main_fdw)) return 0; s_dwProfiler[PROF_IO] += (get_dword_time() - t); log_rotate(); gettimeofday(&now, (struct timezone *) 0); ++process_time_count; if (now.tv_sec - pta.tv_sec > 0) { pt_log("[%3d] event %5d/%-5d idle %-4ld event %-4ld heartbeat %-4ld I/O %-4ld chrUpate %-4ld | WRITE: %-7d | PULSE: %d", process_time_count, num_events_called, event_count(), thecore_profiler[PF_IDLE], s_dwProfiler[PROF_EVENT], s_dwProfiler[PROF_HEARTBEAT], s_dwProfiler[PROF_IO], s_dwProfiler[PROF_CHR_UPDATE], current_bytes_written, thecore_pulse()); num_events_called = 0; current_bytes_written = 0; process_time_count = 0; gettimeofday(&pta, (struct timezone *) 0); memset(&thecore_profiler[0], 0, sizeof(thecore_profiler)); memset(&s_dwProfiler[0], 0, sizeof(s_dwProfiler)); } #ifdef _WIN32 if (_kbhit()) { int c = _getch(); switch (c) { case 0x1b: // Esc return 0; // shutdown break; default: break; } } #endif return 1; }
void heartbeat(LPHEART ht, int pulse) { DWORD t; t = get_dword_time(); num_events_called += event_process(pulse); s_dwProfiler[PROF_EVENT] += (get_dword_time() - t); t = get_dword_time(); // 1ГКё¶ґЩ if (!(pulse % ht->passes_per_sec)) { #ifdef ENABLE_LIMIT_TIME if ((unsigned)get_global_time() >= GLOBAL_LIMIT_TIME) { g_bShutdown = true; } #endif if (!g_bAuthServer) { TPlayerCountPacket pack; pack.dwCount = DESC_MANAGER::instance().GetLocalUserCount(); db_clientdesc->DBPacket(HEADER_GD_PLAYER_COUNT, 0, &pack, sizeof(TPlayerCountPacket)); } else DESC_MANAGER::instance().ProcessExpiredLoginKey(); int count = 0; std::map<DWORD, CLoginSim *>::const_iterator it = g_sim.begin(); while (it != g_sim.end()) { if (!it->second->IsCheck()) { it->second->SendLogin(); if (++count > 50) { sys_log(0, "FLUSH_SENT"); break; } } it++; } if (save_idx < g_vec_save.size()) { count = MIN(100, g_vec_save.size() - save_idx); for (int i = 0; i < count; ++i, ++save_idx) db_clientdesc->DBPacket(HEADER_GD_PLAYER_SAVE, 0, &g_vec_save[save_idx], sizeof(TPlayerTable)); sys_log(0, "SAVE_FLUSH %d", count); } } // // 25 PPS(Pulse per second) ¶у°н °ЎБ¤ЗТ ¶§ // // ѕа 1.16ГКё¶ґЩ if (!(pulse % (passes_per_sec + 4))) CHARACTER_MANAGER::instance().ProcessDelayedSave(); //4ГК ё¶ґЩ #if defined (__FreeBSD__) && defined(__FILEMONITOR__) if (!(pulse % (passes_per_sec * 5))) { FileMonitorFreeBSD::Instance().Update(pulse); } #endif // ѕа 5.08ГКё¶ґЩ if (!(pulse % (passes_per_sec * 5 + 2))) { ITEM_MANAGER::instance().Update(); DESC_MANAGER::instance().UpdateLocalUserCount(); } s_dwProfiler[PROF_HEARTBEAT] += (get_dword_time() - t); DBManager::instance().Process(); AccountDB::instance().Process(); CPVPManager::instance().Process(); if (g_bShutdown) { if (thecore_pulse() > g_shutdown_disconnect_pulse) { const DESC_MANAGER::DESC_SET & c_set_desc = DESC_MANAGER::instance().GetClientSet(); std::for_each(c_set_desc.begin(), c_set_desc.end(), ::SendDisconnectFunc()); g_shutdown_disconnect_pulse = INT_MAX; } else if (thecore_pulse() > g_shutdown_disconnect_force_pulse) { const DESC_MANAGER::DESC_SET & c_set_desc = DESC_MANAGER::instance().GetClientSet(); std::for_each(c_set_desc.begin(), c_set_desc.end(), ::DisconnectFunc()); } else if (thecore_pulse() > g_shutdown_disconnect_force_pulse + PASSES_PER_SEC(5)) { thecore_shutdown(); } } }
void CWarMap::Timeout() { SetTimeoutEvent(NULL); if (m_bTimeout) return; if (m_bEnded) return; DWORD dwWinner = 0; DWORD dwLoser = 0; int iRewardGold = 0; if (get_dword_time() - m_dwStartTime < 60000 * 5) { Notice(LC_TEXT("길드전이 일찍 종료되어 무승부로 판정 되었습니다. (5분이 지나지 않음)")); dwWinner = 0; dwLoser = 0; } else { int iWinnerIdx = -1; if (m_TeamData[0].iMemberCount == 0) iWinnerIdx = 1; else if (m_TeamData[1].iMemberCount == 0) iWinnerIdx = 0; if (iWinnerIdx == -1) { dwWinner = GetWinnerGuild(); if (dwWinner == m_TeamData[0].dwID) { iRewardGold = GetRewardGold(0); dwLoser = m_TeamData[1].dwID; } else if (dwWinner == m_TeamData[1].dwID) { iRewardGold = GetRewardGold(1); dwLoser = m_TeamData[0].dwID; } sys_err("WarMap: member count is not zero, guild1 %u %d guild2 %u %d, winner %u", m_TeamData[0].dwID, m_TeamData[0].iMemberCount, m_TeamData[1].dwID, m_TeamData[1].iMemberCount, dwWinner); } else { dwWinner = m_TeamData[iWinnerIdx].dwID; dwLoser = m_TeamData[iWinnerIdx == 0 ? 1 : 0].dwID; iRewardGold = GetRewardGold(iWinnerIdx); } } sys_log(0, "WarMap: Timeout %u %u winner %u loser %u reward %d map %d", m_TeamData[0].dwID, m_TeamData[1].dwID, dwWinner, dwLoser, iRewardGold, m_kMapInfo.lMapIndex); if (dwWinner) CGuildManager::instance().RequestWarOver(dwWinner, dwLoser, dwWinner, iRewardGold); else CGuildManager::instance().RequestWarOver(m_TeamData[0].dwID, m_TeamData[1].dwID, dwWinner, iRewardGold); m_bTimeout = true; }
void CLoginData::SetLogonTime() { m_dwLogonTime = get_dword_time(); }
void CParty::Update() { sys_log(1, "PARTY::Update"); LPCHARACTER l = GetLeaderCharacter(); if (!l) return; TMemberMap::iterator it; int iNearMember = 0; bool bResendAll = false; for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { LPCHARACTER ch = it->second.pCharacter; it->second.bNear = false; if (!ch) continue; if (l->GetDungeon()) it->second.bNear = l->GetDungeon() == ch->GetDungeon(); else it->second.bNear = (DISTANCE_APPROX(l->GetX()-ch->GetX(), l->GetY()-ch->GetY()) < PARTY_DEFAULT_RANGE); if (it->second.bNear) { ++iNearMember; //sys_log(0,"NEAR %s", ch->GetName()); } } if (iNearMember <= 1 && !l->GetDungeon()) { for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) it->second.bNear = false; iNearMember = 0; } if (iNearMember != m_iCountNearPartyMember) { m_iCountNearPartyMember = iNearMember; bResendAll = true; } m_iLeadership = l->GetLeadershipSkillLevel(); int iNewExpBonus = ComputePartyBonusExpPercent(); m_iAttBonus = ComputePartyBonusAttackGrade(); m_iDefBonus = ComputePartyBonusDefenseGrade(); if (m_iExpBonus != iNewExpBonus) { bResendAll = true; m_iExpBonus = iNewExpBonus; } bool bLongTimeExpBonusChanged = false; // ЖДЖј °бјє ИД ГжєРЗС ЅГ°ЈАМ БціЄёй °жЗиДЎ єёіКЅєё¦ №ЮґВґЩ. if (!m_iLongTimeExpBonus && (get_dword_time() - m_dwPartyStartTime > PARTY_ENOUGH_MINUTE_FOR_EXP_BONUS * 60 * 1000 / (g_iUseLocale?1:2))) { bLongTimeExpBonusChanged = true; m_iLongTimeExpBonus = 5; bResendAll = true; } for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it) { LPCHARACTER ch = it->second.pCharacter; if (!ch) continue; if (bLongTimeExpBonusChanged && ch->GetDesc()) ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ЖДЖјАЗ Зщµї·ВАМ іфѕЖБ® Бц±ЭєОЕН ГЯ°Ў °жЗиДЎ єёіКЅєё¦ №ЮЅАґПґЩ.")); bool bNear = it->second.bNear; ComputeRolePoint(ch, it->second.bRole, bNear); if (bNear) { if (!bResendAll) SendPartyInfoOneToAll(ch); } } // PARTY_ROLE_LIMIT_LEVEL_BUG_FIX m_anMaxRole[PARTY_ROLE_ATTACKER] = m_iLeadership >= 10 ? 1 : 0; m_anMaxRole[PARTY_ROLE_HASTE] = m_iLeadership >= 20 ? 1 : 0; m_anMaxRole[PARTY_ROLE_TANKER] = m_iLeadership >= 20 ? 1 : 0; m_anMaxRole[PARTY_ROLE_BUFFER] = m_iLeadership >= 25 ? 1 : 0; m_anMaxRole[PARTY_ROLE_SKILL_MASTER] = m_iLeadership >= 35 ? 1 : 0; m_anMaxRole[PARTY_ROLE_DEFENDER] = m_iLeadership >= 40 ? 1 : 0; m_anMaxRole[PARTY_ROLE_ATTACKER] += m_iLeadership >= 40 ? 1 : 0; // END_OF_PARTY_ROLE_LIMIT_LEVEL_BUG_FIX // Party Heal Update if (!m_bPartyHealReady) { if (!m_bCanUsePartyHeal && m_iLeadership >= 18) m_dwPartyHealTime = get_dword_time(); m_bCanUsePartyHeal = m_iLeadership >= 18; // ЕлјЦ·В 18 АМ»уАє ИъА» »зїлЗТ јц АЦАЅ. // ЕлјЦ·В 40АМ»уАє ЖДЖј Иъ ДрЕёАУАМ АыґЩ. DWORD PartyHealCoolTime = (m_iLeadership >= 40) ? PARTY_HEAL_COOLTIME_SHORT * 60 * 1000 : PARTY_HEAL_COOLTIME_LONG * 60 * 1000; if (m_bCanUsePartyHeal) { if (get_dword_time() > m_dwPartyHealTime + PartyHealCoolTime) { m_bPartyHealReady = true; // send heal ready if (0) // XXX DELETEME Е¬¶уАМѕрЖ® їП·бµЙ¶§±оБц if (GetLeaderCharacter()) GetLeaderCharacter()->ChatPacket(CHAT_TYPE_COMMAND, "PartyHealReady"); } } } if (bResendAll) { for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it) if (it->second.pCharacter) SendPartyInfoOneToAll(it->second.pCharacter); } }