Jump to content

Poison given by monster crash server


Recommended Posts

  • Management

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

raw

raw

Link to comment
Share on other sites

  • Replies 14
  • Created
  • Last Reply

Top Posters In This Topic

  • 3 weeks later...
  • Management
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

raw

raw

Link to comment
Share on other sites

  • Management
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...

raw

raw

Link to comment
Share on other sites

  • Management

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)

 

raw

raw

Link to comment
Share on other sites

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

  • Management
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?

raw

raw

Link to comment
Share on other sites

  • 5 years later...

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

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 by Karbust
Put code inside spoiler
Link to comment
Share on other sites

  • Active Member
Posted (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 by iMerv3
Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

Announcements



×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.