Me pediram este sistema e eu fiz umas pesquisas sobre o mesmo, e consegui fazer com que caia item exc da box of luck na versão 97d.
Porém eu não usarei isso no meu dev, resolvi postar..
Pode não ser algo tão incrível pra alguns, mas quem quiser usar, tá na mão...

Já lembro que usando isso, perde-se o drop da rena que cai desta box, tem como deixar original, porém como eu fiz a pedido não
quis dar atenção pra esse ponto. Assim também não cai mais aquele 1000 zen^^ apenas os itens configurados no eventitembag.txt.
Segue:

EventItemBag.cpp

CItemBag CIBag;
CItemBag * LuckboxItemBag;

CItemBag::CItemBag()
{
return;
}

CItemBag::~CItemBag()
{
return;
}

void HookBILoadItem()
{
LoadItemBag();
if (LuckboxItemBag != FALSE)
{
delete LuckboxItemBag;
}

LuckboxItemBag = new CItemBag;

if (LuckboxItemBag == NULL)
{
ExchangeMsgBox("CItemBag %s", "memory error alocate");
return;
}

LuckboxItemBag->Init("eventitembag.txt");
}

void CItemBag::Init(LPSTR script_file)
{
CIBag.BagObjectCount = 0;
CIBag.BagNormalItemCount = 0;
CIBag.BagExItemCount = 0;
char PATCH[40];
sprintf(PATCH, "..\\Data\\%s", script_file);
CIBag.LoadItem(PATCH);
}

void CItemBag::LoadItem(LPSTR script_file)
{
FILE *file;
file = fopen(script_file, "r");

char Message[255];
if (file == NULL)
{
return;
}
rewind(file);
char Buff[254];
Buff[0] = NULL;
int Type, Index, Level, Dur, LoopCount = 0;
int Opt1 = 0, Opt2 = 0, Opt3 = 0;
BYTE Opt4 = 0;
int n = 0;

while (!feof(file))
{
n = this->BagObjectCount;
fgets(Buff, 254, file);
//isdigit(fgetc(file)) != 0
if (Buff[0] == '/' || Buff[0] == ';' || Buff[0] == '#')
continue;
if (Buff[0] == '\n')
continue;

if (isdigit(Buff[0]) == 0 || isspace(0) != 0)
continue;

sscanf(Buff, "%d %d %d %d %d %d %d", &Type, &Index, &Level, &Opt1, &Opt2, &Opt3, &Opt4);
this->BagObject[n].m_type = Type;
this->BagObject[n].m_index = Index;
this->BagObject[n].m_level = Level;
this->BagObject[n].m_op1 = Opt1;
this->BagObject[n].m_op2 = Opt2;
this->BagObject[n].m_op3 = Opt3;
this->BagObject[n].m_exc = Opt4;
if (this->BagObject[n].m_exc != 0)
{
this->BagExItemCount++;
}
else
{
this->BagNormalItemCount++;
}

this->BagObjectCount++;

if (this->BagObjectCount > MAX_ITEMBAG_ATTR - 1)
{
break;
}
}
fclose(file);
}

BYTE CItemBag::GetType(int n)
{
if (n< 0 || n > MAX_ITEMBAG_ATTR - 1)
{
return 0;
}

return this->BagObject[n].m_type;
}

BYTE CItemBag::GetIndex(int n)
{
if (n< 0 || n > MAX_ITEMBAG_ATTR - 1)
{
return 0;
}

return this->BagObject[n].m_index;
}


BYTE CItemBag::GetLevel(int n)
{
if (n< 0 || n > MAX_ITEMBAG_ATTR - 1)
{
return 0;
}

return this->BagObject[n].m_level;
}


BYTE CItemBag::GetOp1(int n)
{
if (n< 0 || n > MAX_ITEMBAG_ATTR - 1)
{
return 0;
}

return this->BagObject[n].m_op1;
}


BYTE CItemBag::GetOp2(int n)
{
if (n< 0 || n > MAX_ITEMBAG_ATTR - 1)
{
return 0;
}

return this->BagObject[n].m_op2;
}


BYTE CItemBag::GetOp3(int n)
{
if (n< 0 || n > MAX_ITEMBAG_ATTR - 1)
{
return 0;
}

return this->BagObject[n].m_op3;
}

BYTE CItemBag::GetExc(int n)
{
if (n< 0 || n > MAX_ITEMBAG_ATTR - 1)
{
return 0;
}

return this->BagObject[n].m_exc;
}

