// Clan Manager bool CWorldServer::pakClanManager ( CPlayer* thisclient, CPacket* P ) { int action = GETBYTE((*P),0); switch(action) { case 0xf0: { MYSQL_ROW row; int charid = GETWORD((*P),1); int clanid = GETWORD((*P),3); CPlayer* otherclient = GetClientByCID ( charid ); if(otherclient==NULL) return true; MYSQL_RES *result = DB->QStore("SELECT logo,back,name,grade FROM list_clan where id=%i", clanid); if(result==NULL) return true; if(mysql_num_rows(result)!=1) { Log(MSG_WARNING, "Invalid clan %i", clanid ); DB->QFree( ); return true; } row = mysql_fetch_row(result); otherclient->Clan->logo = atoi(row[0]); otherclient->Clan->back = atoi(row[1]); strcpy(otherclient->Clan->clanname,row[2]); otherclient->Clan->grade = atoi(row[3]); DB->QFree( ); BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x35 );//funcion ADDWORD ( pak, otherclient->clientid );//cleint id ADDWORD ( pak, clanid );//? ADDWORD ( pak, 0x0000 );//? ADDWORD ( pak, otherclient->Clan->back );//? ADDWORD ( pak, otherclient->Clan->logo );//? ADDBYTE ( pak, otherclient->Clan->grade ); ADDBYTE ( pak, otherclient->Clan->clanrank); ADDSTRING ( pak, otherclient->Clan->clanname ); ADDBYTE ( pak, 0x00 ); SendToVisible( &pak, otherclient ); Log(MSG_INFO,"[WS] pakClanManager 0x7e0, case 0xf0 (new member too?) %s",otherclient->CharInfo->charname); } case 0xfa://new member added { MYSQL_ROW row; int charid = GETWORD((*P),1); int clanid = GETWORD((*P),3); CPlayer* otherclient = GetClientByCID ( charid ); if(otherclient==NULL) return true; MYSQL_RES *result = DB->QStore("SELECT logo,back,name,grade FROM list_clan where id=%i", clanid); if(result==NULL) return true; if(mysql_num_rows(result)!=1) { Log(MSG_WARNING, "Invalid clan %i", clanid ); DB->QFree( ); return true; } row = mysql_fetch_row(result); otherclient->Clan->logo = atoi(row[0]); otherclient->Clan->back = atoi(row[1]); strcpy(otherclient->Clan->clanname,row[2]); otherclient->Clan->grade = atoi(row[3]); DB->QFree( ); otherclient->Clan->clanid=clanid; otherclient->Clan->clanrank=1; BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x35 );//funcion ADDWORD ( pak, otherclient->clientid );//cleint id ADDWORD ( pak, clanid );//? ADDWORD ( pak, 0x0000 );//? ADDWORD ( pak, otherclient->Clan->back );//? ADDWORD ( pak, otherclient->Clan->logo );//? ADDBYTE ( pak, otherclient->Clan->grade ); ADDBYTE ( pak, otherclient->Clan->clanrank ); ADDSTRING ( pak, otherclient->Clan->clanname ); ADDBYTE ( pak, 0x00 ); SendToVisible( &pak, otherclient ); Log(MSG_INFO,"[WS] pakClanManager 0x7e0, new member %s",otherclient->CharInfo->charname); } break; case 0xfb://Member Kicked { char nick[30]; memcpy( nick, &P->Buffer[1], P->Size ); CPlayer* otherclient = GetClientByCharName( nick ); if(otherclient!=NULL) { otherclient->Clan->clanid=0; otherclient->Clan->clanrank=1; otherclient->Clan->back=0; otherclient->Clan->logo=0; otherclient->Clan->grade=0; strcpy(otherclient->Clan->clanname,""); BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x35 ); ADDWORD ( pak, otherclient->clientid ); ADDQWORD ( pak, 0 ); ADDWORD ( pak, 0x0001 ); SendToVisible( &pak, otherclient ); Log(MSG_INFO,"[WS] pakClanManager 0x7e0, member kicked, %s",nick); } } break; case 0xfc://member change rank { char nick[30]; int newrank = GETBYTE((*P),1); memcpy( nick, &P->Buffer[2], P->Size ); CPlayer* otherclient = GetClientByCharName( nick ); if(otherclient!=NULL) { otherclient->Clan->clanrank = newrank; Log(MSG_INFO,"[WS] pakClanManager 0x7e0, change rank for %s to %i",nick,newrank); } } break; case 0xfd://disorg { unsigned int clanid = GETWORD((*P),1); unsigned int charid = GETWORD((*P),3); CPlayer* tclient = GetClientByCID( charid ); if(tclient==NULL) return true; tclient->Clan->clanid = 0; tclient->Clan->clanrank = 1; tclient->Clan->grade = 0; tclient->Clan->back = 0; tclient->Clan->logo = 0; memset( &tclient->Clan->clanname, '\0', 17 ); BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x35 ); ADDWORD ( pak, tclient->clientid ); ADDQWORD ( pak, 0 ); ADDWORD ( pak, 0x0001 ); SendToVisible( &pak, tclient ); Log(MSG_INFO,"[WS] pakClanManager 0x7e0, disorg"); } break; case 0xfe://Member Leave { char nick[17]; memcpy( nick, &P->Buffer[1], P->Size ); CPlayer* otherclient = GetClientByCharName(nick); if(otherclient!=NULL) { otherclient->Clan->clanid=0; otherclient->Clan->clanrank=0; otherclient->Clan->back=0; otherclient->Clan->logo=0; otherclient->Clan->grade=0; strcpy(otherclient->Clan->clanname,""); BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x35 ); ADDWORD ( pak, otherclient->clientid ); ADDQWORD ( pak, 0 ); ADDWORD ( pak, 0x0001 ); SendToVisible( &pak, otherclient ); Log(MSG_INFO,"[WS] pakClanManager 0x7e0, member left"); } } break; case 0xff: // update clan mark { unsigned int clanid = GETWORD((*P),1); unsigned int clanlogo = GETDWORD((*P), 3 ); for(unsigned int i=0;i<ClientList.size();i++) { if(ClientList.at(i)->player==NULL) continue; CPlayer* player = (CPlayer*)ClientList.at(i)->player; if(player->Clan->clanid==clanid) { player->Clan->back = 0; player->Clan->logo = clanlogo; BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x35 );//funcion ADDWORD ( pak, player->clientid );//cleint id ADDWORD ( pak, clanid );//? ADDWORD ( pak, 0x0000 );//? ADDWORD ( pak, player->Clan->back );//? ADDWORD ( pak, player->Clan->logo );//? ADDBYTE ( pak, player->Clan->grade ); ADDBYTE ( pak, player->Clan->clanrank ); ADDSTRING ( pak, player->Clan->clanname ); ADDBYTE ( pak, 0x00 ); SendToVisible( &pak, player ); Log(MSG_INFO,"[WS] pakClanManager 0x7e0, update clan mark"); } } } break; default: Log( MSG_INFO, "Clan manager unknown action %i", action ); } return true; }
// Give Exp bool CWorldServer::GiveExp( CMonster* thismon, UINT special_lvl, UINT special_exp ) { if( thismon->owner != 0) // Summon { MapList.Index[thismon->Position->Map]->DeleteMonster( thismon ); return true; } // Give Experience Drops and Quest Items vector<CPartyExp*> PartyExp; for(UINT i=0;i<thismon->PlayersDamage.size();i++) { MonsterDamage* thisplayer = thismon->PlayersDamage.at(i); CPlayer* thisclient = GetClientByCID( thisplayer->charid, thismon->Position->Map ); if( thisplayer->damage>0 && thisclient!=NULL ) { if( thisclient->Battle->target == thismon->clientid ) { ClearBattle( thisclient->Battle ) thisclient->Position->destiny = thisclient->Position->current; //GIVE EXP FUNCTION } if( thismon->MonsterDrop->firsthit == thisclient->CharInfo->charid ) { // Give Quest Item QUESTS* myquest = thisclient->GetQuestByMob( thismon->montype ); if( myquest!=0 ) { BEGINPACKET( pak, 0x731 ) ADDWORD ( pak, thismon->montype ); thisclient->client->SendPacket( &pak ); } } //LMA BEGIN //20070621-211100 //mods for CF... unsigned int exp = (unsigned int)ceil((thismon->thisnpc->exp * thisplayer->damage) / (thismon->thisnpc->hp*thismon->thisnpc->level)+special_exp); //LMA END /*unsigned int cp = (unsigned int)ceil((thismon->thisnpc->level/6 * thisplayer->damage) / thismon->thisnpc->hp); //ADD Clan points under any condition if ((thismon->Position->Map>=11 && thismon->Position->Map<= 13) || thismon->Position->Map== 59) //So far only junon maps { thisclient->AddClanPoints(GetColorExp( cp)); }*/ exp = exp * Config.EXP_RATE * 6; if( thisclient->Party->party!=NULL ) { bool pflag = false; for(int i=0;i<PartyExp.size();i++) { CPartyExp* thisparty = PartyExp.at( i ); if( thisparty->thisparty == thisclient->Party->party ) { thisparty->exp += exp; thisparty->exp += exp * ((thisclient->Party->party->PartyLevel*2) / 100); pflag = true; } } if( !pflag ) { CPartyExp* thisparty = new CPartyExp; thisparty->thisparty = thisclient->Party->party; thisparty->exp = exp; thisparty->flag = false; thisparty->exp += exp * ((thisclient->Party->party->PartyLevel*2) / 100); thisparty->num = 1; thisparty->partymember[0] = thisclient->CharInfo->charid; thisparty->maxlevel = thisclient->Stats->Level; for(int p=0;p<thisclient->VisiblePlayers.size();p++) { CPlayer* otherclient = thisclient->VisiblePlayers.at( p ); if(otherclient->Party->party==NULL) continue; if( thisclient->Party->party == otherclient->Party->party ) { thisparty->partymember[thisparty->num] = otherclient->CharInfo->charid; thisparty->num++; thisparty->maxlevel += otherclient->Stats->Level; } } PartyExp.push_back( thisparty ); } continue; } //LMA BEGIN //20070621-211100 //mod for CF //Adding bonusxp (mileage) thisclient->CharInfo->Exp += thisclient->bonusxp*GetColorExp( thisclient->Stats->Level, thismon->thisnpc->level + special_lvl, exp ); //LMA END BEGINPACKET( pak, 0x79b ); ADDDWORD ( pak, thisclient->CharInfo->Exp ); ADDWORD ( pak, thisclient->CharInfo->stamina ); ADDWORD ( pak, 0 ); thisclient->client->SendPacket( &pak ); } } for(int p=0;p<PartyExp.size();p++) { CPartyExp* thisparty = PartyExp.at( p ); for(int i=0;i<thisparty->num;i++) { CPlayer* partyclient = GetClientByCID( thisparty->partymember[i], thismon->Position->Map ); if( partyclient==NULL ) continue; if(partyclient->Party->party==NULL) continue; if(!thisparty->flag) { partyclient->Party->party->Exp += (thisparty->exp / 6) / 2; if( partyclient->Party->party->PartyLevel == 50) { partyclient->Party->party->Exp = 0; } if( partyclient->Party->party->Exp > GetMaxPartyExp( partyclient->Party->party->PartyLevel ) ) { partyclient->Party->party->PartyLevel++; partyclient->Party->party->Exp -= GetMaxPartyExp( partyclient->Party->party->PartyLevel-1 ); } BEGINPACKET( pak, 0x7d4 ); ADDBYTE ( pak, partyclient->Party->party->PartyLevel ); ADDDWORD ( pak, partyclient->Party->party->Exp ); partyclient->Party->party->SendToMembers( &pak ); thisparty->flag = true; } //LMA Begin //20070621-211100 //mods for CF unsigned int expoption = partyclient->Party->party->Option%0x80; if( expoption==0 ) { partyclient->CharInfo->Exp += GetColorExp( partyclient->Stats->Level, thismon->Stats->Level + special_lvl, (UINT)round(thisparty->exp / thisparty->num) ); } else { partyclient->CharInfo->Exp += GetColorExp( partyclient->Stats->Level, thismon->Stats->Level + special_lvl, (UINT)round(partyclient->Stats->Level * thisparty->exp / thisparty->maxlevel) ); } //LMA END BEGINPACKET( pak, 0x79b ); ADDDWORD ( pak, partyclient->CharInfo->Exp ); ADDWORD ( pak, partyclient->CharInfo->stamina ); ADDWORD ( pak, 0 ); partyclient->client->SendPacket( &pak ); } } MapList.Index[thismon->Position->Map]->DeleteMonster( thismon ); return true; }
// Give Exp bool CWorldServer::GiveExp( CMonster* thismon, UINT special_lvl, UINT special_exp ) { if( thismon->owner != 0) // Summon { MapList.Index[thismon->Position->Map]->DeleteMonster( thismon ); return true; } //LMA TEST bool lma_debug=false; if(thismon->Position->respawn==4589) { lma_debug=true; Log(MSG_INFO,"GiveExp Spawn %u CID %u",thismon->Position->respawn,thismon->clientid); } // Give Experience Drops and Quest Items vector<CPartyExp*> PartyExp; for(UINT i=0;i<thismon->PlayersDamage.size();i++) { MonsterDamage* thisplayer = thismon->PlayersDamage.at(i); CPlayer* thisclient = GetClientByCID( thisplayer->charid, thismon->Position->Map ); //LMA: Player mustn't be dead. if( thisplayer->damage>0 && thisclient!=NULL && !thisclient->IsDead()) { if( thisclient->Battle->target == thismon->clientid ) { ClearBattle( thisclient->Battle ) thisclient->Position->destiny = thisclient->Position->current; //GIVE EXP FUNCTION } if( thismon->MonsterDrop->firsthit == thisclient->CharInfo->charid ) { for( int q=0;q<10;q++) { // Give Quest Item if( thisclient->quest.quests[q].QuestID!=0 ) { BEGINPACKET( pak, 0x731 ) ADDWORD ( pak, thismon->montype ); thisclient->client->SendPacket( &pak ); break; } } } //LMA BEGIN //20070621-211100 //mods for CF... //unsigned int exp = (unsigned int)ceil((thismon->thisnpc->exp * thisplayer->damage) / (thismon->thisnpc->hp*thismon->thisnpc->level)+special_exp); unsigned long long exp = (unsigned long long)ceil((thismon->thisnpc->exp * thisplayer->damage) / (thismon->thisnpc->hp*thismon->thisnpc->level)+special_exp); //LMA END /*unsigned int cp = (unsigned int)ceil((thismon->thisnpc->level/6 * thisplayer->damage) / thismon->thisnpc->hp); //ADD Clan points under any condition if ((thismon->Position->Map>=11 && thismon->Position->Map<= 13) || thismon->Position->Map== 59) //So far only junon maps { thisclient->AddClanPoints(GetColorExp( cp)); }*/ exp = exp * (unsigned long long) (Config.EXP_RATE * 6); if( thisclient->Party->party!=NULL ) { bool pflag = false; for(int i=0;i<PartyExp.size();i++) { CPartyExp* thisparty = PartyExp.at( i ); if( thisparty->thisparty == thisclient->Party->party ) { //LMA: We get exp only if we deserve it. //thisparty->exp += exp; thisparty->exp += GetColorExp( thisclient->Stats->Level, thismon->thisnpc->level + special_lvl, exp ); //LMA: bug... //thisparty->exp += exp * (unsigned long long) ((thisclient->Party->party->PartyLevel*2) / 100); thisparty->exp += (unsigned long long) ((exp*thisclient->Party->party->PartyLevel*2) / 100); pflag = true; } } if( !pflag ) { CPartyExp* thisparty = new CPartyExp; thisparty->thisparty = thisclient->Party->party; //LMA: We get exp only if we deserve it. thisparty->exp = exp; thisparty->exp = GetColorExp( thisclient->Stats->Level, thismon->thisnpc->level + special_lvl, exp ); thisparty->flag = false; //LMA: bug //thisparty->exp += exp * (unsigned long long) ((thisclient->Party->party->PartyLevel*2) / 100); thisparty->exp += (unsigned long long) ((exp*thisclient->Party->party->PartyLevel*2) / 100); thisparty->num = 1; thisparty->partymember[0] = thisclient->CharInfo->charid; thisparty->cheat_max_lvl=thisclient->Stats->Level; thisparty->cheat_min_lvl=thisclient->Stats->Level; thisparty->maxlevel = thisclient->Stats->Level; for(unsigned int p=0;p<ClientList.size();p++) { CPlayer* otherclient = (CPlayer*) ClientList.at( p )->player; if(otherclient->client==NULL) continue; if(otherclient->Party->party==NULL) continue; if(!otherclient->client->isActive) continue; if(!otherclient->Session->inGame) continue; //LMA: checking the gap between the max and min level of people in the party. if (thisclient->Party->party == otherclient->Party->party) { if(otherclient->Stats->Level>thisparty->cheat_max_lvl) { thisparty->cheat_max_lvl=otherclient->Stats->Level; } if(otherclient->Stats->Level<thisparty->cheat_min_lvl) { thisparty->cheat_min_lvl=otherclient->Stats->Level; } } if( IsVisible(thisclient, otherclient)) { if(thisclient->Party->party == otherclient->Party->party ) { //LMA: Little stupid check. if (thisparty->num==7) { Log(MSG_WARNING,"Too many people in this party, already at max, skipping"); break; } thisparty->partymember[thisparty->num] = otherclient->CharInfo->charid; thisparty->num++; thisparty->maxlevel += otherclient->Stats->Level; } } } PartyExp.push_back( thisparty ); } continue; } //LMA BEGIN //20070621-211100 //mod for CF //Adding bonusxp (mileage) //UINT prev_xp=thisclient->CharInfo->Exp; //LMA: Xp nullifier. if(!thisclient->no_exp) { thisclient->CharInfo->Exp += thisclient->bonusxp*GetColorExp( thisclient->Stats->Level, thismon->thisnpc->level + special_lvl, exp ); } //Log(MSG_INFO,"Bonus XP %i, previous XP, %i, new: %i",thisclient->bonusxp,prev_xp,thisclient->CharInfo->Exp); //LMA END //LMA: We don't send exp packet if there is a level up coming up next. if(thisclient->CharInfo->Exp<thisclient->GetLevelEXP()) { //LMA: TEST //Log(MSG_INFO,"new exp in giveexp %I64i",thisclient->CharInfo->Exp); BEGINPACKET( pak, 0x79b ); ADDDWORD ( pak, thisclient->CharInfo->Exp ); ADDWORD ( pak, thisclient->CharInfo->stamina ); //ADDWORD ( pak, 0 ); ADDWORD ( pak, thismon->clientid ); thisclient->client->SendPacket( &pak ); } } } for(int p=0;p<PartyExp.size();p++) { CPartyExp* thisparty = PartyExp.at( p ); //LMA: no exp if a player has a too low level... This is another version in this case, NONE of the guys got exp... //HIGHRATEPARTYEXPNONE /*if(abs(thisparty->cheat_min_lvl-thisparty->cheat_max_lvl)>(Config.Partygap+1)) { Log(MSG_HACK,"A Party tryes to get exp which has min_lvl %i and max_lvl %i that don't fit max gap %i",thisparty->cheat_min_lvl,thisparty->cheat_max_lvl,Config.Partygap+1); continue; }*/ //LMA: End of HIGHRATEPARTYEXPNONE. for(int i=0;i<thisparty->num;i++) { CPlayer* partyclient = GetClientByCID( thisparty->partymember[i], thismon->Position->Map ); if( partyclient==NULL ) continue; if(partyclient->Party->party==NULL) continue; //LMA: no exp if a player has a too low level... //Uncomment this part of code below if you want to use it... (HIGHRATEPARTYEXP) /*if(abs(partyclient->Stats->Level-thisparty->cheat_max_lvl)>(Config.Partygap+1)) { Log(MSG_HACK,"Player %s is lvl %i and tryes to get exp in a party which has max_lvl %i and max gap %i",partyclient->CharInfo->charname,partyclient->Stats->Level,thisparty->cheat_max_lvl,Config.Partygap+1); continue; }*/ //Uncomment should end here for HIGHRATEPARTYEXP. if(!thisparty->flag) { //partyclient->Party->party->Exp += (thisparty->exp / 6) / 2; partyclient->Party->party->Exp += (thisparty->exp / 6) / 6; //Tomiz: thisparty->exp decreased if( partyclient->Party->party->PartyLevel == 50) { partyclient->Party->party->Exp = 0; } //LMA: old code /*if( partyclient->Party->party->Exp > GetMaxPartyExp( partyclient->Party->party->PartyLevel ) ) { partyclient->Party->party->PartyLevel++; partyclient->Party->party->Exp -= GetMaxPartyExp( partyclient->Party->party->PartyLevel-1 ); } */ //New code. bool new_level=false; while(partyclient->Party->party->PartyLevel<50&&partyclient->Party->party->Exp > GetMaxPartyExp( partyclient->Party->party->PartyLevel ) ) { partyclient->Party->party->PartyLevel++; partyclient->Party->party->Exp -= GetMaxPartyExp( partyclient->Party->party->PartyLevel-1 ); Log(MSG_INFO,"Going from party level %i to %i, exp left %I64i",partyclient->Party->party->PartyLevel-1,partyclient->Party->party->PartyLevel,partyclient->Party->party->Exp); new_level=true; } if( partyclient->Party->party->PartyLevel == 50) { partyclient->Party->party->Exp = 0; } //Strange thing when a new level: unsigned long long send_exp=partyclient->Party->party->Exp; if(new_level) { send_exp+=0x80000000; } Log(MSG_INFO,"Exp sent: %I64i",send_exp); //End of code. BEGINPACKET( pak, 0x7d4 ); ADDBYTE ( pak, partyclient->Party->party->PartyLevel ); //LMA: little change. //ADDDWORD ( pak, partyclient->Party->party->Exp ); ADDDWORD ( pak, send_exp ); partyclient->Party->party->SendToMembers( &pak ); thisparty->flag = true; } //LMA: no exp for dead people. if(partyclient->IsDead()) { Log(MSG_INFO,"No exp for player %s, he's dead.",partyclient->CharInfo->charname); continue; } //LMA Begin //20070621-211100 //mods for CF unsigned int expoption = partyclient->Party->party->Option%0x80; //LMA: Exp nullfier. if(!partyclient->no_exp) { if( expoption==0 ) { partyclient->CharInfo->Exp += GetColorExp( partyclient->Stats->Level, thismon->Stats->Level + special_lvl, (UINT)round(thisparty->exp / thisparty->num) ); } else { partyclient->CharInfo->Exp += GetColorExp( partyclient->Stats->Level, thismon->Stats->Level + special_lvl, (UINT)round(partyclient->Stats->Level * thisparty->exp / thisparty->maxlevel) ); } } //LMA END if(partyclient->CharInfo->Exp<partyclient->GetLevelEXP()) { //LMA: TEST //Log(MSG_INFO,"new exp in giveexp %I64i",partyclient->CharInfo->Exp); BEGINPACKET( pak, 0x79b ); ADDDWORD ( pak, partyclient->CharInfo->Exp ); ADDWORD ( pak, partyclient->CharInfo->stamina ); //ADDWORD ( pak, 0 ); ADDWORD ( pak, thismon->clientid ); partyclient->client->SendPacket( &pak ); } } } //LMA: cleaning time. for(int p=0;p<PartyExp.size();p++) { //It seems it's ok, the class party destructor isn't beeing called... delete PartyExp.at(p); } if (lma_debug) { Log(MSG_INFO,"END GiveExp Spawn %u CID %u",thismon->Position->respawn,thismon->clientid); } MapList.Index[thismon->Position->Map]->DeleteMonster( thismon ); return true; }
// Give Exp bool CWorldServer::GiveExp( CMonster* thismon ) { Log(MSG_DEBUG,"Awarding EXP"); int tmpMult = 1; if( thismon->owner != 0) // Summon { MapList.Index[thismon->Position->Map]->DeleteMonster( thismon ); return true; } // Give Experience Drops and Quest Items vector<CPartyExp*> PartyExp; vector<CParty*> PartyList; CMap* map = GServer->MapList.Index[thismon->Position->Map]; for(UINT i=0;i<thismon->PlayersDamage.size();i++) { MonsterDamage* thisplayer = thismon->PlayersDamage.at(i); CPlayer* thisclient = GetClientByCID( thisplayer->charid, thismon->Position->Map ); if( thisplayer->damage > 0 && thisclient != NULL ) //player did some damage { Log(MSG_DEBUG,"Player did %i damage. max = %i",thisplayer->damage,thismon->Stats->MaxHP); float MyPercent = (float)thisplayer->damage / thismon->Stats->MaxHP; if(MyPercent > thisclient->CharInfo->HighestOverkill) { thisclient->CharInfo->HighestOverkill = MyPercent; SendPM(thisclient, "Congratulations!! You have exceeded your highest ever Overkill rate. New Best: %f",thisclient->CharInfo->HighestOverkill); } if(MyPercent > GServer->Config.MaxOverkill)MyPercent = GServer->Config.MaxOverkill; //set overkill ceiling Log(MSG_DEBUG,"Percentage multiplier %f",MyPercent); if( thisclient->Battle->target == thismon->clientid ) { ClearBattle( thisclient->Battle ) thisclient->Position->destiny = thisclient->Position->current; //Log(MSG_DEBUG,"(GiveExp) Destiny set to current position X: %f Y: %f.",thisclient->Position->current.x,thisclient->Position->current.y); } if( thismon->MonsterDrop->firsthit == thisclient->CharInfo->charid ) { for( int q=0;q<10;q++) { // Give Quest Item if( thisclient->quest.quests[q].QuestID != 0 ) { Log(MSG_DEBUG,"Giving quest reward item for quest %i Killed monster type %i",thisclient->quest.quests[q].QuestID,thismon->montype); //P: Suppressing this completely for a test of the drop code added below //BEGINPACKET( pak, 0x731 ) //ADDWORD ( pak, thismon->montype ); //thisclient->client->SendPacket( &pak ); //PY: thismon->thisnpc->die_quest contains the hash needed to complete the trigger so we can just bypass the initial part of this process int success = thisclient->ExecuteQuestTrigger(thismon->thisnpc->die_quest); if(success == 5) // quest success { Log(MSG_DEBUG,"Death QSD Trigger %i successful. Sending success: ",thismon->thisnpc->die_quest); BEGINPACKET ( pak, 0x730); ADDBYTE ( pak, success); ADDBYTE ( pak, 0); ADDDWORD( pak, thismon->thisnpc->die_quest); thisclient->client->SendPacket(&pak); } break; } } } //assign my own exp for monsters that I personally damaged unsigned int exp = (unsigned int)floor(thismon->thisnpc->exp * MyPercent); //unsigned int exp = (unsigned int)ceil((double)((thismon->thisnpc->exp * thisplayer->damage) / (thismon->thisnpc->hp*thismon->thisnpc->level))); exp = exp * Config.EXP_RATE * map->mapXPRate; //calculate base exp for this client. No medals or stuff accounted for yet Log(MSG_DEBUG,"MonXP: %i config rate: %i Map rate : %i My percent: %f Total XP: %i", thismon->thisnpc->exp, Config.EXP_RATE, map->mapXPRate, MyPercent, exp); thisclient->CharInfo->Pending_Exp += (exp * thisclient->Stats->xprate); //store exp into thisclient's pending_exp using personal xprate adjustments Log(MSG_DEBUG,"My personal XPrate: %i ", thisclient->Stats->xprate); if( thisclient->Party->party!=NULL ) { //Log(MSG_DEBUG,"Player is in a party"); //player is in a party so scan the party members CParty* party = thisclient->Party->party; //assign a party if(party == NULL) return true; //Log(MSG_DEBUG,"party found. Counted = %i", party->counted); for(UINT p=0;p<party->Members.size();p++) //loop through all the members in the party { //Log(MSG_DEBUG,"member %i being parsed", p); if(!party->counted) { //Log(MSG_DEBUG,"party added to list. level = %i", party->PartyLevel); party->counted = true; //tag the party so we don't add it to the list twice PartyList.push_back( party ); //we will need this list later to convert pending exp to real exp } CPlayer* thismember = party->Members.at(p); //find a party member if(thismember == NULL) return true; float RawTmpExp = (exp * (party->PartyLevel + 25) / 50); unsigned int tempxp =(unsigned int)(floor)(RawTmpExp); if (tempxp < 1)tempxp = 1; //Log(MSG_DEBUG,"member %i pending exp = %i tempxp: %i", p, thismember->CharInfo->Pending_Exp, tempxp); thismember->CharInfo->Pending_Exp += tempxp; // add a percentage of thisclient's non-adjusted exp to all party members including himself //Log(MSG_DEBUG,"member %i pending exp (after tempxp) = %i", p, thismember->CharInfo->Pending_Exp); } if(party->PartyLevel < 50) //only give party exp if party level is under 50 { party->Pending_Exp += exp; //add thisclient's non-adjusted xp to the pending exp of the party } } else //not in a party so deal with all the exp now { //SendPM(thisclient, "You receive %i EXP",thisclient->CharInfo->Pending_Exp); //Log(MSG_DEBUG,"Player awarded %i experience points",thisclient->CharInfo->Pending_Exp); thisclient->CharInfo->Exp += thisclient->CharInfo->Pending_Exp; thisclient->CharInfo->Pending_Exp = 0; //if(!thisclient->CheckPlayerLevelUP()) if(thisclient->CharInfo->Exp < thisclient->GetLevelEXP()) { BEGINPACKET( pak, 0x79b ); ADDDWORD ( pak, thisclient->CharInfo->Exp ); ADDWORD ( pak, thisclient->CharInfo->stamina ); ADDWORD ( pak, thismon->clientid ); thisclient->client->SendPacket( &pak ); } } } } for(int p=0;p<PartyList.size();p++) //loop through our party list to assign final exp to all party members. We already did non-party members up there^ { CParty* thisparty = PartyList.at( p ); if(thisparty == NULL) { //Log(MSG_DEBUG,"Party not valid"); continue; } //Log(MSG_DEBUG,"Party %i exp: %i pending exp: %i", p, thisparty->Exp, thisparty->Pending_Exp ); thisparty->counted = false; //reset the boolean for next time for(UINT i=0;i<thisparty->Members.size();i++) //loop through all the members in the party { CPlayer* thismember = thisparty->Members.at(i); //find a party member if(thismember == NULL) return true; thismember->CharInfo->Exp += thismember->CharInfo->Pending_Exp; //Log(MSG_DEBUG,"Added pending exp %i to regular exp %i for member %i", thismember->CharInfo->Pending_Exp, thismember->CharInfo->Exp, i); thismember->CharInfo->Pending_Exp = 0; if(!thismember->CheckPlayerLevelUP( )) { BEGINPACKET( pak, 0x79b ); ADDDWORD ( pak, thismember->CharInfo->Exp ); ADDWORD ( pak, thismember->CharInfo->stamina ); //ADDWORD ( pak, 0 ); //PY: not needed ADDWORD ( pak, thismon->clientid ); thismember->client->SendPacket( &pak ); } } thisparty->Exp += thisparty->Pending_Exp; thisparty->Pending_Exp = 0; thisparty->m_bitLevelUP = 0; if( thisparty->Exp > GetMaxPartyExp(thisparty->PartyLevel)) //level up the party { thisparty->PartyLevel++; thisparty->Exp -= GetMaxPartyExp(thisparty->PartyLevel-1); thisparty->m_iEXP = thisparty->Exp; thisparty->m_bitLevelUP = 1; //set levelup bit. See client structure below } //PY: structure of 0x7d4 /* BYTE m_btLEVEL; struct { unsigned int m_iEXP : 31; unsigned int m_bitLevelUP : 1; } ; */ BEGINPACKET ( pak, 0x7d4 ); ADDBYTE ( pak, thisparty->PartyLevel ); ADDWORD ( pak, thisparty->m_iEXP ); // defined as 31 bits ADDWORD ( pak, thisparty->m_bitLevelUP ); // defined as 1 bit thisparty->SendToMembers( &pak ); } return true; }