I tried searching for it but got no results so I'm sharing what I made myself.
1. DevilSquare.h
struct DEVIL_SQUARE_USER
add
int MonsterKillCount;
//
class CDevilSquare
{
private:
add
int m_MonsterKillRequired;
int m_CoinRewardPerKill;
std::vector<int> m_DevilSquareItemIDs;
2. DevilSquare.cpp
///////// Find:
void CDevilSquare::Load(char* path)
////////Modify:
void CDevilSquare::Load(char* path) // OK
{
CMemScript* lpMemScript = new CMemScript;
if (lpMemScript == 0)
{
ErrorMessageBox(MEM_SCRIPT_ALLOC_ERROR, path);
return;
}
if (lpMemScript->SetBuffer(path) == 0)
{
ErrorMessageBox(lpMemScript->GetLastError());
delete lpMemScript;
return;
}
this->m_DevilSquareStartTime.clear();
memset(this->m_DevilSquareRewardExperience, 0, sizeof(this->m_DevilSquareRewardExperience));
memset(this->m_DevilSquareRewardMoney, 0, sizeof(this->m_DevilSquareRewardMoney));
this->m_DevilSquareItemIDs.clear();
try
{
while (true)
{
if (lpMemScript->GetToken() == TOKEN_END)
{
break;
}
int section = lpMemScript->GetNumber();
while (true)
{
if (section == 0)
{
if (strcmp("end", lpMemScript->GetAsString()) == 0)
{
break;
}
this->m_WarningTime = lpMemScript->GetNumber();
this->m_NotifyTime = lpMemScript->GetAsNumber();
this->m_EventTime = lpMemScript->GetAsNumber();
this->m_CloseTime = lpMemScript->GetAsNumber();
}
else if (section == 1)
{
if (strcmp("end", lpMemScript->GetAsString()) == 0)
{
break;
}
DEVIL_SQUARE_START_TIME info;
info.Year = lpMemScript->GetNumber();
info.Month = lpMemScript->GetAsNumber();
info.Day = lpMemScript->GetAsNumber();
info.DayOfWeek = lpMemScript->GetAsNumber();
info.Hour = lpMemScript->GetAsNumber();
info.Minute = lpMemScript->GetAsNumber();
info.Second = lpMemScript->GetAsNumber();
this->m_DevilSquareStartTime.push_back(info);
}
else if (section == 2)
{
if (strcmp("end", lpMemScript->GetAsString()) == 0)
{
break;
}
int level = lpMemScript->GetNumber();
for (int n = 0; n < MAX_DS_RANK; n++)
{
this->m_DevilSquareRewardExperience[level][n] = lpMemScript->GetAsNumber();
}
}
else if (section == 3)
{
if (strcmp("end", lpMemScript->GetAsString()) == 0)
{
break;
}
int level = lpMemScript->GetNumber();
for (int n = 0; n < MAX_DS_RANK; n++)
{
this->m_DevilSquareRewardMoney[level][n] = lpMemScript->GetAsNumber();
}
}
else if (section == 4)
{
if (strcmp("end", lpMemScript->GetAsString()) == 0)
{
break;
}
int level = lpMemScript->GetNumber();
this->m_DevilSquareRewardValue[level][0] = lpMemScript->GetAsNumber();
this->m_DevilSquareRewardValue[level][1] = lpMemScript->GetAsNumber();
this->m_DevilSquareRewardValue[level][2] = lpMemScript->GetAsNumber();
}
else if (section == 5)
{
if (strcmp("end", lpMemScript->GetAsString()) == 0)
{
break;
}
this->m_MonsterKillRequired = lpMemScript->GetNumber();
this->m_CoinRewardPerKill = lpMemScript->GetAsNumber();
while (true)
{
int itemID = lpMemScript->GetAsNumber();
if (itemID == -1)
{
break;
}
this->m_DevilSquareItemIDs.push_back(itemID);
}
}
else
{
break;
}
}
}
}
catch (...)
{
ErrorMessageBox(lpMemScript->GetLastError());
}
delete lpMemScript;
}
/////////// Find:
void CDevilSquare::MonsterDieProc(LPOBJ lpObj, LPOBJ lpTarget)
////////// Modify:
void CDevilSquare::MonsterDieProc(LPOBJ lpObj, LPOBJ lpTarget) // OK
{
int aIndex = gObjMonsterGetTopHitDamageUser(lpObj);
if (OBJECT_RANGE(aIndex) != 0)
{
lpTarget = &gObj[aIndex];
}
int level = this->GetUserAbleLevel(lpTarget);
if (DS_LEVEL_RANGE(level) == 0)
{
return;
}
if (this->GetState(level) != DS_STATE_START)
{
return;
}
if (this->GetMonster(&this->m_DevilSquareLevel[level], lpObj->Index) == 0)
{
return;
}
if (lpTarget->Type != OBJECT_USER)
{
return;
}
DEVIL_SQUARE_USER* lpUser = this->GetUser(&this->m_DevilSquareLevel[level], lpTarget->Index);
if (lpUser == 0)
{
return;
}
lpUser->Score += lpObj->Level * (level + 1);
const int rewardCoin = this->m_CoinRewardPerKill;
GDSetCoinSend(lpTarget->Index, rewardCoin, 0, 0, "MonsterKill");
lpUser->MonsterKillCount++;
gNotice.GCNoticeSend(lpTarget->Index, 1, 0, 0, 0, 0, 0, gMessage.GetMessage(1110), lpUser->MonsterKillCount, this->m_MonsterKillRequired);
if (lpUser->MonsterKillCount >= this->m_MonsterKillRequired)
{
if (!this->m_DevilSquareItemIDs.empty())
{
int randomItemID = this->m_DevilSquareItemIDs[lpObj->Index % this->m_DevilSquareItemIDs.size()];
GDCreateItemSend(lpTarget->Index, 0xEB, 0, 0, randomItemID, 0, 0, 0, 0, 0, lpTarget->Index, 0, 0, 0, 0, 0, 0xFF, 0);
gNotice.GCNoticeSendToAll(0, 0, 0, 0, 0, 0, gMessage.GetMessage(1111), lpTarget->Name);
lpUser->MonsterKillCount = 0;
}
}
}
3. DevilSquare.txt
Add:
//Reward Per Monster kill
5
400 // MonsterKillRequired
3 // CoinRewardPerKill
6159 7181 7182 7184 7190 -1 // Reward Items list, end of list is -1
end
4. Message.txt
1110 "Bạn đã giết được %d/%d quái vật"
1111 "[%s] Đã tiêu diệt đủ quái vật, ngọc rơi đầy chân!"