Management Karbust 4884 Posted September 2, 2018 Management Share Posted September 2, 2018 Hello, Recently I found a bug, that happens every time I'm either breaking a metin and then get poison from some monster that came from the metin or even a stand alone monster... (we found this bug on metin 8009 (monsters from desert, v2), the monsters give poison and the server crash) Sometimes when I teleport to other maps (if the map is on another core) the server crashs (this if poison is given by a player and not a monster) This is the debug: lldb: root@sv1:/usr/home/game/share/bin # lldb game -c game.core (lldb) target create "game" --core "game.core" Core file '/usr/home/game/share/bin/game.core' (i386) was loaded. (lldb) bt all * thread #1, name = 'game', stop reason = signal SIGSEGV * frame #0: game`CHARACTER::Damage(this=0x469f7640, pAttacker=0x00000000, dam=1010, type=DAMAGE_TYPE_POISON) at char_battle.cpp:2121 frame #1: game`long poison_event(event=LPEVENT @ 0x00000008, processing_time=0) at char_resist.cpp:68 frame #2: 0x08490850 game`nBATTLE_ARENA_MAP + 16 thread #2, name = 'game', stop reason = signal SIGSEGV frame #0: 0x2889c8e9 libc.so.7`__umtx_op + 5 frame #1: 0x28888bac libc.so.7`sem_clockwait_np + 236 frame #2: 0x28888c70 libc.so.7`sem_wait + 32 frame #3: 0x0848e4e8 game`CSemaphore::Wait(void) + 24 thread #3, name = 'game', stop reason = signal SIGSEGV frame #0: 0x2889c8e9 libc.so.7`__umtx_op + 5 frame #1: 0x28888bac libc.so.7`sem_clockwait_np + 236 frame #2: 0x28888c70 libc.so.7`sem_wait + 32 frame #3: 0x0848e4e8 game`CSemaphore::Wait(void) + 24 thread #4, name = 'game', stop reason = signal SIGSEGV frame #0: 0x2889c8e9 libc.so.7`__umtx_op + 5 frame #1: 0x28888bac libc.so.7`sem_clockwait_np + 236 frame #2: 0x28888c70 libc.so.7`sem_wait + 32 frame #3: 0x0848e4e8 game`CSemaphore::Wait(void) + 24 (lldb) gdb game.core: root@source:~ # cd /usr/home/game/share/bin root@source:/usr/home/game/share/bin # gdb GNU gdb (GDB) 7.12 [GDB v7.12 for FreeBSD] Copyright (C) 2016 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i386-portbld-freebsd9.3". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word". (gdb) file game Reading symbols from game...done. (gdb) core game.core [New LWP 100257] [New LWP 100259] [New LWP 100260] [New LWP 100264] warning: .dynamic section for "/usr/lib32/libm.so.5" is not at the expected address (wrong library or version mismatch?) warning: .dynamic section for "/usr/lib32/libgcc_s.so.1" is not at the expected address (wrong library or version mismatch?) warning: .dynamic section for "/usr/lib32/libthr.so.3" is not at the expected address (wrong library or version mismatch?) warning: .dynamic section for "/usr/lib32/libc.so.7" is not at the expected address (wrong library or version mismatch?) warning: .dynamic section for "/libexec/ld-elf32.so.1" is not at the expected address (wrong library or version mismatch?) Core was generated by `game'. Program terminated with signal SIGSEGV, Segmentation fault. #0 0x080a7372 in CHARACTER::Damage (this=this@entry=0x5d585fc0, pAttacker=pAttacker@entry=0x0, dam=dam@entry=727, type=type@entry=DAMAGE_TYPE_POISON) at char_battle.cpp:2121 2121 if (IsAffectFlag(AFF_TERROR)) [Current thread is 1 (LWP 100257)] (gdb) bt full #0 0x080a7372 in CHARACTER::Damage (this=this@entry=0x5d585fc0, pAttacker=pAttacker@entry=0x0, dam=dam@entry=727, type=type@entry=DAMAGE_TYPE_POISON) at char_battle.cpp:2121 IsCritical = <optimized out> IsPenetrate = <optimized out> IsDeathBlow = <optimized out> damage_debug = <optimized out> #1 0x080d4337 in poison_event (event=..., processing_time=1) at char_resist.cpp:68 info = 0x5e6ee980 __FUNCTION__ = "poison_event" pkAttacker = 0x0 ch = 0x5d585fc0 dam = 727 #2 0x08142332 in event_process (pulse=pulse@entry=6183) at event.cpp:140 pElem = <optimized out> the_event = {px = 0x5e6f3040} processing_time = 1 new_time = <optimized out> num_events = 0 #3 0x082ed4f9 in heartbeat (ht=0x28c253f0, pulse=6183) at main.cpp:290 t = 268799 #4 0x082eec6a in idle () at main.cpp:1063 pta = {tv_sec = 1535927461, tv_usec = 206} passed_pulses = 0 process_time_count = 19 #5 0x08057d25 in main (argc=1, argv=0xffffde38) at main.cpp:715 title = {<singleton<TitleManager>> = {_vptr.singleton = 0x84d4970 <vtable for TitleManager+8>, static ms_singleton = 0xffffa460}, <No data fields>} lzo_manager = {<singleton<LZOManager>> = {_vptr.singleton = 0x84b18b8 <vtable for LZOManager+8>, static ms_singleton = 0xffffa478}, m_workmem = 0x28c5d700 ""} priv_manager = {<singleton<CPrivManager>> = {_vptr.singleton = 0x84b4a08 <vtable for CPrivManager+8>, static ms_singleton = 0xffffb39c}, m_aakPrivEmpireData = {{{m_value = 0, m_end_time_sec = 0}, {m_value = 0, m_end_time_sec = 0}, {m_value = 0, m_end_time_sec = 0}, {m_value = 0, m_end_time_sec = 0}}, {{m_value = 500, m_end_time_sec = 1536532042}, {m_value = 0, m_end_time_sec = 0}, {m_value = 0, m_end_time_sec = 0}, { m_value = 0, m_end_time_sec = 0}}, {{m_value = 1000, m_end_time_sec = 1536532042}, {m_value = 0, m_end_time_sec = 0}, {m_value = 0, m_end_time_sec = 0}, {m_value = 0, m_end_time_sec = 0}}, {{m_value = 1000, m_end_time_sec = 1536532042}, {m_value = 0, m_end_time_sec = 0}, {m_value = 0, m_end_time_sec = 0}, {m_value = 0, m_end_time_sec = 0}}, {{m_value = 300, m_end_time_sec = 1536532042}, {m_value = 0, m_end_time_sec = 0}, { m_value = 0, m_end_time_sec = 0}, {m_value = 0, m_end_time_sec = 0}}}, m_aPrivGuild = {{_M_t = { _M_impl = {<std::allocator<std::_Rb_tree_node<std::pair<unsigned int const, CPrivManager::SPrivGuildData> > >> = {<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<unsigned int const, CPrivManager::SPrivGuildData> > >> = {<No data fields>}, <No data fields>}, _M_key_compare = {<std::binary_function<unsigned int, unsigned int, bool>> = {<No data fields>}, <No data fields>}, _M_header = {_M_color = std::_S_red, _M_parent = 0x0, _M_left = 0xffffb444, _M_right = 0xffffb444}, _M_node_count = 0}}}, {_M_t = { _M_impl = {<std::allocator<std::_Rb_tree_node<std::pair<unsigned int const, CPrivManager::SPrivGuildData> > >> = {<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<unsigned int const, CPrivManager::SPrivGuildData> > >> = {<No data fields>}, <No data fields>}, _M_key_compare = {<std::binary_function<unsigned int, unsigned int, bool>> = {<No data fields>}, <No data fields>}, _M_header = {_M_color = std::_S_red, _M_parent = 0x0, _M_left = 0xffffb45c, _M_right = 0xffffb45c}, _M_node_count = 0}}}, {_M_t = { _M_impl = {<std::allocator<std::_Rb_tree_node<std::pair<unsigned int const, CPrivManager::SPrivGuildData> > >> = {<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<unsigned int const, CPrivManager::SPrivGuildData> > >> = {<No data fields>}, <No data fields>}, _M_key_compare = {<std::binary_function<unsigned int, unsigned int, bool>> = {<No data fields>}, <No data fields>}, _M_header = {_M_color = std::_S_red, _M_parent = 0x0, _M_left = 0xffffb474, _M_right = 0xffffb474}, _M_node_count = 0}}}, {_M_t = { _M_impl = {<std::allocator<std::_Rb_tree_node<std::pair<unsigned int const, CPrivManager::SPrivGuildData> > >> = {<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<unsigned int const, CPrivManager::SPrivGuildData> > >> = {<No data fields>}, <No data fields>}, _M_key_compare = {<std::binary_function<unsigned int, unsigned int, bool>> = {<No data fields>}, <No data fields>}, _M_header = {_M_color = std::_S_red, _M_parent = 0x0, _M_left = 0xffffb48c, _M_right = 0xffffb48c}, _M_node_count = 0}}}, {_M_t = { _M_impl = {<std::allocator<std::_Rb_tree_node<std::pair<unsigned int const, CPrivManager::SPrivGuildData> > >> = {<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<unsigned int const, CPrivManager::SPrivGuildData> > >> = {<No data fields>}, <No data fields>}, _M_key_compare = {<std::binary_function<unsigned int, unsigned int, bool>> = {<No data fields>}, <No data fields>}, _M_header = {_M_color = std::_S_red, _M_parent = 0x0, _M_left = 0xffffb4a4, _M_right = 0xffffb4a4}, _M_node_count = 0}}}}, m_aPrivChar = {{_M_t = { _M_impl = {<std::allocator<std::_Rb_tree_node<std::pair<unsigned int const, int> > >> = {<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<unsigned int const, int> > >> = {<No data fields>}, <No data fields>}, _M_key_compare = {<std::binary_function<unsigned int, unsigned int, bool>> = {<No data fields>}, <No data fields>}, _M_header = {_M_color = std::_S_red, _M_parent = 0x0, _M_left = 0xffffb4bc, _M_right = 0xffffb4bc}, _M_node_count = 0}}}, {_M_t = { _M_impl = {<std::allocator<std::_Rb_tree_node<std::pair<unsigned int const, int> > >> = {<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<unsigned int const, int> > >> = {<No data fields>}, <No data fields>}, _M_key_compare = {<std::binary_function<unsigned int, unsigned int, bool>> = {<No data fields>}, <No data fields>}, _M_header = {_M_color = std::_S_red, _M_parent = 0x0, _M_left = 0xffffb4d4, _M_right = 0xffffb4d4}, _M_node_count = 0}}}, {_M_t = { _M_impl = {<std::allocator<std::_Rb_tree_node<std::pair<unsigned int const, int> > >> = {<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<unsigned int const, int> > >> = {<No data fields>}, <No data fields>}, _M_key_compare = {<std::binary_function<unsigned int, unsigned int, bool>> = {<No data fields>}, <No data fields>}, _M_header = {_M_color = std::_S_red, _M_parent = 0x0, _M_left = 0xffffb4ec, _M_right = 0xffffb4ec}, _M_node_count = 0}}}, {_M_t = { _M_impl = {<std::allocator<std::_Rb_tree_node<std::pair<unsigned int const, int> > >> = {<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<unsigned int const, int> > >> = {<No data fields>}, <No data fields>}, _M_key_compare = {<std::binary_function<unsigned int, unsigned int, bool>> = {<No data fields>}, <No data fields>}, _M_header = {_M_color = std::_S_red, _M_parent = 0x0, _M_left = 0xffffb504, _M_right = 0xffffb504}, _M_node_count = 0}}}, {_M_t = { _M_impl = {<std::allocator<std::_Rb_tree_node<std::pair<unsigned int const, int> > >> = {<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<unsigned int const, int> > >> = {<No data fields>}, <No data fields>}, _M_key_compare = {<std::binary_function<unsigned int, unsigned int, bool>> = {<No data fields>}, <No data fields>}, _M_header = {_M_color = std::_S_red, _M_parent = 0x0, _M_left = 0xffffb51c, _M_right = 0xffffb51c}, _M_node_count = 0}}}}} spam_mgr = {<singleton<SpamManager>> = {_vptr.singleton = 0x84d9900 <vtable for SpamManager+8>, static ms_singleton = 0xffffa49c}, ---Type <return> to continue, or q <return> to quit---m_vec_word = {<std::_Vector_base<std::pair<std::basic_string<char, std::char_traits<char>, std::alQuit Lines from char_battle.cpp: if (type != DAMAGE_TYPE_NORMAL && type != DAMAGE_TYPE_NORMAL_RANGE) { if (IsAffectFlag(AFF_TERROR)) //THIS IS LINE 2121 { int pct = GetSkillPower(SKILL_TERROR) / 400; if (number(1, 100) <= pct) return false; } } Lines from char_resist.cpp: EVENTFUNC(poison_event) { TPoisonEventInfo * info = dynamic_cast<TPoisonEventInfo *>( event->info ); if ( info == NULL ) { sys_err( "poison_event> <Factor> Null pointer" ); return 0; } LPCHARACTER ch = info->ch; if (ch == NULL) { // <Factor> return 0; } LPCHARACTER pkAttacker = CHARACTER_MANAGER::instance().FindByPID(info->attacker_pid); int dam = ch->GetMaxHP() * GetPoisonDamageRate(ch) / 1000; if (test_server) ch->ChatPacket(CHAT_TYPE_NOTICE, "Poison Damage %d", dam); if (ch->Damage(pkAttacker, dam, DAMAGE_TYPE_POISON)) //THIS IS LINE 68 { ch->m_pkPoisonEvent = NULL; return 0; } --info->count; if (info->count) return PASSES_PER_SEC(3); else { ch->m_pkPoisonEvent = NULL; return 0; } } I've tried comment those lines on char_battle.cpp, but then I got error at line 2057: if (GetRaceNum() == 5001) //THIS IS LINE 2057 { bool bDropMoney = false; int iPercent = (GetHP() * 100) / GetMaxHP(); if (iPercent <= 10 && GetMaxSP() < 5) { SetMaxSP(5); bDropMoney = true; } else if (iPercent <= 20 && GetMaxSP() < 4) { SetMaxSP(4); bDropMoney = true; } else if (iPercent <= 40 && GetMaxSP() < 3) { SetMaxSP(3); bDropMoney = true; } else if (iPercent <= 60 && GetMaxSP() < 2) { SetMaxSP(2); bDropMoney = true; } else if (iPercent <= 80 && GetMaxSP() < 1) { SetMaxSP(1); bDropMoney = true; } if (bDropMoney) { DWORD dwGold = 1000; int iSplitCount = number(10, 13); sys_log(0, "WAEGU DropGoldOnHit %d times", GetMaxSP()); for (int i = 1; i <= iSplitCount; ++i) { PIXEL_POSITION pos; LPITEM item; if ((item = ITEM_MANAGER::instance().CreateItem(1, dwGold / iSplitCount))) { if (i != 0) { pos.x = (number(-14, 14) + number(-14, 14)) * 20; pos.y = (number(-14, 14) + number(-14, 14)) * 20; pos.x += GetX(); pos.y += GetY(); } item->AddToGround(GetMapIndex(), pos); item->StartDestroyEvent(); } } } } Is anyone able to help me? Thank you all Link to comment Share on other sites More sharing options...
Management Karbust 4884 Posted September 5, 2018 Author Management Share Posted September 5, 2018 BUMP Link to comment Share on other sites More sharing options...
Management Karbust 4884 Posted September 23, 2018 Author Management Share Posted September 23, 2018 BUMP Even removing poison (set 0) on every monster it still gives the poison and crashs the server... Link to comment Share on other sites More sharing options...
ridetpro 116 Posted September 23, 2018 Share Posted September 23, 2018 if (type == DAMAGE_TYPE_POISON) { if (GetHP() - dam <= 0) dam = GetHP() - 1; } // char_battle.cpp // REPLACE if (pAttacker and (type == DAMAGE_TYPE_POISON)) { if (GetHP() - dam <= 0) dam = GetHP() - 1; } Try Link to comment Share on other sites More sharing options...
Management Karbust 4884 Posted September 23, 2018 Author Management Share Posted September 23, 2018 1 minute ago, ridetpro said: if (type == DAMAGE_TYPE_POISON) { if (GetHP() - dam <= 0) { dam = GetHP() - 1; } } // char_battle.cpp // REPLACE if (pAttacker and (type == DAMAGE_TYPE_POISON)) { if (GetHP() - dam <= 0) { dam = GetHP() - 1; } } Try I'll test it, meanwhile, I made this in order to remove the poison being loaded on the monsters: void CHARACTER::ApplyMobAttribute(const TMobTable* table) { for (int i = 0; i < MOB_ENCHANTS_MAX_NUM; ++i) { if (table->cEnchants[i] != 0 && table->cEnchants[i] != 2) ApplyPoint(aiMobEnchantApplyIdx[i], table->cEnchants[i]); } for (int i = 0; i < MOB_RESISTS_MAX_NUM; ++i) { if (table->cResists[i] != 0) ApplyPoint(aiMobResistsApplyIdx[i], table->cResists[i]); } } But I don't believe that it's gonna do much, since I already had the poison column filled with 0... I try your way ASAP Link to comment Share on other sites More sharing options...
ridetpro 116 Posted September 23, 2018 Share Posted September 23, 2018 It has nothing to do with monsters. The attacker is NULL, that is the character that tries to attack the monsters. I guess. La 02.09.2018 la 23:16, charparodar a spus: pAttacker=0x00000000 La 02.09.2018 la 23:16, charparodar a spus: pAttacker=pAttacker@entry=0x0 Link to comment Share on other sites More sharing options...
Management Karbust 4884 Posted September 23, 2018 Author Management Share Posted September 23, 2018 4 minutes ago, ridetpro said: It has nothing to do with monsters. The attacker is NULL, that is the character that tries to attack the monsters. I guess. But this is only happen with monsters, if it's given by player it doesn't happen... As soon the player gets the poison the server crashs instantly... If the attacker is NULL, why it doesn't have a check already and crashs? I've compared other game sources and I it didn't have the check either, something must be missing... Link to comment Share on other sites More sharing options...
Management Karbust 4884 Posted September 29, 2018 Author Management Share Posted September 29, 2018 BUMP Monsters aren't crashing the server anymore, but sometimes when players get poison on each other it crashs... # lldb game -c game.core (lldb) target create "game" --core "game.core" Core file '/usr/home/game/cores/channel1/game1/game.core' (i386) was loaded. (lldb) bt all * thread #1, name = 'game', stop reason = signal SIGSEGV * frame #0: game`CHARACTER::Damage(this=0x3eb47840, pAttacker=0x00000000, dam=<unavailable>, type=DAMAGE_TYPE_POISON) at char_battle.cpp:2121 frame #1: game`long poison_event(event=LPEVENT @ 0x00000008, processing_time=0) at char_resist.cpp:68 frame #2: 0x08491210 game`nBATTLE_ARENA_MAP + 16 thread #2, name = 'game', stop reason = signal SIGSEGV frame #0: 0x2889d8e9 libc.so.7`__umtx_op + 5 frame #1: 0x28889bac libc.so.7`sem_clockwait_np + 236 frame #2: 0x28889c70 libc.so.7`sem_wait + 32 frame #3: 0x0848ee98 game`CSemaphore::Wait(void) + 24 thread #3, name = 'game', stop reason = signal SIGSEGV frame #0: 0x2889d8e9 libc.so.7`__umtx_op + 5 frame #1: 0x28889bac libc.so.7`sem_clockwait_np + 236 frame #2: 0x28889c70 libc.so.7`sem_wait + 32 frame #3: 0x0848ee98 game`CSemaphore::Wait(void) + 24 thread #4, name = 'game', stop reason = signal SIGSEGV frame #0: 0x2889d8e9 libc.so.7`__umtx_op + 5 frame #1: 0x28889bac libc.so.7`sem_clockwait_np + 236 frame #2: 0x28889c70 libc.so.7`sem_wait + 32 frame #3: 0x0848ee98 game`CSemaphore::Wait(void) + 24 (lldb) Link to comment Share on other sites More sharing options...
ridetpro 116 Posted September 29, 2018 Share Posted September 29, 2018 Acum 5 ore, charparodar a spus: BUMP Monsters aren't crashing the server anymore, but sometimes when players get poison on each other it crashs... # lldb game -c game.core (lldb) target create "game" --core "game.core" Core file '/usr/home/game/cores/channel1/game1/game.core' (i386) was loaded. (lldb) bt all * thread #1, name = 'game', stop reason = signal SIGSEGV * frame #0: game`CHARACTER::Damage(this=0x3eb47840, pAttacker=0x00000000, dam=<unavailable>, type=DAMAGE_TYPE_POISON) at char_battle.cpp:2121 frame #1: game`long poison_event(event=LPEVENT @ 0x00000008, processing_time=0) at char_resist.cpp:68 frame #2: 0x08491210 game`nBATTLE_ARENA_MAP + 16 thread #2, name = 'game', stop reason = signal SIGSEGV frame #0: 0x2889d8e9 libc.so.7`__umtx_op + 5 frame #1: 0x28889bac libc.so.7`sem_clockwait_np + 236 frame #2: 0x28889c70 libc.so.7`sem_wait + 32 frame #3: 0x0848ee98 game`CSemaphore::Wait(void) + 24 thread #3, name = 'game', stop reason = signal SIGSEGV frame #0: 0x2889d8e9 libc.so.7`__umtx_op + 5 frame #1: 0x28889bac libc.so.7`sem_clockwait_np + 236 frame #2: 0x28889c70 libc.so.7`sem_wait + 32 frame #3: 0x0848ee98 game`CSemaphore::Wait(void) + 24 thread #4, name = 'game', stop reason = signal SIGSEGV frame #0: 0x2889d8e9 libc.so.7`__umtx_op + 5 frame #1: 0x28889bac libc.so.7`sem_clockwait_np + 236 frame #2: 0x28889c70 libc.so.7`sem_wait + 32 frame #3: 0x0848ee98 game`CSemaphore::Wait(void) + 24 (lldb) Pay someone to solve your shitty crash. bool CHARACTER::Damage(LPCHARACTER pAttacker, int dam, EDamageType type) // returns true if dead { if (DAMAGE_TYPE_MAGIC == type) { dam = (int)((float)dam * (100 + (pAttacker->GetPoint(POINT_MAGIC_ATT_BONUS_PER) + pAttacker->GetPoint(POINT_MELEE_MAGIC_ATT_BONUS_PER))) / 100.f + 0.5f); } // With bool CHARACTER::Damage(LPCHARACTER pAttacker, int dam, EDamageType type) { if (pAttacker == NULL) { sys_err("CHARACTER::Damage"); sys_err("pAttacker is null, check your shitty server"); return false; } if (DAMAGE_TYPE_MAGIC == type) { dam = (int)((float)dam * (100 + (pAttacker->GetPoint(POINT_MAGIC_ATT_BONUS_PER) + pAttacker->GetPoint(POINT_MELEE_MAGIC_ATT_BONUS_PER))) / 100.f + 0.5f); } Link to comment Share on other sites More sharing options...
Premium WeedHex 635 Posted September 30, 2018 Premium Share Posted September 30, 2018 Bad using of lua... Link to comment Share on other sites More sharing options...
Management Karbust 4884 Posted September 30, 2018 Author Management Share Posted September 30, 2018 22 hours ago, ridetpro said: Pay someone to solve your shitty crash. bool CHARACTER::Damage(LPCHARACTER pAttacker, int dam, EDamageType type) // returns true if dead { if (DAMAGE_TYPE_MAGIC == type) { dam = (int)((float)dam * (100 + (pAttacker->GetPoint(POINT_MAGIC_ATT_BONUS_PER) + pAttacker->GetPoint(POINT_MELEE_MAGIC_ATT_BONUS_PER))) / 100.f + 0.5f); } // With bool CHARACTER::Damage(LPCHARACTER pAttacker, int dam, EDamageType type) { if (pAttacker == NULL) { sys_err("CHARACTER::Damage"); sys_err("pAttacker is null, check your shitty server"); return false; } if (DAMAGE_TYPE_MAGIC == type) { dam = (int)((float)dam * (100 + (pAttacker->GetPoint(POINT_MAGIC_ATT_BONUS_PER) + pAttacker->GetPoint(POINT_MELEE_MAGIC_ATT_BONUS_PER))) / 100.f + 0.5f); } If I could pay, I would buy marty's source, but, unfortunately I can't, so I stick to my source... Thanks for that, I'll see if the crashs stops... 5 minutes ago, WeedHex said: Bad using of lua... What do you mean about that? Link to comment Share on other sites More sharing options...
Koran 6 Posted April 1 Share Posted April 1 if Battle Pass Extended char_battle.cpp #ifdef ENABLE_EXTENDED_BATTLE_PASS if (type != DAMAGE_TYPE_POISON && type != DAMAGE_TYPE_FIRE) { if (IsPC()) pAttacker->UpdateExtBattlePassMissionProgress(DAMAGE_PLAYER, dam, GetLevel()); else pAttacker->UpdateExtBattlePassMissionProgress(DAMAGE_MONSTER, dam, GetRaceNum()); } #endif Link to comment Share on other sites More sharing options...
Active Member iMerv3 768 Posted April 2 Active Member Share Posted April 2 (edited) Hi, upload char_battle.cpp (or whole Damage func). Nvm is old Edited April 2 by iMerv3 Link to comment Share on other sites More sharing options...
Koran 6 Posted April 2 Share Posted April 2 (edited) 5 hours ago, iMerv3 said: Hi, upload char_battle.cpp (or whole Damage func). Nvm is old Sure, see my CHARACTER::Damage: Spoiler bool CHARACTER::Damage(LPCHARACTER pAttacker, int dam, EDamageType type) // returns true if dead { #ifdef ENABLE_AFK_MODE_SYSTEM if (pAttacker && pAttacker->IsPC() && pAttacker->IsAway()) { if(IsPC()) return false; } #endif if (DAMAGE_TYPE_MAGIC == type) { dam = (int)((float)dam * (100 + (pAttacker->GetPoint(POINT_MAGIC_ATT_BONUS_PER) + pAttacker->GetPoint(POINT_MELEE_MAGIC_ATT_BONUS_PER))) / 100.f + 0.5f); } if (GetRaceNum() == 5001) { bool bDropMoney = false; int iPercent = (GetHP() * 100) / GetMaxHP(); if (iPercent <= 10 && GetMaxSP() < 5) { SetMaxSP(5); bDropMoney = true; } else if (iPercent <= 20 && GetMaxSP() < 4) { SetMaxSP(4); bDropMoney = true; } else if (iPercent <= 40 && GetMaxSP() < 3) { SetMaxSP(3); bDropMoney = true; } else if (iPercent <= 60 && GetMaxSP() < 2) { SetMaxSP(2); bDropMoney = true; } else if (iPercent <= 80 && GetMaxSP() < 1) { SetMaxSP(1); bDropMoney = true; } if (bDropMoney) { DWORD dwGold = 1000; int iSplitCount = number(10, 13); sys_log(0, "WAEGU DropGoldOnHit %d times", GetMaxSP()); for (int i = 1; i <= iSplitCount; ++i) { PIXEL_POSITION pos; LPITEM item; if ((item = ITEM_MANAGER::instance().CreateItem(1, dwGold / iSplitCount))) { if (i != 0) { pos.x = (number(-14, 14) + number(-14, 14)) * 20; pos.y = (number(-14, 14) + number(-14, 14)) * 20; pos.x += GetX(); pos.y += GetY(); } item->AddToGround(GetMapIndex(), pos); item->StartDestroyEvent(); } } } } // 평타가 아닐 때는 공포 처리 if (type != DAMAGE_TYPE_NORMAL && type != DAMAGE_TYPE_NORMAL_RANGE) { if (IsAffectFlag(AFF_TERROR)) { int pct = GetSkillPower(SKILL_TERROR) / 400; if (number(1, 100) <= pct) return false; } } int iCurHP = GetHP(); int iCurSP = GetSP(); bool IsCritical = false; bool IsPenetrate = false; bool IsDeathBlow = false; enum DamageFlag { DAMAGE_NORMAL = (1 << 0), DAMAGE_POISON = (1 << 1), DAMAGE_DODGE = (1 << 2), DAMAGE_BLOCK = (1 << 3), DAMAGE_PENETRATE= (1 << 4), DAMAGE_CRITICAL = (1 << 5), }; //PROF_UNIT puAttr("Attr"); // // 마법형 스킬과, 레인지형 스킬은(궁자객) 크리티컬과, 관통공격 계산을 한다. // 원래는 하지 않아야 하는데 Nerf(다운밸런스)패치를 할 수 없어서 크리티컬과 // 관통공격의 원래 값을 쓰지 않고, /2 이상하여 적용한다. // // 무사 이야기가 많아서 밀리 스킬도 추가 // // 20091109 : 무사가 결과적으로 엄청나게 강해진 것으로 결론남, 독일 기준 무사 비율 70% 육박 // if (type == DAMAGE_TYPE_MELEE || type == DAMAGE_TYPE_RANGE || type == DAMAGE_TYPE_MAGIC) { if (pAttacker) { // 크리티컬 int iCriticalPct = pAttacker->GetPoint(POINT_CRITICAL_PCT); if (!IsPC()) iCriticalPct += pAttacker->GetMarriageBonus(UNIQUE_ITEM_MARRIAGE_CRITICAL_BONUS); if (iCriticalPct) { if (iCriticalPct >= 10) // 10보다 크면 5% + (4마다 1%씩 증가), 따라서 수치가 50이면 20% iCriticalPct = 5 + (iCriticalPct - 10) / 4; else // 10보다 작으면 단순히 반으로 깎음, 10 = 5% iCriticalPct /= 2; //크리티컬 저항 값 적용. iCriticalPct -= GetPoint(POINT_RESIST_CRITICAL); if (number(1, 100) <= iCriticalPct) { IsCritical = true; dam *= 2; EffectPacket(SE_CRITICAL); if (IsAffectFlag(AFF_MANASHIELD)) { RemoveAffect(AFF_MANASHIELD); } } } // 관통공격 int iPenetratePct = pAttacker->GetPoint(POINT_PENETRATE_PCT); if (!IsPC()) iPenetratePct += pAttacker->GetMarriageBonus(UNIQUE_ITEM_MARRIAGE_PENETRATE_BONUS); if (iPenetratePct) { { CSkillProto* pkSk = CSkillManager::instance().Get(SKILL_RESIST_PENETRATE); if (NULL != pkSk) { pkSk->SetPointVar("k", 1.0f * GetSkillPower(SKILL_RESIST_PENETRATE) / 100.0f); iPenetratePct -= static_cast<int>(pkSk->kPointPoly.Eval()); } } if (iPenetratePct >= 10) { // 10보다 크면 5% + (4마다 1%씩 증가), 따라서 수치가 50이면 20% iPenetratePct = 5 + (iPenetratePct - 10) / 4; } else { // 10보다 작으면 단순히 반으로 깎음, 10 = 5% iPenetratePct /= 2; } //관통타격 저항 값 적용. iPenetratePct -= GetPoint(POINT_RESIST_PENETRATE); if (number(1, 100) <= iPenetratePct) { IsPenetrate = true; if (test_server) ChatPacket(CHAT_TYPE_INFO, LC_TEXT("관통 추가 데미지 %d"), GetPoint(POINT_DEF_GRADE) * (100 + GetPoint(POINT_DEF_BONUS)) / 100); dam += GetPoint(POINT_DEF_GRADE) * (100 + GetPoint(POINT_DEF_BONUS)) / 100; if (IsAffectFlag(AFF_MANASHIELD)) { RemoveAffect(AFF_MANASHIELD); } } } } } // // 콤보 공격, 활 공격, 즉 평타 일 때만 속성값들을 계산을 한다. // else if (type == DAMAGE_TYPE_NORMAL || type == DAMAGE_TYPE_NORMAL_RANGE) { if (type == DAMAGE_TYPE_NORMAL) { // 근접 평타일 경우 막을 수 있음 if (GetPoint(POINT_BLOCK) && number(1, 100) <= GetPoint(POINT_BLOCK)) { if (test_server) { pAttacker->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s 블럭! (%d%%)"), GetName(), GetPoint(POINT_BLOCK)); ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s 블럭! (%d%%)"), GetName(), GetPoint(POINT_BLOCK)); } SendDamagePacket(pAttacker, 0, DAMAGE_BLOCK); return false; } } else if (type == DAMAGE_TYPE_NORMAL_RANGE) { // 원거리 평타의 경우 피할 수 있음 if (GetPoint(POINT_DODGE) && number(1, 100) <= GetPoint(POINT_DODGE)) { if (test_server) { pAttacker->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s 회피! (%d%%)"), GetName(), GetPoint(POINT_DODGE)); ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s 회피! (%d%%)"), GetName(), GetPoint(POINT_DODGE)); } SendDamagePacket(pAttacker, 0, DAMAGE_DODGE); return false; } } if (IsAffectFlag(AFF_JEONGWIHON)) dam = (int) (dam * (100 + GetSkillPower(SKILL_JEONGWI) * 25 / 100) / 100); if (IsAffectFlag(AFF_TERROR)) dam = (int) (dam * (95 - GetSkillPower(SKILL_TERROR) / 5) / 100); if (IsAffectFlag(AFF_HOSIN)) dam = dam * (100 - GetPoint(POINT_RESIST_NORMAL_DAMAGE)) / 100; // // 공격자 속성 적용 // if (pAttacker) { if (type == DAMAGE_TYPE_NORMAL) { // 반사 if (GetPoint(POINT_REFLECT_MELEE)) { int reflectDamage = dam * GetPoint(POINT_REFLECT_MELEE) / 100; // NOTE: 공격자가 IMMUNE_REFLECT 속성을 갖고있다면 반사를 안 하는 게 // 아니라 1/3 데미지로 고정해서 들어가도록 기획에서 요청. if (pAttacker->IsImmune(IMMUNE_REFLECT)) reflectDamage = int(reflectDamage / 3.0f + 0.5f); pAttacker->Damage(this, reflectDamage, DAMAGE_TYPE_SPECIAL); } } // 크리티컬 int iCriticalPct = pAttacker->GetPoint(POINT_CRITICAL_PCT); if (!IsPC()) iCriticalPct += pAttacker->GetMarriageBonus(UNIQUE_ITEM_MARRIAGE_CRITICAL_BONUS); if (iCriticalPct) { //크리티컬 저항 값 적용. iCriticalPct -= GetPoint(POINT_RESIST_CRITICAL); if (number(1, 100) <= iCriticalPct) { IsCritical = true; dam *= 2; EffectPacket(SE_CRITICAL); } } // 관통공격 int iPenetratePct = pAttacker->GetPoint(POINT_PENETRATE_PCT); if (!IsPC()) iPenetratePct += pAttacker->GetMarriageBonus(UNIQUE_ITEM_MARRIAGE_PENETRATE_BONUS); { CSkillProto* pkSk = CSkillManager::instance().Get(SKILL_RESIST_PENETRATE); if (NULL != pkSk) { pkSk->SetPointVar("k", 1.0f * GetSkillPower(SKILL_RESIST_PENETRATE) / 100.0f); iPenetratePct -= static_cast<int>(pkSk->kPointPoly.Eval()); } } if (iPenetratePct) { //관통타격 저항 값 적용. iPenetratePct -= GetPoint(POINT_RESIST_PENETRATE); if (number(1, 100) <= iPenetratePct) { IsPenetrate = true; if (test_server) ChatPacket(CHAT_TYPE_INFO, LC_TEXT("관통 추가 데미지 %d"), GetPoint(POINT_DEF_GRADE) * (100 + GetPoint(POINT_DEF_BONUS)) / 100); dam += GetPoint(POINT_DEF_GRADE) * (100 + GetPoint(POINT_DEF_BONUS)) / 100; } } // HP 스틸 if (pAttacker->GetPoint(POINT_STEAL_HP)) { int pct = 1; if (number(1, 10) <= pct) { int iHP = MIN(dam, MAX(0, iCurHP)) * pAttacker->GetPoint(POINT_STEAL_HP) / 100; if (iHP > 0 && GetHP() >= iHP) { CreateFly(FLY_HP_SMALL, pAttacker); pAttacker->PointChange(POINT_HP, iHP); PointChange(POINT_HP, -iHP); } } } // SP 스틸 if (pAttacker->GetPoint(POINT_STEAL_SP)) { int pct = 1; if (number(1, 10) <= pct) { int iCur; if (IsPC()) iCur = iCurSP; else iCur = iCurHP; int iSP = MIN(dam, MAX(0, iCur)) * pAttacker->GetPoint(POINT_STEAL_SP) / 100; if (iSP > 0 && iCur >= iSP) { CreateFly(FLY_SP_SMALL, pAttacker); pAttacker->PointChange(POINT_SP, iSP); if (IsPC()) PointChange(POINT_SP, -iSP); } } } // 돈 스틸 if (pAttacker->GetPoint(POINT_STEAL_GOLD)) { if (number(1, 100) <= pAttacker->GetPoint(POINT_STEAL_GOLD)) { int iAmount = number(1, GetLevel()); pAttacker->PointChange(POINT_GOLD, iAmount); DBManager::instance().SendMoneyLog(MONEY_LOG_MISC, 1, iAmount); } } // 칠 때마다 HP회복 if (pAttacker->GetPoint(POINT_HIT_HP_RECOVERY) && number(0, 4) > 0) // 80% 확률 { // int i = MIN(dam, iCurHP) * pAttacker->GetPoint(POINT_HIT_HP_RECOVERY) / 100; int i = ((iCurHP>=0)?MIN(dam, iCurHP):dam) * pAttacker->GetPoint(POINT_HIT_HP_RECOVERY) / 100; // Fix if (i) { CreateFly(FLY_HP_SMALL, pAttacker); pAttacker->PointChange(POINT_HP, i); } } // 칠 때마다 SP회복 if (pAttacker->GetPoint(POINT_HIT_SP_RECOVERY) && number(0, 4) > 0) // 80% 확률 { // int i = MIN(dam, iCurHP) * pAttacker->GetPoint(POINT_HIT_SP_RECOVERY) / 100; int i = ((iCurHP>=0)?MIN(dam, iCurHP):dam) * pAttacker->GetPoint(POINT_HIT_SP_RECOVERY) / 100; // Fix if (i) { CreateFly(FLY_SP_SMALL, pAttacker); pAttacker->PointChange(POINT_SP, i); } } // 상대방의 마나를 없앤다. if (pAttacker->GetPoint(POINT_MANA_BURN_PCT)) { if (number(1, 100) <= pAttacker->GetPoint(POINT_MANA_BURN_PCT)) PointChange(POINT_SP, -50); } } } // // 평타 또는 스킬로 인한 보너스 피해/방어 계산 // switch (type) { case DAMAGE_TYPE_NORMAL: case DAMAGE_TYPE_NORMAL_RANGE: if (pAttacker) if (pAttacker->GetPoint(POINT_NORMAL_HIT_DAMAGE_BONUS)) dam = dam * (100 + pAttacker->GetPoint(POINT_NORMAL_HIT_DAMAGE_BONUS)) / 100; dam = dam * (100 - MIN(99, GetPoint(POINT_NORMAL_HIT_DEFEND_BONUS))) / 100; break; case DAMAGE_TYPE_MELEE: case DAMAGE_TYPE_RANGE: case DAMAGE_TYPE_FIRE: case DAMAGE_TYPE_ICE: case DAMAGE_TYPE_ELEC: case DAMAGE_TYPE_MAGIC: if (pAttacker) if (pAttacker->GetPoint(POINT_SKILL_DAMAGE_BONUS)) dam = dam * (100 + pAttacker->GetPoint(POINT_SKILL_DAMAGE_BONUS)) / 100; dam = dam * (100 - MIN(99, GetPoint(POINT_SKILL_DEFEND_BONUS))) / 100; break; default: break; } // // 마나쉴드(흑신수호) // if (IsAffectFlag(AFF_MANASHIELD)) { // POINT_MANASHIELD 는 작아질수록 좋다 int iDamageSPPart = dam / 3; int iDamageToSP = iDamageSPPart * GetPoint(POINT_MANASHIELD) / 100; int iSP = GetSP(); // SP가 있으면 무조건 데미지 절반 감소 if (iDamageToSP <= iSP) { PointChange(POINT_SP, -iDamageToSP); dam -= iDamageSPPart; } else { // 정신력이 모자라서 피가 더 깍여야할 PointChange(POINT_SP, -GetSP()); dam -= iSP * 100 / MAX(GetPoint(POINT_MANASHIELD), 1); } } // // 전체 방어력 상승 (몰 아이템) // if (GetPoint(POINT_MALL_DEFBONUS) > 0) { int dec_dam = MIN(200, dam * GetPoint(POINT_MALL_DEFBONUS) / 100); dam -= dec_dam; } if (pAttacker) { // // 전체 공격력 상승 (몰 아이템) // if (pAttacker->GetPoint(POINT_MALL_ATTBONUS) > 0) { int add_dam = MIN(300, dam * pAttacker->GetLimitPoint(POINT_MALL_ATTBONUS) / 100); dam += add_dam; } // // 제국으로 인한 보너스 (한국 올드 버전만 적용) // int iEmpire = GetEmpire(); long lMapIndex = GetMapIndex(); int iMapEmpire = SECTREE_MANAGER::instance().GetEmpireFromMapIndex(lMapIndex); if (LC_IsYMIR() == true) { if (iEmpire && iMapEmpire && iEmpire != iMapEmpire) { dam += (dam * 30) / 100; } } if (pAttacker->IsPC()) { iEmpire = pAttacker->GetEmpire(); lMapIndex = pAttacker->GetMapIndex(); iMapEmpire = SECTREE_MANAGER::instance().GetEmpireFromMapIndex(lMapIndex); // 다른 제국 사람인 경우 데미지 10% 감소 if (iEmpire && iMapEmpire && iEmpire != iMapEmpire) { int percent = 10; if (184 <= lMapIndex && lMapIndex <= 189) { if (LC_IsYMIR() == true) percent = 7; else percent = 9; } else { if (LC_IsYMIR() == true) percent = 8; else percent = 9; } dam = dam * percent / 10; } if (!IsPC() && GetMonsterDrainSPPoint()) { int iDrain = GetMonsterDrainSPPoint(); if (iDrain <= pAttacker->GetSP()) pAttacker->PointChange(POINT_SP, -iDrain); else { int iSP = pAttacker->GetSP(); pAttacker->PointChange(POINT_SP, -iSP); } } } else if (pAttacker->IsGuardNPC()) { SET_BIT(m_pointsInstant.instant_flag, INSTANT_FLAG_NO_REWARD); Stun(); return true; } // // 군주의 금강권 & 사자후 // if (pAttacker->IsPC() && CMonarch::instance().IsPowerUp(pAttacker->GetEmpire())) { // 10% 피해 증가 dam += dam / 10; } if (IsPC() && CMonarch::instance().IsDefenceUp(GetEmpire())) { // 10% 피해 감소 dam -= dam / 10; } } //puAttr.Pop(); if (!GetSectree() || GetSectree()->IsAttr(GetX(), GetY(), ATTR_BANPK)) return false; if (!IsPC()) { if (m_pkParty && m_pkParty->GetLeader()) m_pkParty->GetLeader()->SetLastAttacked(get_dword_time()); else SetLastAttacked(get_dword_time()); // 몬스터 대사 : 맞을 때 MonsterChat(MONSTER_CHAT_ATTACKED); } if (IsStun()) { Dead(pAttacker); return true; } if (IsDead()) return true; // 독 공격으로 죽지 않도록 함. if (type == DAMAGE_TYPE_POISON) { if (GetHP() - dam <= 0) { dam = GetHP() - 1; } } // ------------------------ // 독일 프리미엄 모드 // ----------------------- if (LC_IsGermany() && pAttacker && pAttacker->IsPC()) { int iDmgPct = CHARACTER_MANAGER::instance().GetUserDamageRate(pAttacker); dam = dam * iDmgPct / 100; } // STONE SKIN : 피해 반으로 감소 if (IsMonster() && IsStoneSkinner()) { if (GetHPPct() < GetMobTable().bStoneSkinPoint) dam /= 2; } //PROF_UNIT puRest1("Rest1"); if (pAttacker) { // DEATH BLOW : 확률 적으로 4배 피해 (!? 현재 이벤트나 공성전용 몬스터만 사용함) if (pAttacker->IsMonster() && pAttacker->IsDeathBlower()) { if (pAttacker->IsDeathBlow()) { if (number(1, 4) == GetJob()) { IsDeathBlow = true; dam = dam * 4; } } } dam = BlueDragon_Damage(this, pAttacker, dam); BYTE damageFlag = 0; if (type == DAMAGE_TYPE_POISON) damageFlag = DAMAGE_POISON; else damageFlag = DAMAGE_NORMAL; if (IsCritical == true) damageFlag |= DAMAGE_CRITICAL; if (IsPenetrate == true) damageFlag |= DAMAGE_PENETRATE; //최종 데미지 보정 float damMul = this->GetDamMul(); float tempDam = dam; dam = tempDam * damMul + 0.5f; if (pAttacker) SendDamagePacket(pAttacker, dam, damageFlag); if (test_server) { if(pAttacker) { pAttacker->ChatPacket(CHAT_TYPE_INFO, "-> %s, DAM %d HP %d(%d%%) %s%s", GetName(), dam, GetHP(), (GetHP() * 100) / GetMaxHP(), IsCritical ? "crit " : "", IsPenetrate ? "pene " : "", IsDeathBlow ? "deathblow " : ""); } ChatPacket(CHAT_TYPE_PARTY, "<- %s, DAM %d HP %d(%d%%) %s%s", pAttacker ? pAttacker->GetName() : 0, dam, GetHP(), (GetHP() * 100) / GetMaxHP(), IsCritical ? "crit " : "", IsPenetrate ? "pene " : "", IsDeathBlow ? "deathblow " : ""); } if (m_bDetailLog) { ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s[%d]가 공격 위치: %d %d"), pAttacker->GetName(), (DWORD) pAttacker->GetVID(), pAttacker->GetX(), pAttacker->GetY()); } } #ifdef ENABLE_EXTENDED_BATTLE_PASS if (type != DAMAGE_TYPE_POISON && type != DAMAGE_TYPE_FIRE) { if (IsPC()) pAttacker->UpdateExtBattlePassMissionProgress(DAMAGE_PLAYER, dam, GetLevel()); else pAttacker->UpdateExtBattlePassMissionProgress(DAMAGE_MONSTER, dam, GetRaceNum()); } #endif // // !!!!!!!!! 실제 HP를 줄이는 부분 !!!!!!!!! // if (!cannot_dead) { PointChange(POINT_HP, -dam, false); } //puRest1.Pop(); //PROF_UNIT puRest2("Rest2"); if (pAttacker && dam > 0 && IsNPC()) { //PROF_UNIT puRest20("Rest20"); TDamageMap::iterator it = m_map_kDamage.find(pAttacker->GetVID()); if (it == m_map_kDamage.end()) { m_map_kDamage.insert(TDamageMap::value_type(pAttacker->GetVID(), TBattleInfo(dam, 0))); it = m_map_kDamage.find(pAttacker->GetVID()); } else { it->second.iTotalDamage += dam; } //puRest20.Pop(); //PROF_UNIT puRest21("Rest21"); StartRecoveryEvent(); // 몬스터는 데미지를 입으면 회복을 시작한다. //puRest21.Pop(); //PROF_UNIT puRest22("Rest22"); UpdateAggrPointEx(pAttacker, type, dam, it->second); //puRest22.Pop(); } //puRest2.Pop(); //PROF_UNIT puRest3("Rest3"); if (GetHP() <= 0) { if (pAttacker && !pAttacker->IsNPC()) m_dwKillerPID = pAttacker->GetPlayerID(); else m_dwKillerPID = 0; Stun(true); } return false; } Edited April 2 by Karbust Put code inside spoiler Link to comment Share on other sites More sharing options...
Active Member iMerv3 768 Posted April 2 Active Member Share Posted April 2 (edited) 22 hours ago, Koran said: if Battle Pass Extended char_battle.cpp #ifdef ENABLE_EXTENDED_BATTLE_PASS if (type != DAMAGE_TYPE_POISON && type != DAMAGE_TYPE_FIRE) { if (IsPC()) pAttacker->UpdateExtBattlePassMissionProgress(DAMAGE_PLAYER, dam, GetLevel()); else pAttacker->UpdateExtBattlePassMissionProgress(DAMAGE_MONSTER, dam, GetRaceNum()); } #endif Spoiler #ifdef ENABLE_EXTENDED_BATTLE_PASS if (pAttacker) { pAttacker->UpdateExtBattlePassMissionProgress(IsPC() ? DAMAGE_PLAYER : DAMAGE_MONSTER, dam, IsPC() ? GetLevel() : GetRaceNum()); } #endif Edited April 2 by iMerv3 Link to comment Share on other sites More sharing options...
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now