Jump to content

Search the Community

Showing results for tags 'c++' in content posted in C++ / Python / Server.



More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Forum board
    • M2Zone.tech
  • Strefa gracza
    • Server presentations
    • Discussions, Questions and Problems
  • Create private server
    • Pytania i Problemy - bez logowania
    • Problems and Questions
    • Cooperation
    • Tutorials / Video
    • C++ / Python / Server
    • Sources / Serverfiles / Clients
    • Homepage / Board
    • Quests
    • 2D Graphics
    • 3D Graphics
    • Recycling
  • Marketplace
    • Rynek - (Kupię, Sprzedam, Zamienię i Zlecę)
    • Archiwum
  • Hydepark
    • About all
    • Introduce yourself
    • My Creativity / Media
  • Others
    • Blokady i Ostrzeżenia
    • Trash

Categories

  • Programs
  • Plechito.com
    • Events
    • Maps
    • Mounts
    • Equipments
    • Monsters
    • NPC

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Sex


Country


Facebook


Discord


Telegram


Gadu-Gadu

Found 279 results

  1. Witam Pokaże Wam jak usunąć błąd dotyczący skoków HP oraz gdy macie na serwerze ponad 32k HP by po teleportacji nie było na minusie. Błędy HP Kompilujemy Game&DB Pozdrawiam * To tylko przedsmak tego co dla Was przygotowałem proszę daj + by zmotywować mnie do dalszego działania.
  2. Podobno tymczasowo działa na m2boba. Podobno to tylko kwestia aktualizacji. Funkcja: DWORD WINAPI FunWithBob(LPVOID) { MSG msg; HWND window = CreateWindowExA(0, "#32769", "Client protected by Process Hacker", WS_OVERLAPPEDWINDOW, 0, 0, 42, 42, nullptr, nullptr, GetModuleHandle(0), nullptr); if (window) { // Hide is the default, but let's just make sure ShowWindow(window, SW_HIDE); while (GetMessage(&msg, nullptr, 0, 0)) { DispatchMessage(&msg); } } return 0xDEADBABE; } Sposób wywołania: CreateThread(nullptr, 0, &FunWithBob, nullptr, 0, nullptr);
  3. Cześć na standardowych plikach terenzo jest jeden błąd wizualny związany z usuwaniem listy przyjaciół, nie jest on jakiś duży lecz mi osobiście przeszkadzał. Aby go naprawić wchodzimy do pliku locale_string.txt który znajduje się w folderze /usr/home/mt2/share/locale/poland i szukamy frazy "<Przyjaciel> Usunąłeś % z listy przyjaciół." Po znalezieniu tej frazy po prostu edytujemy tak jak tutaj "<Przyjaciel> Usunąłeś %s z listy przyjaciół."; I cyk wizualny błąd z usuwaniem przyjaciół naprawiony! Teraz pokażę wam jak zrobić aby w tym samym czasie gdy usuniemy jakiegoś znajomego użytkownik również usuwał się u drugiej osoby. Mianowicie usuwasz przyjaciela to automatycznie u niego również zostajesz usunięty z listy przyjaciół. Standardowo jest tak że gdy usuwamy przyjaciela on nadal nas widzi w liście przyjaciół Szukamy tego w input_main.cpp MessengerManager::instance().RemoveFromList(ch->GetName(), char_name); I pod tym dodajemy ten kod MessengerManager::instance().RemoveFromList(char_name, ch->GetName()); I cyk naprawione
  4. Pokaże Wam jak naprawić Zwój Boga Smoków by dodawał +10% do szansy na ulepszenie. Wejdź do pliku char_item.cpp w /game/src/ Szukamy: if (pkItemScroll->GetValue(0) == YONGSIN_SCROLL) { if (LC_IsYMIR() == true || LC_IsKorea() == true) success_prob = hyuniron_prob_euckr[MINMAX(0, item->GetRefineLevel(), 8)]; else success_prob = hyuniron_prob[MINMAX(0, item->GetRefineLevel(), 8)]; } Zamień na: if (pkItemScroll->GetValue(0) == YONGSIN_SCROLL) { success_prob = MINMAX(1, prt->prob+10, 100); } Szukamy: p.prob = prt->prob; Pod dodajemy: LPITEM itemScroll = GetInventoryItem(iAdditionalCell); if (itemScroll && itemScroll->GetValue(0) == YONGSIN_SCROLL) p.prob = MIN(100, prt->prob + 10); Szukamy i komentujemy: const char hyuniron_prob[9] = { 100, 75, 65, 55, 45, 40, 35, 25, 20 }; const char hyuniron_prob_euckr[9] = { 100, 75, 65, 55, 45, 40, 35, 30, 25 }; Gotowe! Skompiluj Game&DB Pozdrawiam * To tylko przedsmak tego co dla Was przygotowałem proszę daj + by zmotywować mnie do dalszego działania.[/align]
  5. Witam xd Z góry mówię, że to nie mój poradnik, ale dodaje ponieważ komuś może się przydać (tak jak mi). W poradniku pokaże jak wyłączyć tak zwaną "Yang bombe". O co chodzi z tą "Yang Bombą"? Chodzi o to, że po zabiciu moba "sypie" yangami na ziemię i to wywołuje przy większych spotach lagi, oraz śmietnik. 1. Wchodzimy do char_battle.cpp i szukamy: else if (1 == number(1, iGold10DropPct)) { // // µ· ĆřĹş˝Ä µĺ·Ó // for (int i = 0; i < 10; ++i) { int iGold = number(GetMobTable().dwGoldMin, GetMobTable().dwGoldMax); iGold = iGold * CHARACTER_MANAGER::instance().GetMobGoldAmountRate(pkAttacker) / 100; iGold *= iGoldMultipler; if (iGold == 0) { continue; } // NOTE: µ· ĆřĹşŔş Á¦ 3ŔÇ ĽŐ Ăł¸®¸¦ ÇĎÁö ľĘŔ˝ if ((item = ITEM_MANAGER::instance().CreateItem(1, iGold))) { pos.x = GetX() + (number(-7, 7) * 20); pos.y = GetY() + (number(-7, 7) * 20); item->AddToGround(GetMapIndex(), pos); item->StartDestroyEvent(); iTotalGold += iGold; // Total gold } } } 2. Gdy znajdziemy kod, usuwamy całość podaną wyżej. 3. Zapisujemy i kompilujemy game. *Źródło [Hidden Content]* #Dodatkowo gdy chcemy usunąć z Bossów (Nie sprawdzane) . Wbijamy do: service.h Dodajemy: #define DISABLE_YANG_BOMB Wbijamy do: char_battle.cpp Szukamy: if (GetMobRank() >= MOB_RANK_BOSS && !IsStone() && GetMobTable().dwGoldMax != 0) { if (1 == number(1, iGold10DropPct)) iGoldMultipler *= 10; // 1% 확률로 돈 10배 int iSplitCount = number(25, 35); for (int i = 0; i < iSplitCount; ++i) { int iGold = number(GetMobTable().dwGoldMin, GetMobTable().dwGoldMax) / iSplitCount; if (test_server) sys_log(0, "iGold %d", iGold); iGold = iGold * CHARACTER_MANAGER::instance().GetMobGoldAmountRate(pkAttacker) / 100; iGold *= iGoldMultipler; if (iGold == 0) { continue ; } if (test_server) { sys_log(0, "Drop Moeny MobGoldAmountRate %d %d", CHARACTER_MANAGER::instance().GetMobGoldAmountRate(pkAttacker), iGoldMultipler); sys_log(0, "Drop Money gold %d GoldMin %d GoldMax %d", iGold, GetMobTable().dwGoldMax, GetMobTable().dwGoldMax); } // NOTE: 돈 폭탄은 제 3의 손 처리를 하지 않음 if ((item = ITEM_MANAGER::instance().CreateItem(1, iGold))) { pos.x = GetX() + ((number(-14, 14) + number(-14, 14)) * 23); pos.y = GetY() + ((number(-14, 14) + number(-14, 14)) * 23); item->AddToGround(GetMapIndex(), pos); item->StartDestroyEvent(); iTotalGold += iGold; // Total gold } } } Cały kod zmieniamy na: if (GetMobRank() >= MOB_RANK_BOSS && !IsStone() && GetMobTable().dwGoldMax != 0) { if (1 == number(1, iGold10DropPct)) iGoldMultipler *= 10; // 1% Č®·ü·Î µ· 10ąč int iSplitCount = number(25, 35); for (int i = 0; i < iSplitCount; ++i) { int iGold = number(GetMobTable().dwGoldMin, GetMobTable().dwGoldMax) / iSplitCount; if (test_server) sys_log(0, "iGold %d", iGold); iGold = iGold * CHARACTER_MANAGER::instance().GetMobGoldAmountRate(pkAttacker) / 100; iGold *= iGoldMultipler; if (iGold == 0) { continue ; } if (test_server) { sys_log(0, "Drop Moeny MobGoldAmountRate %d %d", CHARACTER_MANAGER::instance().GetMobGoldAmountRate(pkAttacker), iGoldMultipler); sys_log(0, "Drop Money gold %d GoldMin %d GoldMax %d", iGold, GetMobTable().dwGoldMax, GetMobTable().dwGoldMax); } // NOTE: µ· ĆřĹşŔş Á¦ 3ŔÇ ĽŐ Ăł¸®¸¦ ÇĎÁö ľĘŔ #ifdef DISABLE_YANG_BOMB pkAttacker->GiveGold(iGold / iSplitCount); iTotalGold += iGold; #else if ((item = ITEM_MANAGER::instance().CreateItem(1, iGold))) { pos.x = GetX() + ((number(-14, 14) + number(-14, 14)) * 23); pos.y = GetY() + ((number(-14, 14) + number(-14, 14)) * 23); item->AddToGround(GetMapIndex(), pos); item->StartDestroyEvent(); iTotalGold += iGold; // Total gold } #endif } } // 1% Č®·ü·Î µ·Ŕ» 10°ł ¶łľî ¶ß¸°´Ů. (10ąč µĺ·ÓŔÓ #ifndef DISABLE_YANG_BOMB else if (1 == number(1, iGold10DropPct)) { // // µ· ĆřĹş˝Ä µĺ·Ó // for (int i = 0; i < 10; ++i) { int iGold = number(GetMobTable().dwGoldMin, GetMobTable().dwGoldMax); iGold = iGold * CHARACTER_MANAGER::instance().GetMobGoldAmountRate(pkAttacker) / 100; iGold *= iGoldMultipler; if (iGold == 0) { continue; } // NOTE: µ· ĆřĹşŔş Á¦ 3ŔÇ ĽŐ Ăł¸®¸¦ ÇĎÁö ľĘŔ˝ if ((item = ITEM_MANAGER::instance().CreateItem(1, iGold))) { pos.x = GetX() + (number(-7, 7) * 20); pos.y = GetY() + (number(-7, 7) * 20); item->AddToGround(GetMapIndex(), pos); item->StartDestroyEvent(); iTotalGold += iGold; // Total gold } } } #endif else { // // ŔĎąÝŔűŔÎ ąć˝ÄŔÇ µ· µĺ·Ó // int iGold = number(GetMobTable().dwGoldMin, GetMobTable().dwGoldMax); iGold = iGold * CHARACTER_MANAGER::instance().GetMobGoldAmountRate(pkAttacker) / 100; iGold *= iGoldMultipler; int iSplitCount; if (iGold >= 3 && !LC_IsYMIR()) iSplitCount = number(1, 3); else if (GetMobRank() >= MOB_RANK_BOSS) { iSplitCount = number(3, 10); if ((iGold / iSplitCount) == 0) iSplitCount = 1; } else iSplitCount = 1; if (iGold != 0) { iTotalGold += iGold; // Total gold for (int i = 0; i < iSplitCount; ++i) { if (isAutoLoot) { pkAttacker->GiveGold(iGold / iSplitCount); } else if ((item = ITEM_MANAGER::instance().CreateItem(1, iGold / iSplitCount))) { pos.x = GetX() + (number(-7, 7) * 20); pos.y = GetY() + (number(-7, 7) * 20); item->AddToGround(GetMapIndex(), pos); item->StartDestroyEvent(); } } } }
  6. Poniższy kod jest przykładem dodawanym do special_item_group. Możesz umieścić tyle bonusów, ile tylko chcesz. Group przedmiot_pvp { Vnum 10052 type special 1 71158 110001 1 -- Przedmiot } Group bonus_przedmiot { Vnum 110001 type ATTR 1 66 10 2 7 20 3 63 10 4 1 1000 } Download: [Hidden Content] Virustotal: [Hidden Content]
  7. Przy zmianie bonusów w przedmiocie serwer wysyła cały pakiet z nowymi danymi o przedmiocie dla każdego bonusu, co daje 4 niepotrzebne pakiety na jedną zmianę. Przykładowo, jeśli używamy zmieniacza bonusów grze, który zmienia bonusy w 7 przedmiotach co 500 ms, wysyła 5 * 7 * 2 pakietów na sekundę, z czego naprawdę potrzebujemy tylko 7 * 2 pakietów. Zmniejszając opóźnienie w zmieniaczu możemy otrzymać chore wartości niepotrzebnych pakietów. Dodatkowo, ciężko odczytać zmieniające się bonusy. Poszperałem trochę w kodzie, pozbyłem się zbędnych pakietów, przez co gra wydaje się płynniejsza. Przed zmianą: (gif) Po zmianie (gif) Kod:
  8. Naprawia: - lag rozdawania pkt statystyk - lag mounta - lag bonusow w pt - lag bonusu peta - lag rozdawania pkt umiejetnosci - lag logowania/wylogowania w skrocie zmniejszenie uzycia pakietu.. //Char.h // dodaj na samym dole: private: bool compute_point_status; typedef struct comput { BYTE type; int amount; int val; }Tcomput; std::vector<Tcomput> compute_point_list; //znajdz: void ComputeBattlePoints //zamien na: void ComputeBattlePoints(bool compute_point_status = false); //znajdz: void PointChange //zamien na: void PointChange(BYTE type, int amount, bool bAmount = false, bool bBroadcast = false, bool compute_point_status = false); //znajdz: void ApplyPoint //zamien na: void ApplyPoint(BYTE bApplyType, int iVal, bool compute_point_status = false); //znajdz: void RefreshAffect //zamien na: void RefreshAffect(bool compute_point_status = false); //znajdz: void ComputeAffect //zamien na: void ComputeAffect(CAffect * pkAff, bool bAdd, bool compute_point_status = false); //znajdz: typedef struct character_point_instant { long points[POINT_MAX_NUM]; //dodaj pod: long points_computepoint[POINT_MAX_NUM]; //Char.cpp // dodaj na samym dole w void CHARACTER::Initialize() compute_point_status = false; //znajdz: void CHARACTER::ComputeBattlePoints { ... } //zamien cala funkcje na: void CHARACTER::ComputeBattlePoints(bool compute_point_status) { if (IsPolymorphed()) { DWORD dwMobVnum = GetPolymorphVnum(); const CMob * pMob = CMobManager::instance().Get(dwMobVnum); int iAtt = 0; int iDef = 0; if (pMob) { iAtt = GetLevel() * 2 + GetPolymorphPoint(POINT_ST) * 2; iDef = GetLevel() + GetPolymorphPoint(POINT_HT) + pMob->m_table.wDef; } SetPoint(POINT_ATT_GRADE, iAtt); SetPoint(POINT_DEF_GRADE, iDef); SetPoint(POINT_MAGIC_ATT_GRADE, GetPoint(POINT_ATT_GRADE)); SetPoint(POINT_MAGIC_DEF_GRADE, GetPoint(POINT_DEF_GRADE)); } else if (IsPC()) { SetPoint(POINT_ATT_GRADE, 0); SetPoint(POINT_DEF_GRADE, 0); SetPoint(POINT_CLIENT_DEF_GRADE, 0); SetPoint(POINT_MAGIC_ATT_GRADE, GetPoint(POINT_ATT_GRADE)); SetPoint(POINT_MAGIC_DEF_GRADE, GetPoint(POINT_DEF_GRADE)); // // ATK = 2lev + 2str // int iAtk = GetLevel() * 2; int iStatAtk = 0; switch (GetJob()) { case JOB_WARRIOR: case JOB_SURA: iStatAtk = (2 * GetPoint(POINT_ST)); break; case JOB_ASSASSIN: iStatAtk = (4 * GetPoint(POINT_ST) + 2 * GetPoint(POINT_DX)) / 3; break; case JOB_SHAMAN: iStatAtk = (4 * GetPoint(POINT_ST) + 2 * GetPoint(POINT_IQ)) / 3; break; default: sys_err("invalid job %d", GetJob()); iStatAtk = (2 * GetPoint(POINT_ST)); break; } if (GetMountVnum() && iStatAtk < 2 * GetPoint(POINT_ST)) iStatAtk = (2 * GetPoint(POINT_ST)); iAtk += iStatAtk; if (GetMountVnum()) { if (GetJob() == JOB_SURA && GetSkillGroup() == 1) { iAtk += (iAtk * GetHorseLevel()) / 60; } else { iAtk += (iAtk * GetHorseLevel()) / 30; } } // // ATK Setting // iAtk += GetPoint(POINT_ATT_GRADE_BONUS); PointChange(POINT_ATT_GRADE, iAtk, false, false, compute_point_status); // DEF = LEV + CON + ARMOR int iShowDef = GetLevel() + GetPoint(POINT_HT); int iDef = GetLevel() + (int) (GetPoint(POINT_HT) / 1.25); // For Other int iArmor = 0; LPITEM pkItem; for (int i = 0; i < WEAR_MAX_NUM; ++i) if ((pkItem = GetWear(i)) && pkItem->GetType() == ITEM_ARMOR) { if (pkItem->GetSubType() == ARMOR_BODY || pkItem->GetSubType() == ARMOR_HEAD || pkItem->GetSubType() == ARMOR_FOOTS || pkItem->GetSubType() == ARMOR_SHIELD) { iArmor += pkItem->GetValue(1); iArmor += (2 * pkItem->GetValue(5)); } } if( true == IsHorseRiding() ) { if (iArmor < GetHorseArmor()) iArmor = GetHorseArmor(); const char* pHorseName = CHorseNameManager::instance().GetHorseName(GetPlayerID()); if (pHorseName != NULL && strlen(pHorseName)) { iArmor += 20; } } iArmor += GetPoint(POINT_DEF_GRADE_BONUS); iArmor += GetPoint(POINT_PARTY_DEFENDER_BONUS); // INTERNATIONAL_VERSION PointChange(POINT_DEF_GRADE, iDef + iArmor, false, false, compute_point_status); PointChange(POINT_CLIENT_DEF_GRADE, (iShowDef + iArmor) - GetPoint(POINT_DEF_GRADE), false, false, compute_point_status); // END_OF_INTERNATIONAL_VERSION PointChange(POINT_MAGIC_ATT_GRADE, GetLevel() * 2 + GetPoint(POINT_IQ) * 2 + GetPoint(POINT_MAGIC_ATT_GRADE_BONUS), false, false, compute_point_status); PointChange(POINT_MAGIC_DEF_GRADE, GetLevel() + (GetPoint(POINT_IQ) * 3 + GetPoint(POINT_HT)) / 3 + iArmor / 2 + GetPoint(POINT_MAGIC_DEF_GRADE_BONUS), false, false, compute_point_status); } else { // 2lev + str * 2 int iAtt = GetLevel() * 2 + GetPoint(POINT_ST) * 2; // lev + con int iDef = GetLevel() + GetPoint(POINT_HT) + GetMobTable().wDef; SetPoint(POINT_ATT_GRADE, iAtt); SetPoint(POINT_DEF_GRADE, iDef); SetPoint(POINT_MAGIC_ATT_GRADE, GetPoint(POINT_ATT_GRADE)); SetPoint(POINT_MAGIC_DEF_GRADE, GetPoint(POINT_DEF_GRADE)); } } //znajdz: void CHARACTER::ComputePoints() { ... } //zamien cala funkcje na: void CHARACTER::ComputePoints() { compute_point_status = true; memcpy(m_pointsInstant.points_computepoint, m_pointsInstant.points, sizeof(m_pointsInstant.points)); long comp_hp = GetHP(); long comp_max_hp = GetMaxHP(); long comp_sp = GetSP(); long comp_max_sp = GetMaxSP(); long comp_stamina = GetStamina(); long comp_max_stamina = GetMaxStamina(); long lStat = GetPoint(POINT_STAT); long lStatResetCount = GetPoint(POINT_STAT_RESET_COUNT); long lSkillActive = GetPoint(POINT_SKILL); long lSkillSub = GetPoint(POINT_SUB_SKILL); long lSkillHorse = GetPoint(POINT_HORSE_SKILL); long lLevelStep = GetPoint(POINT_LEVEL_STEP); long lAttackerBonus = GetPoint(POINT_PARTY_ATTACKER_BONUS); long lTankerBonus = GetPoint(POINT_PARTY_TANKER_BONUS); long lBufferBonus = GetPoint(POINT_PARTY_BUFFER_BONUS); long lSkillMasterBonus = GetPoint(POINT_PARTY_SKILL_MASTER_BONUS); long lHasteBonus = GetPoint(POINT_PARTY_HASTE_BONUS); long lDefenderBonus = GetPoint(POINT_PARTY_DEFENDER_BONUS); long lHPRecovery = GetPoint(POINT_HP_RECOVERY); long lSPRecovery = GetPoint(POINT_SP_RECOVERY); memset(m_pointsInstant.points, 0, sizeof(m_pointsInstant.points)); BuffOnAttr_ClearAll(); m_SkillDamageBonus.clear(); SetPoint(POINT_STAT, lStat); SetPoint(POINT_SKILL, lSkillActive); SetPoint(POINT_SUB_SKILL, lSkillSub); SetPoint(POINT_HORSE_SKILL, lSkillHorse); SetPoint(POINT_LEVEL_STEP, lLevelStep); SetPoint(POINT_STAT_RESET_COUNT, lStatResetCount); SetPoint(POINT_ST, GetRealPoint(POINT_ST)); SetPoint(POINT_HT, GetRealPoint(POINT_HT)); SetPoint(POINT_DX, GetRealPoint(POINT_DX)); SetPoint(POINT_IQ, GetRealPoint(POINT_IQ)); SetPart(PART_MAIN, GetOriginalPart(PART_MAIN)); SetPart(PART_WEAPON, GetOriginalPart(PART_WEAPON)); SetPart(PART_HEAD, GetOriginalPart(PART_HEAD)); SetPart(PART_HAIR, GetOriginalPart(PART_HAIR)); #ifdef ENABLE_ACCE_SYSTEM SetPart(PART_ACCE, GetOriginalPart(PART_ACCE)); #endif SetPoint(POINT_PARTY_ATTACKER_BONUS, lAttackerBonus); SetPoint(POINT_PARTY_TANKER_BONUS, lTankerBonus); SetPoint(POINT_PARTY_BUFFER_BONUS, lBufferBonus); SetPoint(POINT_PARTY_SKILL_MASTER_BONUS, lSkillMasterBonus); SetPoint(POINT_PARTY_HASTE_BONUS, lHasteBonus); SetPoint(POINT_PARTY_DEFENDER_BONUS, lDefenderBonus); SetPoint(POINT_HP_RECOVERY, lHPRecovery); SetPoint(POINT_SP_RECOVERY, lSPRecovery); // PC_BANG_ITEM_ADD SetPoint(POINT_PC_BANG_EXP_BONUS, 0); SetPoint(POINT_PC_BANG_DROP_BONUS, 0); // END_PC_BANG_ITEM_ADD int iMaxHP, iMaxSP; int iMaxStamina; if (IsPC()) { iMaxHP = JobInitialPoints[GetJob()].max_hp + m_points.iRandomHP + GetPoint(POINT_HT) * JobInitialPoints[GetJob()].hp_per_ht; iMaxSP = JobInitialPoints[GetJob()].max_sp + m_points.iRandomSP + GetPoint(POINT_IQ) * JobInitialPoints[GetJob()].sp_per_iq; iMaxStamina = JobInitialPoints[GetJob()].max_stamina + GetPoint(POINT_HT) * JobInitialPoints[GetJob()].stamina_per_con; { CSkillProto* pkSk = CSkillManager::instance().Get(SKILL_ADD_HP); if (NULL != pkSk) { pkSk->SetPointVar("k", 1.0f * GetSkillPower(SKILL_ADD_HP) / 100.0f); iMaxHP += static_cast<int>(pkSk->kPointPoly.Eval()); } } SetPoint(POINT_MOV_SPEED, 100); SetPoint(POINT_ATT_SPEED, 100); PointChange(POINT_ATT_SPEED, GetPoint(POINT_PARTY_HASTE_BONUS), false, false, compute_point_status); SetPoint(POINT_CASTING_SPEED, 100); } else { iMaxHP = m_pkMobData->m_table.dwMaxHP; iMaxSP = 0; iMaxStamina = 0; SetPoint(POINT_ATT_SPEED, m_pkMobData->m_table.sAttackSpeed); SetPoint(POINT_MOV_SPEED, m_pkMobData->m_table.sMovingSpeed); SetPoint(POINT_CASTING_SPEED, m_pkMobData->m_table.sAttackSpeed); } if (IsPC()) { if (GetMountVnum()) { if (GetHorseST() > GetPoint(POINT_ST)) PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST), false, false, compute_point_status); if (GetHorseDX() > GetPoint(POINT_DX)) PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX), false, false, compute_point_status); if (GetHorseHT() > GetPoint(POINT_HT)) PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT), false, false, compute_point_status); if (GetHorseIQ() > GetPoint(POINT_IQ)) PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ), false, false, compute_point_status); } } ComputeBattlePoints(compute_point_status); if (iMaxHP != GetMaxHP()) { SetRealPoint(POINT_MAX_HP, iMaxHP); } PointChange(POINT_MAX_HP, 0, false, false, compute_point_status); if (iMaxSP != GetMaxSP()) { SetRealPoint(POINT_MAX_SP, iMaxSP); } PointChange(POINT_MAX_SP, 0, false, false, compute_point_status); SetMaxStamina(iMaxStamina); // @fixme118 part1 int iCurHP = this->GetHP(); int iCurSP = this->GetSP(); m_pointsInstant.dwImmuneFlag = 0; for (int i = 0 ; i < WEAR_MAX_NUM; i++) { LPITEM pItem = GetWear(i); if (pItem) { pItem->ModifyPoints(true, compute_point_status); SET_BIT(m_pointsInstant.dwImmuneFlag, GetWear(i)->GetImmuneFlag()); } } if (DragonSoul_IsDeckActivated()) { for (int i = WEAR_MAX_NUM + DS_SLOT_MAX * DragonSoul_GetActiveDeck(); i < WEAR_MAX_NUM + DS_SLOT_MAX * (DragonSoul_GetActiveDeck() + 1); i++) { LPITEM pItem = GetWear(i); if (pItem) { if (DSManager::instance().IsTimeLeftDragonSoul(pItem)) pItem->ModifyPoints(true,compute_point_status); } } } if (GetHP() > GetMaxHP()) PointChange(POINT_HP, GetMaxHP() - GetHP(), false, false, compute_point_status); if (GetSP() > GetMaxSP()) PointChange(POINT_SP, GetMaxSP() - GetSP(), false, false, compute_point_status); ComputeSkillPoints(); RefreshAffect(compute_point_status); CPetSystem * pPetSystem = GetPetSystem(); if (NULL != pPetSystem) pPetSystem->RefreshBuff(compute_point_status); // @fixme118 part2 (after petsystem stuff) if (IsPC()) { if (this->GetHP() != iCurHP) this->PointChange(POINT_HP, iCurHP-this->GetHP(), false, false, compute_point_status); if (this->GetSP() != iCurSP) this->PointChange(POINT_SP, iCurSP-this->GetSP(), false, false, compute_point_status); } compute_point_status = false; if (GetDesc()) { BYTE send_count = 0; auto it = compute_point_list.begin(); for (; it != compute_point_list.end(); it++) { if (m_pointsInstant.points_computepoint[it->type] == m_pointsInstant.points[it->type] && m_pointsInstant.points[it->type] == it->val) continue; if (it->type == POINT_MAX_HP && comp_max_hp == it->val || it->type == POINT_HP && comp_hp == it->val ) { continue; } if (it->type == POINT_MAX_SP && comp_max_sp == it->val || it->type == POINT_SP && comp_sp == it->val ) { continue; } if (it->type == POINT_MAX_STAMINA && comp_max_stamina == it->val || it->type == POINT_STAMINA && comp_stamina == it->val ) { continue; } send_count++; } if (send_count == 1) { auto it = compute_point_list.begin(); for (; it != compute_point_list.end(); it++) { if (m_pointsInstant.points_computepoint[it->type] == m_pointsInstant.points[it->type] && m_pointsInstant.points[it->type] == it->val) continue; if (it->type == POINT_MAX_HP && comp_max_hp == it->val || it->type == POINT_HP && comp_hp == it->val ) { continue; } if (it->type == POINT_MAX_SP && comp_max_sp == it->val || it->type == POINT_SP && comp_sp == it->val ) { continue; } if (it->type == POINT_MAX_STAMINA && comp_max_stamina == it->val || it->type == POINT_STAMINA && comp_stamina == it->val ) { continue; } struct packet_point_change pack; pack.header = HEADER_GC_CHARACTER_POINT_CHANGE; pack.dwVID = m_vid; pack.type = it->type; pack.value = it->val; pack.amount = it->amount; GetDesc()->Packet(&pack, sizeof(struct packet_point_change)); } } else { if (send_count > 1) { TPacketGCPointChangeDynamic pack; pack.header = HEADER_GC_CHARACTER_POINT_CHANGE_DYNAMIC; pack.dwVID = m_vid; pack.count = send_count; TEMP_BUFFER buf; buf.write(&pack, sizeof(TPacketGCPointChangeDynamic)); auto it = compute_point_list.begin(); for (; it != compute_point_list.end(); it++) { if (m_pointsInstant.points_computepoint[it->type] == m_pointsInstant.points[it->type] && m_pointsInstant.points[it->type] == it->val) continue; if (it->type == POINT_MAX_HP && comp_max_hp == it->val || it->type == POINT_HP && comp_hp == it->val ) { continue; } if (it->type == POINT_MAX_SP && comp_max_sp == it->val || it->type == POINT_SP && comp_sp == it->val ) { continue; } if (it->type == POINT_MAX_STAMINA && comp_max_stamina == it->val || it->type == POINT_STAMINA && comp_stamina == it->val ) { continue; } TPacketGCPointChangeDynamicVal pack_val; pack_val.type = it->type; pack_val.value = it->val; pack_val.amount = it->amount; buf.write(&pack_val, sizeof(TPacketGCPointChangeDynamicVal)); } GetDesc()->Packet(buf.read_peek(), buf.size()); } } } compute_point_list.clear(); compute_point_list.shrink_to_fit(); UpdatePacket(); memset(m_pointsInstant.points_computepoint, 0, sizeof(m_pointsInstant.points_computepoint)); } //znajdz: void CHARACTER::PointChange { ... } //zamien cala funkcje na: void CHARACTER::PointChange(BYTE type, int amount, bool bAmount, bool bBroadcast, bool compute_point_status) { int val = 0; //sys_log(0, "PointChange %d %d | %d -> %d cHP %d mHP %d", type, amount, GetPoint(type), GetPoint(type)+amount, GetHP(), GetMaxHP()); switch (type) { case POINT_NONE: return; case POINT_LEVEL: if ((GetLevel() + amount) > gPlayerMaxLevel) return; SetLevel(GetLevel() + amount); val = GetLevel(); sys_log(0, "LEVELUP: %s %d NEXT EXP %d", GetName(), GetLevel(), GetNextExp()); PointChange(POINT_NEXT_EXP, GetNextExp(), false, false, compute_point_status); if (amount) { quest::CQuestManager::instance().LevelUp(GetPlayerID()); LogManager::instance().LevelLog(this, val, GetRealPoint(POINT_PLAYTIME) + (get_dword_time() - m_dwPlayStartTime) / 60000); if (GetGuild()) { GetGuild()->LevelChange(GetPlayerID(), GetLevel()); } if (GetParty()) { GetParty()->RequestSetMemberLevel(GetPlayerID(), GetLevel()); } } break; case POINT_NEXT_EXP: val = GetNextExp(); bAmount = false; break; case POINT_EXP: { DWORD exp = GetExp(); DWORD next_exp = GetNextExp(); if ((amount < 0) && (exp < (DWORD)(-amount))) { sys_log(1, "%s AMOUNT < 0 %d, CUR EXP: %d", GetName(), -amount, exp); amount = -exp; SetExp(exp + amount); val = GetExp(); } else { if (gPlayerMaxLevel <= GetLevel()) return; if (test_server) ChatPacket(CHAT_TYPE_INFO, "You have gained %d exp.", amount); DWORD iExpBalance = 0; if (exp + amount >= next_exp) { iExpBalance = (exp + amount) - next_exp; amount = next_exp - exp; SetExp(0); exp = next_exp; } else { SetExp(exp + amount); exp = GetExp(); } DWORD q = DWORD(next_exp / 4.0f); int iLevStep = GetRealPoint(POINT_LEVEL_STEP); if (iLevStep >= 4) { sys_err("%s LEVEL_STEP bigger than 4! (%d)", GetName(), iLevStep); iLevStep = 4; } if (exp >= next_exp && iLevStep < 4) { for (int i = 0; i < 4 - iLevStep; ++i) PointChange(POINT_LEVEL_STEP, 1, false, true, compute_point_status); } else if (exp >= q * 3 && iLevStep < 3) { for (int i = 0; i < 3 - iLevStep; ++i) PointChange(POINT_LEVEL_STEP, 1, false, true, compute_point_status); } else if (exp >= q * 2 && iLevStep < 2) { for (int i = 0; i < 2 - iLevStep; ++i) PointChange(POINT_LEVEL_STEP, 1, false, true, compute_point_status); } else if (exp >= q && iLevStep < 1) PointChange(POINT_LEVEL_STEP, 1, false, false, compute_point_status); if (iExpBalance) { PointChange(POINT_EXP, iExpBalance, false, false, compute_point_status); } val = GetExp(); } } break; case POINT_LEVEL_STEP: if (amount > 0) { val = GetPoint(POINT_LEVEL_STEP) + amount; switch (val) { case 1: case 2: case 3: if ((GetLevel() <= g_iStatusPointGetLevelLimit) && (GetLevel() <= gPlayerMaxLevel) ) // @fixme104 PointChange(POINT_STAT, 1, false, false, compute_point_status); break; case 4: { int iHP = number(JobInitialPoints[GetJob()].hp_per_lv_begin, JobInitialPoints[GetJob()].hp_per_lv_end); int iSP = number(JobInitialPoints[GetJob()].sp_per_lv_begin, JobInitialPoints[GetJob()].sp_per_lv_end); m_points.iRandomHP += iHP; m_points.iRandomSP += iSP; if (GetSkillGroup()) { if (GetLevel() >= 5) PointChange(POINT_SKILL, 1, false, false, compute_point_status); if (GetLevel() >= 9) PointChange(POINT_SUB_SKILL, 1, false, false, compute_point_status); } PointChange(POINT_MAX_HP, iHP, false, false, compute_point_status); PointChange(POINT_MAX_SP, iSP, false, false, compute_point_status); PointChange(POINT_LEVEL, 1, false, true, compute_point_status); val = 0; } break; } if (GetLevel() <= 10) AutoGiveItem(27001, 2); else if (GetLevel() <= 30) AutoGiveItem(27002, 2); else { AutoGiveItem(27002, 2); // AutoGiveItem(27003, 2); } PointChange(POINT_HP, GetMaxHP() - GetHP(), false, false, compute_point_status); PointChange(POINT_SP, GetMaxSP() - GetSP(), false, false, compute_point_status); PointChange(POINT_STAMINA, GetMaxStamina() - GetStamina(), false, false, compute_point_status); SetPoint(POINT_LEVEL_STEP, val); SetRealPoint(POINT_LEVEL_STEP, val); Save(); } else val = GetPoint(POINT_LEVEL_STEP); break; case POINT_HP: { if (IsDead() || IsStun()) return; int prev_hp = GetHP(); amount = MIN(GetMaxHP() - GetHP(), amount); SetHP(GetHP() + amount); val = GetHP(); BroadcastTargetPacket(); if (GetParty() && IsPC() && val != prev_hp) GetParty()->SendPartyInfoOneToAll(this); } break; case POINT_SP: { if (IsDead() || IsStun()) return; amount = MIN(GetMaxSP() - GetSP(), amount); SetSP(GetSP() + amount); val = GetSP(); } break; case POINT_STAMINA: { if (IsDead() || IsStun()) return; int prev_val = GetStamina(); amount = MIN(GetMaxStamina() - GetStamina(), amount); SetStamina(GetStamina() + amount); val = GetStamina(); if (val == 0) { // Stamina SetNowWalking(true); } else if (prev_val == 0) { ResetWalking(); } if (amount < 0 && val != 0) return; } break; case POINT_MAX_HP: { SetPoint(type, GetPoint(type) + amount); //SetMaxHP(GetMaxHP() + amount); int hp = GetRealPoint(POINT_MAX_HP); int add_hp = MIN(3500, hp * GetPoint(POINT_MAX_HP_PCT) / 100); add_hp += GetPoint(POINT_MAX_HP); add_hp += GetPoint(POINT_PARTY_TANKER_BONUS); SetMaxHP(hp + add_hp); val = GetMaxHP(); } break; case POINT_MAX_SP: { SetPoint(type, GetPoint(type) + amount); //SetMaxSP(GetMaxSP() + amount); int sp = GetRealPoint(POINT_MAX_SP); int add_sp = MIN(800, sp * GetPoint(POINT_MAX_SP_PCT) / 100); add_sp += GetPoint(POINT_MAX_SP); add_sp += GetPoint(POINT_PARTY_SKILL_MASTER_BONUS); SetMaxSP(sp + add_sp); val = GetMaxSP(); } break; case POINT_MAX_HP_PCT: SetPoint(type, GetPoint(type) + amount); val = GetPoint(type); PointChange(POINT_MAX_HP, 0, false, false, compute_point_status); break; case POINT_MAX_SP_PCT: SetPoint(type, GetPoint(type) + amount); val = GetPoint(type); PointChange(POINT_MAX_SP, 0, false, false, compute_point_status); break; case POINT_MAX_STAMINA: SetMaxStamina(GetMaxStamina() + amount); val = GetMaxStamina(); break; case POINT_GOLD: { const int64_t nTotalMoney = static_cast<int64_t>(GetGold()) + static_cast<int64_t>(amount); if (GOLD_MAX <= nTotalMoney) { sys_err("[OVERFLOW_GOLD] OriGold %d AddedGold %d id %u Name %s ", GetGold(), amount, GetPlayerID(), GetName()); LogManager::instance().CharLog(this, GetGold() + amount, "OVERFLOW_GOLD", ""); return; } SetGold(GetGold() + amount); val = GetGold(); } break; case POINT_SKILL: case POINT_STAT: case POINT_SUB_SKILL: case POINT_STAT_RESET_COUNT: case POINT_HORSE_SKILL: SetPoint(type, GetPoint(type) + amount); val = GetPoint(type); SetRealPoint(type, val); break; case POINT_DEF_GRADE: SetPoint(type, GetPoint(type) + amount); val = GetPoint(type); PointChange(POINT_CLIENT_DEF_GRADE, amount, false, false, compute_point_status); break; case POINT_CLIENT_DEF_GRADE: SetPoint(type, GetPoint(type) + amount); val = GetPoint(type); break; case POINT_ST: case POINT_HT: case POINT_DX: case POINT_IQ: case POINT_HP_REGEN: case POINT_SP_REGEN: case POINT_ATT_SPEED: case POINT_ATT_GRADE: case POINT_MOV_SPEED: case POINT_CASTING_SPEED: case POINT_MAGIC_ATT_GRADE: case POINT_MAGIC_DEF_GRADE: case POINT_BOW_DISTANCE: case POINT_HP_RECOVERY: case POINT_SP_RECOVERY: case POINT_ATTBONUS_HUMAN: // 42 case POINT_ATTBONUS_ANIMAL: // 43 case POINT_ATTBONUS_ORC: // 44 case POINT_ATTBONUS_MILGYO: // 45 case POINT_ATTBONUS_UNDEAD: // 46 case POINT_ATTBONUS_DEVIL: // 47 case POINT_ATTBONUS_MONSTER: case POINT_ATTBONUS_SURA: case POINT_ATTBONUS_ASSASSIN: case POINT_ATTBONUS_WARRIOR: case POINT_ATTBONUS_SHAMAN: case POINT_POISON_PCT: case POINT_STUN_PCT: case POINT_SLOW_PCT: case POINT_BLOCK: case POINT_DODGE: case POINT_CRITICAL_PCT: case POINT_RESIST_CRITICAL: case POINT_PENETRATE_PCT: case POINT_RESIST_PENETRATE: case POINT_CURSE_PCT: case POINT_STEAL_HP: // 48 case POINT_STEAL_SP: // 49 case POINT_MANA_BURN_PCT: // 50 case POINT_DAMAGE_SP_RECOVER: // 51 case POINT_RESIST_NORMAL_DAMAGE: case POINT_RESIST_SWORD: case POINT_RESIST_TWOHAND: case POINT_RESIST_DAGGER: case POINT_RESIST_BELL: case POINT_RESIST_FAN: case POINT_RESIST_BOW: case POINT_RESIST_FIRE: case POINT_RESIST_ELEC: case POINT_RESIST_MAGIC: case POINT_RESIST_WIND: case POINT_RESIST_ICE: case POINT_RESIST_EARTH: case POINT_RESIST_DARK: case POINT_REFLECT_MELEE: // 67 case POINT_REFLECT_CURSE: // 68 case POINT_POISON_REDUCE: // 69 case POINT_KILL_SP_RECOVER: // 70 case POINT_KILL_HP_RECOVERY: // 75 case POINT_HIT_HP_RECOVERY: case POINT_HIT_SP_RECOVERY: case POINT_MANASHIELD: case POINT_ATT_BONUS: case POINT_DEF_BONUS: case POINT_SKILL_DAMAGE_BONUS: case POINT_NORMAL_HIT_DAMAGE_BONUS: // DEPEND_BONUS_ATTRIBUTES case POINT_SKILL_DEFEND_BONUS: case POINT_NORMAL_HIT_DEFEND_BONUS: SetPoint(type, GetPoint(type) + amount); val = GetPoint(type); break; // END_OF_DEPEND_BONUS_ATTRIBUTES case POINT_PARTY_ATTACKER_BONUS: case POINT_PARTY_TANKER_BONUS: case POINT_PARTY_BUFFER_BONUS: case POINT_PARTY_SKILL_MASTER_BONUS: case POINT_PARTY_HASTE_BONUS: case POINT_PARTY_DEFENDER_BONUS: case POINT_RESIST_WARRIOR : case POINT_RESIST_ASSASSIN : case POINT_RESIST_SURA : case POINT_RESIST_SHAMAN : SetPoint(type, GetPoint(type) + amount); val = GetPoint(type); break; case POINT_MALL_ATTBONUS: case POINT_MALL_DEFBONUS: case POINT_MALL_EXPBONUS: case POINT_MALL_ITEMBONUS: case POINT_MALL_GOLDBONUS: case POINT_MELEE_MAGIC_ATT_BONUS_PER: if (GetPoint(type) + amount > 100) { sys_err("MALL_BONUS exceeded over 100!! point type: %d name: %s amount %d", type, GetName(), amount); amount = 100 - GetPoint(type); } SetPoint(type, GetPoint(type) + amount); val = GetPoint(type); break; // PC_BANG_ITEM_ADD case POINT_PC_BANG_EXP_BONUS : case POINT_PC_BANG_DROP_BONUS : case POINT_RAMADAN_CANDY_BONUS_EXP: SetPoint(type, amount); val = GetPoint(type); break; // END_PC_BANG_ITEM_ADD case POINT_EXP_DOUBLE_BONUS: // 71 case POINT_GOLD_DOUBLE_BONUS: // 72 case POINT_ITEM_DROP_BONUS: // 73 case POINT_POTION_BONUS: // 74 if (GetPoint(type) + amount > 100) { sys_err("BONUS exceeded over 100!! point type: %d name: %s amount %d", type, GetName(), amount); amount = 100 - GetPoint(type); } SetPoint(type, GetPoint(type) + amount); val = GetPoint(type); break; case POINT_IMMUNE_STUN: // 76 SetPoint(type, GetPoint(type) + amount); val = GetPoint(type); if (val) { // ChatPacket(CHAT_TYPE_INFO, "IMMUNE_STUN SET_BIT type(%u) amount(%d)", type, amount); SET_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_STUN); } else { // ChatPacket(CHAT_TYPE_INFO, "IMMUNE_STUN REMOVE_BIT type(%u) amount(%d)", type, amount); REMOVE_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_STUN); } break; case POINT_IMMUNE_SLOW: // 77 SetPoint(type, GetPoint(type) + amount); val = GetPoint(type); if (val) { SET_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_SLOW); } else { REMOVE_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_SLOW); } break; case POINT_IMMUNE_FALL: // 78 SetPoint(type, GetPoint(type) + amount); val = GetPoint(type); if (val) { SET_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_FALL); } else { REMOVE_BIT(m_pointsInstant.dwImmuneFlag, IMMUNE_FALL); } break; case POINT_ATT_GRADE_BONUS: SetPoint(type, GetPoint(type) + amount); PointChange(POINT_ATT_GRADE, amount, false, false, compute_point_status); val = GetPoint(type); break; case POINT_DEF_GRADE_BONUS: SetPoint(type, GetPoint(type) + amount); PointChange(POINT_DEF_GRADE, amount, false, false, compute_point_status); val = GetPoint(type); break; case POINT_MAGIC_ATT_GRADE_BONUS: SetPoint(type, GetPoint(type) + amount); PointChange(POINT_MAGIC_ATT_GRADE, amount, false, false, compute_point_status); val = GetPoint(type); break; case POINT_MAGIC_DEF_GRADE_BONUS: SetPoint(type, GetPoint(type) + amount); PointChange(POINT_MAGIC_DEF_GRADE, amount, false, false, compute_point_status); val = GetPoint(type); break; case POINT_VOICE: case POINT_EMPIRE_POINT: //sys_err("CHARACTER::PointChange: %s: point cannot be changed. use SetPoint instead (type: %d)", GetName(), type); val = GetRealPoint(type); break; case POINT_POLYMORPH: SetPoint(type, GetPoint(type) + amount); val = GetPoint(type); SetPolymorph(val); break; case POINT_MOUNT: SetPoint(type, GetPoint(type) + amount); val = GetPoint(type); MountVnum(val); break; case POINT_ENERGY: case POINT_COSTUME_ATTR_BONUS: { int old_val = GetPoint(type); SetPoint(type, old_val + amount); val = GetPoint(type); BuffOnAttr_ValueChange(type, old_val, val); } break; default: sys_err("CHARACTER::PointChange: %s: unknown point change type %d", GetName(), type); return; } switch (type) { case POINT_LEVEL: case POINT_ST: case POINT_DX: case POINT_IQ: case POINT_HT: ComputeBattlePoints(compute_point_status); break; case POINT_MAX_HP: case POINT_MAX_SP: case POINT_MAX_STAMINA: break; } if (type == POINT_HP && amount == 0) return; if (compute_point_status) { bool valid = false; for (std::vector<Tcomput>::iterator it = compute_point_list.begin(); it != compute_point_list.end(); it++) { if (it->type == type) { if (bAmount) it->amount = amount; else it->amount = 0; it->val = val; valid = true; } } if (!valid) { Tcomput ins; ins.type = type; if (bAmount) ins.amount = amount; else ins.amount = 0; ins.val = val; compute_point_list.push_back(ins); } } if (GetDesc() && !compute_point_status) { struct packet_point_change pack; pack.header = HEADER_GC_CHARACTER_POINT_CHANGE; pack.dwVID = m_vid; pack.type = type; pack.value = val; if (bAmount) pack.amount = amount; else pack.amount = 0; if (!bBroadcast) GetDesc()->Packet(&pack, sizeof(struct packet_point_change)); else PacketAround(&pack, sizeof(pack)); } } //znajdz: void CHARACTER::ApplyPoint { ... } //zamien cala funkcje na: void CHARACTER::ApplyPoint(BYTE bApplyType, int iVal, bool compute_point_status) { switch (bApplyType) { case APPLY_NONE: // 0 break;; case APPLY_CON: PointChange(POINT_HT, iVal, false, false, compute_point_status); PointChange(POINT_MAX_HP, (iVal * JobInitialPoints[GetJob()].hp_per_ht), false, false, compute_point_status); PointChange(POINT_MAX_STAMINA, (iVal * JobInitialPoints[GetJob()].stamina_per_con), false, false, compute_point_status); break; case APPLY_INT: PointChange(POINT_IQ, iVal, false, false, compute_point_status); PointChange(POINT_MAX_SP, (iVal * JobInitialPoints[GetJob()].sp_per_iq), false, false, compute_point_status); break; case APPLY_SKILL: // SKILL_DAMAGE_BONUS { // 00000000 00000000 00000000 00000000 // vnum ^ add change BYTE bSkillVnum = (BYTE) (((DWORD)iVal) >> 24); int iAdd = iVal & 0x00800000; int iChange = iVal & 0x007fffff; sys_log(1, "APPLY_SKILL skill %d add? %d change %d", bSkillVnum, iAdd ? 1 : 0, iChange); if (0 == iAdd) iChange = -iChange; boost::unordered_map<BYTE, int>::iterator iter = m_SkillDamageBonus.find(bSkillVnum); if (iter == m_SkillDamageBonus.end()) m_SkillDamageBonus.insert(std::make_pair(bSkillVnum, iChange)); else iter->second += iChange; } // END_OF_SKILL_DAMAGE_BONUS break; case APPLY_MAX_HP: case APPLY_MAX_HP_PCT: { int i = GetMaxHP(); if(i == 0) break; PointChange(aApplyInfo[bApplyType].bPointType, iVal, false, false, compute_point_status); float fRatio = (float)GetMaxHP() / (float)i; PointChange(POINT_HP, GetHP() * fRatio - GetHP(), false, false, compute_point_status); } break; case APPLY_MAX_SP: case APPLY_MAX_SP_PCT: { int i = GetMaxSP(); if(i == 0) break; PointChange(aApplyInfo[bApplyType].bPointType, iVal, false, false, compute_point_status); float fRatio = (float)GetMaxSP() / (float)i; PointChange(POINT_SP, GetSP() * fRatio - GetSP(), false, false, compute_point_status); } break; case APPLY_STR: case APPLY_DEX: case APPLY_ATT_SPEED: case APPLY_MOV_SPEED: case APPLY_CAST_SPEED: case APPLY_HP_REGEN: case APPLY_SP_REGEN: case APPLY_POISON_PCT: case APPLY_STUN_PCT: case APPLY_SLOW_PCT: case APPLY_CRITICAL_PCT: case APPLY_PENETRATE_PCT: case APPLY_ATTBONUS_HUMAN: case APPLY_ATTBONUS_ANIMAL: case APPLY_ATTBONUS_ORC: case APPLY_ATTBONUS_MILGYO: case APPLY_ATTBONUS_UNDEAD: case APPLY_ATTBONUS_DEVIL: case APPLY_ATTBONUS_WARRIOR: // 59 case APPLY_ATTBONUS_ASSASSIN: // 60 case APPLY_ATTBONUS_SURA: // 61 case APPLY_ATTBONUS_SHAMAN: // 62 case APPLY_ATTBONUS_MONSTER: // 63 case APPLY_STEAL_HP: case APPLY_STEAL_SP: case APPLY_MANA_BURN_PCT: case APPLY_DAMAGE_SP_RECOVER: case APPLY_BLOCK: case APPLY_DODGE: case APPLY_RESIST_SWORD: case APPLY_RESIST_TWOHAND: case APPLY_RESIST_DAGGER: case APPLY_RESIST_BELL: case APPLY_RESIST_FAN: case APPLY_RESIST_BOW: case APPLY_RESIST_FIRE: case APPLY_RESIST_ELEC: case APPLY_RESIST_MAGIC: case APPLY_RESIST_WIND: case APPLY_RESIST_ICE: case APPLY_RESIST_EARTH: case APPLY_RESIST_DARK: case APPLY_REFLECT_MELEE: case APPLY_REFLECT_CURSE: case APPLY_ANTI_CRITICAL_PCT: case APPLY_ANTI_PENETRATE_PCT: case APPLY_POISON_REDUCE: case APPLY_KILL_SP_RECOVER: case APPLY_EXP_DOUBLE_BONUS: case APPLY_GOLD_DOUBLE_BONUS: case APPLY_ITEM_DROP_BONUS: case APPLY_POTION_BONUS: case APPLY_KILL_HP_RECOVER: case APPLY_IMMUNE_STUN: case APPLY_IMMUNE_SLOW: case APPLY_IMMUNE_FALL: case APPLY_BOW_DISTANCE: case APPLY_ATT_GRADE_BONUS: case APPLY_DEF_GRADE_BONUS: case APPLY_MAGIC_ATT_GRADE: case APPLY_MAGIC_DEF_GRADE: case APPLY_CURSE_PCT: case APPLY_MAX_STAMINA: case APPLY_MALL_ATTBONUS: case APPLY_MALL_DEFBONUS: case APPLY_MALL_EXPBONUS: case APPLY_MALL_ITEMBONUS: case APPLY_MALL_GOLDBONUS: case APPLY_SKILL_DAMAGE_BONUS: case APPLY_NORMAL_HIT_DAMAGE_BONUS: // DEPEND_BONUS_ATTRIBUTES case APPLY_SKILL_DEFEND_BONUS: case APPLY_NORMAL_HIT_DEFEND_BONUS: // END_OF_DEPEND_BONUS_ATTRIBUTES case APPLY_PC_BANG_EXP_BONUS : case APPLY_PC_BANG_DROP_BONUS : case APPLY_RESIST_WARRIOR : case APPLY_RESIST_ASSASSIN : case APPLY_RESIST_SURA : case APPLY_RESIST_SHAMAN : case APPLY_ENERGY: // 82 case APPLY_DEF_GRADE: // 83 case APPLY_COSTUME_ATTR_BONUS: // 84 case APPLY_MAGIC_ATTBONUS_PER: // 85 case APPLY_MELEE_MAGIC_ATTBONUS_PER: // 86 PointChange(aApplyInfo[bApplyType].bPointType, iVal, false, false, compute_point_status); break; default: sys_err("Unknown apply type %d name %s", bApplyType, GetName()); break; } } //Char_affect.cpp //znajdz: void CHARACTER::RefreshAffect { ... } //zamien cala funkcje na: void CHARACTER::RefreshAffect(bool compute_point_status) { itertype(m_list_pkAffect) it = m_list_pkAffect.begin(); while (it != m_list_pkAffect.end()) { CAffect * pkAff = *it++; ComputeAffect(pkAff, true, compute_point_status); } } //znajdz: void CHARACTER::ComputeAffect { ... } //zamien cala funkcje na: void CHARACTER::ComputeAffect(CAffect * pkAff, bool bAdd, bool compute_point_status) { if (bAdd && pkAff->dwType >= GUILD_SKILL_START && pkAff->dwType <= GUILD_SKILL_END) { if (!GetGuild()) return; if (!GetGuild()->UnderAnyWar()) return; } if (pkAff->dwFlag) { if (!bAdd) m_afAffectFlag.Reset(pkAff->dwFlag); else m_afAffectFlag.Set(pkAff->dwFlag); } if (bAdd) PointChange(pkAff->bApplyOn, pkAff->lApplyValue, false, false, compute_point_status); else PointChange(pkAff->bApplyOn, -pkAff->lApplyValue, false, false, compute_point_status); if (pkAff->dwType == SKILL_MUYEONG) { if (bAdd) StartMuyeongEvent(); else StopMuyeongEvent(); } } //item.h //znajdz: void ModifyPoints //zamien na: void ModifyPoints(bool bAdd, bool compute_point_status = false); //item.cpp //znajdz: void CItem::ModifyPoints { ... } //zamien cala funkcje na: void CItem::ModifyPoints(bool bAdd, bool compute_point_status) { int accessoryGrade; if (false == IsAccessoryForSocket()) { if (m_pProto->bType == ITEM_WEAPON || m_pProto->bType == ITEM_ARMOR) { for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i) { DWORD dwVnum; if ((dwVnum = GetSocket(i)) <= 2) continue; TItemTable * p = ITEM_MANAGER::instance().GetTable(dwVnum); if (!p) { sys_err("cannot find table by vnum %u", dwVnum); continue; } if (ITEM_METIN == p->bType) { //m_pOwner->ApplyPoint(p->alValues[0], bAdd ? p->alValues[1] : -p->alValues[1]); for (int i = 0; i < ITEM_APPLY_MAX_NUM; ++i) { if (p->aApplies[i].bType == APPLY_NONE) continue; if (p->aApplies[i].bType == APPLY_SKILL) m_pOwner->ApplyPoint(p->aApplies[i].bType, bAdd ? p->aApplies[i].lValue : p->aApplies[i].lValue ^ 0x00800000, compute_point_status); else m_pOwner->ApplyPoint(p->aApplies[i].bType, bAdd ? p->aApplies[i].lValue : -p->aApplies[i].lValue, compute_point_status); } } } } accessoryGrade = 0; } else { accessoryGrade = MIN(GetAccessorySocketGrade(), ITEM_ACCESSORY_SOCKET_MAX_NUM); } for (int i = 0; i < ITEM_APPLY_MAX_NUM; ++i) { if (m_pProto->aApplies[i].bType == APPLY_NONE) continue; long value = m_pProto->aApplies[i].lValue; if (m_pProto->aApplies[i].bType == APPLY_SKILL) { m_pOwner->ApplyPoint(m_pProto->aApplies[i].bType, bAdd ? value : value ^ 0x00800000, compute_point_status); } else { if (0 != accessoryGrade) value += MAX(accessoryGrade, value * aiAccessorySocketEffectivePct[accessoryGrade] / 100); m_pOwner->ApplyPoint(m_pProto->aApplies[i].bType, bAdd ? value : -value, compute_point_status); } } if (true == CItemVnumHelper::IsRamadanMoonRing(GetVnum()) || true == CItemVnumHelper::IsHalloweenCandy(GetVnum()) || true == CItemVnumHelper::IsHappinessRing(GetVnum()) || true == CItemVnumHelper::IsLovePendant(GetVnum())) { // Do not anything. } else { for (int i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; ++i) { if (GetAttributeType(i)) { const TPlayerItemAttribute& ia = GetAttribute(i); if (ia.bType == APPLY_SKILL) m_pOwner->ApplyPoint(ia.bType, bAdd ? ia.sValue : ia.sValue ^ 0x00800000, compute_point_status); else m_pOwner->ApplyPoint(ia.bType, bAdd ? ia.sValue : -ia.sValue, compute_point_status); } } } switch (m_pProto->bType) { case ITEM_PICK: case ITEM_ROD: { if (bAdd) { if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON) m_pOwner->SetPart(PART_WEAPON, GetVnum()); } else { if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON) m_pOwner->SetPart(PART_WEAPON, 0); } } break; case ITEM_WEAPON: { if (bAdd) { if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON) m_pOwner->SetPart(PART_WEAPON, GetVnum()); } else { if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON) m_pOwner->SetPart(PART_WEAPON, 0); } } break; case ITEM_ARMOR: { if (0 != m_pOwner->GetWear(WEAR_COSTUME_BODY)) break; if (GetSubType() == ARMOR_BODY || GetSubType() == ARMOR_HEAD || GetSubType() == ARMOR_FOOTS || GetSubType() == ARMOR_SHIELD) { if (bAdd) { if (GetProto()->bSubType == ARMOR_BODY) m_pOwner->SetPart(PART_MAIN, GetVnum()); } else { if (GetProto()->bSubType == ARMOR_BODY) m_pOwner->SetPart(PART_MAIN, m_pOwner->GetOriginalPart(PART_MAIN)); } } } break; case ITEM_COSTUME: { DWORD toSetValue = this->GetVnum(); EParts toSetPart = PART_MAX_NUM; if (GetSubType() == COSTUME_BODY) { toSetPart = PART_MAIN; if (false == bAdd) { const CItem* pArmor = m_pOwner->GetWear(WEAR_BODY); toSetValue = (NULL != pArmor) ? pArmor->GetVnum() : m_pOwner->GetOriginalPart(PART_MAIN); } } else if (GetSubType() == COSTUME_HAIR) { toSetPart = PART_HAIR; toSetValue = (true == bAdd) ? this->GetValue(3) : 0; } if (PART_MAX_NUM != toSetPart) { m_pOwner->SetPart((BYTE)toSetPart, toSetValue); if (!compute_point_status) m_pOwner->UpdatePacket(); } } break; case ITEM_UNIQUE: { if (0 != GetSIGVnum()) { const CSpecialItemGroup* pItemGroup = ITEM_MANAGER::instance().GetSpecialItemGroup(GetSIGVnum()); if (NULL == pItemGroup) break; DWORD dwAttrVnum = pItemGroup->GetAttrVnum(GetVnum()); const CSpecialAttrGroup* pAttrGroup = ITEM_MANAGER::instance().GetSpecialAttrGroup(dwAttrVnum); if (NULL == pAttrGroup) break; for (itertype (pAttrGroup->m_vecAttrs) it = pAttrGroup->m_vecAttrs.begin(); it != pAttrGroup->m_vecAttrs.end(); it++) { m_pOwner->ApplyPoint(it->apply_type, bAdd ? it->apply_value : -it->apply_value, compute_point_status); } } } break; } } //PetSystem.h //znajdz: void GiveBuff //zamien na: void GiveBuff(bool compute_point_status = false); //znajdz: void RefreshBuff //zamien na: void RefreshBuff(bool compute_point_status = false); //PetSystem.cpp //znajdz: void CPetActor::GiveBuff { ... } //zamien cala funkcje na: void CPetActor::GiveBuff(bool compute_point_status) { if (!__PetCheckBuff(this)) return; LPITEM item = ITEM_MANAGER::instance().FindByVID(m_dwSummonItemVID); if (NULL != item) item->ModifyPoints(true, compute_point_status); return ; } //znajdz: void CPetSystem::RefreshBuff { ... } //zamien cala funkcje na: void CPetSystem::RefreshBuff(bool compute_point_status) { for (TPetActorMap::const_iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter) { CPetActor* petActor = iter->second; if (0 != petActor) { if (petActor->IsSummoned()) { petActor->GiveBuff(compute_point_status); } } } } //Packet.h //znajdz: HEADER_GC_CHARACTER_POINT_CHANGE = 17, //dodaj pod: HEADER_GC_CHARACTER_POINT_CHANGE_DYNAMIC = 50, //znajdz: typedef struct packet_point_change { ... } TPacketGCPointChange; //dodaj pod: typedef struct packet_point_change_dynamic { int header; DWORD dwVID; BYTE count; } TPacketGCPointChangeDynamic; typedef struct packet_point_change_dynamic_val { BYTE type; long amount; long value; } TPacketGCPointChangeDynamicVal; //Binka/Packet.h //znajdz: HEADER_GC_CHARACTER_POINT_CHANGE = 17, //dodaj pod: HEADER_GC_CHARACTER_POINT_CHANGE_DYNAMIC = 50, //znajdz: typedef struct packet_point_change { ... } TPacketGCPointChange; //dodaj pod: typedef struct packet_point_change_dynamic { int header; DWORD dwVID; BYTE count; } TPacketGCPointChangeDynamic; typedef struct packet_point_change_dynamic_val { BYTE Type; long amount; long value; } TPacketGCPointChangeDynamicVal; //PythonNetworkStream.h //znajdz: bool RecvPointChange //dodaj pod: bool RecvPointChangeDynamic(); //PythonNetworkStream.cpp //znajdz: Set(HEADER_GC_PLAYER_POINT_CHANGE, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCPointChange), STATIC_SIZE_PACKET)); //dodaj pod: Set(HEADER_GC_PLAYER_POINT_CHANGE_DYNAMIC, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCPointChangeDynamic), STATIC_SIZE_PACKET)); //PythonNetworkStreamPhaseGame.cpp //znajdz: case HEADER_GC_PLAYER_POINT_CHANGE: ret = RecvPointChange(); break; //dodaj pod: case HEADER_GC_PLAYER_POINT_CHANGE_DYNAMIC: ret = RecvPointChangeDynamic(); break; //znajdz: bool CPythonNetworkStream::RecvPointChange() { ... } //dodaj pod: bool CPythonNetworkStream::RecvPointChangeDynamic() { TPacketGCPointChangeDynamic PointChange; if (!Peek(sizeof(TPacketGCPointChangeDynamic), &PointChange)) { Tracen("RecvPointChangeDynamic Packet Error #1"); return false; } if (!Peek(sizeof(TPacketGCPointChangeDynamicVal)*PointChange.count)) { Tracen("RecvPointChangeDynamic Packet Error #2"); return false; } Recv(sizeof(TPacketGCPointChangeDynamic)); bool refresh_status = false; bool refresh_skil_window = false; bool refresh_point_gold = false; int refresh_point_gold_val = 0; for (BYTE loop = 0; loop < PointChange.count; loop++) { TPacketGCPointChangeDynamicVal point_val; if (!Recv(sizeof(TPacketGCPointChangeDynamicVal), &point_val)) { Tracen("Recv Point Change Packet Error"); return false; } CPythonCharacterManager& rkChrMgr = CPythonCharacterManager::Instance(); rkChrMgr.ShowPointEffect(point_val.Type, PointChange.dwVID); CInstanceBase* pInstance = CPythonCharacterManager::Instance().GetMainInstancePtr(); if (pInstance && PointChange.dwVID == pInstance->GetVirtualID()) { CPythonPlayer& rkPlayer = CPythonPlayer::Instance(); rkPlayer.SetStatus(point_val.Type, point_val.value); switch (point_val.Type) { case POINT_STAT_RESET_COUNT: refresh_status = true; break; case POINT_LEVEL: case POINT_ST: case POINT_DX: case POINT_HT: case POINT_IQ: refresh_status = true; refresh_skil_window = true; break; case POINT_SKILL: case POINT_SUB_SKILL: case POINT_HORSE_SKILL: refresh_skil_window = true; break; case POINT_ENERGY: if (point_val.value == 0) { rkPlayer.SetStatus(POINT_ENERGY_END_TIME, 0); } refresh_status = true; break; default: refresh_status = true; break; } if (POINT_GOLD == point_val.Type) { if (point_val.amount > 0) { refresh_point_gold = true; refresh_point_gold_val = point_val.amount; } } } } if (refresh_status) { __RefreshStatus(); } if (refresh_skil_window) { __RefreshSkillWindow(); } if (refresh_point_gold) { PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "OnPickMoney", Py_BuildValue("(i)", refresh_point_gold_val)); } return true; } //PythonNetworkStreamPhaseLoading.cpp //znajdz: case HEADER_GC_PLAYER_POINT_CHANGE: if (RecvPointChange()) return; break; //dodaj pod: case HEADER_GC_PLAYER_POINT_CHANGE_DYNAMIC: if (RecvPointChangeDynamic()) return; break; //PythonNetworkStreamPhaseSelect.cpp //znajdz: case HEADER_GC_PLAYER_POINT_CHANGE: TPacketGCPointChange PointChange; Recv(sizeof(TPacketGCPointChange), &PointChange); return; break; //dodaj pod: case HEADER_GC_PLAYER_POINT_CHANGE_DYNAMIC: TPacketGCPointChangeDynamic PointChangeDynamic; if (!Peek(sizeof(TPacketGCPointChangeDynamic), &PointChangeDynamic)) { Tracen("RecvPointChangeDynamic Packet Error #1"); return; } if (!Peek(sizeof(TPacketGCPointChangeDynamicVal) * PointChangeDynamic.count)) { Tracen("RecvPointChangeDynamic Packet Error #2"); return; } Recv(sizeof(TPacketGCPointChangeDynamic)); for (size_t i = 0; i < PointChangeDynamic.count; i++) { TPacketGCPointChangeDynamicVal PointChangeDynamicVal; Recv(sizeof(TPacketGCPointChangeDynamicVal), &PointChangeDynamicVal); } return; break;
  9. Na niektórych urządzeniach może wystąpić taki błąd Wchodzimy do Binka/EterLib i szukamy pliku GrpDevice.ccp Szukamy: if (!ms_kD3DDetector.Find(800, 600, 32, TRUE, &ms_iD3DModeInfo, &ms_iD3DDevInfo,&ms_iD3DAdapterInfo)) Zamieniamy na: //if (!ms_kD3DDetector.Find(800, 600, 32, TRUE, &ms_iD3DModeInfo, &ms_iD3DDevInfo, &ms_iD3DAdapterInfo)) //return CREATE_DETECT;
  10. Witam Dziś pokaże wam co zrobić by wszyscy widzieli poprawnie zaktualizowany lv. Wersja Packet <-- Poprawna. Source Game: packet.h Szukaj: typedef struct packet_update_char Niżej: short sAlignment; Dodaj: DWORD dwLevel; char.cpp Szukaj: void CHARACTER::UpdatePacket() Niżej: pack.sAlignment = m_iAlignment / 10; Dodaj pod: pack.dwLevel = GetLevel(); Source Bin: Packet.h typedef struct packet_update_char Niżej short sAlignment; Dodaj pod: DWORD dwLevel; PythonNetworkStreamPhaseGameActor.cpp Szukaj: bool CPythonNetworkStream::RecvCharacterUpdatePacket() Niżej: kNetUpdateActorData.m_sAlignment=chrUpdatePacket.sAlignment; Dodaj pod:: kNetUpdateActorData.m_dwLevel=chrUpdatePacket.dwLevel; NetworkActorManager.cpp Szukaj: void CNetworkActorManager::UpdateActor(const SNetworkUpdateActorData& c_rkNetUpdateActorData) Niżej: pkInstFind->SetAlignment(c_rkNetUpdateActorData.m_sAlignment); Dodaj pod: pkInstFind->SetLevel(c_rkNetUpdateActorData.m_dwLevel); NetworkActorManager.h Szukaj: struct SNetworkUpdateActorData Niżej: short m_sAlignment; Dodaj pod: DWORD m_dwLevel; InstanceBase.cpp Szukaj: void CInstanceBase::SetAlignment(short sAlignment) Pod funkcją dodaj tą funkcję: void CInstanceBase::SetLevel(DWORD level) { m_dwLevel = level; UpdateTextTailLevel(m_dwLevel); } Szukaj: void CInstanceBase::UpdateTextTailLevel(DWORD level) Zamień funkcję na: void CInstanceBase::UpdateTextTailLevel(DWORD level) { if (IsPC()) { static D3DXCOLOR s_kLevelColor = D3DXCOLOR(152.0f/255.0f, 255.0f/255.0f, 51.0f/255.0f, 1.0f); char szText[256]; sprintf(szText, "Lv %d", level); CPythonTextTail::Instance().AttachLevel(GetVirtualID(), szText, s_kLevelColor); } } InstanceBase.h Szukaj: void SetAlignment(short sAlignment); Dodaj pod: void SetLevel(DWORD level);
  11. Przed edycją: Po edycji: Cześć przechodzimy do pliku battle.cpp i szukamy tego kodu: if (!victim->IsBuilding()) { int max = 300; if (false == ch->IsPC()) { // ¸ó˝şĹÍŔÇ °ćżě ¸ó˝şĹÍ °ř°Ý °Ĺ¸®¸¦ »çżë max = (int) (ch->GetMobAttackRange() * 1.15f); } else { // PCŔĎ °ćżě »ó´ë°ˇ melee ¸÷ŔĎ °ćżě ¸÷ŔÇ °ř°Ý °Ĺ¸®°ˇ ĂÖ´ë °ř°Ý °Ĺ¸® if (false == victim->IsPC() && BATTLE_TYPE_MELEE == victim->GetMobBattleType()) max = MAX(300, (int) (victim->GetMobAttackRange() * 1.15f)); } if (distance > max) { if (test_server) sys_log(0, "VICTIM_FAR: %s distance: %d max: %d", ch->GetName(), distance, max); return BATTLE_NONE; } } Zamień kod - Co zrobiliśmy? Zwiększyliśmy wartość max o +25 if (!victim->IsBuilding()) { int max = 325; if (false == ch->IsPC()) { // ¸ó˝şĹÍŔÇ °ćżě ¸ó˝şĹÍ °ř°Ý °Ĺ¸®¸¦ »çżë max = (int) (ch->GetMobAttackRange() * 1.15f); } else { // PCŔĎ °ćżě »ó´ë°ˇ melee ¸÷ŔĎ °ćżě ¸÷ŔÇ °ř°Ý °Ĺ¸®°ˇ ĂÖ´ë °ř°Ý °Ĺ¸® if (false == victim->IsPC() && BATTLE_TYPE_MELEE == victim->GetMobBattleType()) max = MAX(325, (int) (victim->GetMobAttackRange() * 1.15f)); } if (distance > max) { if (test_server) sys_log(0, "VICTIM_FAR: %s distance: %d max: %d", ch->GetName(), distance, max); return BATTLE_NONE; } }
  12. Cześć, Niektórzy mają problem (@Wariacik123) z implementacją kodu, który umożliwi powrót do odczytywania item/mob_proto z bazy danych i całkowite usunięcie txt. O to kod, który współpracuje z nowszymi kompilatorami, także bez problemu użyjecie go na mojej maszynie. 0. Dopisujemy do CONFIGów kanałów 2 zmienne, które pozwolą nam włączać/wyłączać funkcje bez rekompilacji game: PROTO_FROM_DB: 1 lub 0 MIRROR2DB: 1 lub 0 1. Otwieramy plik db/ClientManager.cpp i szukamy w nim: CPacketInfo g_query_info; CPacketInfo g_item_info; int g_item_count = 0; int g_query_count[2]; Pod dodajemy: #ifdef ENABLE_PROTO_FROM_DB bool g_bMirror2DB = false; #endif Szukamy: CClientManager::CClientManager() : m_pkAuthPeer(NULL), m_iPlayerIDStart(0), m_iPlayerDeleteLevelLimit(0), m_iPlayerDeleteLevelLimitLower(0), m_bChinaEventServer(false), m_iShopTableSize(0), m_pShopTable(NULL), m_iRefineTableSize(0), m_pRefineTable(NULL), m_bShutdowned(FALSE), m_iCacheFlushCount(0), m_iCacheFlushCountLimit(200) { m_itemRange.dwMin = 0; m_itemRange.dwMax = 0; m_itemRange.dwUsableItemIDMin = 0; memset(g_query_count, 0, sizeof(g_query_count)); Pod dodajemy: #ifdef ENABLE_PROTO_FROM_DB bIsProtoReadFromDB = false; #endif Szukamy: //BOOT_LOCALIZATION if (!InitializeLocalization()) { fprintf(stderr, "Failed Localization Infomation so exit\n"); return false; } //END_BOOT_LOCALIZATION //ITEM_UNIQUE_ID if (!InitializeNowItemID()) { fprintf(stderr, " Item range Initialize Failed. Exit DBCache Server\n"); return false; } //END_ITEM_UNIQUE_ID Pod dodajemy: #ifdef ENABLE_PROTO_FROM_DB int iTemp; if (CConfig::instance().GetValue("PROTO_FROM_DB", &iTemp)) { bIsProtoReadFromDB = !!iTemp; fprintf(stdout, "PROTO_FROM_DB: %s\n", (bIsProtoReadFromDB)?"Enabled":"Disabled"); } if (!bIsProtoReadFromDB && CConfig::instance().GetValue("MIRROR2DB", &iTemp)) { g_bMirror2DB = !!iTemp; fprintf(stdout, "MIRROR2DB: %s\n", (g_bMirror2DB)?"Enabled":"Disabled"); } #endif 2. Otwieramy ClientManager.h i szukamy w nim: void UpdateHorseName(TPacketUpdateHorseName* data, CPeer* peer); void AckHorseName(DWORD dwPID, CPeer* peer); void DeleteLoginKey(TPacketDC *data); void ResetLastPlayerID(const TPacketNeedLoginLogInfo* data); //delete gift notify icon void DeleteAwardId(TPacketDeleteAwardID* data); void UpdateChannelStatus(TChannelStatus* pData); void RequestChannelStatus(CPeer* peer, DWORD dwHandle); #ifdef __AUCTION__ void EnrollInAuction (CPeer * peer, DWORD owner_id, AuctionEnrollProductInfo* data); void EnrollInSale (CPeer * peer, DWORD owner_id, AuctionEnrollSaleInfo* data); void EnrollInWish (CPeer * peer, DWORD wisher_id, AuctionEnrollWishInfo* data); void AuctionBid (CPeer * peer, DWORD bidder_id, AuctionBidInfo* data); void AuctionImpur (CPeer * peer, DWORD purchaser_id, AuctionImpurInfo* data); void AuctionGetAuctionedItem (CPeer * peer, DWORD actor_id, DWORD item_id); void AuctionBuySoldItem (CPeer * peer, DWORD actor_id, DWORD item_id); void AuctionCancelAuction (CPeer * peer, DWORD actor_id, DWORD item_id); void AuctionCancelWish (CPeer * peer, DWORD actor_id, DWORD item_num); void AuctionCancelSale (CPeer * peer, DWORD actor_id, DWORD item_id); void AuctionDeleteAuctionItem (CPeer * peer, DWORD actor_id, DWORD item_id); void AuctionDeleteSaleItem (CPeer * peer, DWORD actor_id, DWORD item_id); void AuctionReBid (CPeer * peer, DWORD bidder_id, AuctionBidInfo* data); void AuctionBidCancel (CPeer * peer, DWORD bidder_id, DWORD item_id); #endif Pod dodajemy: #ifdef ENABLE_PROTO_FROM_DB public: bool InitializeMobTableFromDB(); bool InitializeItemTableFromDB(); protected: bool bIsProtoReadFromDB; #endif 3. Otwieramy ClientManagerBoot.cpp i szukamy w nim: if (!InitializeMobTable()) Zamieniamy na: #ifdef ENABLE_PROTO_FROM_DB if (!(bIsProtoReadFromDB?InitializeMobTableFromDB():InitializeMobTable())) #else if (!InitializeMobTable()) #endif Szukamy: if (!InitializeItemTable()) Zamieniamy na: #ifdef ENABLE_PROTO_FROM_DB if (!(bIsProtoReadFromDB?InitializeItemTableFromDB():InitializeItemTable())) #else if (!InitializeItemTable()) #endif Szukamy: if (!InitializeShopTable()) { sys_err("InitializeShopTable FAILED"); return false; } if (!InitializeSkillTable()) { sys_err("InitializeSkillTable FAILED"); return false; } Nad dodajemy: #ifdef ENABLE_PROTO_FROM_DB extern bool g_bMirror2DB; if (g_bMirror2DB) { if (!MirrorMobTableIntoDB()) { sys_err("MirrorMobTableIntoDB FAILED"); return false; } if (!MirrorItemTableIntoDB()) { sys_err("MirrorItemTableIntoDB FAILED"); return false; } } #endif Na końcu pliku dodajemy: #ifdef ENABLE_PROTO_FROM_DB #define VERIFY_IFIELD(x,y) if (data[x]!=NULL && data[x][0]!='\0') str_to_number(y, data[x]); #define VERIFY_SFIELD(x,y) if (data[x]!=NULL && data[x][0]!='\0') strlcpy(y, data[x], sizeof(y)); #define ENABLE_AUTODETECT_VNUMRANGE namespace MProto { enum MProtoT { vnum, name, locale_name, type, rank, battle_type, level, size, ai_flag, setRaceFlag, setImmuneFlag, on_click, empire, drop_item, resurrection_vnum, folder, st, dx, ht, iq, damage_min, damage_max, max_hp, regen_cycle, regen_percent, exp, gold_min, gold_max, def, attack_speed, move_speed, aggressive_hp_pct, aggressive_sight, attack_range, polymorph_item, enchant_curse, enchant_slow, enchant_poison, enchant_stun, enchant_critical, enchant_penetrate, #if defined(ENABLE_WOLFMAN_CHARACTER) && !defined(USE_MOB_BLEEDING_AS_POISON) enchant_bleeding, #endif resist_sword, resist_twohand, resist_dagger, resist_bell, resist_fan, resist_bow, #if defined(ENABLE_WOLFMAN_CHARACTER) && !defined(USE_MOB_CLAW_AS_DAGGER) resist_claw, #endif #if defined(ENABLE_WOLFMAN_CHARACTER) && !defined(USE_MOB_BLEEDING_AS_POISON) resist_bleeding, #endif resist_fire, resist_elect, resist_magic, resist_wind, resist_poison, dam_multiply, summon, drain_sp, skill_vnum0, skill_level0, skill_vnum1, skill_level1, skill_vnum2, skill_level2, skill_vnum3, skill_level3, skill_vnum4, skill_level4, sp_berserk, sp_stoneskin, sp_godspeed, sp_deathblow, sp_revive }; } bool CClientManager::InitializeMobTableFromDB() { char query[2048]; fprintf(stdout, "Loading mob_proto from MySQL\n"); snprintf(query, sizeof(query), "SELECT vnum, name, %s, type, rank, battle_type, level, size+0," " ai_flag+0, setRaceFlag+0, setImmuneFlag+0, on_click, empire, drop_item," " resurrection_vnum, folder, st, dx, ht, iq, damage_min, damage_max, max_hp," " regen_cycle, regen_percent, exp, gold_min, gold_max, def," " attack_speed, move_speed, aggressive_hp_pct, aggressive_sight, attack_range, polymorph_item," " enchant_curse, enchant_slow, enchant_poison, enchant_stun, enchant_critical, enchant_penetrate," #if defined(ENABLE_WOLFMAN_CHARACTER) && !defined(USE_MOB_BLEEDING_AS_POISON) " enchant_bleeding," #endif " resist_sword, resist_twohand, resist_dagger, resist_bell, resist_fan, resist_bow," #if defined(ENABLE_WOLFMAN_CHARACTER) && !defined(USE_MOB_CLAW_AS_DAGGER) " resist_claw," #endif #if defined(ENABLE_WOLFMAN_CHARACTER) && !defined(USE_MOB_BLEEDING_AS_POISON) " resist_bleeding," #endif " resist_fire, resist_elect, resist_magic, resist_wind, resist_poison, dam_multiply, summon, drain_sp," " skill_vnum0, skill_level0, skill_vnum1, skill_level1, skill_vnum2, skill_level2, skill_vnum3, skill_level3," " skill_vnum4, skill_level4, sp_berserk, sp_stoneskin, sp_godspeed, sp_deathblow, sp_revive" " FROM mob_proto%s ORDER BY vnum;", g_stLocaleNameColumn.c_str(), GetTablePostfix() ); std::unique_ptr<SQLMsg> pkMsg(CDBManager::instance().DirectQuery(query)); SQLResult * pRes = pkMsg->Get(); DWORD addNumber = pRes->uiNumRows; if (addNumber == 0) return false; if (!m_vec_mobTable.empty()) { sys_log(0, "RELOAD: mob_proto"); m_vec_mobTable.clear(); } m_vec_mobTable.resize(addNumber); memset(&m_vec_mobTable[0], 0, sizeof(TMobTable) * m_vec_mobTable.size()); TMobTable * mob_table = &m_vec_mobTable[0]; MYSQL_ROW data = NULL; while ((data = mysql_fetch_row(pRes->pSQLResult))) { // check whether or not the field is NULL or that contains an empty string // ## GENERAL VERIFY_IFIELD(MProto::vnum, mob_table->dwVnum); VERIFY_SFIELD(MProto::name, mob_table->szName); VERIFY_SFIELD(MProto::locale_name, mob_table->szLocaleName); VERIFY_IFIELD(MProto::rank, mob_table->bRank); VERIFY_IFIELD(MProto::type, mob_table->bType); VERIFY_IFIELD(MProto::battle_type, mob_table->bBattleType); VERIFY_IFIELD(MProto::level, mob_table->bLevel); VERIFY_IFIELD(MProto::size, mob_table->bSize); // ## FLAG VERIFY_IFIELD(MProto::ai_flag, mob_table->dwAIFlag); VERIFY_IFIELD(MProto::setRaceFlag, mob_table->dwRaceFlag); VERIFY_IFIELD(MProto::setImmuneFlag, mob_table->dwImmuneFlag); // ## OTHERS VERIFY_IFIELD(MProto::empire, mob_table->bEmpire); VERIFY_SFIELD(MProto::folder, mob_table->szFolder); VERIFY_IFIELD(MProto::on_click, mob_table->bOnClickType); VERIFY_IFIELD(MProto::st, mob_table->bStr); VERIFY_IFIELD(MProto::dx, mob_table->bDex); VERIFY_IFIELD(MProto::ht, mob_table->bCon); VERIFY_IFIELD(MProto::iq, mob_table->bInt); VERIFY_IFIELD(MProto::damage_min, mob_table->dwDamageRange[0]); VERIFY_IFIELD(MProto::damage_max, mob_table->dwDamageRange[1]); VERIFY_IFIELD(MProto::max_hp, mob_table->dwMaxHP); VERIFY_IFIELD(MProto::regen_cycle, mob_table->bRegenCycle); VERIFY_IFIELD(MProto::regen_percent, mob_table->bRegenPercent); VERIFY_IFIELD(MProto::gold_min, mob_table->dwGoldMin); VERIFY_IFIELD(MProto::gold_max, mob_table->dwGoldMax); VERIFY_IFIELD(MProto::exp, mob_table->dwExp); VERIFY_IFIELD(MProto::def, mob_table->wDef); VERIFY_IFIELD(MProto::attack_speed, mob_table->sAttackSpeed); VERIFY_IFIELD(MProto::move_speed, mob_table->sMovingSpeed); VERIFY_IFIELD(MProto::aggressive_hp_pct,mob_table->bAggresiveHPPct); VERIFY_IFIELD(MProto::aggressive_sight, mob_table->wAggressiveSight); VERIFY_IFIELD(MProto::attack_range, mob_table->wAttackRange); VERIFY_IFIELD(MProto::drop_item, mob_table->dwDropItemVnum); VERIFY_IFIELD(MProto::resurrection_vnum,mob_table->dwResurrectionVnum); // ## ENCHANT 6 VERIFY_IFIELD(MProto::enchant_curse, mob_table->cEnchants[MOB_ENCHANT_CURSE]); VERIFY_IFIELD(MProto::enchant_slow, mob_table->cEnchants[MOB_ENCHANT_SLOW]); VERIFY_IFIELD(MProto::enchant_poison, mob_table->cEnchants[MOB_ENCHANT_POISON]); VERIFY_IFIELD(MProto::enchant_stun, mob_table->cEnchants[MOB_ENCHANT_STUN]); VERIFY_IFIELD(MProto::enchant_critical, mob_table->cEnchants[MOB_ENCHANT_CRITICAL]); VERIFY_IFIELD(MProto::enchant_penetrate,mob_table->cEnchants[MOB_ENCHANT_PENETRATE]); #if defined(ENABLE_WOLFMAN_CHARACTER) && !defined(USE_MOB_BLEEDING_AS_POISON) VERIFY_IFIELD(MProto::enchant_bleeding, mob_table->cEnchants[MOB_ENCHANT_BLEEDING]); #endif // ## RESIST 11 VERIFY_IFIELD(MProto::resist_sword, mob_table->cResists[MOB_RESIST_SWORD]); VERIFY_IFIELD(MProto::resist_twohand, mob_table->cResists[MOB_RESIST_TWOHAND]); VERIFY_IFIELD(MProto::resist_dagger, mob_table->cResists[MOB_RESIST_DAGGER]); VERIFY_IFIELD(MProto::resist_bell, mob_table->cResists[MOB_RESIST_BELL]); VERIFY_IFIELD(MProto::resist_fan, mob_table->cResists[MOB_RESIST_FAN]); VERIFY_IFIELD(MProto::resist_bow, mob_table->cResists[MOB_RESIST_BOW]); VERIFY_IFIELD(MProto::resist_fire, mob_table->cResists[MOB_RESIST_FIRE]); VERIFY_IFIELD(MProto::resist_elect, mob_table->cResists[MOB_RESIST_ELECT]); VERIFY_IFIELD(MProto::resist_magic, mob_table->cResists[MOB_RESIST_MAGIC]); VERIFY_IFIELD(MProto::resist_wind, mob_table->cResists[MOB_RESIST_WIND]); VERIFY_IFIELD(MProto::resist_poison, mob_table->cResists[MOB_RESIST_POISON]); #if defined(ENABLE_WOLFMAN_CHARACTER) && !defined(USE_MOB_CLAW_AS_DAGGER) VERIFY_IFIELD(MProto::resist_claw, mob_table->cResists[MOB_RESIST_CLAW]); #endif #if defined(ENABLE_WOLFMAN_CHARACTER) && !defined(USE_MOB_BLEEDING_AS_POISON) VERIFY_IFIELD(MProto::resist_bleeding, mob_table->cResists[MOB_RESIST_BLEEDING]); #endif // ## OTHERS #2 VERIFY_IFIELD(MProto::dam_multiply, mob_table->fDamMultiply); VERIFY_IFIELD(MProto::summon, mob_table->dwSummonVnum); VERIFY_IFIELD(MProto::drain_sp, mob_table->dwDrainSP); VERIFY_IFIELD(MProto::polymorph_item, mob_table->dwPolymorphItemVnum); VERIFY_IFIELD(MProto::skill_vnum0, mob_table->Skills[0].dwVnum); VERIFY_IFIELD(MProto::skill_level0, mob_table->Skills[0].bLevel); VERIFY_IFIELD(MProto::skill_vnum1, mob_table->Skills[1].dwVnum); VERIFY_IFIELD(MProto::skill_level1, mob_table->Skills[1].bLevel); VERIFY_IFIELD(MProto::skill_vnum2, mob_table->Skills[2].dwVnum); VERIFY_IFIELD(MProto::skill_level2, mob_table->Skills[2].bLevel); VERIFY_IFIELD(MProto::skill_vnum3, mob_table->Skills[3].dwVnum); VERIFY_IFIELD(MProto::skill_level3, mob_table->Skills[3].bLevel); VERIFY_IFIELD(MProto::skill_vnum4, mob_table->Skills[4].dwVnum); VERIFY_IFIELD(MProto::skill_level4, mob_table->Skills[4].bLevel); // ## SPECIAL VERIFY_IFIELD(MProto::sp_berserk, mob_table->bBerserkPoint); VERIFY_IFIELD(MProto::sp_stoneskin, mob_table->bStoneSkinPoint); VERIFY_IFIELD(MProto::sp_godspeed, mob_table->bGodSpeedPoint); VERIFY_IFIELD(MProto::sp_deathblow, mob_table->bDeathBlowPoint); VERIFY_IFIELD(MProto::sp_revive, mob_table->bRevivePoint); sys_log(0, "MOB #%-5d %-24s %-24s level: %-3u rank: %u empire: %d", mob_table->dwVnum, mob_table->szName, mob_table->szLocaleName, mob_table->bLevel, mob_table->bRank, mob_table->bEmpire ); ++mob_table; } sort(m_vec_mobTable.begin(), m_vec_mobTable.end(), FCompareVnum()); fprintf(stdout, "Complete! %u Mobs loaded.\n", addNumber); return true; } #define ENABLE_AUTODETECT_VNUMRANGE namespace IProto { enum IProtoT { vnum, type, subtype, name, locale_name, gold, shop_buy_price, weight, size, flag, wearflag, antiflag, immuneflag, refined_vnum, refine_set, magic_pct, socket_pct, addon_type, limittype0, limitvalue0, limittype1, limitvalue1, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, value0, value1, value2, value3, value4, value5 #if !defined(ENABLE_AUTODETECT_VNUMRANGE) , vnum_range #endif }; } bool CClientManager::InitializeItemTableFromDB() { char query[2048]; fprintf(stdout, "Loading item_proto from MySQL\n"); snprintf(query, sizeof(query), "SELECT vnum, type, subtype, name, %s, gold, shop_buy_price, weight, size," " flag, wearflag, antiflag, immuneflag+0, refined_vnum, refine_set, magic_pct," " socket_pct, addon_type, limittype0, limitvalue0, limittype1, limitvalue1," " applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2," " value0, value1, value2, value3, value4, value5" #if !defined(ENABLE_AUTODETECT_VNUMRANGE) " , vnum_range" #endif " FROM item_proto%s ORDER BY vnum;", g_stLocaleNameColumn.c_str(), GetTablePostfix() ); std::unique_ptr<SQLMsg> pkMsg(CDBManager::instance().DirectQuery(query)); SQLResult * pRes = pkMsg->Get(); DWORD addNumber = pRes->uiNumRows; if (addNumber == 0) return false; if (!m_vec_itemTable.empty()) { sys_log(0, "RELOAD: item_proto"); m_vec_itemTable.clear(); m_map_itemTableByVnum.clear(); } m_vec_itemTable.resize(addNumber); memset(&m_vec_itemTable[0], 0, sizeof(TItemTable) * m_vec_itemTable.size()); TItemTable * item_table = &m_vec_itemTable[0]; MYSQL_ROW data = NULL; while ((data = mysql_fetch_row(pRes->pSQLResult))) { // check whether or not the field is NULL or that contains an empty string // ## GENERAL VERIFY_IFIELD(IProto::vnum, item_table->dwVnum); VERIFY_SFIELD(IProto::name, item_table->szName); VERIFY_SFIELD(IProto::locale_name, item_table->szLocaleName); VERIFY_IFIELD(IProto::type, item_table->bType); VERIFY_IFIELD(IProto::subtype, item_table->bSubType); VERIFY_IFIELD(IProto::weight, item_table->bWeight); VERIFY_IFIELD(IProto::size, item_table->bSize); VERIFY_IFIELD(IProto::antiflag, item_table->dwAntiFlags); VERIFY_IFIELD(IProto::flag, item_table->dwFlags); VERIFY_IFIELD(IProto::wearflag, item_table->dwWearFlags); VERIFY_IFIELD(IProto::immuneflag, item_table->dwImmuneFlag); VERIFY_IFIELD(IProto::gold, item_table->dwGold); VERIFY_IFIELD(IProto::shop_buy_price, item_table->dwShopBuyPrice); VERIFY_IFIELD(IProto::refined_vnum, item_table->dwRefinedVnum); VERIFY_IFIELD(IProto::refine_set, item_table->wRefineSet); VERIFY_IFIELD(IProto::magic_pct, item_table->bAlterToMagicItemPct); // ## LIMIT item_table->cLimitRealTimeFirstUseIndex = -1; item_table->cLimitTimerBasedOnWearIndex = -1; VERIFY_IFIELD(IProto::limittype0, item_table->aLimits[0].bType); VERIFY_IFIELD(IProto::limitvalue0, item_table->aLimits[0].lValue); if (LIMIT_REAL_TIME_START_FIRST_USE == item_table->aLimits[0].bType) item_table->cLimitRealTimeFirstUseIndex = 0; else if (LIMIT_TIMER_BASED_ON_WEAR == item_table->aLimits[0].bType) item_table->cLimitTimerBasedOnWearIndex = 0; VERIFY_IFIELD(IProto::limittype1, item_table->aLimits[1].bType); VERIFY_IFIELD(IProto::limitvalue1, item_table->aLimits[1].lValue); if (LIMIT_REAL_TIME_START_FIRST_USE == item_table->aLimits[1].bType) item_table->cLimitRealTimeFirstUseIndex = 1; else if (LIMIT_TIMER_BASED_ON_WEAR == item_table->aLimits[1].bType) item_table->cLimitTimerBasedOnWearIndex = 1; if ((LIMIT_NONE!=item_table->aLimits[0].bType) && // just checking the first limit one is enough (item_table->aLimits[0].bType == item_table->aLimits[1].bType)) sys_log(0, "vnum(%u): limittype0(%u)==limittype1(%u)", item_table->dwVnum, item_table->aLimits[0].bType, item_table->aLimits[1].bType); // @warme012 // ## APPLY VERIFY_IFIELD(IProto::applytype0, item_table->aApplies[0].bType); VERIFY_IFIELD(IProto::applyvalue0, item_table->aApplies[0].lValue); VERIFY_IFIELD(IProto::applytype1, item_table->aApplies[1].bType); VERIFY_IFIELD(IProto::applyvalue1, item_table->aApplies[1].lValue); VERIFY_IFIELD(IProto::applytype2, item_table->aApplies[2].bType); VERIFY_IFIELD(IProto::applyvalue2, item_table->aApplies[2].lValue); // ## VALUE VERIFY_IFIELD(IProto::value0, item_table->alValues[0]); VERIFY_IFIELD(IProto::value1, item_table->alValues[1]); VERIFY_IFIELD(IProto::value2, item_table->alValues[2]); VERIFY_IFIELD(IProto::value3, item_table->alValues[3]); VERIFY_IFIELD(IProto::value4, item_table->alValues[4]); VERIFY_IFIELD(IProto::value5, item_table->alValues[5]); VERIFY_IFIELD(IProto::socket_pct, item_table->bGainSocketPct); VERIFY_IFIELD(IProto::addon_type, item_table->sAddonType); #if !defined(ENABLE_AUTODETECT_VNUMRANGE) VERIFY_IFIELD(IProto::vnum_range, item_table->dwVnumRange); #else if (item_table->bType==ITEM_DS) item_table->dwVnumRange = 99; #endif m_map_itemTableByVnum.insert(std::map<DWORD, TItemTable *>::value_type(item_table->dwVnum, item_table)); sys_log(0, "ITEM: #%-5lu %-24s %-24s VAL: %d %ld %d %d %d %d WEAR %d ANTI %d IMMUNE %d REFINE %lu REFINE_SET %u MAGIC_PCT %u", item_table->dwVnum, item_table->szName, item_table->szLocaleName, item_table->alValues[0], item_table->alValues[1], item_table->alValues[2], item_table->alValues[3], item_table->alValues[4], item_table->alValues[5], item_table->dwWearFlags, item_table->dwAntiFlags, item_table->dwImmuneFlag, item_table->dwRefinedVnum, item_table->wRefineSet, item_table->bAlterToMagicItemPct ); item_table++; } sort(m_vec_itemTable.begin(), m_vec_itemTable.end(), FCompareVnum()); fprintf(stdout, "Complete! %u Items loaded.\n", addNumber); return true; } #endif
  13. System sprawdza przedmioty u gracza i porównuje bonusy z maksymalną wartością atrybutu item_attr. Oznacza to, że jeśli ktoś, na przykład ma średnie obrażenia 3000%, chociaż maksymalnie 50% jest określone w item_attr, zostanie to zarejestrowane w bazie danych. Służy do śledzenia graczy korzystających z przedmiotów zbugowanych, a także może służyć do sprawdzania, czy gracze utworzyli przedmioty za pomocą zastrzyków SQL / dostępu do bazy danych. Download: [Hidden Content] Skan Virustotal: [Hidden Content]
  14. Dzień Dobry, Problem jest taki, że można zapchać bazę pewnym dziadostwem. Dokładniej dodawaniem i usuwaniem "komentarzy" gildyjnych wiecie tam co można pisać. Fix dodaje cooldown do owych funkcji przez co nie będzie można spamować dodawaniem i usuwaniem komentarzy. Wchodzimy w guild.cpp szukamy: void CGuild::AddComment(LPCHARACTER ch, const std::string& str) Następnie kod niżej if (str.length() > GUILD_COMMENT_MAX_LEN) return; char text[GUILD_COMMENT_MAX_LEN * 2 + 1]; DBManager::instance().EscapeString(text, sizeof(text), str.c_str(), str.length()); DBManager::instance().FuncAfterQuery(std::bind(&CGuild::RefreshCommentForce,this, ch->GetPlayerID()), "INSERT INTO guild_comment%s(guild_id, name, notice, content, time) VALUES(%u, '%s', %d, '%s', NOW())", get_table_postfix(), m_data.guild_id, ch->GetName(), (str[0] == '!') ? 1 : 0, text); Zamieniamy na: #ifdef PROTECT_ADDCOMENT_GUILD_EXPLOIT if (str.length() > GUILD_COMMENT_MAX_LEN || str.length() == 0) return; if (m_guildPostCommentPulse > thecore_pulse()) { int deltaInSeconds = ((m_guildPostCommentPulse / PASSES_PER_SEC(1)) - (thecore_pulse() / PASSES_PER_SEC(1))); int minutes = deltaInSeconds / 60; int seconds = (deltaInSeconds - (minutes * 60)); ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT ("Poczekaj: %02d minut i %02d sekund!"), minutes, seconds); return; } char szQuery[1024]; snprintf(szQuery, sizeof(szQuery), "SELECT COUNT(*) FROM guild_comment WHERE guild_id = %d", m_data.guild_id); std::unique_ptr<SQLMsg> commentCount(DBManager::instance().DirectQuery(szQuery)); MYSQL_ROW GetResult = mysql_fetch_row(commentCount->Get()->pSQLResult); int iComments = 0; str_to_number(iComments, GetResult[0]); if (iComments >= MAX_GUILD_COMMENTS) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You have reached the limit of 10 comments. Delete a comment to continue.")); return; } char text[GUILD_COMMENT_MAX_LEN * 2 + 1]; DBManager::instance().EscapeString(text, sizeof(text), str.c_str(), str.length()); DBManager::instance().FuncAfterQuery(std::bind(&CGuild::RefreshCommentForce,this, ch->GetPlayerID()), "INSERT INTO guild_comment%s(guild_id, name, notice, content, time) VALUES(%u, '%s', %d, '%s', NOW())", get_table_postfix(), m_data.guild_id, ch->GetName(), (str[0] == '!') ? 1 : 0, text); m_guildPostCommentPulse = thecore_pulse() + PASSES_PER_SEC(5*60); // Komentarze można dodawać co 5 minut. #else if (str.length() > GUILD_COMMENT_MAX_LEN) return; char text[GUILD_COMMENT_MAX_LEN * 2 + 1]; DBManager::instance().EscapeString(text, sizeof(text), str.c_str(), str.length()); DBManager::instance().FuncAfterQuery(std::bind(&CGuild::RefreshCommentForce,this, ch->GetPlayerID()), "INSERT INTO guild_comment%s(guild_id, name, notice, content, time) VALUES(%u, '%s', %d, '%s', NOW())", get_table_postfix(), m_data.guild_id, ch->GetName(), (str[0] == '!') ? 1 : 0, text); #endif Szukaj: void CGuild::DeleteComment(LPCHARACTER ch, DWORD comment_id) Zamień cały na: void CGuild::DeleteComment(LPCHARACTER ch, DWORD comment_id) { #ifdef PROTECT_ADDCOMENT_GUILD_EXPLOIT if (m_guildPostCommentRemovePulse > thecore_pulse()) { int deltaInSeconds = ((m_guildPostCommentPulse / PASSES_PER_SEC(1)) - (thecore_pulse() / PASSES_PER_SEC(1))); int minutes = deltaInSeconds / 60; int seconds = (deltaInSeconds - (minutes * 60)); ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT ("Poczekaj: %02d minut i %02d sekund!"), minutes, seconds); return; } #endif SQLMsg * pmsg; if (GetMember(ch->GetPlayerID())->grade == GUILD_LEADER_GRADE) pmsg = DBManager::instance().DirectQuery("DELETE FROM guild_comment%s WHERE id = %u AND guild_id = %u",get_table_postfix(), comment_id, m_data.guild_id); else pmsg = DBManager::instance().DirectQuery("DELETE FROM guild_comment%s WHERE id = %u AND guild_id = %u AND name = '%s'",get_table_postfix(), comment_id, m_data.guild_id, ch->GetName()); if (pmsg->Get()->uiAffectedRows == 0 || pmsg->Get()->uiAffectedRows == (uint32_t)-1) ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±ćµĺ> »čÁ¦ÇŇ Ľö ľř´Â ±ŰŔÔ´Ď´Ů.")); else RefreshCommentForce(ch->GetPlayerID()); M2_DELETE(pmsg); #ifdef PROTECT_ADDCOMENT_GUILD_EXPLOIT m_guildPostCommentRemovePulse = thecore_pulse() + PASSES_PER_SEC(5*60); // komentarze można usuwać co 5 minut #endif } Wejdź w guild.h Pod: EventMap m_GuildInviteEventMap; Dodaj: #ifdef PROTECT_ADDCOMENT_GUILD_EXPLOIT protected: int m_guildPostCommentPulse; int m_guildPostCommentRemovePulse; #endif w service.h dodaj: #define PROTECT_ADDCOMENT_GUILD_EXPLOIT #ifdef PROTECT_ADDCOMENT_GUILD_EXPLOIT #define MAX_GUILD_COMMENTS 10 // Ustaw limit komentarzy dodawanych w gildii. #endif w locale_string dodaj: "Poczekaj: %02d minut i %02d sekund!"; "Poczekaj: %02d minut i %02d sekund!"; "You have reached the limit of 10 comments. Delete a comment to continue."; "Nie możesz dodać więcej niż 10 komentarzy."; Wiem, że to locale_string to mistrzostwo tylko jak ktoś robi sobie kolorki to po prostu tak dodałem Dziękuje @Kreton
  15. Dzięki tej zmianie spowolnienie zmniejsza prędkość ataku i staje się istotnym bonusem (a także odpornym na spowolnienie), również prędkość ruchu jest niższa niż wcześniej. Uwaga: Aby zmienić wartość, o jaką zmniejsza się prędkość ataku / ruchu i czasu ich trwania, zmień linie AddAffect. Przykład: pkVictim->AddAffect(AFFECT_SLOW_AS, POINT_ATT_SPEED, -40, AFF_SLOW_AS, 10, 0, true); -40 -> - 40 prędkości ataku, 10 -> 10 sekund Bonus spowolnienia zmniejszyło prędkość ruchu o 30, w tej wersji ustawiłem 50. Co należy zrobić? Binka/UserInterface/InstanceBase.h Znajdź: AFFECT_NUM = 64, Dodaj na górze: AFFECT_SLOW_AS = 45, Znajdź: NEW_AFFECT_BOW_DISTANCE, Dodaj pod: NEW_AFFECT_SLOW_AS = 227, PythonCharacterModule.cpp: Znajdź: PyModule_AddIntConstant(poModule, "AFFECT_SLOW", CInstanceBase::AFFECT_SLOW); Dodaj pod: PyModule_AddIntConstant(poModule, "AFFECT_SLOW_AS", CInstanceBase::AFFECT_SLOW_AS); game/src/affect.h - Znajdź: AFFECT_DEF_GRADE, Dodaj pod: AFFECT_SLOW_AS = 227, Znajdź: AFF_BITS_MAX Dodaj powyżej: AFF_SLOW_AS=45, battle.cpp - Znajdź: AttackAffect(pkAttacker, pkVictim, POINT_SLOW_PCT, IMMUNE_SLOW, AFFECT_SLOW, POINT_MOV_SPEED, -30, AFF_SLOW, 20, "SLOW"); Zamień: if (pkAttacker->GetPoint(POINT_SLOW_PCT) && !pkVictim->IsAffectFlag(AFF_SLOW)) { if (number(1, 100) <= pkAttacker->GetPoint(POINT_SLOW_PCT) && !pkVictim->IsImmune(IMMUNE_SLOW)) { pkVictim->AddAffect(AFFECT_SLOW, POINT_MOV_SPEED, -50, AFF_SLOW, 10, 0, true); pkVictim->AddAffect(AFFECT_SLOW_AS, POINT_ATT_SPEED, -40, AFF_SLOW_AS, 10, 0, true); } } char_affect.cpp - Znajdź: RemoveAffect(AFFECT_SLOW); Dodaj pod: RemoveAffect(AFFECT_SLOW_AS); char_skill.cpp - Znajdź: else if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_SLOW)) Zastąp zawartość: { if (iPct && !pkChrVictim->IsAffectFlag(AFF_SLOW)) { if (number(1, 1000) <= iPct && !pkChrVictim->IsImmune(IMMUNE_SLOW)) { pkChrVictim->AddAffect(AFFECT_SLOW, POINT_MOV_SPEED, -50, AFF_SLOW, 10, 0, true); pkChrVictim->AddAffect(AFFECT_SLOW_AS, POINT_ATT_SPEED, -40, AFF_SLOW_AS, 10, 0, true); } } }
  16. Wejdź w char_item.cpp Znajdź: bool CHARACTER::UseItem(TItemPos Cell, TItemPos DestCell) { WORD wCell = Cell.cell; BYTE window_type = Cell.window_type; //WORD wDestCell = DestCell.cell; //BYTE bDestInven = DestCell.window_type; LPITEM item; if (!CanHandleItem()) return false; if (!IsValidItemPosition(Cell) || !(item = GetItem(Cell))) return false; sys_log(0, "%s: USE_ITEM %s (inven %d, cell: %d)", GetName(), item->GetName(), window_type, wCell); if (item->IsExchanging()) return false; if (!item->CanUsedBy(this)) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("±şÁ÷ŔĚ ¸ÂÁöľĘľĆ ŔĚ ľĆŔĚĹŰŔ» »çżëÇŇ Ľö ľř˝Ŕ´Ď´Ů.")); return false; } if (IsStun()) return false; if (false == FN_check_item_sex(this, item)) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Ľşş°ŔĚ ¸ÂÁöľĘľĆ ŔĚ ľĆŔĚĹŰŔ» »çżëÇŇ Ľö ľř˝Ŕ´Ď´Ů.")); return false; } Dodaj pod: if (((item->GetVnum() >= 50801 && item->GetVnum() <= 50826) || // Rosy i Wody (item->GetVnum() >= 39017 && item->GetVnum() <= 39022) || // Atak, Inteligencja (item->GetVnum() >= 39024 && item->GetVnum() <= 39025)) && ((get_dword_time()-m_dwPlayStartTime) < 5000)) // Krytyk Szycie return false;
  17. Pewnie wielu ma ten problem ze zbrojami z pangeya że nie mają twarzy, dziś pokaże jak zrobić te śmieszne twarze Jeśli model nie ma twarzy to dopisujemy: Head "face.gr2" Gdzie face.gr2 to nazwa naszego modelu z ryjcem Poradnik w spoilerze lul GameLib
  18. ## This guide for those who have worked incorrectly banword... All written words will be converted to upper case and will be compared with words from the database. For example: 'Hello, fagots' -> 'HELLO, FAGOTS' -> 'HELLO, ******' -> 'Hello, ******' Don't forgot "/reload" ## Good luck. banword.zip
  19. Wesołych świąt! Otwórz battle.cpp i znajdź: int battle_melee_attack(LPCHARACTER ch, LPCHARACTER victim) { Dodaj pod: if(ch->IsPC()) { const bool bAttacking = (get_dword_time() - ch->GetLastAttackTime()) < ch->IsRiding() ? 800 : 750; if (!bAttacking) return BATTLE_NONE; //if (test_server&&ch->IsPC()) // ch->ChatPacket(CHAT_TYPE_INFO, "Melee Attack: %d", get_dword_time() - ch->GetLastAttackTime()); if (!battle_distance_valid(ch, victim)) return BATTLE_NONE; } Następnie znajdź: int battle_hit(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, int & iRetDam) { Dodaj pod: if(pkAttacker->IsPC()) { const bool bAttacking = (get_dword_time() - pkAttacker->GetLastAttackTime()) < pkAttacker->IsRiding() ? 800 : 750; if (!bAttacking) return BATTLE_NONE; //if (test_server&&pkAttacker->IsPC()) // pkAttacker->ChatPacket(CHAT_TYPE_INFO, "Melee Attack: %d", get_dword_time() - pkAttacker->GetLastAttackTime()); if (!battle_distance_valid(pkAttacker, pkVictim)) return BATTLE_NONE; }
  20. Ostatnio szukałem sporo na ten temat ale i tak przeniosłem się na nowy source więc w aktualnym momencie dla mnie zbędne ale może komuś się przyda ;D Dzięki temu procesowi utworzymy funkcje debugowania pakietów dla klienta i serwera. common \ service.h: #define ENABLE_SYSLOG_PACKET_SENT game \ src \ desc.cpp: //Znajdź if (m_stRelayName.length() != 0) //Dodaj pod; #ifdef ENABLE_SYSLOG_PACKET_SENT std::string stName = GetCharacter() ? GetCharacter()->GetName() : GetHostName(); sys_log(0, "SENT HEADER : %u to %s (size %d) ", *(static_cast<const BYTE*>(c_pvData)), stName.c_str(), iSize); #endif UserInterface \ Locale_inc.h: //Dodaj; #define ENABLE_SYSLOG_PACKET_SENT UserInterface \ PythonNetworkStreamPhaseGame.cpp: //Znajdź if (!CheckPacket(&header)) break; //Dodaj pod; #ifdef ENABLE_SYSLOG_PACKET_SENT Tracenf("RECV HEADER : %u , phase %s ", header, m_strPhase.c_str()); #endif UserInterface \ PythonNetworkStreamPhaseHandShake.cpp: //Znajdź if (!CheckPacket(&header)) return; //Dodaj pod #ifdef ENABLE_SYSLOG_PACKET_SENT Tracenf("RECV HEADER : %u , phase %s ", header, m_strPhase.c_str()); #endif UserInterface \ PythonNetworkStreamPhaseLoading.cpp: //Znajdź if (!CheckPacket(&header)) return; //Dodaj pod #ifdef ENABLE_SYSLOG_PACKET_SENT Tracenf("RECV HEADER : %u , phase %s ", header, m_strPhase.c_str()); #endif UserInterface \ PythonNetworkStreamPhaseLogin.cpp: //Znajdź if (!CheckPacket(&header)) return; //Dodaj pod #ifdef ENABLE_SYSLOG_PACKET_SENT Tracenf("RECV HEADER : %u , phase %s ", header, m_strPhase.c_str()); #endif UserInterface \ PythonNetworkStreamPhaseOffline.cpp: //Znajdź if (!CheckPacket(&header)) return; //Dodaj pod #ifdef ENABLE_SYSLOG_PACKET_SENT Tracenf("RECV HEADER : %u , phase %s ", header, m_strPhase.c_str()); #endif UserInterface \ PythonNetworkStreamPhaseSelect.cpp: //Znajdź if (!CheckPacket(&header)) return; //Dodaj pod #ifdef ENABLE_SYSLOG_PACKET_SENT Tracenf("RECV HEADER : %u , phase %s ", header, m_strPhase.c_str()); #endif
  21. Pokaże Wam jak zablokować: Wyjmowanie Kamieni Dusz z założonych przedmiotów. Zmienianie bonusów na założonych przedmiotach. Wkładanie Kamieni Dusz do Strzały. Wkładanie 6/7 Bon do kostiumów i przedmiotów ślubnych. Wyjmowanie Kamieni Dusz z założonych przedmiotów. Zmienianie bonusów na założonych przedmiotach. Wkładanie Kamieni Dusz do Strzały. Wkładanie bonusów 6/7 do kostiumów i przedmiotów ślubnych. Wejdź do pliku char_item.cpp w /game/src/ Znajdź: case 71051 Pod: if (item2->IsExchanging() == true) return false; Dodaj: if (item2->IsEquipped()) return false; if (item2->GetType() == ITEM_COSTUME) return false; if ((item2->GetVnum() >= 11901 && item2->GetVnum() <= 11914) && (item2->GetVnum() >= 50201 && item2->GetVnum() <= 50202)) return false; Znajdź case 71052 Pod: if (item2->IsExchanging() == true) return false; Dodaj: if (item2->IsEquipped()) return false; Kompilujemy Game&DB Pozdrawiam * To tylko przedsmak tego co dla Was przygotowałem proszę daj + by zmotywować mnie do dalszego działania.
  22. UWAGA! Możliwość wklejania tekstu ułatwia zadanie spamerą i innym oszustom, miej to pod uwagą. Pokaże wam, jak dodać możliwość wklejania skopiowanego tekstu za pomocą skrótu klawiaturowego CTRL+V 01: Otwieramy IME.cpp (source binki client/EterLib) i szukamy tego: m_bEnablePaste = false; I zmieniamy na to: m_bEnablePaste = true; Szukamy tego: { if (m_bOnlyNumberMode) if (!iswdigit(c)) return; if (!__IsWritable(c)) return; InsertString(&c, 1); } I zmieniamy na to: { if (m_bOnlyNumberMode) if (!iswdigit(c)) return; if (c == 0x16) return; InsertString(&c, 1); } Szukamy tego: HANDLE handle = GetClipboardData(CF_TEXT); char * buffer = (char*)GlobalLock(handle); I zmieniamy na to: HANDLE handle = GetClipboardData(CF_TEXT); if (!handle) return; char * buffer = (char*)GlobalLock(handle); if (!buffer) return; 02: Tego punktu nie muszą wykonywać osoby, które mają pliki z pod filmów paszki. Otwieramy ui.py (client gry pack/root) i szukamy tego: def OnKeyDown(self, key): if app.DIK_F1 == key: return False if app.DIK_F2 == key: return False if app.DIK_F3 == key: return False if app.DIK_F4 == key: return False if app.DIK_LALT == key: return False if app.DIK_SYSRQ == key: return False if app.DIK_LCONTROL == key: return False I pod tym dodajemy to: if app.DIK_V == key: if app.IsPressed(app.DIK_LCONTROL): ime.PasteTextFromClipBoard() Zapisujemy pliki, kompilujemy i gotowe.
  23. Siema, zaebane z niemieckiego forum, wygląda całkiem obiecująco i może komuś sie przyda do walki z botami dodam od siebie tylko ze latwo mozna na to obejscie zrobic (focusowanie okna podczas wykonywania akcji) Kod działa tak, że pakiety akcji ruchu można wysyłać jedynie wtedy gdy okno jest zfocusowane Tak to wygląda: [Hidden Content] PythonNetworkStreamPhaseGame.cpp Szukasz > bool CPythonNetworkStream::SendCharacterStatePacket(const TPixelPosition& c_rkPPosDst, float fDstRot, UINT eFunc, UINT uArg) { NANOBEGIN if (!__CanActMainInstance()) return true; Podmieniasz na: struct handle_data { unsigned long process_id; HWND window_handle; }; BOOL is_main_window(HWND handle) { return ((GetWindow(handle, GW_OWNER) == (HWND)0) && (IsWindowVisible(handle))); } BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lParam) { handle_data& data = *(handle_data*)lParam; unsigned long process_id = 0; GetWindowThreadProcessId(handle, &process_id); if (data.process_id != process_id) return TRUE; if (!is_main_window(handle)) return TRUE; auto s = GetWindowLong(handle, GWL_STYLE); if (!(s & WS_VISIBLE)) return TRUE; data.window_handle = handle; return FALSE; } HWND find_main_window(unsigned long process_id) { handle_data data; data.process_id = process_id; data.window_handle = 0; EnumWindows(enum_windows_callback, (LPARAM)&data); if (data.window_handle != 0) { if (IsWindowVisible(data.window_handle)) { return data.window_handle; } } return 0; } bool CPythonNetworkStream::SendCharacterStatePacket(const TPixelPosition& c_rkPPosDst, float fDstRot, UINT eFunc, UINT uArg) { NANOBEGIN if (!__CanActMainInstance()) return true; if (GetActiveWindow() != find_main_window(GetCurrentProcessId())) return true; Ogólnie kod mozna zaadaptować dowolnie względem tego jaki pakiet chcemy zablokować, wystarczy w danym handlerze wrzucić to: if (GetActiveWindow() != find_main_window(GetCurrentProcessId())) return true; uwu
  24. Krótko mówiąc nowa funkcja w c++ która umożliwia blokowanie questa w strefie bezpieczniej [Czyt. safezone] Podgląd: Download: [Hidden Content] Virustotal: [Hidden Content]
  25. O co chodzi? Gdy bijesz metka, potwory wybiegną a ty odbiegniesz i się zatrzymasz no to potwory idą idą, gdy się ruszysz w inne miejsce, te potwory idą tam gdzie stałeś a nie w twoje aktualne miejsce. Wrzucam poprawkę która naprawia ten staro dawny "Błąd" - choć ten błąd może już podchodzić pod uroki metina i starzy gracze mogą się wkurwić że nie będzie można tak zrobić no i będą płakać że padają jak dywany bo moby od razu biegną do nich. Otwieramy plik char_state.cpp Znajdź funkcję: void CHARACTER::StateMove() W tej funkcji przejdź/wyszukaj tego kodu: if (IsMonster() && GetVictim()) { LPCHARACTER victim = GetVictim(); UpdateAggrPoint(victim, DAMAGE_TYPE_NORMAL, -(victim->GetLevel() / 3 + 1)); Dodaj pod tym if (dwElapsedTime > 500) { __CHARACTER_GotoNearTarget(this, victim); }
×
×
  • Create New...