// check if player can level up bool CPlayer::CheckPlayerLevelUP( ) { if (CharInfo->Exp >= GetLevelEXP()) { CharInfo->Exp -= GetLevelEXP(); Stats->Level++; Stats->HP = GetMaxHP( ); Stats->MP = GetMaxMP( ); CharInfo->StatPoints += int((Stats->Level * 0.8) + 10); //if(Stats->Level>=10) CharInfo->SkillPoints += ((Stats->Level + 2) / 2); BEGINPACKET( pak, 0x79e ); ADDWORD( pak, clientid ); ADDWORD( pak, Stats->Level ); ADDDWORD( pak, CharInfo->Exp ); ADDWORD( pak, CharInfo->StatPoints ); ADDWORD( pak, CharInfo->SkillPoints ); client->SendPacket( &pak ); RESETPACKET( pak, 0x79e ); ADDWORD( pak, clientid ); GServer->SendToVisible( &pak, this ); SetStats( ); //SendLevelUPtoChar(this); return true; } return false; }
// Return to char select bool CCharServer::pakWSCharSelect ( CCharClient* thisclient, CPacket* P ) { if(!thisclient->isLoggedIn) return false; Log( MSG_INFO, "World server requested char select" ); DWORD userid = GETDWORD( (*P), 0 ); CCharClient* otherclient = GetClientByUserID( userid ); if(otherclient==NULL) { Log(MSG_WARNING, "Invalid userid: %i", userid ); return true; } BEGINPACKET( pak, 0x71c ); ADDBYTE ( pak, 0x00 ); otherclient->SendPacket( &pak ); Log( MSG_INFO, "Client returning to char select" ); RESETPACKET( pak, 0x505 ); ADDDWORD( pak, thisclient->userid ); //cryptPacket( (char*)&pak, NULL ); CChanels* thischannel = GetChannelByID( thisclient->channel ); if(thischannel!=NULL) { send( thischannel->sock, (char*)&pak, pak.Size, 0 ); } //LMA: resetting chatroom ID. DisconnectClientFromChat(thisclient); return true; }
void CMap::UpdateArena( CPlayer* thisclient ) { if(thisclient== NULL || thisclient->Groupga->Groupga == NULL) return; GAGroup* thisgroup = thisclient->Groupga->Groupga; int fragments = -1; for( UINT i=0; i< MonsterList.size();i++) { CMonster* thismon = MonsterList.at(i); if(thismon->team == thisgroup->GroupId && thismon->montype == 3708) fragments++; } Log(MSG_INFO,"called updatearena fragments = %i",fragments); if(fragments == 7) { for(UINT i=0;i<NPCList.size();i++) { CNPC* thisnpc = NPCList.at(i); if(thisnpc->thisnpc->id == 3704 && thisnpc->pos.x > 5160 && thisnpc->pos.x < 5170 && thisnpc->pos.y > 4915 && thisnpc->pos.y < 4925 && thisnpc->team == thisgroup->GroupId) { Log(MSG_INFO,"remove wall"); DeleteNPC(thisnpc); BEGINPACKET( pak, 0x794 ); ADDWORD( pak, thisnpc->clientid ); GServer->SendToVisible( &pak, thisclient ); RESETPACKET( pak, 0x799 ); ADDWORD ( pak, thisnpc->clientid ); ADDWORD ( pak, thisnpc->clientid ); ADDDWORD ( pak, 0 ); ADDDWORD ( pak, 16 ); GServer->SendToVisible( &pak, thisclient ); break; } } BEGINPACKET( pak, 0x7f8 ); ADDSTRING ( pak, "HUD_DawnSea_Destroyed_Gate1" ); ADDBYTE ( pak, 0x00 ); thisgroup->SendToMembers(&pak); } if(fragments == 0) { for(UINT i=0;i<NPCList.size();i++) { CNPC* thisnpc = NPCList.at(i); if(thisnpc->npctype == 3704 && thisnpc->pos.x == 5167 && thisnpc->pos.x == 4920 && thisnpc->team == thisgroup->GroupId) DeleteNPC(thisnpc); break; } BEGINPACKET( pak, 0x7f8 ); ADDSTRING ( pak, "HUD_DawnSea_Destroyed_Gate2" ); ADDBYTE ( pak, 0x00 ); thisgroup->SendToMembers(&pak); } }
// check if player can level up bool CPlayer::CheckPlayerLevelUP( ) { if (CharInfo->Exp >= GetLevelEXP()) { CharInfo->Exp -= GetLevelEXP(); Stats->Level++; Stats->HP = GetMaxHP( ); Stats->MP = GetMaxMP( ); CharInfo->StatPoints += int((Stats->Level*0.8)+10); // Proper skill point distribution for Pre-Evo switch (Stats->Level) { case 10: case 14: CharInfo->SkillPoints += 2; break; case 18: CharInfo->SkillPoints += 3; break; case 22: CharInfo->SkillPoints += 4; break; } // 5 skill points every 4 levels from 22 if (Stats->Level > 22 && Stats->Level < 99 && ((Stats->Level - 22) % 4) == 0) CharInfo->SkillPoints += 5; // 5 skill points every 2 levels from 98 if (Stats->Level > 98 && (Stats->Level % 2) == 0) CharInfo->SkillPoints += 5; BEGINPACKET( pak, 0x79e ); ADDWORD( pak, clientid ); ADDWORD( pak, Stats->Level ); ADDDWORD( pak, CharInfo->Exp ); ADDWORD( pak, CharInfo->StatPoints ); ADDWORD( pak, CharInfo->SkillPoints ); client->SendPacket( &pak ); RESETPACKET( pak, 0x79e ); ADDWORD( pak, clientid ); GServer->SendToVisible( &pak, this ); SetStats( ); //SendLevelUPtoChar(this); return true; } return false; }
// Messenger actions (add/remove/invite) bool CCharServer::pakMessengerManager ( CCharClient* thisclient, CPacket* P ) { BYTE action = GETBYTE((*P),0); switch (action) { case 0x01://wanna be my friend? { char* nick = new (nothrow) char[P->Size-7]; if(nick==NULL) { Log(MSG_ERROR, "Error allocing memory: pakMessengerManager 1" ); return false; } memcpy( nick, &P->Buffer[1], P->Size-7 ); Log(MSG_INFO,"%s Trying to invite %s",nick,thisclient->charname); CCharClient* otherclient = (CCharClient*) GetClientByName (nick); if(otherclient!=NULL) {//Send friend invitation (check this one) BEGINPACKET( pak, 0x7e1 ); ADDBYTE ( pak, 0x01 ); ADDWORD ( pak, 0x0000 ); ADDSTRING ( pak, thisclient->charname ); ADDBYTE ( pak, 0x00 ); otherclient->SendPacket(&pak); Log(MSG_INFO,"%s exists, invite sent to %s",nick,otherclient->charname); } else {//This charname doesnt exist BEGINPACKET( pak, 0x7e1 ); ADDBYTE ( pak, 0x04 ); ADDSTRING ( pak, nick ); ADDBYTE ( pak, 0x00 ); thisclient->SendPacket(&pak); Log(MSG_INFO,"invite: %s doesn't exist",nick); } delete []nick; } break; case 0x02://yes i want { char* nick = new (nothrow) char[P->Size-9]; if(nick==NULL) { Log(MSG_ERROR, "Error allocing memory: pakMessengerManager 2" ); return false; } memcpy( nick, &P->Buffer[3], P->Size-9 ); CCharClient* otherclient = (CCharClient*) GetClientByName (nick); if(otherclient!=NULL) { BEGINPACKET( pak, 0x7e1 ); ADDBYTE ( pak, 0x02 ); ADDWORD ( pak, thisclient->charid ); ADDBYTE ( pak, 0x00 ); ADDWORD ( pak, 0x0000 ); ADDSTRING ( pak, thisclient->charname ); ADDBYTE ( pak, 0x00); otherclient->SendPacket(&pak); //Add friend to my friend list(sql) if(!DB->QExecute("INSERT INTO list_friend (id,idfriend,namefriend) VALUES (%i,%i,'%s')",otherclient->charid,thisclient->charid,thisclient->charname)) { Log(MSG_WARNING,"error addind %s to %s friend list",otherclient->charname,thisclient->charname); return false; } CFriendList * newfriend1 = new (nothrow) CFriendList; if(newfriend1==NULL) return false; newfriend1->id = otherclient->charid; //friendid strcpy(newfriend1->name, otherclient->charname); //friend name thisclient->FriendList.push_back( newfriend1 ); RESETPACKET( pak, 0x7e1 ); ADDBYTE ( pak, 0x02 ); ADDWORD ( pak, otherclient->charid ); ADDBYTE ( pak, 0x00 ); ADDWORD ( pak, 0x0000 ); ADDSTRING ( pak, otherclient->charname ); ADDBYTE ( pak, 0x00); thisclient->SendPacket(&pak); //Add me to his friend list (sql) if(!DB->QExecute("INSERT INTO list_friend (id,idfriend,namefriend) VALUES (%i,%i,'%s')", thisclient->charid,otherclient->charid,otherclient->charname)) return false; CFriendList * newfriend2 = new (nothrow) CFriendList; if(newfriend2==NULL) return false; newfriend2->id = thisclient->charid; //friendid strcpy(newfriend2->name, thisclient->charname); //friend name otherclient->FriendList.push_back( newfriend2 ); Log(MSG_INFO,"accept %s ok",nick); } else//not founded { BEGINPACKET( pak, 0x7e1 ); ADDBYTE ( pak, 0x04 ); ADDSTRING ( pak, nick ); ADDBYTE ( pak, 0x00 ); thisclient->SendPacket(&pak); Log(MSG_INFO,"accept: %s doesn't exist",nick); } delete []nick; } break; case 0x03://no, i dont want { char* nick = new (nothrow) char[P->Size-9]; if(nick==NULL) { Log(MSG_ERROR, "Error allocing memory: pakMessengerManager 3" ); return false; } memcpy( nick, &P->Buffer[3], P->Size-9 ); CCharClient* otherclient = (CCharClient*) GetClientByName (nick); if(otherclient!=NULL) { BEGINPACKET( pak, 0x7e1 ); ADDBYTE ( pak, 0x03 ); ADDSTRING ( pak, thisclient->charname ); ADDBYTE ( pak, 0x00); otherclient->SendPacket(&pak); Log(MSG_INFO,"refuse: %s ok",nick); } else { BEGINPACKET( pak, 0x7e1 ); ADDBYTE ( pak, 0x04 ); ADDWORD ( pak, 0x0000 ); ADDSTRING ( pak, nick ); ADDBYTE ( pak, 0x00 ); thisclient->SendPacket(&pak); Log(MSG_INFO,"refuse: %s doesn't exist",nick); } } break; case 0x05://delete user. { WORD id = GETWORD ((*P),1); if(!DB->QExecute("DELETE FROM list_friend WHERE id=%i and idfriend=%i",thisclient->charid,id)) { Log(MSG_INFO,"user failed to delete friend slot %i",thisclient->charname,id); return false; } Log(MSG_INFO,"user %s deletes friend slot %i",thisclient->charname,id); CCharClient* otherclient = (CCharClient*) GetClientByID(id); if(otherclient!=NULL) { ChangeMessengerStatus ( thisclient, otherclient, 0x08); } } break; case 0xfa://messenger logout { WORD id = GETWORD ((*P),1); CCharClient* ctherclient = (CCharClient*) GetClientByID(id); if(ctherclient==NULL) return true; ctherclient->logout = true; for(UINT i=0;i<ctherclient->FriendList.size();i++) { CFriendList* thisfriend = ctherclient->FriendList.at( i ); CCharClient* otherclient = (CCharClient*) GetClientByID( thisfriend->id ); if(otherclient!=NULL) { ChangeMessengerStatus ( ctherclient, otherclient, 0x08); } } //Logout in clan ClanLogout ( ctherclient ); } break; default: Log( MSG_INFO, "Friend action unknown: %i", action ); break; } return true; }
// Create a new clan bool CWorldServer::pakCreateClan ( CPlayer* thisclient, CPacket* P ) { if(thisclient->CharInfo->Zulies<1000000) return true; thisclient->CharInfo->Zulies -= 1000000; MYSQL_ROW row; int background = GETWORD((*P),1); int icon = GETWORD((*P),3); char *name = ""; char *slogan = ""; name=(char*)&P->Buffer[5]; slogan=(char*)&P->Buffer[strlen(name)+6]; //Check if name already exists MYSQL_RES *result = DB->QStore("SELECT name FROM list_clan WHERE name='%s'", name); if(result==NULL) return true; if ( mysql_num_rows( result ) > 0 ) { BEGINPACKET( pak, 0x07e0 ); ADDWORD ( pak, 0x42 ); thisclient->client->SendPacket( &pak ); DB->QFree( ); return true; } DB->QFree( ); //Check if user can create a clan if( thisclient->Clan->clanid != 0 ) { BEGINPACKET( pak, 0x07e0 ); ADDWORD ( pak, 0x44 ); thisclient->client->SendPacket( &pak ); return true; } //Add clan to sql table //LMA: inserting slogan now char * lma_slogan = new char[strlen(slogan) + 1]; //char lma_slogan[200]=""; strcpy(lma_slogan,slogan); char * new_slogan = new char[strlen(lma_slogan)*3 +1]; mysql_real_escape_string(DB->Mysql, new_slogan,lma_slogan,strlen(lma_slogan)); //mysql_real_escape_string(DB->Mysql, new_slogan,"abcdefghijk",11); Log(MSG_INFO,"[WS] New clan %s created, slogan detected=%s, cleaned=%s ",name,slogan,new_slogan); DB->QExecute( "INSERT into list_clan (logo,back,name,cp,grade,slogan,news) values (%i,%i,'%s',0,1,'%s','')",icon,background,name,new_slogan); thisclient->Clan->clanid = mysql_insert_id(DB->Mysql); thisclient->Clan->clanrank = 6; thisclient->Clan->logo = icon; thisclient->Clan->back = background; strncpy(thisclient->Clan->clanname,name,16); thisclient->Clan->grade = 1; //Update user clan information DB->QExecute( "UPDATE characters set clanid=%i,clan_rank=6 where id=%i", thisclient->Clan->clanid,thisclient->CharInfo->charid); //load clan info in char server BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0xfa ); //action to update clan informacion (charserver) ADDWORD ( pak, thisclient->Clan->clanid ); ADDWORD ( pak, thisclient->CharInfo->charid ); ADDWORD ( pak, thisclient->clientid ); cryptPacket( (char*)&pak, cct ); send( csock, (char*)&pak, pak.Size, 0 ); //Send to other players RESETPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x35 ); ADDWORD ( pak, thisclient->clientid ); ADDWORD ( pak, 0x081b );//??? ADDWORD ( pak, 0x0000 );//??? ADDWORD ( pak, background ); ADDWORD ( pak, icon ); ADDBYTE ( pak, 0x01 );//clan grade ADDBYTE ( pak, 0x06 );//clan rank ADDSTRING ( pak, name ); ADDBYTE ( pak, 0x00 ); SendToVisible( &pak, thisclient ); return true; }
// start action [attack] void CCharacter::StartAction( CCharacter* Target, BYTE action, UINT skillid) { BEGINPACKET( pak, 0 ); switch(action) { case NORMAL_ATTACK: { //Log( MSG_INFO, "case NORMAL_ATTACK"); RESETPACKET( pak, 0x798 ); ADDWORD ( pak, clientid ); ADDWORD ( pak, Target->clientid ); ADDWORD ( pak, Stats->Move_Speed ); ADDFLOAT ( pak, Target->Position->current.x*100 ); ADDFLOAT ( pak, Target->Position->current.y*100 ); Battle->target = Target->clientid; Battle->atktarget = Target->clientid; Battle->atktype = action; Position->destiny = Target->Position->current; Position->lastMoveTime = clock(); } break; case SKILL_ATTACK: //Log( MSG_INFO, "case SKILL_ATTACK"); case SKILL_BUFF: { //Log( MSG_INFO, "case SKILL_BUFF"); //Log( MSG_INFO, "clientid :%i Target id :%i skillid :%i", clientid, Target->clientid, skillid); RESETPACKET( pak, 0x7b3 ); ADDWORD ( pak, clientid ); ADDWORD ( pak, Target->clientid ); ADDWORD ( pak, skillid ); if (clientid==Target->clientid) { ADDWORD( pak, 0x0000 ); } else { ADDWORD (pak, Stats->Move_Speed); } ADDFLOAT ( pak, Target->Position->current.x*100 ); ADDFLOAT ( pak, Target->Position->current.y*100 ); if (CharType==2&&action==SKILL_ATTACK) ADDBYTE ( pak, 0x08);//8 monster skill attack nMotion ? Battle->target = Target->clientid; if(action==SKILL_ATTACK) Battle->skilltarget = Target->clientid; else Battle->bufftarget = Target->clientid; Battle->atktype = action; Position->destiny = Target->Position->current; Battle->skillid = skillid; Position->lastMoveTime = clock(); } break; case SKILL_AOE://Log( MSG_INFO, "case SKILL_AOE"); case BUFF_SELF://Log( MSG_INFO, "case BUFF_SELF"); case BUFF_AOE: { //Log( MSG_INFO, "case BUFF_AOE"); RESETPACKET( pak, 0x7b2); ADDWORD ( pak, clientid ); ADDWORD ( pak, skillid ); Battle->atktype = action; Battle->skillid = skillid; } break; case AOE_TARGET: { //Log( MSG_INFO, "case AOE_TARGET"); RESETPACKET( pak, 0x7b4 ); ADDWORD ( pak, clientid ); ADDWORD ( pak, skillid ); ADDFLOAT ( pak, Position->skilltargetpos.x*100 ); ADDFLOAT ( pak, Position->skilltargetpos.y*100 ); Battle->atktype = action; Battle->skillid = skillid; Battle->skilltarget = 0; } break; default: return; } GServer->SendToVisible( &pak, this ); Battle->contatk = true; }
// Spawn Another User on the Screen bool CPlayer::SpawnToPlayer( CPlayer* player, CPlayer* otherclient ) { BEGINPACKET( pak, 0x793 ); ADDWORD( pak, clientid); // USER ID ANYONE? ADDFLOAT( pak, Position->current.x*100 ); // POS X ADDFLOAT( pak, Position->current.y*100 ); // POS Y ADDFLOAT( pak, Position->destiny.x*100 ); // GOING TO X ADDFLOAT( pak, Position->destiny.y*100 ); // GOINT TO Y if(Status->Stance == 0x01) { ADDWORD( pak, 0x000a ); ADDWORD( pak, 0x0000 ); } else if(Stats->HP <= 0) { ADDWORD( pak, 0x0003 ); ADDWORD( pak, 0x0000 ); } else if(Position->destiny.x != Position->current.y || Position->destiny.y != Position->current.y) { ADDWORD( pak, 0x0001 ); ADDWORD( pak, Battle->atktarget ); } else if(Battle->atktarget!=0) { ADDWORD( pak, 0x0002 ); ADDWORD( pak, Battle->atktarget ); } else { ADDWORD( pak, 0x0001 ); ADDWORD( pak, 0x0000 ); } switch (Status->Stance) { case WALKING: ADDBYTE( pak, 0x00 ); break; case RUNNING: ADDBYTE( pak, 0x01 ); break; case DRIVING: ADDBYTE( pak, 0x02 ); break; default: ADDBYTE( pak, 0x0b ); } ADDWORD( pak, 0x0000 ); ADDWORD( pak, 0x0000 ); if(otherclient->Party->party==NULL || otherclient->Party->party != player->Party->party || otherclient->Party->party == player->Party->party) { CMap* map = GServer->MapList.Index[player->Position->Map]; if(map->allowpvp==1){ADDDWORD(pak, 0x00000051 );} // pvp all vs all else if(map->allowpvp==2) // pvp group vs group { if((player->Clan->clanid != otherclient->Clan->clanid) && ((map->id>0) && (map->id<121))) { ADDDWORD(pak, 0x00000051 ); }//Clan War map (pedion) else if((player->Clan->clanid == otherclient->Clan->clanid) && ((map->id>0) && (map->id<=100))) { ADDDWORD(pak, 0x00000051 ); }//other pvp group vs group map else { ADDDWORD(pak, 0x00000000 ); } } else { ADDDWORD(pak, 0x00000000 ); } } else {ADDDWORD(pak, 0x00000000 );} ADDDWORD( pak, GServer->BuildBuffs( this ) );//BUFFS ADDBYTE( pak, CharInfo->Sex ); // GENDER ADDWORD( pak, Stats->Move_Speed ); // WALK SPEED MAYBE? ADDWORD( pak, 0 ); // ?? ADDBYTE( pak, 0x01 ); // ?? ADDDWORD( pak, CharInfo->Face ); // FACE TYPE ADDDWORD( pak, CharInfo->Hair ); // HAIR TYPE ADDWORD( pak, items[2].itemnum ); // CAP ADDWORD( pak, GServer->BuildItemRefine( items[2] ) ); // CAP REFINE ADDWORD( pak, items[3].itemnum ); // BODY ADDWORD( pak, GServer->BuildItemRefine( items[3] ) ); // BODY REFINE ADDWORD( pak, items[5].itemnum ); // GLOVES ADDWORD( pak, GServer->BuildItemRefine( items[5] ) ); // GLOVES REFINE ADDWORD( pak, items[6].itemnum ); // BOOTS ADDWORD( pak, GServer->BuildItemRefine( items[6] ) ); // BOOTS REFINE ADDWORD( pak, items[1].itemnum ); // FACE ADDWORD( pak, GServer->BuildItemRefine( items[1] ) ); // FACE REFINE ADDWORD( pak, items[4].itemnum ); // BACK ADDWORD( pak, GServer->BuildItemRefine( items[4] ) ); // BACK REFINE ADDWORD( pak, items[7].itemnum ); // WEAPON ADDWORD( pak, GServer->BuildItemRefine( items[7] ) ); // WEAPON REFINE ADDWORD( pak, items[8].itemnum ); // SUBWEAPON ADDWORD( pak, GServer->BuildItemRefine( items[8] ) ); // SUBWEAPON REFINE /* ADDWORD( pak, ((items[132].itemnum << 5) & 0x3ff) );//arrows ADDWORD( pak, ((items[133].itemnum << 5) & 0x3ff) );//bullets ADDWORD( pak, ((items[134].itemnum << 5) & 0x3ff) );//cannons */ //Fix from maximz ADDWORD( pak, ((items[132].itemnum << 5) ));//arrows ADDWORD( pak, ((items[133].itemnum << 5) ));//bullets ADDWORD( pak, ((items[134].itemnum << 5) ));//cannons ADDWORD( pak, CharInfo->Job ); ADDBYTE( pak, Stats->Level ); ADDWORD( pak, items[135].itemnum); // CART FRAME ADDWORD( pak, GServer->BuildItemRefine( items[135] ) ); ADDWORD( pak, items[136].itemnum ); // CART ENGINE ADDWORD( pak, GServer->BuildItemRefine( items[136] ) ); ADDWORD( pak, items[137].itemnum ); // CART WHEELS ADDWORD( pak, GServer->BuildItemRefine( items[137] ) ); ADDWORD( pak, items[138].itemnum ); // CART WEAPON ADDWORD( pak, GServer->BuildItemRefine( items[138] ) ); ADDWORD( pak, items[139].itemnum ); // CART ABILITY ADDWORD( pak, GServer->BuildItemRefine( items[139] ) ); ADDWORD( pak, (Stats->HP<=0)?0x0:0xea7b ); if(Shop->open) { ADDBYTE( pak, 0x02 ); } else { ADDBYTE( pak, 0x00 ); } ADDBYTE( pak, 0x00); ADDBYTE( pak, 0x00); if( Fairy ) { ADDBYTE( pak, 0x61); } else { ADDBYTE( pak, 0x00); } ADDSTRING( pak, CharInfo->charname ); ADDBYTE( pak, 0x00); if(Shop->open) { ADDBYTE( pak, Shop->ShopType); ADDBYTE( pak, 0x00); ADDSTRING(pak, Shop->name); ADDBYTE( pak, 0x00); //LMA 139+ } if(Clan->clanid!=0) { ADDDWORD( pak, Clan->clanid ); ADDWORD( pak, Clan->back); ADDWORD( pak, Clan->logo); ADDBYTE( pak, Clan->grade); ADDBYTE( pak, 0x00); ADDSTRING( pak, Clan->clanname); Log(MSG_INFO,"[WS] Clan info in player packet 0x793"); } ADDWORD( pak, 0x0000 ); player->client->SendPacket(&pak); if( Party->party!=NULL && Party->party == player->Party->party) { BEGINPACKET( pak, 0x7d5 ); ADDDWORD ( pak, CharInfo->charid ); ADDWORD ( pak, clientid ); ADDWORD ( pak, GetMaxHP( ) ); ADDWORD ( pak, Stats->HP ); ADDDWORD ( pak, 0x01000000 ); ADDDWORD ( pak, 0x0000000f ); ADDWORD ( pak, 0x1388 ); player->client->SendPacket( &pak ); } if( Ride->Ride ) { CPlayer* rideclient = GServer->GetClientByCID( Ride->charid, Position->Map ); if(rideclient==NULL) { Ride->Ride = false; Ride->Drive= false; Ride->charid = 0; return true; } if( GServer->IsVisible( player, rideclient ) || player->CharInfo->charid == rideclient->CharInfo->charid ) { BEGINPACKET( pak, 0x796 ); if( Ride->Drive ) { ADDWORD ( pak, rideclient->clientid ); ADDFLOAT ( pak, rideclient->Position->current.x*100 ); ADDFLOAT ( pak, rideclient->Position->current.y*100 ); } else { ADDWORD ( pak, clientid ); ADDFLOAT ( pak, Position->current.x*100 ); ADDFLOAT ( pak, Position->current.y*100 ); } ADDWORD ( pak, 0x0000 ); player->client->SendPacket( &pak ); RESETPACKET( pak, 0x7dd ); ADDBYTE ( pak, 0x02 ); if( rideclient->Ride->Drive ) { ADDWORD ( pak, rideclient->clientid ); ADDWORD ( pak, clientid ); } else { ADDWORD ( pak, clientid ); ADDWORD ( pak, rideclient->clientid ); } player->client->SendPacket( &pak ); } } //Little addition till the nonsense in server sync is fixed. //StartAction(NULL, 0, 0, true); return true; }
// start action [attack] void CCharacter::StartAction( CCharacter* Target, BYTE action, UINT skillid, bool restart, CCharacter* receiver ) { if(IsPlayer()) { Log(MSG_INFO,"A Player does an action %i, skill %i",action,skillid); } else { Log(MSG_INFO,"A Monster does an action %i, skill %i",action,skillid); } BEGINPACKET( pak, 0 ); if (restart) { Target=GetCharTarget( ); action=Battle->atktype; skillid=Battle->skillid; } //Drakia: If the target is NULL, we should only do something that doesn't require a target. if (Target == NULL && (action != SKILL_AOE &&action != BUFF_SELF &&action != BUFF_AOE &&action != MONSTER_BUFF_SELF &&action != AOE_TARGET)) { Log(MSG_WARNING,"We tried to start attack %i without a target",action); return; } //LMA: don't attack a dead or an offline player... It's stupid... if(Target!=NULL) { if(Target->IsPlayer()) { CPlayer* thisplayer=reinterpret_cast<CPlayer*>(Target); if(!thisplayer->Session->inGame) { //Log(MSG_HACK,"We don't attack a player not in game yet..., %s",thisplayer->CharInfo->charname); return; } } if(Target->IsDead()) { //but we can if it's a friendly (restore...). if(action!=SKILL_BUFF) { ClearBattle(Battle); return; } } } switch(action) { case NORMAL_ATTACK: { RESETPACKET( pak, 0x798 ); ADDWORD ( pak, clientid ); ADDWORD ( pak, Target->clientid ); //ADDWORD ( pak, Stats->Move_Speed ); ADDWORD ( pak, Stats->Base_Speed ); //Log(MSG_INFO,"move speed %u, base speed %u",Stats->Move_Speed,Stats->Base_Speed); ADDFLOAT ( pak, Target->Position->current.x*100 ); ADDFLOAT ( pak, Target->Position->current.y*100 ); Battle->target = Target->clientid; Battle->atktarget = Target->clientid; Battle->atktype = action; Position->destiny = Target->Position->current; Position->lastMoveTime = clock( ); } break; case SKILL_ATTACK: case SKILL_BUFF: { RESETPACKET( pak, 0x7b3 ); ADDWORD ( pak, clientid ); ADDWORD ( pak, Target->clientid ); ADDWORD ( pak, skillid ); ADDWORD ( pak, 50000 ); ADDFLOAT ( pak, Target->Position->current.x*100 ); ADDFLOAT ( pak, Target->Position->current.y*100 ); ADDFLOAT ( pak, Position->aoedestiny.x*100 ); ADDFLOAT ( pak, Position->aoedestiny.y*100 ); Battle->target = Target->clientid; if(action==SKILL_ATTACK) Battle->skilltarget = Target->clientid; else Battle->bufftarget = Target->clientid; Battle->atktype = action; Position->destiny = Target->Position->current; Battle->skillid = skillid; Position->lastMoveTime = clock( ); } break; case MONSTER_SKILL_ATTACK: case MONSTER_SKILL_BUFF: { RESETPACKET( pak, 0x7b3 ); ADDWORD ( pak, clientid ); ADDWORD ( pak, Target->clientid ); ADDWORD ( pak, skillid ); ADDBYTE (pak,0x2b); ADDBYTE (pak,0x01); ADDFLOAT ( pak, Target->Position->current.x*100 ); ADDFLOAT ( pak, Target->Position->current.y*100 ); ADDBYTE ( pak, 0x06); Battle->target = Target->clientid; if(action==MONSTER_SKILL_ATTACK) Battle->skilltarget = Target->clientid; else Battle->bufftarget = Target->clientid; Battle->atktype = action; Position->destiny = Target->Position->current; Battle->skillid = skillid; Position->lastMoveTime = clock( ); } break; case SUMMON_BUFF: { //LMA: Special case for Support summons RESETPACKET( pak, 0x7b3 ); ADDWORD ( pak, clientid ); ADDWORD ( pak, Target->clientid ); ADDWORD ( pak, skillid ); ADDBYTE (pak,0x2b); ADDBYTE (pak,0x01); ADDFLOAT ( pak, Target->Position->current.x*100 ); ADDFLOAT ( pak, Target->Position->current.y*100 ); /* ADDFLOAT ( pak, Position->current.x*100 ); ADDFLOAT ( pak, Position->current.y*100 ); */ ADDBYTE ( pak, 0x06); Battle->target = 0; //Battle->skilltarget = Target->clientid; Battle->bufftarget = Target->clientid; Battle->atktype = action; Position->destiny = Target->Position->current; Battle->skillid = skillid; Position->lastMoveTime = clock( ); GServer->SendToVisible( &pak, Target ); return; } break; case SKILL_AOE: case BUFF_SELF: case BUFF_AOE: { RESETPACKET( pak, 0x7b2); ADDWORD ( pak, clientid ); ADDWORD ( pak, skillid ); Battle->atktype = action; Battle->skillid = skillid; } break; case MONSTER_BUFF_SELF: { RESETPACKET( pak, 0x7b2); ADDWORD ( pak, clientid ); ADDWORD ( pak, skillid ); Battle->atktype = action; Battle->skillid = skillid; } break; case AOE_TARGET: { //LMA 2008/09/02: new version, the target is a zone, not a monster... so we stick with aoedestiny ;) //PY mods //Target is NULL for this function when cast by a player //Target is NOT NULL when it comes from a monster if(Target != NULL) //monster attack { Position->aoedestiny.x = Target->Position->current.x; Position->aoedestiny.y = Target->Position->current.y; } RESETPACKET( pak, 0x7b4 ); ADDWORD ( pak, clientid ); ADDWORD ( pak, skillid ); ADDFLOAT ( pak, Position->aoedestiny.x*100 ); ADDFLOAT ( pak, Position->aoedestiny.y*100 ); Battle->atktype = action; Battle->skillid = skillid; Battle->skilltarget = 0; Battle->target = Battle->atktarget; Position->destiny = Position->aoedestiny; Position->lastMoveTime = clock( ); Log(MSG_INFO,"StartAction, AOE_TARGET, target (%.2f,%.2f)",Position->aoedestiny.x,Position->aoedestiny.y); } break; case STAY_STILL_ATTACK: { //LMA: Very special case where the monster don't really attack (mc) Battle->atktype = action; Battle->skillid = skillid; Battle->skilltarget = Target->clientid; return; } default: return; } //if (getClient()==NULL) GServer->SendToVisible( &pak, this ); /*else getClient();*/ }
// Create a new clan bool CWorldServer::pakCreateClan ( CPlayer* thisclient, CPacket* P ) { if(thisclient->CharInfo->Zulies < 1000000) return true; thisclient->CharInfo->Zulies -= 1000000; //MYSQL_ROW row; int background = GETWORD((*P),1); int icon = GETWORD((*P),3); char*name=(char*)&P->Buffer[5]; char*slogan=(char*)&P->Buffer[strlen(name)+6]; //LMA: Check if name already exists and is short enough. if(!CheckValidName(thisclient,name)) { return true; } //LMA: Checking if it needs to be escaped. if(!CheckEscapeMySQL(name,50,true)) { return true; } //LMA: checking if the name is ok. MYSQL_RES *result = DB->QStore("SELECT name FROM list_clan WHERE name='%s'", name); if(result==NULL) return true; if ( mysql_num_rows( result ) > 0 ) { BEGINPACKET( pak, 0x07e0 ); ADDWORD ( pak, 0x42 ); thisclient->client->SendPacket( &pak ); DB->QFree( ); return true; } DB->QFree( ); //Check if user can create a clan if( thisclient->Clan->clanid != 0 ) { BEGINPACKET( pak, 0x7e0 ); ADDWORD ( pak, 0x44 ); thisclient->client->SendPacket( &pak ); return true; } char * lma_slogan = new char[strlen(slogan) + 1]; strcpy(lma_slogan,slogan); char * new_slogan = new char[strlen(lma_slogan)*3 +1]; mysql_real_escape_string(DB->Mysql, new_slogan,lma_slogan,strlen(lma_slogan)); //mysql_real_escape_string(DB->Mysql, new_slogan,"abcdefghijk",11); Log(MSG_INFO,"[WS] New clan %s created, slogan detected=%s, cleaned=%s ",name,slogan,new_slogan); //LMA: checking slogan's size. if(strlen(new_slogan)>=100) { Log(MSG_HACK,"%s tried to create clan %s with too long slogan %s (%i>=100)",thisclient->CharInfo->charname,name,new_slogan,strlen(new_slogan)); return true; } DB->QExecute( "INSERT into list_clan (logo,back,name,cp,grade,slogan,news) values (%i,%i,'%s',0,1,'%s','')",icon,background,name,new_slogan); thisclient->Clan->clanid = mysql_insert_id(DB->Mysql); thisclient->Clan->clanrank = 6; thisclient->Clan->logo = icon; thisclient->Clan->back = background; strncpy(thisclient->Clan->clanname,name,16); thisclient->Clan->grade = 1; //Update user clan information DB->QExecute( "UPDATE characters set clanid=%i,clan_rank=6 where id=%i", thisclient->Clan->clanid,thisclient->CharInfo->charid); //load clan info in char server BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0xfa ); //action to update clan informacion (charserver) ADDWORD ( pak, thisclient->Clan->clanid ); //ADDWORD ( pak, thisclient->CharInfo->charid ); ADDDWORD ( pak, thisclient->CharInfo->charid ); ADDWORD ( pak, thisclient->clientid ); cryptPacket( (char*)&pak, cct ); send( csock, (char*)&pak, pak.Size, 0 ); //Send to other players RESETPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x35 ); ADDWORD ( pak, thisclient->clientid ); ADDDWORD ( pak, thisclient->Clan->clanid );//clanid ADDWORD ( pak, thisclient->Clan->back ); ADDWORD ( pak, thisclient->Clan->logo ); ADDBYTE ( pak, thisclient->Clan->grade );//clan grade ADDBYTE ( pak, thisclient->Clan->clanrank );//clan rank ADDSTRING ( pak, thisclient->Clan->clanname ); ADDBYTE ( pak, 0x00 ); SendToVisible( &pak, thisclient ); delete[] lma_slogan; delete[] new_slogan; return true; }
// Send a PM to client with user information bool CPlayer::GetPlayerInfo( ) { char text[50]; sprintf(text,"Attack: %i | Critical: %i",Stats->Attack_Power, Stats->Critical ); BEGINPACKET( pak, 0x0784 ); ADDSTRING( pak, "[GM]PlayerInfo" ); ADDBYTE( pak, 0 ); ADDSTRING( pak, text ); ADDBYTE( pak, 0 ); client->SendPacket(&pak); sprintf(text,"Defense: %i | Magic Defense: %i",Stats->Defense, Stats->Magic_Defense); RESETPACKET( pak, 0x0784 ); ADDSTRING( pak, "[GM]PlayerInfo" ); ADDBYTE( pak, 0 ); ADDSTRING( pak, text ); ADDBYTE( pak, 0 ); client->SendPacket(&pak); sprintf(text,"Accury: %i | Dodge: %i",Stats->Accury,Stats->Dodge ); RESETPACKET( pak, 0x0784 ); ADDSTRING( pak, "[GM]PlayerInfo" ); ADDBYTE( pak, 0 ); ADDSTRING( pak, text ); ADDBYTE( pak, 0 ); client->SendPacket(&pak); sprintf(text,"aspeed: %i | mspeed: %i",Stats->Attack_Speed,Stats->Move_Speed ); RESETPACKET( pak, 0x0784 ); ADDSTRING( pak, "[GM]PlayerInfo" ); ADDBYTE( pak, 0 ); ADDSTRING( pak, text ); ADDBYTE( pak, 0 ); client->SendPacket(&pak); sprintf(text,"HP: %i/%i , MP: %i/%i",Stats->HP,Stats->MaxHP,Stats->MP,Stats->MaxMP); RESETPACKET( pak, 0x0784 ); ADDSTRING( pak, "[GM]PlayerInfo" ); ADDBYTE( pak, 0 ); ADDSTRING( pak, text ); ADDBYTE( pak, 0 ); client->SendPacket(&pak); sprintf(text,"Position[%i]: (%.0f,%.0f)",Position->Map,Position->current.x,Position->current.y); RESETPACKET( pak, 0x0784 ); ADDSTRING( pak, "[GM]PlayerInfo" ); ADDBYTE( pak, 0 ); ADDSTRING( pak, text ); ADDBYTE( pak, 0 ); client->SendPacket(&pak); sprintf(text,"ClientID: %u | CharID: %u", clientid, CharInfo->charid ); RESETPACKET( pak, 0x0784 ); ADDSTRING( pak, "[GM]PlayerInfo" ); ADDBYTE( pak, 0 ); ADDSTRING( pak, text ); ADDBYTE( pak, 0 ); client->SendPacket(&pak); sprintf(text,"inGame: %i | Logged: %i", Session->inGame, Session->isLoggedIn ); RESETPACKET( pak, 0x0784 ); ADDSTRING( pak, "[GM]PlayerInfo" ); ADDBYTE( pak, 0 ); ADDSTRING( pak, text ); ADDBYTE( pak, 0 ); client->SendPacket(&pak); sprintf(text,"ClanName[%u]: %s | ClanGrade: %i | ClanRank: %i", Clan->clanid, Clan->clanname, Clan->grade, Clan->clanrank ); RESETPACKET( pak, 0x0784 ); ADDSTRING( pak, "[GM]PlayerInfo" ); ADDBYTE( pak, 0 ); ADDSTRING( pak, text ); ADDBYTE( pak, 0 ); client->SendPacket(&pak); return true; }
// Clan manager for all the clan functions bool CCharServer::pakClanManager ( CCharClient* thisclient, CPacket* P ) { if(!thisclient->isLoggedIn) return false; MYSQL_RES *result; MYSQL_ROW row; BYTE action = GETBYTE ((*P),0); switch (action) { case 0x01: break; case 0x02://invite clan { char* nick = new (nothrow) char[P->Size]; if(nick==NULL) { Log(MSG_ERROR, "Error allocing memory" ); return false; } memcpy( nick, &P->Buffer[1], P->Size ); if(strcmp(nick,thisclient->charname)==0) return true; CCharClient* otherclient = (CCharClient*) GetClientByName( nick ); if(otherclient!=NULL) { BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x0b );//invite action ADDSTRING ( pak, thisclient->charname ); ADDBYTE ( pak, 0x0 ); otherclient->SendPacket( &pak ); } delete []nick; } break; case 0x03://Kick from clan { char* nick = new (nothrow) char[P->Size]; if(nick==NULL) { Log(MSG_ERROR, "Error allocing memory" ); return false; } memcpy( nick, &P->Buffer[1], P->Size ); CClans* thisclan = GetClanByID(thisclient->clanid); if(thisclan==NULL) { delete []nick; return true; } BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x81 );//xxx have kicket to yyyy ADDSTRING ( pak, nick ); ADDBYTE ( pak, 0x00); ADDSTRING ( pak, thisclient->charname ); ADDBYTE ( pak, 0x00); SendToClanMembers(thisclient->clanid,&pak); for(UINT i=0;i<thisclan->ClanMembers.size( );i++) { CClanMembers* ClanMember = thisclan->ClanMembers.at( i ); if(strcmp(ClanMember->name,nick)==0) { thisclan->ClanMembers.erase( thisclan->ClanMembers.begin() + i ); break; } } CCharClient* otherclient = (CCharClient*) GetClientByName( nick ); if( otherclient!=NULL ) { otherclient->clanid = 0; otherclient->clan_rank=1; RESETPACKET( pak, 0x7e1 );//Update world clan information ADDBYTE ( pak, 0xfb );//action (kick) ADDSTRING ( pak, nick ); ADDBYTE ( pak, 0x00 ); CChanels* thischannel = GetChannelByID( otherclient->channel ); if(thischannel!=NULL) { send( thischannel->sock, (char*)&pak, pak.Size, 0 ); } else { Log(MSG_ERROR, "Check serverid in worldserver.conf it should be the same as ID in channels in the mysql database %i",thisclient->channel);} pakClanMembers( otherclient ); } if(!DB->QExecute("UPDATE characters SET clanid=0 AND clan_rank=1 WHERE char_name='%s'",nick)) { delete []nick; return false; } delete []nick; } break; case 0x04://up rank { bool online = true; char* nick = new (nothrow) char[P->Size-7]; if(nick==NULL) { Log(MSG_ERROR, "Error allocing memory" ); return false; } memcpy( nick, &P->Buffer[1], P->Size-7 ); int clan_rank=0; int level=0; int job=0; int channel=0xff; if(strcmp(nick,thisclient->charname)==0) { delete []nick; return true; } CCharClient* otherclient = GetClientByName ( nick ); if(otherclient!=NULL) { clan_rank = otherclient->clan_rank; if(otherclient->clan_rank<5) { otherclient->clan_rank++; } else { delete []nick; return true; } CClans* thisclan = GetClanByID(otherclient->clanid); for(UINT i=0;i<thisclan->ClanMembers.size();i++) { CClanMembers* thismember = thisclan->ClanMembers.at(i); if(thismember!=0) { if (thismember->id==otherclient->charid) { thismember->clan_rank=otherclient->clan_rank; } } } job = otherclient->job; level = otherclient->level; channel=otherclient->channel; BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x83 ); ADDSTRING ( pak, nick ); ADDBYTE ( pak, 0x00 ); ADDBYTE ( pak, otherclient->clan_rank ); otherclient->SendPacket(&pak); } else { online=false; result = DB->QStore("SELECT clan_rank,classid,level FROM characters WHERE char_name='%s'",nick); if(result==NULL) { delete []nick; DB->QFree( ); return false; } if(mysql_num_rows(result)!=1) { Log(MSG_WARNING, "Invalid charname: %s" , nick ); delete []nick; DB->QFree( ); return false; } row = mysql_fetch_row( result ); clan_rank=atoi(row[0]); job = atoi(row[1]); level = atoi(row[2]); DB->QFree( ); } if(clan_rank<5) { clan_rank++; } if(!DB->QExecute("UPDATE characters SET clan_rank=%i WHERE char_name='%s'",clan_rank,nick)) { delete []nick; return false; } BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x75 ); ADDBYTE ( pak, clan_rank ); ADDBYTE ( pak, channel );//channel ADDWORD ( pak, 0x0000 ); ADDWORD ( pak, 0x0000 ); ADDWORD ( pak, level ); // level ADDWORD ( pak, job ); // job ADDSTRING ( pak, nick ); // Nick ADDBYTE ( pak, 0x00 ); SendToClanMembers(thisclient->clanid,&pak); if (online==true) { RESETPACKET( pak, 0x7e1 );//update world information ADDBYTE ( pak, 0xfc ); ADDBYTE ( pak, clan_rank ); ADDSTRING ( pak, nick ); ADDBYTE ( pak, 0x00 ); CChanels* thischannel = GetChannelByID( channel ); if(thischannel!=NULL){ send( thischannel->sock, (char*)&pak, pak.Size, 0 );} else { Log(MSG_ERROR, "Check serverid in worldserver.conf it should be the same as ID in channels in the mysql database %i",thisclient->channel);} } delete []nick; } break; case 0x05://down rank { bool online = true; char* nick = new (nothrow) char[P->Size-7]; if(nick==NULL) { Log(MSG_ERROR, "Error allocing memory" ); return false; } memcpy( nick, &P->Buffer[1], P->Size-7 ); int clan_rank=0; int level=0; int job=0; int channel=0xff; if(strcmp(nick,thisclient->charname)==0) { delete []nick; return true; } CCharClient* otherclient = GetClientByName ( nick ); if(otherclient!=NULL) { clan_rank = otherclient->clan_rank; if(otherclient->clan_rank>1) { otherclient->clan_rank--; } else { delete []nick; return true; } CClans* thisclan = GetClanByID(otherclient->clanid); for(UINT i=0;i<thisclan->ClanMembers.size();i++) { CClanMembers* thismember = thisclan->ClanMembers.at(i); if(thismember!=0) { if (thismember->id==otherclient->charid) { thismember->clan_rank=otherclient->clan_rank; } } } job = otherclient->job; level = otherclient->level; channel=otherclient->channel; BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x83 ); ADDSTRING ( pak, nick ); ADDBYTE ( pak, 0x00 ); ADDBYTE ( pak, otherclient->clan_rank ); otherclient->SendPacket(&pak); } else { online=false; result = DB->QStore("SELECT clan_rank,classid,level FROM characters WHERE char_name='%s'",nick); if(result==NULL) { delete []nick; DB->QFree( ); return false; } if(mysql_num_rows(result)!=1) { Log(MSG_WARNING, "Invalid charname: %s" , nick ); delete []nick; DB->QFree( ); return false; } row = mysql_fetch_row( result ); clan_rank=atoi(row[0]); job = atoi(row[1]); level = atoi(row[2]); DB->QFree( ); } if(clan_rank>1) { clan_rank--; } if(!DB->QExecute("UPDATE characters SET clan_rank=%i WHERE char_name='%s'",clan_rank,nick)) { delete []nick; return false; } BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x75 ); ADDBYTE ( pak, clan_rank ); ADDBYTE ( pak, channel );//channel ADDWORD ( pak, 0x0000 ); ADDWORD ( pak, 0x0000 ); ADDWORD ( pak, level ); // level ADDWORD ( pak, job ); // job ADDSTRING ( pak, nick ); // Nick ADDBYTE ( pak, 0x00 ); SendToClanMembers(thisclient->clanid,&pak); if (online==true) { RESETPACKET( pak, 0x7e1 );//update world information ADDBYTE ( pak, 0xfc ); ADDBYTE ( pak, clan_rank ); ADDSTRING ( pak, nick ); ADDBYTE ( pak, 0x00 ); CChanels* thischannel = GetChannelByID( channel ); if(thischannel!=NULL){ send( thischannel->sock, (char*)&pak, pak.Size, 0 );} else { Log(MSG_ERROR, "Check serverid in worldserver.conf it should be the same as ID in channels in the mysql database %i",thisclient->channel);} } delete []nick; } break; case 0x06://Change news { if(thisclient->clan_rank<5) return true; char* news = new (nothrow) char[P->Size-7]; if(news==NULL) { Log(MSG_ERROR, "Error allocing memory" ); return false; } memcpy( news, &P->Buffer[1], P->Size-7 ); CClans* thisclan = GetClanByID(thisclient->clanid); if(thisclan!=NULL) { strcpy(thisclan->news,news); BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x34 ); ADDSTRING ( pak, thisclan->news ); ADDBYTE ( pak, 0x00 ); SendToClanMembers(thisclan->id,&pak); if(!DB->QExecute("UPDATE list_clan SET news='%s' WHERE id=%i", thisclan->news, thisclan->id)) return false; } delete []news; } break; case 0x07://Leave Clan { if( thisclient->clan_rank == 6 ) return true; CClans* thisclan = GetClanByID( thisclient->clanid ); if(thisclan==NULL) return true; BEGINPACKET( pak, 0x7e0 ); ADDBYTE( pak, 0x82 ); ADDSTRING( pak, thisclient->charname ); ADDBYTE( pak, 0x00); SendToClanMembers(thisclient->clanid,&pak); for(UINT i=0;i<thisclan->ClanMembers.size();i++) { CClanMembers* ClanMember = thisclan->ClanMembers.at( i ); if(strcmp(ClanMember->name,thisclient->charname)==0) { thisclan->ClanMembers.erase( thisclan->ClanMembers.begin()+i ); delete ClanMember; break; } } thisclient->clanid = 0; thisclient->clan_rank=1; if(!DB->QExecute("UPDATE characters SET clanid=0 , clan_rank=0 WHERE char_name='%s'",thisclient->charname)) return false; RESETPACKET( pak, 0x7e1 );//Update world clan information ADDBYTE ( pak, 0xfb );//action (leave) ADDSTRING ( pak, thisclient->charname ); ADDBYTE ( pak, 0x00 ); CChanels* thischannel = GetChannelByID( thisclient->channel ); if(thischannel!=NULL){ send( thischannel->sock, (char*)&pak, pak.Size, 0 );} else { Log(MSG_ERROR, "Check serverid in worldserver.conf it should be the same as ID in channels in the mysql database %i",thisclient->channel);} } break; case 0x08: { pakClanMembers ( thisclient ); } break; case 0x09://Give Master { int clan_rank=0; int level=0; int job=0; int channel=0xff; char* nick = new (nothrow) char[P->Size-7]; if(nick==NULL) { Log(MSG_ERROR, "Error allocing memory" ); return false; } memcpy( nick, &P->Buffer[1], P->Size-7 ); if(strcmp(nick,thisclient->charname)==0) { delete []nick; return true; } //Convert to master CCharClient* otherclient = GetClientByName ( nick ); if(otherclient!=NULL) { clan_rank = 6; otherclient->clan_rank = clan_rank; job = otherclient->job; level = otherclient->level; channel = otherclient->channel; BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x83 ); ADDSTRING ( pak, nick ); ADDBYTE ( pak, 0x00 ); ADDBYTE ( pak, otherclient->clan_rank ); otherclient->SendPacket(&pak); } else { // 0 1 result = DB->QStore("SELECT classid,level FROM characters where char_name='%s'",nick); if(result==NULL) { delete []nick; return false; } if(mysql_num_rows(result)!=1) { DB->QFree( ); Log(MSG_WARNING, "Invalid charname: %s" , nick ); delete []nick; return false; } row = mysql_fetch_row( result ); job = atoi(row[0]); level = atoi(row[1]); DB->QFree( ); } if(!DB->QExecute("UPDATE characters SET clan_rank=%i WHERE char_name='%s'",clan_rank,nick)) { delete []nick; return false; } BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x75 ); ADDBYTE ( pak, clan_rank ); ADDBYTE ( pak, channel );//canal ADDWORD ( pak, 0x0000 ); ADDWORD ( pak, 0x0000 ); ADDWORD ( pak, level ); //level? ADDWORD ( pak, job ); // job? ADDSTRING ( pak, nick ); ADDBYTE ( pak, 0x00 ); SendToClanMembers(thisclient->clanid,&pak); RESETPACKET( pak, 0x7e1 );//update world information ADDBYTE ( pak, 0xfc ); ADDBYTE ( pak, clan_rank ); ADDSTRING ( pak, nick ); ADDBYTE ( pak, 0x00 ); CChanels* thischannel = GetChannelByID( channel ); if(thischannel!=NULL){ send( thischannel->sock, (char*)&pak, pak.Size, 0 );} else { Log(MSG_ERROR, "Check serverid in worldserver.conf it should be the same as ID in channels in the mysql database %i",thisclient->channel);} //Convert to commander clan_rank = 4; thisclient->clan_rank=clan_rank; job = thisclient->job; level = thisclient->level; channel = thisclient->channel; RESETPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x83 ); ADDSTRING ( pak, thisclient->charname ); ADDBYTE ( pak, 0x00 ); ADDBYTE ( pak, thisclient->clan_rank ); thisclient->SendPacket(&pak); if(!DB->QExecute("UPDATE characters SET clan_rank=%i WHERE char_name='%s'",clan_rank,thisclient->charname)) { delete []nick; return false; } RESETPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x75 ); ADDBYTE ( pak, clan_rank ); ADDBYTE ( pak, channel );//canal ADDWORD ( pak, 0x0000 ); ADDWORD ( pak, 0x0000 ); ADDWORD ( pak, level ); //level? ADDWORD ( pak, job ); // job? ADDSTRING ( pak, thisclient->charname ); ADDBYTE ( pak, 0x00 ); SendToClanMembers(thisclient->clanid,&pak); RESETPACKET( pak, 0x7e1 );//update world information ADDBYTE ( pak, 0xfc ); ADDBYTE ( pak, clan_rank ); ADDSTRING ( pak, thisclient->charname ); ADDBYTE ( pak, 0x00 ); thischannel = GetChannelByID( channel ); if(thischannel!=NULL){ send( thischannel->sock, (char*)&pak, pak.Size, 0 );} else { Log(MSG_ERROR, "Check serverid in worldserver.conf it should be the same as ID in channels in the mysql database %i",thisclient->channel);} delete []nick; } break; case 0x0a://disorganize clan { if(thisclient->clan_rank<6) return true; unsigned int clanid = thisclient->clanid; CClans* thisclan = GetClanByID(thisclient->clanid); if(thisclan==NULL) return true; if(thisclan->ClanMembers.size()>1)//Can't be deleted if there are members return true; if(!DB->QExecute("UPDATE characters SET clanid=0 AND clan_rank=1 WHERE clanid=%i",thisclient->clanid)) return false; if(!DB->QExecute("DELETE FROM list_clan WHERE id=%i",thisclient->clanid)) return false; BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x51 ); ADDBYTE ( pak, 0x00 ); SendToClanMembers(thisclient->clanid, &pak); thisclan->ClanMembers.clear( ); //delete from clan list for(UINT i=0;i<ClanList.size( );i++) { CClans* clan = ClanList.at( i ); if(thisclan == clan) { ClanList.erase( ClanList.begin() + i ); delete clan; break; } } RESETPACKET( pak, 0x7e1 );//Update world clan information ADDBYTE ( pak, 0xfd );//action (disorg) ADDWORD ( pak, clanid ); ADDWORD ( pak, thisclient->charid ); CChanels* thischannel = GetChannelByID( thisclient->channel ); if(thischannel!=NULL){ send( thischannel->sock, (char*)&pak, pak.Size, 0 );} else { Log(MSG_ERROR, "Check serverid in worldserver.conf it should be the same as ID in channels in the mysql database %i",thisclient->channel);} thisclient->clanid = 0; thisclient->clan_rank = 1; //send( wct } break; case 0x0c://invitation accepted { char* nick = new (nothrow) char[P->Size-7]; if(nick==NULL) { Log(MSG_ERROR, "Error allocing memory" ); return false; } memcpy( nick, &P->Buffer[1], P->Size-7 ); CCharClient* otherclient = (CCharClient*) GetClientByName(nick ); if(otherclient!=NULL) { thisclient->clanid = otherclient->clanid; thisclient->clan_rank=1; if(!DB->QExecute("UPDATE characters SET clanid=%i , clan_rank=1 WHERE char_name='%s'",thisclient->clanid,thisclient->charname)) { delete []nick; return false; } CClans* thisclan = GetClanByID(thisclient->clanid); if(thisclan==NULL) { Log(MSG_ERROR, "Clan with id %d doesn't exist", thisclient->clanid); delete []nick; return true; } CClanMembers* newmember = new (nothrow) CClanMembers; if(newmember==NULL) { Log( MSG_WARNING, "Error allocing memory" ); delete []nick; return false; } newmember->id = thisclient->charid; strcpy(newmember->name,thisclient->charname); newmember->clan_rank = 1; thisclan->ClanMembers.push_back( newmember ); } else { Log(MSG_ERROR, "Char with name %s doesn't exist", nick); delete []nick; return true; } SendClanInfo(thisclient); pakClanMembers(thisclient); BEGINPACKET( pak, 0x7e0 );//xxx have invited to xxx ADDBYTE( pak, 0x61 ); ADDSTRING( pak, thisclient->charname ); ADDBYTE( pak, 0x00); ADDSTRING( pak, otherclient->charname ); ADDBYTE( pak, 0x00); SendToClanMembers(thisclient->clanid,&pak); RESETPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x84 ); ADDWORD ( pak, thisclient->level ); ADDWORD ( pak, thisclient->job ); ADDSTRING ( pak, thisclient->charname ); ADDBYTE ( pak, 0x00 ); SendToClanMembers(thisclient->clanid,&pak); RESETPACKET( pak, 0x7e1 );//update clan info in world ADDBYTE( pak, 0xfa ); ADDWORD( pak, thisclient->charid ); ADDWORD( pak, thisclient->clanid ); CChanels* thischannel = GetChannelByID( thisclient->channel ); if(thischannel!=NULL) { send( thischannel->sock, (char*)&pak, pak.Size, 0 ); } else { Log(MSG_ERROR, "Check serverid in worldserver.conf it should be the same as ID in channels in the mysql database %i",thisclient->channel); } CChanels* otherchannel = GetChannelByID( otherclient->channel ); if(otherchannel!=NULL && thischannel!=otherchannel) { send( thischannel->sock, (char*)&pak, pak.Size, 0 ); } delete []nick; } break; case 0x0d://invitation no accepted { char* nick = new (nothrow) char[P->Size-7]; if(nick==NULL) { Log(MSG_ERROR, "Error allocing memory" ); return false; } memcpy( nick, &P->Buffer[1], P->Size-7 ); CCharClient* otherclient = (CCharClient*) GetClientByName(nick ); if(otherclient!=NULL) { BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x0d ); ADDSTRING ( pak, thisclient->charname ); ADDBYTE ( pak, 0x00 ); otherclient->SendPacket(&pak); } delete []nick; } break; case 0x0f:// Update Clan window with Level and Job { CClans* thisclan = (CClans*) GetClanByID( thisclient->clanid ); if(thisclan!=NULL) { BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x84 ); ADDWORD ( pak, GETWORD ((*P),1) ); ADDWORD ( pak, GETWORD ((*P),3) ); ADDSTRING ( pak, thisclient->charname ); ADDBYTE ( pak, 0x00 ); SendToClanMembers(thisclient->clanid,&pak); } } break; case 0x5C://message from worldserver to load the new clan information { UINT clanid = GETWORD((*P),1); UINT clientrank = GETWORD((*P),3); CClans* thisclan = (CClans*) GetClanByID( clanid ); if(thisclan==NULL) return true; thisclan->cp=GETDWORD ((*P),5); BEGINPACKET( pak, 0x7e0); ADDBYTE ( pak, 0x71); ADDWORD ( pak, clanid); ADDWORD ( pak, 0x0000);// ADDWORD ( pak, thisclan->back );//clan background ADDWORD ( pak, thisclan->logo );//clanlogo ADDBYTE ( pak, thisclan->grade);//clan grade ADDBYTE ( pak, 0xCC); ADDDWORD ( pak, thisclan->cp ); ADDDWORD ( pak, 0x00000064 ); ADDDWORD ( pak, 0x00000000 ); ADDDWORD ( pak, 0x00000000 ); ADDWORD ( pak, 0xCCCC ); ADDWORD ( pak, 0xCCCC ); ADDWORD ( pak, 0xCCCC ); for(int i=0;i<119;i++) ADDBYTE ( pak, 0x00); SendToClanMembers(clanid,&pak); UpdateClanWindow(clanid); } break; case 0xfa://message from worldserver to load the new clan information { int id = GETWORD((*P),1); // clanid int charid = GETWORD((*P),3); // charid int clientid = GETWORD((*P),5); // clientid CCharClient* otherclient = (CCharClient*) GetClientByID ( charid ); if(otherclient==NULL) return true; // Load all our clan information // 0 1 2 3 4 5 6 7 result = DB->QStore("SELECT id,logo,back,name,cp,grade,slogan,news FROM list_clan where id=%i",id); if(result == NULL) return false; if(mysql_num_rows(result)!=1) { DB->QFree( ); Log(MSG_WARNING, "Invalid clan: %i" , id ); return false; } row = mysql_fetch_row(result); //clan info CClans* newclan = new CClans; assert(newclan); newclan->id = atoi(row[0]); newclan->logo = atoi(row[1]); newclan->back = atoi(row[2]); strncpy(newclan->name,row[3],16); newclan->cp = atoi(row[4]); newclan->grade = atoi(row[5]); strncpy(newclan->slogan,row[6],29); strcpy(newclan->news,row[7]); ClanList.push_back( newclan ); DB->QFree( ); //member info CClanMembers* newmember = new CClanMembers; newmember->id = otherclient->charid; strcpy(newmember->name,otherclient->charname); newmember->clan_rank = 6; newclan->ClanMembers.push_back( newmember ); otherclient->clanid = id; otherclient->clan_rank = 6; //Send new clan information BEGINPACKET( pak, 0x7e0); ADDBYTE ( pak, 0x30); ADDWORD ( pak, clientid); ADDWORD ( pak, 0x0100);// ADDWORD ( pak, newclan->back );//clan background ADDWORD ( pak, newclan->logo );//clanlogo ADDBYTE ( pak, newclan->grade);//clan grade ADDBYTE ( pak, otherclient->clan_rank);// clan rank ADDDWORD ( pak, newclan->cp ); ADDDWORD ( pak, 0x00000000 ); // Unk ADDDWORD ( pak, 0x00000000 ); // Clan Funds ADDDWORD ( pak, 0x00000000 ); // Unk ADDWORD ( pak, 0x0000 ); // Unk ADDDWORD ( pak, 0x00000000 ); // Contribution for(int i=0;i<120;i++) ADDBYTE ( pak, 0x00); ADDSTRING ( pak, newclan->name);//clan name ADDBYTE ( pak, 0x00); ADDSTRING ( pak, newclan->slogan);//clan slogan ADDBYTE ( pak, 0x00); otherclient->SendPacket(&pak); } break; case 0xfb: { UINT clanid = GETWORD((*P),1); UINT grade = GETWORD((*P),3); CClans* thisclan = (CClans*) GetClanByID( clanid ); if(thisclan!=NULL) { BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x84 ); ADDWORD ( pak, GETWORD ((*P),1) ); ADDWORD ( pak, GETWORD ((*P),3) ); ADDSTRING ( pak, thisclient->charname ); ADDBYTE ( pak, 0x00 ); SendToClanMembers(thisclient->clanid,&pak); } } default: Log( MSG_INFO, "Clan action unknow %i ", action); break; } return true; }
// start action [attack] void CCharacter::StartAction( CCharacter* Target, BYTE action, UINT skillid) { BEGINPACKET( pak, 0 ); switch(action) { case NORMAL_ATTACK: { //Log( MSG_INFO, "case NORMAL_ATTACK"); if(Target == NULL)return; RESETPACKET( pak, 0x798 ); ADDWORD ( pak, clientid ); ADDWORD ( pak, Target->clientid ); ADDWORD ( pak, Stats->Move_Speed ); ADDFLOAT ( pak, Target->Position->current.x * 100 ); ADDFLOAT ( pak, Target->Position->current.y * 100 ); Battle->target = Target->clientid; Battle->atktarget = Target->clientid; Battle->atktype = action; Battle->skilltarget = 0; Battle->bufftarget = 0; Battle->skillid = 0; Position->destiny = Target->Position->current; Position->lastMoveTime = clock(); } break; case SKILL_ATTACK: //Log( MSG_INFO, "case SKILL_ATTACK"); case SKILL_BUFF: { if(Target == NULL)return; RESETPACKET( pak, 0x7b3 ); ADDWORD ( pak, clientid ); ADDWORD ( pak, Target->clientid ); ADDWORD ( pak, skillid ); ADDWORD ( pak, 0x0000 ); ADDFLOAT ( pak, Target->Position->current.x * 100 ); ADDFLOAT ( pak, Target->Position->current.y * 100 ); Battle->target = Target->clientid; if(action == SKILL_ATTACK) { //Log( MSG_INFO, "case SKILL_ATTACK"); Battle->skilltarget = Target->clientid; Battle->bufftarget = 0; } else { //Log( MSG_INFO, "case SKILL_BUFF"); Battle->bufftarget = Target->clientid; Battle->skilltarget = 0; } Battle->atktype = action; Position->destiny = Target->Position->current; Battle->skillid = skillid; Position->lastMoveTime = clock(); } break; case SKILL_AOE://Log( MSG_INFO, "case SKILL_AOE"); case BUFF_SELF://Log( MSG_INFO, "case BUFF_SELF"); case BUFF_AOE: { //Log( MSG_INFO, "case BUFF_AOE"); RESETPACKET( pak, 0x7b2); ADDWORD ( pak, clientid ); ADDWORD ( pak, skillid ); Battle->atktype = action; Battle->skillid = skillid; //Log( MSG_INFO, "BUFF_AOE packet sent"); } break; case AOE_TARGET: { //Log( MSG_INFO, "case AOE_TARGET"); //Target is NULL for this function when cast by a player //Target is NOT NULL when it comes from a monster if(Target != NULL) //monster attack { Position->skilltargetpos.x = Target->Position->current.x; Position->skilltargetpos.y = Target->Position->current.y; } RESETPACKET( pak, 0x7b4 ); ADDWORD ( pak, clientid ); ADDWORD ( pak, skillid ); ADDFLOAT ( pak, Position->skilltargetpos.x * 100 ); ADDFLOAT ( pak, Position->skilltargetpos.y * 100 ); Battle->atktype = action; Battle->skillid = skillid; Battle->skilltarget = 0; Battle->bufftarget = 0; } break; default: return; break; } GServer->SendToVisible( &pak, this ); Battle->contatk = true; //Log(MSG_INFO,"Battle Attacktype = %i",Battle->atktype); return; }
// Send away the world IP bool CCharServer::pakRequestWorld( CCharClient* thisclient, CPacket* P ) { if (!thisclient->isLoggedIn) return false; MYSQL_ROW row; MYSQL_RES *result; memset( &thisclient->charname, '\0', 17 ); memcpy( thisclient->charname, &P->Buffer[3], (P->Size-6-4)>16?16:(P->Size-6-4) ); if(!CheckEscapeMySQL(thisclient->charname,17,true)) { Log(MSG_WARNING,"A charname contains incorrect caracters or incorrect size (see warnings above)"); return false; } Log( MSG_INFO,"User %s(%i) selected char '%s'", thisclient->username, thisclient->userid, thisclient->charname); if(!DB->QExecute("UPDATE accounts SET lastchar='%s' WHERE id=%i", thisclient->charname, thisclient->userid)) return false; result = DB->QStore("SELECT host,port,lanip,lansubmask FROM channels WHERE id=%u and owner=%u and type=2", thisclient->channel, Config.ServerID); if(result==NULL) return false; if(mysql_num_rows( result )!=1 ) { Log( MSG_WARNING, "Invalid Server: %i", thisclient->channel ); DB->QFree( ); return false; } row = mysql_fetch_row( result ); BEGINPACKET( pak, 0x711 ); ADDWORD ( pak, atoi(row[1]) ); // PORT ADDDWORD ( pak, thisclient->userid ); ADDDWORD ( pak, 0x87654321 ); if(strcmp(thisclient->ClientSubNet,row[3])==0)//from lan { ADDSTRING( pak, row[2] ); Log(MSG_INFO, "Sending LanIP" ); } else if(strcmp( thisclient->ClientSubNet ,"127.0.0")==0)//same computer { ADDSTRING( pak, "127.0.0.1" ); Log(MSG_INFO, "Sending Localhost IP" ); } else { ADDSTRING( pak, row[0] ); Log(MSG_INFO, "Sending InetIP"); } ADDBYTE ( pak, 0 ); thisclient->SendPacket( &pak ); DB->QFree( ); //CHAR INFORMATION 0 1 2 3 4 result = DB->QStore("SELECT clanid,clan_rank,id,level,classid,rewardpoints FROM characters WHERE char_name='%s'", thisclient->charname); if(result==NULL) return false; if(mysql_num_rows(result)!=1) { Log( MSG_WARNING, "Number of user with charname '%s' is %i", thisclient->charname,mysql_num_rows(result)); DB->QFree( ); return false; } row = mysql_fetch_row( result ); thisclient->clanid = atoi( row[0] ); thisclient->clan_rank = atoi( row[1] ); thisclient->charid = atoi( row[2] ); thisclient->level = atoi( row[3] ); thisclient->job = atoi( row[4] ); thisclient->reward_points=atoi( row[5] ); //LMA: reward points: DB->QFree( ); //MESSENGER INFORMATION // // 0 1 result = DB->QStore("SELECT idfriend,namefriend FROM list_friend WHERE id=%i", thisclient->charid); if(result==NULL) return false; BYTE nfriends = mysql_num_rows(result) & 0xff; RESETPACKET( pak, 0x7e1 );// Friend list command ADDBYTE ( pak, 0x06 );// Sending Friend List ADDBYTE ( pak, nfriends );// # friends while(row = mysql_fetch_row( result )) { CFriendList * newfriend = new CFriendList; assert(newfriend); newfriend->id = atoi(row[0]); //friendid strcpy(newfriend->name, row[1]); //friend name thisclient->FriendList.push_back( newfriend ); ADDWORD (pak, newfriend->id);// friend id ADDWORD (pak, 0x0000 ); CCharClient* otherclient = (CCharClient*) GetClientByID( newfriend->id ); if(otherclient!=NULL) //is online?? { ADDBYTE (pak, 0x07 ); //online ChangeMessengerStatus ( thisclient, otherclient, 0x07); } else { ADDBYTE (pak, 0x08 );//offline } ADDSTRING (pak, newfriend->name); //friend name ADDBYTE (pak, 0x00 ); } thisclient->SendPacket( &pak ); DB->QFree( ); thisclient->logout = false; //SEND CLAN INFORMATION SendClanInfo (thisclient); return true; }
// use skill attack void CCharacter::UseAtkSkill( CCharacter* Enemy, CSkills* skill, bool deBuff) { // new formula long int skillpower = skill->atkpower + Stats->Attack_Power; Log( MSG_INFO, "Skillpower = %i (%i + %i)",skillpower,skill->atkpower,Stats->Attack_Power); float levelmult = (float) Stats->Level / Enemy->Stats->Level; if(levelmult > 2)levelmult = 2; //cap level multiplier at 2 Log( MSG_INFO, "Level Multiplier = %f",levelmult ); float atkdefmult = 0; float attack = 0; float constant = 2.5; if(skill->skilltype == 6 || skill->skilltype == 7) //magical damage { atkdefmult = (float) Stats->Attack_Power / Enemy->Stats->Magic_Defense; } else { atkdefmult = (float) Stats->Attack_Power / Enemy->Stats->Defense; } Log( MSG_INFO, "Attack / Def multiplier = %f",atkdefmult ); attack = (skillpower * levelmult * atkdefmult) / constant; Log( MSG_INFO, "Attack before random mod = %f",attack ); if(attack < 5) attack = 5; float d_attack = attack / 100; float mod = GServer->RandNumber( 0, 10 ) * d_attack; attack += mod; Log( MSG_INFO, "Attack after random mod = %f",attack ); long int hitpower = (long int)floor(attack); skillpower = (int)attack; Log( MSG_INFO, "skillpower = %i",skillpower ); bool bflag = false; Enemy->OnBeAttacked( this ); if(skillpower <= 0) skillpower = 0; if(IsPlayer()) { skillpower += (int)(skillpower * (Stats->ExtraDamage))/100; } if (skill->atkpower == 0) { skillpower = 0; // If the skill has a 0 atk power, it isn't meant to damage Log( MSG_INFO, "This skill does no damage" ); //ClearBattle( Battle ); return; // probably need to add some alternative code here for legitimate skills that have no attack power. } if(skillpower > 2046)skillpower = 2046; //Log(MSG_DEBUG,"Cast a skill. damage is %i",skillpower); if(!Enemy->IsSummon( ) && Enemy->IsMonster( )) { Enemy->AddDamage( this, skillpower ); Enemy->damagecounter += skillpower;// is for AI } Log( MSG_INFO, "modified skillpower = %i",skillpower ); Enemy->Stats->HP -= skillpower; //if(IsPlayer()) // Log(MSG_DEBUG,"Player Spell did damage %i",skillpower); //if(IsMonster()) // Log(MSG_DEBUG,"Monster spell did damage %i",skillpower); BEGINPACKET( pak, 0x7b6 ); ADDWORD ( pak, Enemy->clientid ); ADDWORD ( pak, clientid ); ADDDWORD ( pak, 0x000007f8 ); ADDBYTE ( pak, 0x00 ); if (Enemy->Stats->HP < 1) { ADDWORD ( pak, skillpower + 0x8000 ); } else { ADDWORD ( pak, skillpower + 0x2000 ); } if(Enemy->IsDead()) { //Log(MSG_DEBUG,"Enemy died"); CDrop* thisdrop = NULL; ADDDWORD ( pak, 16 ); if(!Enemy->IsSummon( ) && !Enemy->IsPlayer( )) { thisdrop = Enemy->GetDrop( ); if(thisdrop != NULL) { CMap* map = GServer->MapList.Index[thisdrop->posMap]; map->AddDrop( thisdrop ); } } //GServer->SendToVisible( &pak, Enemy, thisdrop ); GServer->SendToVisible( &pak, Enemy ); //Suppressing drop for now. trying a different trick OnEnemyDie( Enemy ); } else { ADDDWORD ( pak, 4 ); GServer->SendToVisible( &pak, Enemy ); bflag = GServer->AddBuffs( skill, Enemy, GetInt( ) ); //Send (de)buff information to the whole world if(skill->nbuffs > 0 && bflag) { BEGINPACKET( pak, 0x7b5 ); ADDWORD ( pak, Battle->skilltarget ); ADDWORD ( pak, clientid ); ADDWORD ( pak, Battle->skillid ); ADDWORD ( pak, GetInt( ) ); ADDBYTE ( pak, skill->nbuffs ); GServer->SendToVisible( &pak, Enemy ); } } if (deBuff) return; //Send skill animation to the world RESETPACKET( pak, 0x7b9); ADDWORD ( pak, clientid); ADDWORD ( pak, Battle->skillid); ADDWORD ( pak, 1); GServer->SendToVisible( &pak, this ); Battle->bufftarget = 0; Battle->skilltarget = 0; Battle->skillid = 0; //Battle->atktype = NORMAL_ATTACK; }
// Party Manager bool CWorldServer::pakPartyManager( CPlayer* thisclient, CPacket* P ) { unsigned int action = GETBYTE((*P),0); switch(action) { case 0x02://Acepto { if(thisclient->Party->party!=NULL)// have party return true; unsigned int clientid = GETWORD((*P),1); if (clientid == thisclient->clientid) { Log(MSG_WARNING, "User %s tried to party with himself\n", thisclient->CharInfo->charname); return false; //kick the cheater } CPlayer* otherclient = GetClientByID( clientid, thisclient->Position->Map ); if(otherclient==NULL) { BEGINPACKET( pak, 0x7d1 ); ADDBYTE ( pak, 0x00 );//No encontro el ID ADDWORD ( pak, clientid ); ADDBYTE ( pak, 0x00 ); thisclient->client->SendPacket( &pak ); return true; } CParty* party = otherclient->Party->party; if(party!=NULL) { //LMA: Refreshing Capacity if needed party->RefreshMax(); if(party->Members.size()>=party->Capacity) { SendSysMsg( thisclient, "Party is Full" ); return true; } } if(abs(otherclient->Stats->Level-thisclient->Stats->Level)>(Config.Partygap+1)) { BEGINPACKET( pak, 0x7d1 ); ADDBYTE ( pak, 0x07 );//Level inapropiado ADDWORD ( pak, clientid ); ADDBYTE ( pak, 0x00 ); thisclient->client->SendPacket( &pak ); return true; } BEGINPACKET( pak, 0x7d1 ); ADDBYTE ( pak, 0x02 );//Acepto Party ADDWORD ( pak, otherclient->clientid ); ADDBYTE ( pak, 0x00 ); otherclient->client->SendPacket( &pak ); if( party==NULL ) { // new party CParty* thisparty = new CParty; thisparty->AddPlayer( otherclient ); AddParty( thisparty ); otherclient->Party->IsMaster = true; party = thisparty; } //Send Party Level and Party Exp RESETPACKET( pak, 0x7d4 ); // ADDBYTE ( pak, party->PartyLevel ); ADDDWORD ( pak, party->Exp ); thisclient->client->SendPacket( &pak ); thisclient->Party->IsMaster = false; // Send New Party Member info to other players RESETPACKET( pak, 0x7d2 ); ADDBYTE ( pak, party->Option ); ADDBYTE ( pak, 0x01 ); ADDDWORD ( pak, thisclient->CharInfo->charid ); ADDWORD ( pak, thisclient->clientid ); ADDWORD ( pak, thisclient->Stats->MaxHP ); ADDWORD ( pak, thisclient->Stats->HP ); //ADDDWORD ( pak, 0x00000000 );//Tomiz: Was not commented before ADDDWORD ( pak, BuildBuffs( thisclient ));//Tomiz: Buff Data //ADDDWORD ( pak, 0x0000000f );//Tomiz: Was not commented before ADDDWORD ( pak, 0x1f40008c );//Tomiz ADDWORD ( pak, 0x1388 ); ADDSTRING ( pak, thisclient->CharInfo->charname ); ADDBYTE ( pak, 0x00 ); party->SendToMembers( &pak ); // Send To New Party Member the members List RESETPACKET( pak, 0x7d2 ); ADDBYTE ( pak, party->Option ); ADDBYTE ( pak, party->Members.size() ); for(int i=0;i<party->Members.size();i++) { CPlayer* member= party->Members.at(i); ADDDWORD ( pak, member->CharInfo->charid ); ADDWORD ( pak, member->clientid ); ADDWORD ( pak, member->Stats->MaxHP ); ADDWORD ( pak, member->Stats->HP ); //ADDDWORD ( pak, 0x00000000 );//Tomiz: Was not commented before ADDDWORD ( pak, BuildBuffs( member ));//Tomiz: Buff Data //ADDDWORD ( pak, 0x0000000f );//Tomiz: Was not commented before ADDDWORD ( pak, 0x7200005b );//Tomiz ADDWORD ( pak, 0x1388 ); ADDSTRING ( pak, member->CharInfo->charname ); ADDBYTE ( pak, 0x00 ); } thisclient->client->SendPacket( &pak ); party->AddPlayer( thisclient ); } break; case 0x04://No acepto { unsigned int clientid = GETWORD((*P),1); CPlayer* otherclient = GetClientByID( clientid, thisclient->Position->Map ); if(otherclient==NULL) { BEGINPACKET( pak, 0x7d1 ); ADDBYTE ( pak, 0x00 );//No encontro el ID ADDWORD ( pak, clientid ); ADDBYTE ( pak, 0x00 ); thisclient->client->SendPacket( &pak ); return true; } BEGINPACKET( pak, 0x7d1 ); ADDBYTE ( pak, 0x04 );//No acepto ADDWORD ( pak, thisclient->clientid ); ADDBYTE ( pak, 0x00 ); otherclient->client->SendPacket( &pak ); } break; default: Log(MSG_WARNING,"Party Manager unknown action: %i", action); } return true; }
// Party Actions [invite/leave/kick] bool CWorldServer::pakPartyActions( CPlayer* thisclient, CPacket* P ) { unsigned int action = GETBYTE((*P),0); CMap* map = MapList.Index[thisclient->Position->Map]; switch(action) { case 0x00://Invita a new party case 0x01://invite a existent party { UINT clientid = GETWORD((*P),1); if(thisclient->Party->party!=NULL) { //LMA: Refreshing Capacity if needed thisclient->Party->party->RefreshMax(); if(thisclient->Party->party->Members.size()>=thisclient->Party->party->Capacity) { SendSysMsg( thisclient, "Party is full" ); return true; } } CPlayer* otherclient = map->GetPlayerInMap( clientid );// have to be in same map if(otherclient==NULL) { BEGINPACKET( pak, 0x7d1 ); ADDBYTE ( pak, 0x00 );//No encontro el ID ADDWORD ( pak, clientid ); ADDBYTE ( pak, 0x00 ); thisclient->client->SendPacket( &pak ); return true; } if(otherclient->Party->party!=NULL) { BEGINPACKET( pak, 0x7d1 ); ADDBYTE ( pak, 0x01 );//No puede ser solicitado (ya tiene party) ADDWORD ( pak, clientid ); ADDBYTE ( pak, 0x00 ); thisclient->client->SendPacket( &pak ); return true; } if(abs(otherclient->Stats->Level-thisclient->Stats->Level)>(Config.Partygap+1)) { BEGINPACKET( pak, 0x7d1 ); ADDBYTE ( pak, 0x07 );//Level inapropiado ADDWORD ( pak, clientid ); ADDBYTE ( pak, 0x00 ); thisclient->client->SendPacket( &pak ); return true; } BEGINPACKET( pak, 0x7d0 ); ADDBYTE ( pak, action ); ADDWORD ( pak, thisclient->clientid ); ADDBYTE ( pak, 0x00 ); otherclient->client->SendPacket( &pak ); } break; case 0x02://Leave Party { if(thisclient->Party->party==NULL) return true; CParty* party = thisclient->Party->party; BEGINPACKET( pak, 0x7d2 ); ADDWORD ( pak, 0xff00 ); ADDDWORD ( pak, thisclient->CharInfo->charid ); bool pflag = false; if(!party->RemovePlayer( thisclient )) //if this player is not in this party return true; if(party->Members.size()>1) { for(UINT i=0;i<party->Members.size();i++) { CPlayer* thismember = party->Members.at(i); if(!pflag) { ADDDWORD( pak, thismember->CharInfo->charid ); if(thisclient->Party->IsMaster) thismember->Party->IsMaster = true; pflag = true; } thismember->client->SendPacket( &pak ); } } else { for(UINT i=0;i<party->Members.size();i++) { CPlayer* thismember = party->Members.at(i); BEGINPACKET( pak, 0x7d1 ); ADDBYTE ( pak, 0x05 ); ADDWORD ( pak, 0x0000 ); ADDWORD ( pak, 0x0000 ); thismember->client->SendPacket( &pak ); thismember->Party->party = NULL; thismember->Party->IsMaster = true; } RemoveParty( party ); delete party; } } break; case 0x03: //Tomiz: Give leader New Way { if(thisclient->Party->party==NULL) return true; unsigned int clientid = GETWORD((*P),1); if ( !thisclient->Party->IsMaster || clientid == thisclient->clientid ) return true; CPlayer* otherclient = GetClientByID( clientid ); if(otherclient==NULL) return true; BEGINPACKET(pak, 0x7d1); ADDBYTE(pak, 8); ADDWORD(pak, otherclient->clientid); ADDWORD(pak, 0); otherclient->Party->IsMaster = true; thisclient->Party->IsMaster = false; thisclient->Party->party->SendToMembers( &pak ); } break; case 0x81: //Kick from party { unsigned int charid = GETDWORD((*P),1); if(thisclient->Party->party==NULL) return true; if(!thisclient->Party->IsMaster || thisclient->CharInfo->charid==charid) return true; CParty* party = thisclient->Party->party; CPlayer* thismember = party->GetMemberByCharID( charid ); if(thismember==NULL) return true; BEGINPACKET( pak, 0x7d1 ); // Kicked from party message ADDBYTE ( pak, 0x80 ); ADDDWORD ( pak, thismember->CharInfo->charid ); thismember->client->SendPacket( &pak ); RESETPACKET( pak, 0x7d2 ); ADDWORD ( pak, 0xff00 ); ADDDWORD ( pak, thismember->CharInfo->charid ); bool pflag = false; if(!party->RemovePlayer( thismember )) //if this player is not in this party return true; if(party->Members.size()>1) { for(UINT i=0;i<party->Members.size();i++) { CPlayer* othermember = party->Members.at(i); if(!pflag) { ADDDWORD( pak, othermember->CharInfo->charid ); if(thismember->Party->IsMaster) othermember->Party->IsMaster = true; pflag = true; } othermember->client->SendPacket( &pak ); } } else { for(UINT i=0;i<party->Members.size();i++) { CPlayer* othermember = party->Members.at(i); BEGINPACKET( pak, 0x7d1 ); ADDBYTE ( pak, 0x05 ); ADDWORD ( pak, 0x0000 ); ADDWORD ( pak, 0x0000 ); othermember->client->SendPacket( &pak ); othermember->Party->party = NULL; othermember->Party->IsMaster = true; } RemoveParty( party ); delete party; } } break; default: Log(MSG_WARNING,"Party unknown action: %i", action); } return true; }
// Learn Skill bool CWorldServer::LearnSkill( CPlayer* thisclient, UINT skill, bool cost ) { /* 0 - ya aprendido 1 - aprendio 2 - no job 3 - falta otro skill 4 - no status points (lvl) 5 - no se puede subir de lvl el skill 6 - numero incorrecto de skill 7 - no tienes suficientes sp */ BEGINPACKET(pak1, 0 ); BEGINPACKET(pak2, 0 ); BEGINPACKET(pak3, 0 ); //int b=1; CSkills* thisskill = SkillList.at( skill); char skilltype = thisskill->type; //int skillpoints = thisskill->sp; int newslot = thisclient->GetNewSkillSlot(skilltype); //CSkills* thisskill = 0; if (newslot != 0xffff) { switch(skilltype) { case 0: thisclient->bskills[newslot]= skill; //thisskill = GetSkillByID(thisclient->bskills[newslot]); if (cost) thisclient->CharInfo->SkillPoints-=thisskill->sp; RESETPACKET(pak1, 0x7b0); ADDBYTE(pak1, 1); ADDBYTE(pak1, newslot); ADDWORD(pak1, skill); ADDWORD(pak1, thisclient->CharInfo->SkillPoints); thisclient->client->SendPacket(&pak1); thisclient->SetStats(); return true; case 1: thisclient->askill[newslot]= skill; //thisskill = GetSkillByID( (thisclient->askill[newslot])+(thisclient->askilllvl[newslot])); if (cost) thisclient->CharInfo->SkillPoints-=thisskill->sp; RESETPACKET(pak2, 0x7b0); ADDBYTE(pak2, 1); ADDBYTE(pak2, 30+newslot); ADDWORD(pak2, skill); ADDWORD(pak2, thisclient->CharInfo->SkillPoints); thisclient->client->SendPacket(&pak2); thisclient->SetStats(); return true; case 2: thisclient->pskill[newslot]= skill; //thisskill = GetSkillByID( (thisclient->pskill[newslot])+(thisclient->pskilllvl[newslot])); if (cost) thisclient->CharInfo->SkillPoints-=thisskill->sp; RESETPACKET(pak3, 0x7b0); ADDBYTE(pak3, 1); ADDBYTE(pak3, 60+newslot); ADDWORD(pak3, skill); ADDWORD(pak3, thisclient->CharInfo->SkillPoints); thisclient->client->SendPacket(&pak3); thisclient->SetStats(); return true; } } return false; }