void HookLuckyBoxOpenEven(LPOBJ lpObj)
{
float dur;
int type, level, x, y;
int Option1 = 0;
int Option2 = 0;
int Option3 = 0;
int Exc = 0;
int DropItemNum;


if (LuckboxItemBag == NULL)
{
LogAdd("EventChip Event ErrOrR");
return;
}
if (CIBag.GetBagCount() > 0)
{
DropItemNum = (rand() % CIBag.GetBagCount());
dur = 255;
x = lpObj->X;
y = lpObj->Y;


level = CIBag.GetLevel(DropItemNum);

type = ItemGetNumberMake(CIBag.GetType(DropItemNum), CIBag.GetIndex(DropItemNum));

Option1 = CIBag.GetOp1(DropItemNum);
Option2 = CIBag.GetOp2(DropItemNum);
Option3 = CIBag.GetOp3(DropItemNum);
Exc = CIBag.GetExc(DropItemNum);


//
if ((type == (12 << 4) + 15) ||
(type == (14 << 4) + 13) ||
(type == (14 << 4) + 14))
{
Option1 = 0;
Option2 = 0;
Option3 = 0;
level = 0;
Exc = 0;
}
if (type == ITEMGET(13, 0) ||
type == ITEMGET(13, 1) ||
type == ITEMGET(13, 2) ||
type == ITEMGET(13, 8) ||
type == ITEMGET(13, 9) ||
type == ITEMGET(13, 12) ||
type == ITEMGET(13, 13))
{
level = 0;
}
ItemSerialCreateSend(lpObj->m_Index, lpObj->Map, (BYTE)x, (BYTE)y, type, level, (BYTE)dur, Option1, Option2, Option3, lpObj->m_Index, Exc);

PMSG_SERVERCMD pMsg;

PHeadSubSetB((LPBYTE)&pMsg, 0xF3, 0x40, sizeof(pMsg));
pMsg.CmdType = 2;
pMsg.X = x;
pMsg.Y = y;

MsgSendV2(lpObj, (LPBYTE)&pMsg, sizeof(pMsg));
DataSend(lpObj->m_Index, (LPBYTE)&pMsg, sizeof(pMsg));

LogAdd("Event ItemDropEx : Item:%d Level:%d op1:%d op2:%d op3:%d exc:%d Cont :%d", type, level, Option1, Option2, Option3, Exc, CIBag.GetBagCount());
}
}

EventItemBag.h

#pragma once

#define MAX_ITEMBAG_ATTR 150
//Teste itembag

struct CItemBagAttr
{

public:

CItemBagAttr() // line : 28
{
this->m_type = 0;
this->m_index = 0;
this->m_level = 0;
this->m_op1 = 0;
this->m_op2 = 0;
this->m_op3 = 0;
this->m_exc = 0;
} // line : 36

public:

BYTE m_type; // 0
BYTE m_index; // 1
BYTE m_level; // 2
BYTE m_op1; // 3
BYTE m_op2; // 4
BYTE m_op3; // 5
BYTE m_exc;

};


class CItemBag
{

public:

CItemBag();
virtual ~CItemBag();

static void Init(LPSTR script_file);
void LoadItem(LPSTR script_file);
int GetBagCount() // line : 62
{
return this->BagObjectCount;
}; // line : 64
BYTE GetType(int n);
BYTE GetIndex(int n);
BYTE GetLevel(int n);
BYTE GetOp1(int n);
BYTE GetOp2(int n);
BYTE GetOp3(int n);
BYTE GetExc(int n);
int GetNormalItemCount(){ return this->BagNormalItemCount; } // line : 72
int GetExItemCount(){ return this->BagExItemCount; } // line : 73


CItemBagAttr BagObject[MAX_ITEMBAG_ATTR]; // 4
int BagObjectCount; // 388
int BagNormalItemCount; // 38C
int BagExItemCount; // 390
};

extern CItemBag CIBag;
extern CItemBag * LuckboxItemBag;
void HookLuckyBoxOpenEven(LPOBJ lpObj);
void HookBILoadItem();

Offset:
#define LoadItemBag ((void(*)()) 0x48E9A0)

Hook:
HookThis((DWORD)&HookLuckyBoxOpenEven, 0x401843); //box of luck
HookThis((DWORD)&HookBILoadItem, 0x40142E); // box of luck

Créditos: Konvict
Base da class: webzen