party.check_item(vnum, count) and party.remove_item(vnum, count) LUA functions

This commit is contained in:
d1str4ught
2026-02-09 04:24:52 +01:00
parent 570510f345
commit c1cf1a141e
4 changed files with 98 additions and 45 deletions

View File

@@ -1129,7 +1129,7 @@ class CHARACTER : public CEntity, public CFSM, public CHorseRider
int CountEmptyInventory() const;
int CountSpecifyItem(DWORD vnum) const;
void RemoveSpecifyItem(DWORD vnum, DWORD count = 1);
bool RemoveSpecifyItem(DWORD vnum, DWORD count = 1);
LPITEM FindSpecifyItem(DWORD vnum) const;
LPITEM FindItemByID(DWORD id) const;

View File

@@ -6382,70 +6382,54 @@ LPITEM CHARACTER::FindItemByID(DWORD id) const
int CHARACTER::CountSpecifyItem(DWORD vnum) const
{
int count = 0;
LPITEM item;
for (int i = 0; i < INVENTORY_MAX_NUM; ++i)
{
item = GetInventoryItem(i);
if (NULL != item && item->GetVnum() == vnum)
{
// 개인 상점에 등록된 물건이면 넘어간다.
if (m_pkMyShop && m_pkMyShop->IsSellingItem(item->GetID()))
{
continue;
}
else
{
count += item->GetCount();
}
}
for (int i = 0; i < INVENTORY_MAX_NUM; ++i) {
LPITEM item = GetInventoryItem(i);
if (!item) continue;
if (item->GetVnum() != vnum)
continue;
if (m_pkMyShop && m_pkMyShop->IsSellingItem(item->GetID()))
continue;
count += item->GetCount();
}
return count;
}
void CHARACTER::RemoveSpecifyItem(DWORD vnum, DWORD count)
bool CHARACTER::RemoveSpecifyItem(DWORD vnum, DWORD count)
{
if (0 == count)
return;
return false;
for (UINT i = 0; i < INVENTORY_MAX_NUM; ++i)
{
if (NULL == GetInventoryItem(i))
continue;
for (UINT i = 0; i < INVENTORY_MAX_NUM; ++i) {
LPITEM item = GetInventoryItem(i);
if (!item) continue;
if (GetInventoryItem(i)->GetVnum() != vnum)
if (item->GetVnum() != vnum)
continue;
//개인 상점에 등록된 물건이면 넘어간다. (개인 상점에서 판매될때 이 부분으로 들어올 경우 문제!)
if(m_pkMyShop)
{
bool isItemSelling = m_pkMyShop->IsSellingItem(GetInventoryItem(i)->GetID());
if (isItemSelling)
continue;
}
if (m_pkMyShop && m_pkMyShop->IsSellingItem(item->GetID()))
continue;
if (vnum >= 80003 && vnum <= 80007)
LogManager::instance().GoldBarLog(GetPlayerID(), GetInventoryItem(i)->GetID(), QUEST, "RemoveSpecifyItem");
LogManager::instance().GoldBarLog(GetPlayerID(), item->GetID(), QUEST, "RemoveSpecifyItem");
if (count >= GetInventoryItem(i)->GetCount())
{
count -= GetInventoryItem(i)->GetCount();
GetInventoryItem(i)->SetCount(0);
DWORD item_count = std::min(count, item->GetCount());
item->SetCount(item->GetCount() - item_count);
count -= item_count;
if (0 == count)
return;
}
else
{
GetInventoryItem(i)->SetCount(GetInventoryItem(i)->GetCount() - count);
return;
}
if (0 == count) return true;
}
if (0 == count) return true;
// 예외처리가 약하다.
if (count)
sys_log(0, "CHARACTER::RemoveSpecifyItem cannot remove enough item vnum %u, still remain %d", vnum, count);
sys_log(0, "CHARACTER::RemoveSpecifyItem cannot remove enough item vnum %u, still remain %d", vnum, count);
return false;
}
int CHARACTER::CountSpecifyTypeItem(BYTE type) const

View File

@@ -152,6 +152,9 @@ class CParty
inline int ComputePartyBonusAttackGrade();
inline int ComputePartyBonusDefenseGrade();
TMemberMap::iterator MemberBegin() { return m_memberMap.begin(); }
TMemberMap::iterator MemberEnd() { return m_memberMap.end(); }
template <class Func> void ForEachMember(Func & f);
template <class Func> void ForEachMemberPtr(Func & f);
template <class Func> void ForEachOnlineMember(Func & f);

View File

@@ -388,6 +388,70 @@ namespace quest
return f.vecPIDs.size();
}
int party_check_item(lua_State* L)
{
if (!lua_isnumber(L, 1) || lua_isnumber(L, 2)) {
lua_pushboolean(L, false);
return 1;
}
uint32_t vnum = lua_tonumber(L, 1);
uint32_t count = lua_tonumber(L, 2);
LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
if(!ch) {
lua_pushboolean(L, false);
return 1;
}
LPPARTY party = ch->GetParty();
if (!party) {
lua_pushboolean(L, ch->CountSpecifyItem(vnum) >= count);
return 1;
}
bool success = std::all_of(party->MemberBegin(), party->MemberEnd(), [vnum, count](const auto& pair) {
LPCHARACTER ch = pair.second.pCharacter;
if (!ch) return true;
return ch->CountSpecifyItem(vnum) >= count;
});
lua_pushboolean(L, success);
return 1;
}
int party_remove_item(lua_State* L)
{
if (!lua_isnumber(L, 1) || lua_isnumber(L, 2)) {
lua_pushboolean(L, false);
return 1;
}
uint32_t vnum = lua_tonumber(L, 1);
uint32_t count = lua_tonumber(L, 2);
LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
if (!ch) {
lua_pushboolean(L, false);
return 1;
}
LPPARTY party = ch->GetParty();
if (!party) {
lua_pushboolean(L, ch->RemoveSpecifyItem(vnum, count));
return 1;
}
bool success = std::all_of(party->MemberBegin(), party->MemberEnd(), [vnum, count](const auto& pair) {
LPCHARACTER ch = pair.second.pCharacter;
if (!ch) return true;
return ch->RemoveSpecifyItem(vnum, count);
});
lua_pushboolean(L, success);
return 1;
}
void RegisterPartyFunctionTable()
{
luaL_reg party_functions[] =
@@ -409,6 +473,8 @@ namespace quest
{ "give_buff", party_give_buff },
{ "is_map_member_flag_lt", party_is_map_member_flag_lt },
{ "get_member_pids", party_get_member_pids }, // 파티원들의 pid를 return
{ "check_item", party_check_item },
{ "remove_item", party_remove_item },
{ NULL, NULL }
};