void testRand(void) { time_t start, end; int * result = NULL; printf("n = %d, k = %d\n", COUNT, COUNT/2); start = time(NULL); result = RandNumber(COUNT, COUNT/2); end = time(NULL); printf("time = %d\n\n", end - start); if (result) { if (COUNT < 200) {//数量较小时,查看结果是否符合要求 int i; for (i = 0; i < COUNT / 2; i++) { printf("%d, ", result[i]); } printf("\n"); } free(result); result = NULL; } else { printf("RandNumber failed!\n\n"); } }
int main(int argc, char **argv) { Element stack[MAX_STACK]; int i; for (i = 0; i < 10; i++) { Push(stack, RandNumber(i+5)); } #ifdef DEBUG printf("top = %d\n", top); #endif Print(stack); printf("\nTest Pop operation: %d\n", Pop(stack).item); return 0; }
//游戏开始 bool __cdecl CTableFrameSink::OnEventGameStart() { m_bIsGameEnd=false; m_pITableFrame->SetGameStatus(GS_PLAYING); srand((UINT)time(NULL)); int nRandNum=rand()%19; CMD_S_GameStart start; //ZeroMemory(&start,sizeof(start)); //memset(&start,ERROR_ALL,sizeof(start)); memset(start.bChess, ERROR_ALL, sizeof(start.bChess)); //初始化棋盘 int tempvalue,randnum; CArrayTemplate<CPoint> Map; for(int i=0;i<CHESSCOUNT_H;i++) { for(int j=0;j<CHESSCOUNT_W;j++) { if(LLK_MAP[nRandNum][i][j]) { Map.Add(CPoint(i,j)); } } } if(Map.GetCount()%2 == 1) { TRACE("地图棋子为奇数"); return false; } //随地图 for(; Map.GetCount()!=0;) { //随机一个棋子类型 if(rand()%10) { tempvalue = RandNumber(0,MAX_CHESS_VALUE); } else { tempvalue =RandNumber(PROP_MIN_VALUE,PROP_MIN_VALUE+PROP_MAX_CNT); } //找出第一个位置 randnum = RandNumber(0,(int)Map.GetCount()); start.bChess[Map.ElementAt(randnum).x][Map.ElementAt(randnum).y] = tempvalue; Map.RemoveAt(randnum); //找出第二个位置 randnum = RandNumber(0,(int)Map.GetCount()); start.bChess[Map.ElementAt(randnum).x][Map.ElementAt(randnum).y] = tempvalue; Map.RemoveAt(randnum); } IServerUserItem * pIServerUserItem; for (WORD i=0;i<GAME_PLAYER;i++) { pIServerUserItem=m_pITableFrame->GetServerUserItem(i); if (pIServerUserItem!=NULL) { m_bPlayStatus [i] = GS_PLAYING; memcpy(m_bChess[i],start.bChess,sizeof(m_bChess[i])); } else m_bPlayStatus [i] = GS_FREE; } memcpy(start.bPlayState, m_bPlayStatus, sizeof(m_bPlayStatus)); //发送地图数据 for(int i=0;i<GAME_PLAYER;i++) { memcpy(start.bPropCnt,m_bPropCnt[i],sizeof(m_bPropCnt[i])); m_pITableFrame->SendTableData(i,SUB_S_GAME_START,&start,sizeof(start)); m_pITableFrame->SendLookonData(i,SUB_S_GAME_START,&start,sizeof(start)); } return true; }
//游戏消息处理 bool __cdecl CTableFrameSink::OnGameMessage(WORD wSubCmdID, const void * pDataBuffer, WORD wDataSize, IServerUserItem * pIServerUserItem) { if(m_bIsGameEnd) { return true; } switch (wSubCmdID) { case SUB_C_GUIDE: { WORD wSeat = pIServerUserItem->GetChairID(); //指南针道具 m_bPropCnt[wSeat][PROP_GUIDE]--; return true; } case SUB_C_BOMB: { WORD wSeat = pIServerUserItem->GetChairID(); //指南针道具 m_bPropCnt[wSeat][PROP_BOM]--; return true; } case SUB_C_STOPIT: { if(wDataSize != sizeof(CMD_C_StopIt)) return false; CMD_C_StopIt *pCnt = (CMD_C_StopIt *)pDataBuffer; WORD wSeat = pIServerUserItem->GetChairID(); CMD_S_StopIt Stop; Stop.nSrcUserId =(BYTE)wSeat; Stop.nDesUserId =pCnt->nDesUserId; //禁手道具 m_bPropCnt[wSeat][PROP_STOPIT]--; Stop.nPropCount = m_bPropCnt[wSeat][PROP_STOPIT]; m_pITableFrame->SendTableData(INVALID_CHAIR,SUB_S_STOPIT,&Stop,sizeof(Stop)); m_pITableFrame->SendLookonData(INVALID_CHAIR,SUB_S_STOPIT,&Stop,sizeof(Stop)); return true; } case SUB_C_CLOG: { if(wDataSize != sizeof(CMD_C_Clog)) return false; CMD_C_Clog *pCnt = (CMD_C_Clog *)pDataBuffer; WORD wSeat = pIServerUserItem->GetChairID(); CMD_S_Clog Clog; memset(&Clog,ERROR_ALL,sizeof(Clog)); Clog.nDesUserId = pCnt->nDesUserId; Clog.nSrcUserId = (BYTE)wSeat; CArrayTemplate<CPoint> Map; for(int i=0;i<CHESSCOUNT_H;i++) { for(int j=0;j<CHESSCOUNT_W;j++) { if(m_bChess[pCnt->nDesUserId][i][j] == ERROR_ALL &&i>0 &&i<CHESSCOUNT_H-1&&\ j>0 && j<CHESSCOUNT_W-1) { Map.Add(CPoint(i,j)); } } } if(Map.GetCount()) { int randMaxNum=(int)Map.GetCount() >=12?12:(int)Map.GetCount(); //取偶数 randMaxNum = randMaxNum%2?randMaxNum-1:randMaxNum; srand((unsigned int)time(NULL)); int pos=0; while(randMaxNum>0) { BYTE chessValue =RandNumber(0,MAX_CHESS_VALUE); int randNum = rand()%(int)Map.GetCount(); Clog.nChessPosX[pos] =(BYTE)Map.GetAt(randNum).y; Clog.nChessPosY[pos] =(BYTE)Map.GetAt(randNum).x; Clog.nChessFace[pos]=chessValue; pos++; Map.RemoveAt(randNum); randMaxNum--; randNum = rand()%(int)Map.GetCount(); Clog.nChessPosX[pos] =(BYTE)Map.GetAt(randNum).y; Clog.nChessPosY[pos] =(BYTE)Map.GetAt(randNum).x; Clog.nChessFace[pos]=chessValue; pos++; Map.RemoveAt(randNum); randMaxNum--; } } //障碍道具 m_bPropCnt[wSeat][PROP_CLOG]--; Clog.nPropCount = m_bPropCnt[wSeat][PROP_CLOG]; m_pITableFrame->SendTableData(INVALID_CHAIR,SUB_S_CLOG,&Clog,sizeof(Clog)); m_pITableFrame->SendLookonData(INVALID_CHAIR,SUB_S_CLOG,&Clog,sizeof(Clog)); return true; } case SUB_C_TIMER: { if(wDataSize != sizeof(CMD_C_Timer)) return false; CMD_C_Timer *pCnt = (CMD_C_Timer *)pDataBuffer; WORD wSeat = pIServerUserItem->GetChairID(); m_bTimerCnt[wSeat]=pCnt->nTime; CString str; str.Format("--%d--\n",m_bTimerCnt[wSeat]); TRACE(str); if(m_bTimerCnt[wSeat] ==0) { return SubGameLost(wSeat); } return true; } case SUB_C_LINK: { if(wDataSize != sizeof(CMD_C_Link)) return false; CMD_C_Link *pPos = (CMD_C_Link *)pDataBuffer; WORD wSeat = pIServerUserItem->GetChairID(); CArrayTemplate<CPoint> path; CPoint p1,p2; if(!m_GameLogic.IsLink(m_bChess[wSeat],CPoint(pPos->nFirst_X,pPos->nFirst_Y),CPoint(pPos->nEnd_X,pPos->nEnd_Y),\ &path,&p1,&p2)) { return false; } else { if(pPos->bLinkKind ==LK_SERIES_LINK) { m_bSeriesLinkCnt[wSeat] ++; } BYTE bValue =m_bChess[wSeat][pPos->nFirst_Y][pPos->nFirst_X]; m_bChess[wSeat][pPos->nFirst_Y][pPos->nFirst_X]=ERROR_ALL; m_bChess[wSeat][pPos->nEnd_Y][pPos->nEnd_X]=ERROR_ALL; CMD_S_Link LinkPos; ZeroMemory(&LinkPos,sizeof(LinkPos)); LinkPos.nEnd_X =pPos->nEnd_X; LinkPos.nEnd_Y =pPos->nEnd_Y; LinkPos.nFirst_X =pPos->nFirst_X; LinkPos.nFirst_Y =pPos->nFirst_Y; LinkPos.nCurrentPlayer = (BYTE)wSeat; if(bValue >=PROP_MIN_VALUE) { m_bPropCnt[wSeat][bValue-PROP_MIN_VALUE] ++; LinkPos.nPropCount =m_bPropCnt[wSeat][bValue-PROP_MIN_VALUE]; LinkPos.nPropType = bValue-PROP_MIN_VALUE; } else LinkPos.nPropType = ERROR_ALL; m_pITableFrame->SendTableData(INVALID_CHAIR,SUB_S_LINK,&LinkPos,sizeof(LinkPos)); m_pITableFrame->SendLookonData(INVALID_CHAIR,SUB_S_LINK,&LinkPos,sizeof(LinkPos)); //检验游戏是否结束 bool bIsGameEnd=true; for(int i=0;i<CHESSCOUNT_H;i++) { for(int j=0;j<CHESSCOUNT_W;j++) { if(m_bChess[wSeat][i][j] != ERROR_ALL) { i=CHESSCOUNT_H; bIsGameEnd=false; break; } } } if(bIsGameEnd) { GameEnd(wSeat,GER_NORMAL); } return true; } } case SUB_C_REALIGN: { if(wDataSize != sizeof(CMD_C_Realign)) return false; CMD_C_Realign *pcRealign = (CMD_C_Realign *)pDataBuffer; WORD wSeat = pIServerUserItem->GetChairID(); memcpy(m_bChess[wSeat],pcRealign->nChess,sizeof(pcRealign->nChess)); CMD_S_Realign sRealign; sRealign.nCurrentPlayer = (BYTE)wSeat; memcpy(sRealign.nChess,pcRealign->nChess,sizeof(pcRealign->nChess)); //4为障碍道具 m_bPropCnt[wSeat][PROP_RESET]--; sRealign.nPropCount = m_bPropCnt[wSeat][PROP_RESET]; m_pITableFrame->SendTableData(INVALID_CHAIR,SUB_S_REALIGN,&sRealign,sizeof(sRealign)); m_pITableFrame->SendLookonData(INVALID_CHAIR,SUB_S_REALIGN,&sRealign,sizeof(sRealign)); return true; } default: { return false; } } return false; }
// Build Drop CDrop* CWorldServer::GetDrop( CMonster* thismon ) { try{ CDrop* newdrop = new (nothrow) CDrop; if(newdrop==NULL) { Log(MSG_WARNING, "Error allocing memory [getdrop]" ); return NULL; } newdrop->clientid = GetNewClientID( ); newdrop->posMap = thismon->Position->Map; newdrop->pos = RandInCircle( thismon->Position->current, 3 ); newdrop->droptime = time(NULL); newdrop->owner = thismon->MonsterDrop->firsthit; newdrop->thisparty = thismon->thisparty; ClearItem(newdrop->item); int randv = RandNumber( 1, 100); if(thismon->MonsterDrop->mapdrop->level_max<thismon->MonsterDrop->firstlevel) randv = 100; if(randv<=30)//30% zuly [zulies will count as mapdrop] { if(thismon->MonsterDrop->mapdrop->level_max>=thismon->MonsterDrop->firstlevel) { newdrop->type = 1; //Drop Zuly newdrop->amount = thismon->thisnpc->level*5*Config.ZULY_RATE + RandNumber( 1, 10 ); return newdrop; } delete newdrop; return NULL; } CMDrops* thisdrops; newdrop->type = 2; //drop item drop switch( Config.DROP_TYPE ) { case 0://only map thisdrops = thismon->MonsterDrop->mobdrop; if(thisdrops->level_max<thismon->MonsterDrop->firstlevel) { delete newdrop; return NULL; } break; case 1://mob only thisdrops = thismon->MonsterDrop->mapdrop; if(thismon->thisnpc->level-thismon->MonsterDrop->firstlevel<-14) { delete newdrop; return NULL; } break; default://both randv = RandNumber(1,100); if(thismon->MonsterDrop->mapdrop!=NULL) if(thismon->MonsterDrop->mapdrop->level_max<thismon->MonsterDrop->firstlevel) randv = 100; if(randv>60)//select wich drop will use (map or mob) //40 - 60% { thisdrops = thismon->MonsterDrop->mobdrop; if((int)(thismon->thisnpc->level-thismon->MonsterDrop->firstlevel) < -14) { delete newdrop; return NULL; } } else { thisdrops = thismon->MonsterDrop->mapdrop; if(thisdrops->level_max<thismon->MonsterDrop->firstlevel) { delete newdrop; return NULL; } } break; } if(thisdrops==NULL) { thisdrops = thismon->MonsterDrop->mobdrop; if(thisdrops==NULL) { thisdrops = thismon->MonsterDrop->mapdrop; if(thisdrops==NULL) { newdrop->type = 1; //Drop Zuly newdrop->amount = thismon->thisnpc->level*5*Config.ZULY_RATE - RandNumber( 1, 20 ); return newdrop; } } } randv = 0; randv = RandNumber( 1, thisdrops->probmax ); DWORD prob = 1; for(UINT i=0;i<thisdrops->Drops.size();i++) { CDropInfo* dropinfo = thisdrops->Drops.at( i ); prob += dropinfo->prob; if(randv<=prob) { newdrop->item.itemtype = dropinfo->type; newdrop->item.itemnum = dropinfo->item; break; } } if(newdrop->item.itemtype==0) { Log(MSG_WARNING, "Drop Probability Highter: %i", randv ); delete newdrop; return NULL; } if(newdrop->item.itemtype>1 && newdrop->item.itemtype<10 && newdrop->item.itemtype!=JEWEL) { // Items drop with 0 refine newdrop->item.refine = 0; newdrop->item.lifespan = RandNumber( 30, 100 ); newdrop->item.durability = RandNumber( 35, 70 ); newdrop->item.socketed = false; randv = RandNumber( 1, 100 ); if( randv < 30 ) // 30% newdrop->item.stats = rand()%300; newdrop->item.appraised = newdrop->item.stats==0?true:false; } else { newdrop->item.lifespan = 100; newdrop->item.durability = 40; newdrop->item.socketed = false; newdrop->item.stats = 0; } newdrop->item.count = 1; if( newdrop->item.itemtype == 10 || newdrop->item.itemtype == 12 ) { newdrop->item.count = RandNumber( 1, 3 ); } if(newdrop->item.durability>100)newdrop->item.durability=100; if(newdrop->item.lifespan>100)newdrop->item.lifespan=100; newdrop->item.gem = 0; return newdrop; } catch(...) { Log(MSG_WARNING, "Error in CWorldServer::GetDrop( CMonster* thismon )(serverFunctions.cpp)" ); return NULL; } }
// Build Drop the PY way CDrop* CWorldServer::GetPYDrop( CMonster* thismon, UINT droptype ) { //if droptype = 1 then it is a normal drop. if it is 2 then it is a potential side drop. //Log( MSG_INFO, "PYDrops function selected" ); //Log( MSG_INFO, "monster is %i", thismon->montype ); if(droptype == 2) // monster is still alive { // this part of the function reserved for the later addition of side drops //return NULL; //temporary bypass for the side drop function // kicks it straight back if the monster is not dead if(thismon->thisnpc->side != 0) //perhaps we get a side drop?? { if(GServer->RandNumber(0,100) < thismon->thisnpc->sidechance) { droptype = thismon->thisnpc->side; } else { return NULL; //No drop this time } } else { return NULL; //No drop this time } } CDrop* newdrop = new (nothrow) CDrop; if(newdrop==NULL) { Log(MSG_WARNING, "Error allocing memory [getdrop]" ); return NULL; } newdrop->clientid = GetNewClientID( ); newdrop->posMap = thismon->Position->Map; newdrop->pos = RandInCircle( thismon->Position->current, 3 ); newdrop->droptime = time(NULL); newdrop->owner = thismon->MonsterDrop->firsthit; newdrop->thisparty = thismon->thisparty; ClearItem(newdrop->item); CPlayer* thisclient = GServer->GetClientByCID(thismon->MonsterDrop->firsthit); // code to modify drop chance for different levels //float charm = 0; //float droprate = thismon->thisnpc->dropchance; float droprate = Config.DROP_RATE; float leveldif = (float)thismon->thisnpc->level - (float)thisclient->Stats->Level; float dropchance = (droprate + (droprate * 0.01 * leveldif)); if(dropchance < 10) dropchance = 10; //always a small chance of a drop even when the mob is more than 20 levels beneath your own if(thismon->thisnpc->level == 1) dropchance = 80; if (GServer->RandNumber(0, 100)> dropchance) return NULL; // no drop here. not this time anyway. CItemType prob[MDropList.size()]; bool isdrop = false; int n = 0; int test = 0; long int probmax = 0; int itemnumber[MDropList.size()]; int itemtype[MDropList.size()]; int probability[MDropList.size()]; int alternate[MDropList.size()][8]; if( thismon->IsGhost()) { // Stuff to do if the mob is a ghost of any type int selection = 1 + rand()%10; if( selection <= 5 ) { newdrop->type = 1; //Drop Zuly. newdrop->amount = thismon->thisnpc->level * 10 * Config.ZULY_RATE + RandNumber( 1, 10 ); return newdrop; } else { for(int i=0; i<SkillbookList.size( ); i++) { newdrop->type = 2; CMDrops* thisdrop = GServer->SkillbookList.at(i); if(thisdrop->level_min <= thismon->thisnpc->level && thisdrop->level_max >= thismon->thisnpc->level) { itemnumber[n] = thisdrop->itemnum; itemtype[n] = thisdrop->itemtype; probability[n] = thisdrop->prob; probmax += thisdrop->prob; n++; } } } } else // Stuff to do if the mob isn't a ghost { int dropmode = 0; int randv = RandNumber( 1, 100); // Each monster has its own rates for zuly and item drops defined in the database if(randv > thismon->thisnpc->item + thismon->thisnpc->money) return NULL; // did not qualify to drop anything this time if(randv <= thismon->thisnpc->money) // zuly drop instead of item drop { newdrop->type = 1; newdrop->amount = thismon->thisnpc->level * 5 * Config.ZULY_RATE + RandNumber( 1, 10 ); return newdrop; } // this means it is an item drop randv = RandNumber( 1, 100); if(randv > 70) // 30% map drop { dropmode = 1; // map drop selected } else if(randv > 30) // 40% mob drop { dropmode = 2; //mob drop selected } else // 30% level drop { dropmode = 3; //leveldrop selected } int randomdrop = GServer->RandNumber(1, 100); for(int i=0; i<MDropList.size( ); i++) { isdrop=false; CMDrops* thisdrop = GServer->MDropList.at(i); if(thisdrop->mob == thismon->montype && dropmode == 2) // monster drop { test = GServer->RandNumber(1, 1000); if(test < thisdrop->prob) { isdrop = true; } } if(thisdrop->map == thismon->Position->Map && dropmode == 1) // map drop { test = GServer->RandNumber(1, 1000); if(thismon->thisnpc->level == 1) test = GServer->RandNumber(1, 10000); // make it less likely to get map drops from event mobs if(test < thisdrop->prob) { isdrop = true; } } if(thismon->thisnpc->level >= thisdrop->level_min && thismon->thisnpc->level <= thisdrop->level_max && dropmode == 3) { //Log(MSG_INFO, "Level drop selected. type %i number %i", thisdrop->itemtype, thisdrop->itemnum ); test = GServer->RandNumber(1, 1000); if(test < thisdrop->prob) { isdrop = true; } //else } if(isdrop == true) { if(droptype != 1) //side drops only. Skip if the item is not a match for side type { if(itemtype[n] != droptype)continue; } //droptype 1 is a regular drop itemnumber[n] = thisdrop->itemnum; itemtype[n] = thisdrop->itemtype; //probability[n] = thisdrop->prob; alternate[n][0] = 0; for(int i=1;i<8;i++) { alternate[n][i] = thisdrop->alt[i]; } n++; } } } int newn = n; if(n == 0) return NULL; int maxitems = n; // randomize the item from the list n = GServer->RandNumber(0, maxitems); newdrop->item.itemnum = itemnumber[n]; newdrop->item.itemtype = itemtype[n]; newdrop->type = 2; newdrop->item.lifespan = 10 + rand()%80; float dmod = 0; //random number from 0 to 100 made up of 4 sub numbers to keep //the average value near to 50 for(int i=0; i<4; i++) { float r1 = rand()%20; dmod += r1; } newdrop->item.durability = 10 + (int)dmod; if( newdrop->item.itemtype == 8 || newdrop->item.itemtype == 9 ) { //This probability is now configurable from WorldServer.conf int psocked = rand()%101; //Probability of finding a socketed item if( psocked < Config.SlotChance) //default should be around 5% needs to be rare { newdrop->item.socketed = true; } else { newdrop->item.socketed = false; } } else { newdrop->item.socketed = false; } //Log( MSG_INFO, "Socket are OK"); newdrop->item.appraised = false; newdrop->item.stats = 0; newdrop->item.count = 1; //int chamod = 0; int chamod = (int)floor(thisclient->Attr->Cha / 30); if(chamod <0) chamod = 0; int basedrop = 6 + chamod; //Base number of items to be dropped. add CHA to increase this. if( newdrop->item.itemtype == 10 || newdrop->item.itemtype == 12 ) { newdrop->item.count = RandNumber(0, basedrop); if(thismon->thisnpc->level == 1 && newdrop->item.count > 6) newdrop->item.count = 6; //limit the drop rate of items from level 1 event mobs if(newdrop->item.count==0) newdrop->item.count = 1; if(newdrop->item.itemtype == 10) { if(newdrop->item.itemnum >=441 && newdrop->item.itemnum <= 888)// skillbooks newdrop->item.count = 1; } if(newdrop->item.itemtype == 11) //gems only get 1 newdrop->item.count = 1; if(newdrop->item.itemtype == 12) { if(newdrop->item.itemnum > 300 && newdrop->item.itemnum < 360) //bullets get a lot higher count. { newdrop->item.count *= 10; newdrop->item.count += 10; } } } else if( newdrop->item.itemtype >1 && newdrop->item.itemtype !=7 && newdrop->item.itemtype < 10) { // check to see if the item will be refined int prefine = rand()%100; //Probability of finding a refined item int refinechance = Config.RefineChance; if(prefine < refinechance) // default = 5% { int refinelevel = rand()%101; //which level of refine do we actually get if( refinelevel < 5) //default 5% newdrop->item.refine = 4 * 16; else if( refinelevel < 15 ) //10% newdrop->item.refine = 3 * 16; else if(refinelevel < 35 ) // 20% newdrop->item.refine = 2 * 16; else // 65% newdrop->item.refine = 16; } else //99% newdrop->item.refine = 0; // will the item be a blue? bool blue = false; int bluechance1 = RandNumber( 1, 100); int bluechance2 = Config.BlueChance + chamod; Log( MSG_INFO, "Blue chance = %i", bluechance2); //This probability is now configurable from WorldServer.conf. CHA also has an effect if(bluechance1 < bluechance2) // some percentage of drops will be specials or blues whenever one is available. { Log( MSG_INFO, "Selected a blue item"); int p = 1; while(alternate[n][p] != 0 && p < 8) { p++; } if(p > 1) // blues available for this item { //Log( MSG_INFO, "blue item available"); p--; int bluenum = RandNumber( 1, p); newdrop->item.itemnum = alternate[n][bluenum]; blue=true; } } // will the items get stats? All blue items will. Uniques count as blues. int pstats = rand()%101; //Probability of the item having stats. default = 5% if(blue == true) { pstats = 1; } int StatChance = Config.StatChance; if( pstats < StatChance) // default 5% newdrop->item.stats = RandNumber( 1, 300); } newdrop->item.gem = 0; return newdrop; }
//hidden // Build Drop the PY way CDrop* CWorldServer::GetPYDrop( CMonster* thismon, UINT droptype ) { //if droptype = 1 then it is a normal drop. if it is 2 then it is a potential side drop. //Log(MSG_INFO,"GetPYDrop, monster %i, droptype %i",thismon->montype,droptype); if(droptype == 2) // monster is still alive { // kicks it straight back if the monster is not dead if(thismon->thisnpc->side != 0) //perhaps we get a side drop?? { if(GServer->RandNumber(0,100) < thismon->thisnpc->sidechance) { droptype = thismon->thisnpc->side; } else { return NULL; //No drop this time } } else { return NULL; //No drop this time } } CDrop* newdrop = new (nothrow) CDrop; if(newdrop==NULL) { Log(MSG_WARNING, "Error allocing memory [getdrop]" ); return NULL; } newdrop->clientid = GetNewClientID( ); newdrop->posMap = thismon->Position->Map; newdrop->pos = RandInCircle( thismon->Position->current, 3 ); newdrop->droptime = time(NULL); newdrop->owner = thismon->MonsterDrop->firsthit; newdrop->thisparty = thismon->thisparty; ClearItem(newdrop->item); CPlayer* thisclient = GServer->GetClientByCID(thismon->MonsterDrop->firsthit); if(thisclient == NULL) { Log(MSG_WARNING,"GetPYDrop:: Failed to create player"); return NULL; } // code to modify drop chance for different levels //float charm = 0; float charm = (float)thisclient->Attr->Cha / 5; float leveldif = (float)thismon->thisnpc->level - (float)thisclient->Stats->Level; float droprate = (float)GServer->Config.DROP_RATE + charm; //basic server rate + extra for player charm float dropchance = (droprate + (droprate * 0.01 * leveldif)); //Log(MSG_INFO,"charm %.2f, leveldif %.2f, droprate %.2f, dropchance %.2f",charm,leveldif,droprate,dropchance); if(dropchance < 10) dropchance = 10; //always a small chance of a drop even when the mob is more than 20 levels beneath your own //Log(MSG_INFO,"dropchance %.2f",dropchance); if(thismon->thisnpc->level == 1) dropchance = 80; //Log(MSG_INFO,"dropchance %.2f",dropchance); UINT lma_save_rand=0; lma_save_rand=GServer->RandNumber(0, 100); if (lma_save_rand>dropchance) { //Log(MSG_INFO,"no drop, %i > %.2f",lma_save_rand,dropchance); return NULL; // no drop here. not this time anyway. } //Log(MSG_INFO,"drop possible, %i <= %.2f",lma_save_rand,dropchance); CItemType prob[MDropList.size()]; bool isdrop = false; int n = 0; int test = 0; long int probmax = 0; int itemnumber[MDropList.size()]; int itemtype[MDropList.size()]; int probability[MDropList.size()]; int alternate[MDropList.size()][8]; if( thismon->IsGhost()) { // Stuff to do if the mob is a ghost of any type int selection = 1 + rand()%10; if( selection <= 3 ) //MP water { newdrop->type = 2; itemnumber[n] = 399; itemtype[n] = 12; probability[n] = 10; probmax =10; n++; } else if( selection <=6 ) //HP water { newdrop->type = 2; itemnumber[n] = 400; itemtype[n] = 12; probability[n] = 10; probmax =10; n++; } else //skillbooks { for(int i=0; i<SkillbookList.size( ); i++) { newdrop->type = 2; CMDrops* thisdrop = GServer->SkillbookList.at(i); if(thisdrop->level_min <= thismon->thisnpc->level && thisdrop->level_max >= thismon->thisnpc->level) { itemnumber[n] = thisdrop->itemnum; itemtype[n] = thisdrop->itemtype; probability[n] = thisdrop->prob; probmax += thisdrop->prob; n++; } } } } else { int randv = RandNumber( 1, 100); if(randv <= 30)//30% zuly drop instead of item drop { newdrop->type = 1; //Drop Zuly newdrop->amount = thismon->thisnpc->level * 5 * Config.ZULY_RATE + RandNumber( 1, 10 ); //Log(MSG_INFO,"zuly drop %i",newdrop->amount); return newdrop; } // Stuff to do if the mob isn't a ghost int randomdrop = GServer->RandNumber(1, 100); //enable the next line for debug purposes if you want to confirm a drop is working. //Log(MSG_INFO, "Mob type %i. Map = %i. Level = %i", thismon->montype, thismon->Position->Map,thismon->thisnpc->level); for(int i=0; i<MDropList.size( ); i++) { isdrop=false; CMDrops* thisdrop = GServer->MDropList.at(i); if(thisdrop->mob == thismon->montype) { //Mob drop possible. test = GServer->RandNumber(1, 1000); if(test < thisdrop->prob) { isdrop = true; //item will be added to the short list } } if(thisdrop->map == thismon->Position->Map) { //Map drop possible. test = GServer->RandNumber(1, 1000); if(thismon->thisnpc->level == 1) test = GServer->RandNumber(1, 10000); // make it less likely to get map drops from event mobs if(test < thisdrop->prob) { isdrop = true; //item will be added to the short list } } if(thismon->thisnpc->level >= thisdrop->level_min && thismon->thisnpc->level <= thisdrop->level_max) { //Level drop possible test = GServer->RandNumber(1, 1000); if(test < thisdrop->prob) { isdrop = true; //item will be added to the short list } } if(isdrop == true) //Add item to the short list { if(droptype != 1) //side drops only. Skip if the item is not a match for side type { if(itemtype[n] != droptype)continue; } //droptype 1 is a regular drop itemnumber[n] = thisdrop->itemnum; itemtype[n] = thisdrop->itemtype; //probability[n] = thisdrop->prob; alternate[n][0] = 0; for(int i=1;i<8;i++) { alternate[n][i] = thisdrop->alt[i]; } n++; } } } int newn = n; if(n == 0) return NULL; int maxitems = n; //maxitems is the number of items in the shortlist // randomize the item from the shortlist. items get equal chance n = GServer->RandNumber(0, maxitems); newdrop->item.itemnum = itemnumber[n]; newdrop->item.itemtype = itemtype[n]; newdrop->type = 2; newdrop->item.lifespan = 10 + rand()%80; float dmod = 0; //random number from 0 to 100 made up of 4 sub numbers to keep //the average value near to 50 for(int i=0; i<4; i++) { float r1 = rand()%20; dmod += r1; } newdrop->item.durability = 10 + (int)dmod; if( newdrop->item.itemtype == 8 || newdrop->item.itemtype == 9 ) { //This probability is now configurable from WorldServer.conf int psocked = rand()%101; //Probability of finding a socketed item if( psocked < Config.SlotChance) //default should be around 5% needs to be rare { newdrop->item.socketed = true; } else { newdrop->item.socketed = false; } } else { newdrop->item.socketed = false; } newdrop->item.appraised = false; newdrop->item.stats = 0; newdrop->item.count = 1; //chamod = a modifier based on the character's CHA stat. Increases the number of drops int chamod = (int)floor(thisclient->Attr->Cha / 20); if(chamod <0) chamod = 0; int basedrop = 6 + chamod; //Base number of items to be dropped. add CHA to increase this. if( newdrop->item.itemtype == 10 || newdrop->item.itemtype == 12 ) { newdrop->item.count = RandNumber(0, basedrop); if(thismon->thisnpc->level == 1 && newdrop->item.count > 6) newdrop->item.count = 6; //limit the drop rate of items from level 1 event mobs if(newdrop->item.count==0) newdrop->item.count = 1; // Skillbooks & Chests if(newdrop->item.itemtype == 10) { if((newdrop->item.itemnum >=441 && newdrop->item.itemnum <= 888) || (newdrop->item.itemnum >=247 && newdrop->item.itemnum <= 249) || (newdrop->item.itemnum >=270 && newdrop->item.itemnum <= 275) || (newdrop->item.itemnum >=1001 && newdrop->item.itemnum <= 1028) || (newdrop->item.itemnum >=1110 && newdrop->item.itemnum <= 1178) || (newdrop->item.itemnum >=1080 && newdrop->item.itemnum <= 1090) ) newdrop->item.count = 1; // just one skill book or chest per drop /* 441-888 Skills 247-249 Christmas Presents 270-275 Dirty Stones 1001-1028 Prison Chests 1110-1178 Dispensers 1080-1090 Event Boxes 1200-1201 Christmas Gift - Present Box - Mileage 1202-1203 Boy and Girl Snow Suit - Mileage */ } // Gem Drops if(newdrop->item.itemtype == 11) newdrop->item.count = 1; // just one gem per drop if(newdrop->item.itemtype == 12) { if(newdrop->item.itemnum > 300 && newdrop->item.itemnum < 360) //bullets get a lot higher count. { newdrop->item.count *= 10; newdrop->item.count += 10; } } } else if( newdrop->item.itemtype >1 && newdrop->item.itemtype !=7 && newdrop->item.itemtype < 10) { // check to see if the item will be refined int prefine = rand()%100; //Probability of finding a refined item if(prefine < Config.RefineChance) // default = 5% { int refinelevel = rand()%101; //which level of refine do we actually get if( refinelevel < 5) //default 5% newdrop->item.refine = 3 * 16; else if( refinelevel < 11 ) //10% newdrop->item.refine = 2 * 16; else // 90% newdrop->item.refine = 16; } else //99% newdrop->item.refine = 0; // will the item be a blue? int blue = 0; int bluechance1 = RandNumber( 1, 100); int bluechance2 = Config.BlueChance + chamod; // will the items get stats? All blue items will. int pstats = rand()%101; //Probability of the item having stats. default = 5% //This probability is now configurable from WorldServer.conf. CHA also has an effect if(bluechance1 < bluechance2) // some percentage of drops will be specials or blues whenever one is available. { //Log( MSG_INFO, "Selected a blue item"); int p = 1; while(alternate[n][p] != 0 && p < 8) { p++; } if(p > 1) // blues available for this item { p--; int bluenum = RandNumber( 1, p); newdrop->item.itemnum = alternate[n][bluenum]; pstats = 1; //make sure we get stats for this item } /*else { //Sorry blue item not available for this item }*/ } //Uniques count as blues. if(newdrop->item.itemnum > 900)pstats = 1; //make sure we get stats for this unique item if( pstats < Config.StatChance) { // default 5% //PY stats newdrop->item.stats = GetExtraStats( 0 ); //newdrop->item.stats = rand()%300; } } newdrop->item.gem = 0; //Log(MSG_INFO,"drop %i* (%i:%i)",newdrop->amount,newdrop->type,newdrop->item); return newdrop; }