static bool TryStackGiveItem(LPCHARACTER ch, LPITEM item)
{
if (!ch || !item)
return false;
// Basit güvenlik: attr yok ve soket boşsa "saf" kabul edelim.
// (Özellikli eşyalar stack'lenmez; bu durumda false döneriz.)
if (item->GetAttributeCount() > 0)
return false;
if (item->GetSocket(0) || item->GetSocket(1) || item->GetSocket(2))
return false;
// vnum + count ile stack'lemeyi dene
const DWORD vnum = item->GetVnum();
const int cnt = item->GetCount();
if (cnt <= 0)
return false;
// STACK yapan sürüm budur
ch->AutoGiveItem(vnum, cnt);
// Orijinal drop nesnesini kaldır
ITEM_MANAGER::instance().RemoveItem(item);
return true;
}
void CHARACTER::Reward(bool bItemDrop)
{
if (GetRaceNum() == 5001)
{
PIXEL_POSITION pos;
if (!SECTREE_MANAGER::instance().GetMovablePosition(GetMapIndex(), GetX(), GetY(), pos))
return;
LPITEM item;
#ifdef ENABLE_YANG_LIMIT_SYSTEM
long long iGold = number(GetMobTable().llGoldMin, GetMobTable().llGoldMax);
#else
int iGold = number(GetMobTable().dwGoldMin, GetMobTable().dwGoldMax);
#endif
iGold = iGold * CHARACTER_MANAGER::instance().GetMobGoldAmountRate(nullptr) / 100;
iGold *= GetGoldMultipler; // sende değişkense böyle kalmalı
int iSplitCount = number(25, 35);
sys_log(0, "WAEGU Dead gold %d split %d", iGold, iSplitCount);
for (int i = 1; i <= iSplitCount; ++i)
{
if ((item = ITEM_MANAGER::instance().CreateItem(1, iGold / iSplitCount)))
{
if (i != 0)
{
pos.x = number(-7, 7) * 20;
pos.y = number(-7, 7) * 20;
pos.x += GetX();
pos.y += GetY();
}
item->AddToGround(GetMapIndex(), pos);
item->StartDestroyEvent();
}
}
return;
}
//PROF_UNIT puReward("Reward");
LPCHARACTER pkAttacker = DistributeExp();
#ifdef __ENABLE_KILL_EVENT_FIX__
if (!pkAttacker && !(pkAttacker = GetMostAttacked()))
return;
#else
if (!pkAttacker)
return;
#endif
#ifdef ENABLE_ALIGNMENT_BONUS
if (pkAttacker->IsPC())
{
if (GetLevel() - pkAttacker->GetLevel() >= -10)
if (pkAttacker->GetRealAlignment() < 200000)
{
if (pkAttacker->GetRealAlignment() < 0)
{
if (pkAttacker->IsEquipUniqueItem(UNIQUE_ITEM_FASTER_ALIGNMENT_UP_BY_KILL))
pkAttacker->UpdateAlignment(14);
else
pkAttacker->UpdateAlignment(7);
}
else
{
pkAttacker->UpdateAlignment(2);
}
}
#else
if (pkAttacker->IsPC())
{
if (GetLevel() - pkAttacker->GetLevel() >= -10)
if (pkAttacker->GetRealAlignment() < 0)
{
if (pkAttacker->IsEquipUniqueItem(UNIQUE_ITEM_FASTER_ALIGNMENT_UP_BY_KILL))
pkAttacker->UpdateAlignment(14);
else
pkAttacker->UpdateAlignment(7);
}
else
pkAttacker->UpdateAlignment(2);
#endif
pkAttacker->SetQuestNPCID(GetVID());
quest::CQuestManager::instance().Kill(pkAttacker->GetPlayerID(), GetRaceNum());
CHARACTER_MANAGER::instance().KillLog(GetRaceNum());
if (!number(0, 9))
{
if (pkAttacker->GetPoint(POINT_KILL_HP_RECOVERY))
{
int iHP = pkAttacker->GetMaxHP() * pkAttacker->GetPoint(POINT_KILL_HP_RECOVERY) / 100;
pkAttacker->PointChange(POINT_HP, iHP);
CreateFly(FLY_HP_SMALL, pkAttacker);
}
if (pkAttacker->GetPoint(POINT_KILL_SP_RECOVER))
{
int iSP = pkAttacker->GetMaxSP() * pkAttacker->GetPoint(POINT_KILL_SP_RECOVER) / 100;
pkAttacker->PointChange(POINT_SP, iSP);
CreateFly(FLY_SP_SMALL, pkAttacker);
}
}
}
if (!bItemDrop)
return;
PIXEL_POSITION pos = GetXYZ();
if (!SECTREE_MANAGER::instance().GetMovablePosition(GetMapIndex(), pos.x, pos.y, pos))
return;
if (test_server)
sys_log(0, "Drop money : Attacker %s", pkAttacker->GetName());
RewardGold(pkAttacker);
LPITEM item;
static std::vector<LPITEM> s_vec_item;
s_vec_item.clear();
if (ITEM_MANAGER::instance().CreateDropItem(this, pkAttacker, s_vec_item))
{
if (s_vec_item.size() == 0)
{
// boş drop
}
else if (s_vec_item.size() == 1)
{
item = s_vec_item[0];
if (!item)
return;
// --- STACK ÖNCELİK: basit item ise stack'li ver, başarılıysa bitir
if (TryStackGiveItem(pkAttacker, item))
{
pkAttacker->ChatPacket(CHAT_TYPE_INFO, "%s envanterine eklendi.", item->GetName());
return; // yere atma akışına girmesin
}
// STACK olmadıysa klasik yere at
item->AddToGround(GetMapIndex(), pos);
if (CBattleArena::instance().IsBattleArenaMap(pkAttacker->GetMapIndex()) == false)
{
#ifdef ENABLE_DICE_SYSTEM
if (pkAttacker->GetParty())
{
FPartyDropDiceRoll f(item, pkAttacker);
f.Process(this);
}
else
item->SetOwnership(pkAttacker);
#else
item->SetOwnership(pkAttacker);
#endif
}
item->StartDestroyEvent();
pos.x = number(-7, 7) * 20;
pos.y = number(-7, 7) * 20;
pos.x += GetX();
pos.y += GetY();
sys_log(0, "DROP_ITEM: %s %d %d from %s", item->GetName(), pos.x, pos.y, GetName());
}
else
{
int iItemIdx = s_vec_item.size() - 1;
std::priority_queue<std::pair<int, LPCHARACTER> > pq;
int total_dam = 0;
for (TDamageMap::iterator it = m_map_kDamage.begin(); it != m_map_kDamage.end(); ++it)
{
int iDamage = it->second.iTotalDamage;
if (iDamage > 0)
{
LPCHARACTER ch = CHARACTER_MANAGER::instance().Find(it->first);
if (ch)
{
pq.push(std::make_pair(iDamage, ch));
total_dam += iDamage;
}
}
}
std::vector<LPCHARACTER> v;
while (!pq.empty() && pq.top().first * 10 >= total_dam)
{
v.push_back(pq.top().second);
pq.pop();
}
if (v.empty())
{
while (iItemIdx >= 0)
{
item = s_vec_item[iItemIdx--];
if (!item)
{
sys_err("item null in vector idx %d", iItemIdx + 1);
continue;
}
// --- STACK ÖNCELİK: öldürene dene
if (TryStackGiveItem(pkAttacker, item))
{
pkAttacker->ChatPacket(CHAT_TYPE_INFO, "%s envanterine eklendi.", item->GetName());
}
else
{
item->AddToGround(GetMapIndex(), pos);
item->SetOwnership(pkAttacker);
item->StartDestroyEvent();
pos.x = number(-7, 7) * 20;
pos.y = number(-7, 7) * 20;
pos.x += GetX();
pos.y += GetY();
sys_log(0, "DROP_ITEM: %s %d %d by %s", item->GetName(), pos.x, pos.y, GetName());
}
}
}
else
{
std::vector<LPCHARACTER>::iterator it = v.begin();
while (iItemIdx >= 0)
{
item = s_vec_item[iItemIdx--];
if (!item)
{
sys_err("item null in vector idx %d", iItemIdx + 1);
continue;
}
LPCHARACTER ch = *it;
if (ch->GetParty())
ch = ch->GetParty()->GetNextOwnership(ch, GetX(), GetY());
++it;
if (it == v.end())
it = v.begin();
// --- STACK ÖNCELİK: hakkı olana dene
if (TryStackGiveItem(ch, item))
{
ch->ChatPacket(CHAT_TYPE_INFO, "%s envanterine eklendi.", item->GetName());
}
else
{
item->AddToGround(GetMapIndex(), pos);
if (CBattleArena::instance().IsBattleArenaMap(ch->GetMapIndex()) == false)
{
#ifdef ENABLE_DICE_SYSTEM
if (ch->GetParty())
{
FPartyDropDiceRoll f(item, ch);
f.Process(this);
}
else
item->SetOwnership(ch);
#else
item->SetOwnership(ch);
#endif
}
item->StartDestroyEvent();
pos.x = number(-7, 7) * 20;
pos.y = number(-7, 7) * 20;
pos.x += GetX();
pos.y += GetY();
sys_log(0, "DROP_ITEM: %s %d %d by %s", item->GetName(), pos.x, pos.y, GetName());
}
}
}
}
}
m_map_kDamage.clear();
}