void CInstance::CreateMonsterRun(const int64 &time) { if (time > m_CreateTime + m_CreateMonsterDelayTime) { if (m_MonsterCount == 0) { CSVData::stInstanceMonster *monsterinfo; while (!m_InstanceMonster.empty()) { monsterinfo = m_InstanceMonster.front(); if (monsterinfo->nWave == m_NowWave) { if (AddMonster(monsterinfo->nMonsterID, monsterinfo->nX, monsterinfo->nY, monsterinfo->nZ)) { ++m_MonsterCount; } else { RunStateError("副本:%d 地图:%d 添加monster:%d 失败!", GetInstanceBaseID(), GetMapID(), monsterinfo->nMonsterID); } m_InstanceMonster.pop_front(); } } } } }
// Respawn a Monster void CMap::RespawnMonster( ) { #ifndef USEIFO for(UINT k=0;k<MonsterSpawnList.size( );k++) { CSpawnArea* thisspawn = MonsterSpawnList.at(k); if (thisspawn->respawntime<2)thisspawn->respawntime=2; clock_t rtime = clock() - thisspawn->lastRespawnTime; if((rtime > thisspawn->respawntime*CLOCKS_PER_SEC && thisspawn->amon<thisspawn->max)|| thisspawn->amon<thisspawn->min ) { fPoint position = GServer->RandInPoly( thisspawn->points, thisspawn->pcount ); AddMonster( thisspawn->montype, position, 0, thisspawn->mobdrop, thisspawn->mapdrop, thisspawn->id ); thisspawn->lastRespawnTime = clock(); } } #else for (UINT j = 0; j < MobGroupList.size(); j++) { CMobGroup* thisgroup = MobGroupList.at(j); clock_t rtime = clock() - thisgroup->lastRespawnTime; if (rtime < (long)thisgroup->respawntime*CLOCKS_PER_SEC || thisgroup->active >= thisgroup->limit) continue; for (UINT k = thisgroup->active; k < thisgroup->limit; k++) { CMob *thismob; if (thisgroup->tacMobs.size() > 0 && thisgroup->basicKills >= thisgroup->tacticalpoints) { thismob = thisgroup->tacMobs.at(thisgroup->curTac); thisgroup->basicKills = 0; thisgroup->curTac++; if (thisgroup->curTac >= thisgroup->tacMobs.size()) thisgroup->curTac = 0; } else { thismob = thisgroup->basicMobs.at(thisgroup->curBasic); thisgroup->curBasic++; if (thisgroup->curBasic >= thisgroup->basicMobs.size()) thisgroup->curBasic = 0; } for (UINT i = 0; i < thismob->amount; i++) { fPoint position = GServer->RandInCircle( thisgroup->point, thisgroup->range ); AddMonster( thismob->mobId, position, 0, thismob->mobdrop, thismob->mapdrop, thisgroup->id ); } } } #endif }
// Respawn a Monster void CMap::RespawnMonster( ) { for(UINT k=0; k<MonsterSpawnList.size( ); k++) { CSpawnArea* thisspawn = MonsterSpawnList.at(k); clock_t rtime = clock() - thisspawn->lastRespawnTime; if((rtime > thisspawn->respawntime*CLOCKS_PER_SEC && thisspawn->amon<thisspawn->max) || thisspawn->amon<thisspawn->min ) { fPoint position = GServer->RandInPoly( thisspawn->points, thisspawn->pcount ); AddMonster( thisspawn->montype, position, 0, thisspawn->mobdrop, thisspawn->mapdrop, thisspawn->id ); thisspawn->lastRespawnTime = clock(); } } }
SFight* CFightCopy::AddFightToMonster( SUser *puser, uint32 target_id ) { if ( NULL == puser ) return NULL; //7天超时 SFight *psfight = theFightDC.add( 86400 * 7 ); if ( NULL == psfight ) return NULL; psfight->fight_type = kFightTypeCopy; psfight->box_randomseed = (uint32)rand_r( thread_rand_seed() ); psfight->fight_randomseed = (uint32)rand_r( thread_rand_seed() ); //user::SetFightId( puser, psfight->fight_id ); psfight->ack_id = puser->guid; AddSoldier( psfight, puser->guid, kFightLeft ); CMonsterData::SData *pmonster = theMonsterExt.Find( target_id ); if ( NULL == pmonster ) { theFightDC.del( psfight->fight_id ); return NULL; } uint32 copy_id = (target_id-1)/100+1; psfight->def_id = target_id; for( std::vector<uint32>::iterator jter = pmonster->fight_monster.begin(); jter != pmonster->fight_monster.end(); ++jter ) { AddMonster( psfight, *jter, kFightRight ); } //需要判断是不是已经打通 SCopyLog copy_log = copy::get_copy_log( puser, copy_id ); if ( copy_log.copy_id == 0 ) psfight->help_monster = pmonster->help_monster; //初始化seqno_map psfight->seqno_map[puser->guid] = 0; SetFightInfo( psfight ); return psfight; }
// convert a npc to other [not working] CMonster* CMap::ConverToMonster( CNPC* npc, UINT newmontype ) { CMonster* monster = AddMonster( newmontype, npc->pos, 0, NULL, NULL, 0, true ); if(monster==NULL) // invalid montype return NULL; GServer->ClearClientID( monster->clientid ); monster->clientid = npc->clientid; for(UINT i=0;i<NPCList.size();i++) { if(NPCList.at(i)==npc) NPCList.erase( NPCList.begin()+i ); } delete npc; BEGINPACKET( pak, 0x774 ); ADDWORD ( pak, npc->clientid ); ADDWORD ( pak, newmontype ); GServer->SendToVisible( &pak, monster ); return monster; }
// Respawn a Monster void CMap::RespawnMonster( ) { //PY new test version. Comment out to use older lmame version for(UINT j=0;j<MonsterSpawnList.size();j++) { CSpawnArea* thisspawn = MonsterSpawnList.at(j); //check to see if the spawn is currently empty if(thisspawn->MCount <= 0 and thisspawn->ResetSpawn == false) { //set start of spawn timer. We want it to count from the last death, not last spawn. thisspawn->lastRespawnTime = clock(); thisspawn->ResetSpawn = true; } //check to see if enough time has passed and that the spawn clock_t rtime = clock() - thisspawn->lastRespawnTime; if (rtime > thisspawn->respawntime*CLOCKS_PER_SEC && thisspawn->MCount <= 0) { //spawn has been empty for long enough. Now we need to respawn it. //first move the pointer to the next bmob or tmob //Yes I know I could simplify this sequence but it's much clearer this way. if(thisspawn->MobPointer == 6) { //tactical mobs cleared. reset to basic mobs again thisspawn->MobPointer = 1; } if(thisspawn->MobPointer == 5) { //reached the end of bmobs. Time to move onto tmobs thisspawn->MobPointer = 6; } if(thisspawn->MobPointer < 5) { //increment the pointer to the next basic mob thisspawn->MobPointer++; } thisspawn->MCount = 0; //make sure the count is set to zero thisspawn->ResetSpawn = false; //OK pointer and counter set. now we spawn em if(thisspawn->MobPointer > 5) //Do this only if we are spawning tactical mobs { //tactical mobs. We spawn both groups at the same time. the monster count becomes the combined total if(thisspawn->tcount[1] > 0) { for (UINT k=0;k<thisspawn->tcount[1];k++) //spawn the tactical monsters within this tmob { fPoint position = GServer->RandInCircle( thisspawn->points, thisspawn->radius ); AddMonster( thisspawn->tmob[1], position, 0, NULL, NULL, thisspawn->id ); thisspawn->MCount++; } } if(thisspawn->tcount[2] > 0) { for (UINT k=0;k<thisspawn->tcount[2];k++) //spawn the tactical monsters within this tmob { fPoint position = GServer->RandInCircle( thisspawn->points, thisspawn->radius ); AddMonster( thisspawn->tmob[2], position, 0, NULL, NULL, thisspawn->id ); thisspawn->MCount++; } } if(thisspawn->tcount[1] == 0 && thisspawn->tcount[2] == 0) { //reset Mob pointer to 1 if there are no tactical mobs in the spawn thisspawn->MobPointer = 1; } } if(thisspawn->MobPointer <6) //basic mobs { { if(thisspawn->bcount[thisspawn->MobPointer] > 0) { for (UINT k=0;k<thisspawn->bcount[thisspawn->MobPointer];k++) //spawn the basic monsters within this bmob { fPoint position = GServer->RandInCircle( thisspawn->points, thisspawn->radius ); AddMonster( thisspawn->bmob[thisspawn->MobPointer], position, 0, NULL, NULL, thisspawn->id ); thisspawn->MCount++; } } else //bcount for this spawn is zero so reset mob pointer to first spawn or tactical spawn { if(thisspawn->tcount[1] == 0 && thisspawn->tcount[2] == 0) { // No tactical spawns so set pointer to 1 thisspawn->MobPointer = 1; } else { // There are tactical spawns so set pointer to 6. Don't think this will ever happen but added it for completeness thisspawn->MobPointer = 6; } } } } } } return; //This kicks it out before it ever runs the following code. //if the spawn didn't contain any entries then MCount will still be zero so the pointer will move on next time around //Well that was pretty simple to rewrite. //Way more elegant that all that convoluted stuff down below ^_^ //PY END //LMA: daynight int last_map = 0; bool is_night = false; bool lma_debug = false; //LMA: debugging spawn problem for (UINT j = 0; j < MobGroupList.size(); j++) { CMobGroup* thisgroup = MobGroupList.at(j); //LMA: debugging spawn problem lma_debug = false; if(thisgroup->id == 4589) { lma_debug=true; Log(MSG_INFO,"Spawn %u:: Respawn time?",thisgroup->id); } clock_t rtime = clock() - thisgroup->lastRespawnTime; if (rtime < thisgroup->respawntime*CLOCKS_PER_SEC || thisgroup->active >= thisgroup->limit) { if(lma_debug) { Log(MSG_INFO,"Spawn %u:: No respawn (time %u < %u ? or limit %u>=%u ?)",thisgroup->id,rtime,thisgroup->respawntime*CLOCKS_PER_SEC,thisgroup->active,thisgroup->limit); } continue; } //LMA: handling day and night this time. if(thisgroup->daynight!=0) { if (last_map!=thisgroup->map) { CMap* map = GServer->MapList.Index[thisgroup->map]; last_map=map->id; is_night=map->IsNight(); } if((thisgroup->daynight == 2 && !is_night) || (thisgroup->daynight == 1 && is_night)) continue; } //LMA: new way. //calling in tactictal points if needed. CMob *thismob; bool groupFull = false; if(lma_debug) { Log(MSG_INFO,"Spawn %u:: Tactical? %u>=%u ?",thisgroup->id,thisgroup->basicKills,thisgroup->tacticalpoints); } if (thisgroup->tacMobs.size() > 0 && thisgroup->basicKills >= thisgroup->tacticalpoints) { if(lma_debug) { Log(MSG_INFO,"Spawn %u:: Tactical time",thisgroup->id); } //adding ALL tacticals. for (UINT k=0;k<thisgroup->tacMobs.size();k++) { if (thisgroup->curTac >= thisgroup->tacMobs.size()) { thisgroup->curTac = 0; } thismob = thisgroup->tacMobs.at(thisgroup->curTac); thisgroup->basicKills = 0; thisgroup->lastKills = 0; thisgroup->curTac++; //we add the monsters. for (UINT i = 0; i < thismob->amount; i++) { //We load an entire group, not relying to active already there. /* if (thisgroup->active >= thisgroup->limit) { groupFull=true; break; } */ //adding the monster as tactical. fPoint position = GServer->RandInCircle( thisgroup->point, thisgroup->range ); AddMonster( thismob->mobId, position, 0, thismob->mobdrop, thismob->mapdrop, thisgroup->id,false,true); } //We load an entire group, not relying to active already there. /* if(groupFull) { break; } */ } } //LMA: basic mobs again? we only add one group. //we do it only if enough monsters were killed since last time. int last_group = thisgroup->curBasic - 1; if(last_group < 0) { last_group = thisgroup->basicMobs.size() - 1; if(last_group < 0) { last_group = 0; } } if(lma_debug) { Log(MSG_INFO,"Spawn %u:: Basic group check, this one %u, previous %u, laskills %u>=amount %u ?",thisgroup->id,thisgroup->curBasic,last_group,thisgroup->lastKills,thisgroup->basicMobs.at(last_group)->real_amount); } //if(thisgroup->lastKills>=thisgroup->basicMobs.at(last_group)->amount) if(thisgroup->lastKills >= thisgroup->basicMobs.at(last_group)->real_amount) { if(!thisgroup->group_ready) { //extra loop since it's the last dead monster that triggers the respawn time. thisgroup->lastRespawnTime = clock(); thisgroup->group_ready = true; if(lma_debug) { Log(MSG_INFO,"Spawn %u:: Group wasn't ready to spawn, he is now.",thisgroup->id); } return; } thisgroup->group_ready=false; thismob = thisgroup->basicMobs.at(thisgroup->curBasic); thisgroup->curBasic++; if (thisgroup->curBasic >= thisgroup->basicMobs.size()) { thisgroup->curBasic = 0; } if(lma_debug) { Log(MSG_INFO,"Spawn %u:: new group will be %u, active for now %u",thisgroup->id,thisgroup->curBasic,thisgroup->active); } //we add the monsters. //LMA: Don't spawn all the mobs at once. thismob->real_amount = 1; if(thismob->amount != 1) { thismob->real_amount=GServer->RandNumber(1,thismob->amount); if(thismob->real_amount>thismob->amount) { thismob->real_amount=thismob->amount; } } if(lma_debug) { Log(MSG_INFO,"Spawn %u:: We'll spawn %u monsters (rand from 1 to %u)",thismob->real_amount,thismob->amount); } thisgroup->lastKills = 0; //LMA: setting the respawn time here. thisgroup->lastRespawnTime = clock(); //for (UINT i = 0; i < thismob->amount; i++) for (UINT i = 0; i < thismob->real_amount; i++) { if (thisgroup->active >= thisgroup->limit) { if(lma_debug) { Log(MSG_INFO,"Spawn %u:: Stop spawning monster %u>=%u",thisgroup->id,thisgroup->active,thisgroup->limit); } break; } fPoint position = GServer->RandInCircle( thisgroup->point, thisgroup->range ); //LMA: We get the monster for test purposes. //AddMonster( thismob->mobId, position, 0, thismob->mobdrop, thismob->mapdrop, thisgroup->id ); CMonster* tempmonster=AddMonster( thismob->mobId, position, 0, thismob->mobdrop, thismob->mapdrop, thisgroup->id ); if(lma_debug) { if (tempmonster != NULL) { Log(MSG_INFO,"Spawn %u:: Spawing monster %u (CID %u) at (%.2f;%.2f) (%u<%u), active now %u",thisgroup->id,thismob->mobId,tempmonster->clientid,position.x,position.y,thismob->mobId,i,thismob->real_amount,thisgroup->active); } else { Log(MSG_WARNING,"Spawn %u:: FAILURE Spawing monster %u at (%.2f;%.2f) (%u<%u), active now %u",thisgroup->id,thismob->mobId,position.x,position.y,thismob->mobId,i,thismob->real_amount,thisgroup->active); } } } } } return; }
BYTE process_f0(BYTE* aPacket,DWORD len) { char str[100]; static int box_status=-1; static int big_box_status=-1; DWORD id; static int socket_count=0; static int blue=0,green=0,red=0; str[0]=0; if(len==4 && aPacket[0]==0x40 && aPacket[1]==0x80 && aPacket[2]==0 && aPacket[3]==0) //dead monster { //RemoveMonster(_monster.id); _monster.id=0; } if(aPacket==NULL && len==0) //packet over { if(_monster.type==0) _monster.id=0; if(_monster.quality== ITEM_RARE || _monster.quality==ITEM_UNIQUE) _monster.good_item=1; if(strstr(_itemTypeStr,"Wand") && _monster.total_sockets==3 && _monster.sockets_link==3) _monster.good_item=1; // if(_monster.total_sockets>2 && _monster.sockets_link>2) // _monster.good_item=1; if(blue+green+red==3 && _monster.sockets_link>2) _monster.good_item=1; if(_monster.total_sockets>4) _monster.good_item=1; if(strstr(_itemTypeStr,"Items/Flask") && _monster.quality==ITEM_MAGIC) _monster.good_item=1; if(strstr(_itemTypeStr,"Items/Currency")) _monster.good_item=1; if(strstr(_itemTypeStr,"Items/Gems")) _monster.good_item=1; if(_show=='3') { if(_monster.type==OBJ_ITEM) showinfo("type:%d, id:%x, quality:%d, socket:%d, link%d, type:%s",_monster.type,_monster.id,_monster.quality,_monster.total_sockets,_monster.sockets_link,_itemTypeStr); if(_monster.type==OBJ_MONSTER) showinfo("monster type:%d, %s",_monster.type,_objTypeStr); } /* if(_action.count<25) //can be box,wp,door,flask,jewel && _monster.type==OBJ_ITEM) //special object { if(box_status==1) //opened boxpe _monster.id=0;[0 else if(box_status==0) _monster.type = OBJ_BOX; else if(big_box_status==1) //opened box _monster.id=0; else if(big_box_status==0) _monster.type = OBJ_BIGBOX; else if(_monster.type == OBJ_NOT_SURE) _monster.type = OBJ_DOOR; } if(_monster.id!=0) AddMonster(&_monster); box_status=-1; big_box_status=-1; return 0; */ if(_monster.id!=0) { _monster.type=GetObjectType(_objTypeStr); AddMonster(&_monster); memset(&_monster,0,sizeof(MONSTER)); _itemTypeStr[0]=0; _objTypeStr[0]=0; // showinfo("add 1, type:%d", _monster.type); } // showinfo("total colore:%d", blue+green+red); socket_count=0; blue=0;green=0;red=0; } if(aPacket==NULL && len==1) //from total number of sockets call { socket_count=1; return 0; } if(socket_count>0) socket_count++; switch(socket_count) { case 2: case 4: case 6: case 8: case 10: case 12: if(aPacket[0]==3) blue=1; if(aPacket[0]==2) green=1; if(aPacket[0]==1) red=1; // showinfo("socket_count:%d,color: %d",socket_count,aPacket[0]); if(socket_count>=_monster.total_sockets*2) socket_count=0; break; } switch(_action.count) { case 1: _monster.object_type_id = htonl(*((DWORD*)(aPacket))); _objTypeStr[0]=0; readObjectType(_monster.object_type_id); break; case 2: _monster.type=GetObjectType(_objTypeStr); // showinfo("%d, %s",_objTypeStr); // showinfo("%d, %s",_monster.type,_objTypeStr); _monster.id=htons(*((WORD*)(aPacket+2))); sprintf_s(str,"id: %x",_monster.id); break; case 4: _monster.pos.x = htons(*((WORD*)(aPacket+2))); sprintf_s(str,"pos.x: %x",_monster.pos.x); break; case 5: _monster.pos.y = htons(*((WORD*)(aPacket+2))); sprintf_s(str,"pos.y: %x",_monster.pos.y); // showinfo("new monster,id:%x,x=%d,y=%d",_monster.id,_monster.pos.x,_monster.pos.y); break; case 7: if(_monster.type==OBJ_PLAYER && _player.id==0) //player { _player.id=_monster.id; _player.pos.x=_monster.pos.x; _player.pos.y=_monster.pos.y; strcpy_s(str,"this is player"); showinfo("player id:%x",_player.id); } break; case 8: if(!(aPacket[0]==0x3f && aPacket[1]==0x80 && aPacket[2]==0 && aPacket[3]==0)) //unique { //_monster.quality = MONSTER_UNIQUE; } break; case 11: // if(len==1) _monster.type=OBJ_ITEM; // if(len==2) _monster.type=OBJ_MONSTER; // if(len==4) _monster.type=OBJ_NOT_SURE; //door,wp,big coffin break; case 12: if(len==1 && _monster.type==OBJ_CHEST) { box_status=aPacket[0]; if(box_status==1) _monster.id=0; } break; case 14: if(_monster.type==OBJ_ITEM && len==4) { _monster.item_type_id = htonl(*((DWORD*)(aPacket))); readItemType(_monster.item_type_id); } break; case 16: if(len==1 && _monster.type==OBJ_CHEST) { big_box_status=aPacket[0]; if(big_box_status==1) _monster.id=0; } break; case 24: break; if(_monster.type == OBJ_ITEM) { if(len==1 && aPacket[0]==2) { _monster.quality=ITEM_RARE; // UpdateMonster(&_monster); } if(len==1 && aPacket[0]==1) { _monster.quality=ITEM_MAGIC; // UpdateMonster(&_monster); } } break; case 50: // _monster.type = OBJ_MONSTER; strcpy_s(str,"should be monster"); // UpdateMonster(&_monster); break; } FormatOutput((char*)aPacket,_tempbuf,len); sprintf_s(_tempbuf,"%s *** %s (%d) ,type:%d",_tempbuf,str,_action.count,_monster.type); // showinfo(_tempbuf); return 0; }
// Respawn a Monster void CMap::RespawnMonster( ) //PY: rewriting this function for CNMSpawns { /* for (UINT j = 0; j < MonsterSpawnList.size(); j++) { CNMSpawns* thisspawn = MonsterSpawnList.at(j); if(thisspawn->MonCount == 0) //only spawn the single spawner if the spawn is empty. Further spawns are handled by AIP only { AddMonster(thisspawn->MonType,thisspawn->point,0,thisspawn->ID); } } */ //PY: New code for cascade spawn system imported from KTRose for(UINT k=0;k<MonsterSpawnList.size( );k++) { CSpawnArea* thisspawn = MonsterSpawnList.at(k); clock_t rtime = clock() - thisspawn->lastRespawnTime; if(thisspawn->limit == 1 && IsNight()) //spawn limit is set to day only continue; if(thisspawn->RefVar != 0 && thisspawn->RefVal != 0) //only allow this spawn if the correct ObjVar is set to non zero { if(GServer->ObjVar[thisspawn->RefVar][0] == thisspawn->RefVal) continue; } if(thisspawn->limit == 2 && !IsNight()) //spawn limit is set to night only continue; switch (thisspawn->type) { case 0: // no spawn. this spawn area is inactive break; case 1: //normal spawn if(rtime > (thisspawn->respawntime * CLOCKS_PER_SEC) && thisspawn->amon < thisspawn->max) { fPoint position = GServer->RandInCircle( thisspawn->point, thisspawn->radius ); UINT aggro = thisspawn->aggressive; AddMonster( thisspawn->montype, position, 0, thisspawn->id, aggro, false, thisspawn->limit ); thisspawn->lastRespawnTime = clock(); UpdateSpawnCounter( thisspawn->montype, thisspawn->id, 1); // update the counters thisspawn->triggercount = 0; } break; case 2: //normal but fill the spawn if(rtime > (thisspawn->respawntime * CLOCKS_PER_SEC) && thisspawn->amon < thisspawn->max) { for(int i=1;i<thisspawn->max;i++) { fPoint position = GServer->RandInCircle( thisspawn->point, thisspawn->radius ); UINT aggro = thisspawn->aggressive; AddMonster( thisspawn->montype, position, 0, thisspawn->id, aggro, false, thisspawn->limit ); UpdateSpawnCounter( thisspawn->montype, thisspawn->id, 1); // update the counters } } break; case 3: //cascade spawn if(thisspawn->triggercount > thisspawn->triggeramount && thisspawn->amon < thisspawn->max) { fPoint position = GServer->RandInCircle( thisspawn->point, thisspawn->radius ); UINT aggro = thisspawn->aggressive; AddMonster( thisspawn->montype, position, 0, thisspawn->id, aggro, false, thisspawn->limit ); thisspawn->lastRespawnTime = clock(); UpdateSpawnCounter( thisspawn->montype, thisspawn->id, 1); // update the counters thisspawn->triggercount = 0; } break; case 4: //cascade to max if(thisspawn->triggercount > thisspawn->triggeramount && thisspawn->amon < thisspawn->max) { for(int i=1;i<thisspawn->max;i++) { fPoint position = GServer->RandInCircle( thisspawn->point, thisspawn->radius ); UINT aggro = thisspawn->aggressive; AddMonster( thisspawn->montype, position, 0, thisspawn->id, aggro, false, thisspawn->limit ); UpdateSpawnCounter( thisspawn->montype, thisspawn->id, 1); // update the counters } thisspawn->lastRespawnTime = clock(); thisspawn->triggercount = 0; } break; case 5: //sub spawns. needs to trigger from a specific montype if(rtime > (thisspawn->respawntime * CLOCKS_PER_SEC) && thisspawn->amon < thisspawn->max) { //find if any of the trigger mobs exist for(UINT j=0;j<MonsterList.size();j++) { CMonster* monster = MonsterList.at(j); //if(monster->montype == thisspawn->triggertype && (thisspawn->spawnkey == 4 || thisspawn->triggercount >= thisspawn->triggeramount)) if(monster->montype == thisspawn->triggertype) { //found the right monster. now spawn the servant mob in a circle around it fPoint position = GServer->RandInCircle(monster->Position->current,5); UINT aggro = thisspawn->aggressive; AddMonster( thisspawn->montype, position, 0, thisspawn->id, aggro, false, thisspawn->limit ); UpdateSpawnCounter( thisspawn->montype, thisspawn->id, 1); // update the counters thisspawn->triggercount = 0; thisspawn->lastRespawnTime = clock(); } } } break; case 6: if(rtime > (thisspawn->respawntime * CLOCKS_PER_SEC) && thisspawn->amon < thisspawn->max) { //find if any of the trigger mobs exist for(UINT j=0;j<MonsterList.size();j++) { CMonster* monster = MonsterList.at(j); //if(monster->montype == thisspawn->triggertype && (thisspawn->spawnkey == 4 || thisspawn->triggercount >= thisspawn->triggeramount)) if(monster->montype == thisspawn->triggertype) { //found the right monster. now spawn the servant mobs around it up to the spawn max for(int i=thisspawn->amon;i<thisspawn->max;i++) { fPoint position = GServer->RandInCircle(monster->Position->current,5); UINT aggro = thisspawn->aggressive; AddMonster( thisspawn->montype, position, 0, thisspawn->id, aggro, false, thisspawn->limit ); UpdateSpawnCounter( thisspawn->montype, thisspawn->id, 1); // update the counters } thisspawn->lastRespawnTime = clock(); thisspawn->triggercount = 0; } } } break; case 7: //TDEF spawn. Spawns thisspawn->max monsters one by one using triggercount to track them if(rtime > (thisspawn->respawntime * CLOCKS_PER_SEC) && thisspawn->triggercount < thisspawn->max) { fPoint position = GServer->RandInCircle( thisspawn->point, thisspawn->radius ); AddMonster( thisspawn->montype, position, 0, thisspawn->id, 0, true, 0 ); UpdateSpawnCounter( thisspawn->montype, thisspawn->id, 3); // update the counters thisspawn->lastRespawnTime = clock(); } break; default: break; } } }