Files
mir_server/server/LogicServer/base/BoxDrop.cpp

469 lines
11 KiB
C++
Raw Normal View History

2025-01-09 17:45:40 +08:00
#include "StdAfx.h"
#include "Container.hpp"
LONG CBoxDropMgr::s_boxDropMgrCnt = 0;
CBoxDropMgr * CBoxDropMgr::s_BoxDropMgr = NULL;
TCHAR CBaseScriptExportObject::m_sClassName[] = _T("CBaseScriptExportObject");
TCHAR CBoxDrop::m_sClassName[] = _T("CBoxDrop");
const char *DropTableName = "drops";
CBoxDrop::CBoxDrop()
{
ZeroMemory(&m_dropGroup, sizeof(m_dropGroup));
}
bool CBoxDrop::load(const char *sFile)
{
if (!sFile) return false;
wylib::stream::CMemoryStream ms;
if (ms.loadFromFile(sFile) <= 0)
{
OutputMsg(rmError, _T("load script file(%s) failed"), sFile);
return false;
}
CCustomLuaPreProcessor pp;
GetLogicServer()->GetVSPDefine().RegisteToPreprocessor(pp);
LPCSTR sScript = pp.parse((LPCSTR)ms.getMemory(), sFile);
if (!sScript)
{
OutputMsg(rmError, _T("script file(%s) preprocess failed"), sFile);
return false;
}
bool bRet = setScript(sScript);
if (!bRet)
{
OutputMsg(rmError, _T("setscript failed(%s)"), sFile);
return false;
}
bRet = loadData();
setScript(NULL);
return bRet;
}
bool CBoxDrop::loadData()
{
releaseData();
if (!openGlobalTable(DropTableName))
{
OutputMsg(rmError, _T("load box drop data failed, can't find table: %s"), DropTableName);
return false;
}
const INT_PTR dropCount = lua_objlen(m_pLua, -1);
memset(m_dropGroup.groupMemberCount, 0, sizeof(m_dropGroup.groupMemberCount));
memset(m_dropGroup.groupNextHitIndex, 0, sizeof(m_dropGroup.groupNextHitIndex));
if (dropCount > 0)
{
m_dropGroup.data.count = dropCount;
m_dropGroup.data.pData = (PONEDROPDATA)malloc(dropCount * sizeof(ONEDROPDATA));
ZeroMemory(m_dropGroup.data.pData, dropCount * sizeof(ONEDROPDATA));
int nIdx = 0;
if (enumTableFirst())
{
PONEDROPDATA pBegin =(PONEDROPDATA )m_dropGroup.data.pData;
do
{
PONEDROPDATA pData = pBegin +nIdx;
int nDef = 0;
pData->bAwardType = (char)getFieldInt("type",&nDef); //奖励类型
pData->bStrong = (char)getFieldInt("strong",&nDef);
pData->bQuality = (char)getFieldInt("quality",&nDef);
pData->bBind = (char)getFieldInt("bind", &nDef);
//最小数量
pData->nMinCount = (int)getFieldInt("mincount", &nDef);
//最大数量
pData->nMaxCount = (int)getFieldInt("maxcount", &nDef);
pData->nCount = (int)getFieldInt("count", &nDef);
pData->wItemID = (WORD)getFieldInt("id",&nDef);
pData->nPropability = getFieldInt("propability",&nDef);
pData->bGroupId = (BYTE)getFieldInt("group",&nDef);
pData->nTime = getFieldInt("time", &nDef);
//最低的强化
pData->bMinStrong =(char) getFieldInt("strongMin",&nDef );
//最低的品质
pData->bMinQuality =(char) getFieldInt("qualityMin",&nDef );
//-1表示任何性别
nDef =-1;
pData->bSex =(char) getFieldInt("sex",&nDef );
//0表示任何的职业
nDef =0;
pData->bJob =(char) getFieldInt("job",&nDef );
pData->bAuxParam =(char)getFieldInt("broadcast",&nDef);
pData->nQualityDataIndex = (WORD)getFieldInt("qualityDataIndex",&nDef);
if (pData->bGroupId > MAX_DROP_GROUP_COUNT)
{
OutputMsg(rmError,_T("%s 掉落组的ID=%d过大最大=%d"), __FUNCTION__, (int)(pData->bGroupId), MAX_DROP_GROUP_COUNT);
//pData->bGroupId = 0;
return false;
}
if (pData->bGroupId) {
m_dropGroup.groupMemberCount[pData->bGroupId-1]++;
}
if (pData->nPropability) {
pData->nSeed = int(wrand(pData->nPropability)+1);
}
nIdx++;
}
while (enumTableNext());
}
}
closeTable();
return true;
}
DropItemList CBoxDrop::drop(void * pEntity )
{
int sex=-1, job=0;
if(pEntity )
{
CEntity * pActor = (CEntity*) pEntity;
if( pActor->GetType() == enActor)
{
//玩家的职业和等级
sex = pActor->GetProperty<int>(PROP_ACTOR_SEX);
job = pActor->GetProperty<int>(PROP_ACTOR_VOCATION);
}
}
DropItemList dropList;
INT_PTR nDropCount= m_dropGroup.data.count;
if (nDropCount <=0 ) return dropList;
const CStdItemProvider& itemProvider = GetLogicServer()->GetDataProvider()->GetStdItemProvider();
int nLastGroupID=-1; //遍历的上1个组的ID
int nLastGroupIndex =-1;
bool bGroupHasDrop =false; //这个组是1否已经掉落过了
bool bBagFullFlag[MAX_TEAM_MEMBER_COUNT] = {0}; // 小队玩家任务背包已满标记,用于给用户提示用
int nGroupCurrentPos =0; //组内开始的位置
int nCurrentGroupHeadPos =0; //当前遍历的组的第一个元素的位置
for(INT_PTR i =0 ; i< nDropCount; i++)
{
bool flag =true; //掉落的标记
ONEDROPDATA * pData = &m_dropGroup.data[i];
//这个物品无法掉落
if(pData->bGroupId )
{
if( pData->bGroupId != nLastGroupID )
{
nCurrentGroupHeadPos = (int)i;
nLastGroupID = pData->bGroupId;
nGroupCurrentPos = m_dropGroup.groupNextHitIndex [pData->bGroupId -1];
bGroupHasDrop = false;
}
pData = &m_dropGroup.data[nCurrentGroupHeadPos + nGroupCurrentPos]; //实际数据是取后面的那一个
nGroupCurrentPos ++;
nGroupCurrentPos %= m_dropGroup.groupMemberCount[pData->bGroupId -1]; //组内的下一
}
if(CanDrop(pData,sex,job) == false) continue;
pData->nDeadTimes ++; //死亡次数++
if(pData->nDeadTimes != pData->nSeed )
{
flag =false;
}
if(pData->bGroupId )
{
if( flag )
{
if(!bGroupHasDrop )
{
bGroupHasDrop = true ; //这个组里已经掉落了
//如果已经掉落了,那么下次要从下一个开始遍历
m_dropGroup.groupNextHitIndex [pData->bGroupId -1]= nGroupCurrentPos;
}
else
{
flag =false; //如果已经掉落了,那么就不掉了了
}
}
}
if(pData->nPropability >0 && pData->nDeadTimes >= pData->nPropability) //已经死了很多次了,需要循环
{
pData->nDeadTimes =0;
//第几次死亡能够掉落
pData->nSeed = GetGlobalLogicEngine()->GetRandValue() %pData->nPropability +1;
}
if(!flag) continue;
SetItemInfo(dropList,pData); //添加
}
return dropList;
}
void CBoxDrop::SetItemInfo(DropItemList& dropList,ONEDROPDATA * pData )
{
// INT_PTR nItemID= pData->wItemID;
// if(nItemID)
// {
//去掉nItemID判断修改为通过bAwardType奖励类型 进行奖励
DropItemInfo dropItem;
dropItem.btAwardType = pData->bAwardType;
dropItem.wItemId = pData->wItemID;
dropItem.btCount = (int)pData->nCount;
int nRandCount = 0;
//随机奖励数量
if (pData->nMinCount >= 0 && pData->nMaxCount > 0 )
{
dropItem.btCount = (pData->nMinCount + wrand(abs((int)(pData->nMaxCount-pData->nMinCount))+1));
}
//dropItem.nRandCount = (unsigned int)nRandCount;
//支持随机属性
if (pData->bQuality <0)
{
int nValue =0;
if( pData->bMinQuality >0 )
{
nValue = -1* pData->bQuality;
if( nValue > pData->bMinQuality)
{
nValue = pData->bMinQuality + GetGlobalLogicEngine()->GetRandValue() % (nValue - pData->bMinQuality +1);
}
else
{
nValue = pData->bMinQuality;
}
}
else
{
nValue = -1 * pData->bQuality;
nValue = GetGlobalLogicEngine()->GetRandValue() % (nValue +1);
}
dropItem.btQuality = (BYTE)nValue;
}
else
{
dropItem.btQuality = (BYTE)pData->bQuality;
}
if(pData->bStrong <0)
{
int nValue =0;
if( pData->bMinStrong >0 )
{
nValue = -1* pData->bStrong;
if( nValue > pData->bMinStrong)
{
nValue = pData->bMinStrong + GetGlobalLogicEngine()->GetRandValue() % (nValue - pData->bMinStrong +1);
}
else
{
nValue = pData->bMinStrong;
}
}
else
{
nValue = -1 * pData->bStrong;
nValue = GetGlobalLogicEngine()->GetRandValue() % (nValue +1);
}
dropItem.btStrong = (BYTE)nValue;
}
else
{
dropItem.btStrong = (BYTE)pData->bStrong;
}
dropItem.btBind = (BYTE)pData->bBind;
dropItem.btAuxParam = pData->bAuxParam;
dropItem.nTime = pData->nTime;
dropItem.nQualityDataIndex = pData->nQualityDataIndex; //附加属性idx
dropList.addItem(dropItem);
// }
// else //0表示金钱,金钱直接发给玩家了
// {
// dropList.addMoney(pData->nCount);
// }
}
DropItemList CBoxDrop::proabilityDrop(void * pEntity )
{
int sex=-1, job=0;
if(pEntity )
{
CEntity * pActor = (CEntity*) pEntity;
if( pActor->GetType() == enActor)
{
//玩家的职业和等级
sex = pActor->GetProperty<int>(PROP_ACTOR_SEX);
job = pActor->GetProperty<int>(PROP_ACTOR_VOCATION);
}
}
DropItemList dropList;
int total[MAX_DROP_GROUP_COUNT]; //最大的掉落组
int rand[MAX_DROP_GROUP_COUNT]; //随机数
int result[MAX_DROP_GROUP_COUNT]; //结果
memset(&total,0,sizeof(total));
memset(&rand,0,sizeof(rand));
memset(&result,0,sizeof(result));
INT_PTR nDropCount = m_dropGroup.data.count;
//计算概率的总和
for(INT_PTR i =0 ; i< nDropCount; i++)
{
ONEDROPDATA * pData = &m_dropGroup.data[i];
if(pData->bGroupId && pData->bGroupId <= MAX_DROP_GROUP_COUNT)
{
if(CanDrop(pData,sex,job) == false) continue;
{
total[pData->bGroupId -1] += pData->nPropability;
}
}
}
//计算出随机数
for(INT_PTR i=0; i< MAX_DROP_GROUP_COUNT; i++)
{
if(total[i] >0)
{
rand[i] =(int)(1+ wrand( total[i]));
}
}
INT_PTR nCurrentGroupId=0;
INT_PTR nCurrentTotal=0;
for(INT_PTR i =0 ; i< nDropCount; i++)
{
bool isHit =false; //是否命中了
ONEDROPDATA * pData = &m_dropGroup.data[i];
INT_PTR nGroupPos= pData->bGroupId -1;
if(nGroupPos >=0 && nGroupPos < MAX_DROP_GROUP_COUNT)
{
if(result[nGroupPos] >=0)
{
if(CanDrop(pData,sex,job) == false) continue;
result[nGroupPos] += pData->nPropability;
if (result[nGroupPos] >=rand[nGroupPos] )
{
result[nGroupPos] =-1;//一个组里已经有命中的了
isHit =true;
}
}
}
else
{
isHit =CanDrop(pData,sex,job);
}
if(!isHit) continue;
SetItemInfo(dropList,pData);
}
return dropList;
}
void CBoxDrop::releaseData()
{
if (m_dropGroup.data.pData)
{
free(m_dropGroup.data.pData);
m_dropGroup.data.pData = 0;
}
}
void CBoxDrop::destroy()
{
releaseData();
CBoxDropMgr::getSingleton().destroyBoxDrop(this);
}
CBoxDropMgr& CBoxDropMgr::getSingleton()
{
return *s_BoxDropMgr;
}
void CBoxDropMgr::initialize()
{
if (::InterlockedIncrement(&s_boxDropMgrCnt) == 1)
{
s_BoxDropMgr = new CBoxDropMgr();
}
}
void CBoxDropMgr::release()
{
if (::InterlockedDecrement(&s_boxDropMgrCnt) == 0)
{
SafeDelete(s_BoxDropMgr);
}
}
CBoxDropMgr::~CBoxDropMgr()
{
INT_PTR count = m_boxObjectList.count();
for (INT_PTR i = 0; i < count; i++)
{
// 强制销毁
m_boxObjectList[i]->releaseData();
destroyBoxDropImpl(m_boxObjectList[i]);
}
m_boxObjectList.clear();
}
CBoxDrop* CBoxDropMgr::createBoxDrop(const char *pKey)
{
if (!pKey) return 0;
CBoxDrop *box = m_dataAllocator.allocObject();
if (box) {
new(box)CBoxDrop();
box->SetObjectName(pKey);
box->addRef();
GlobalObjectMgr::getSingleton().SetGlobalObject(pKey, box);
m_boxObjectList.add(box);
}
return box;
}
void CBoxDropMgr::destroyBoxDrop(CBoxDrop *bd)
{
destroyBoxDropImpl(bd);
removeFromList(bd);
}
void CBoxDropMgr::removeFromList(CBoxDrop *bd)
{
for (INT_PTR i = 0; i < m_boxObjectList.count(); i++)
{
if (m_boxObjectList[i] == bd)
m_boxObjectList.remove(i);
}
}
void CBoxDropMgr::destroyBoxDropImpl(CBoxDrop *bd)
{
if (bd) {
GlobalObjectMgr::getSingleton().ClearGlobalObject(bd->GetObjectName());
bd->~CBoxDrop();
m_dataAllocator.freeObject(bd);
}
}