void send_paperdoll( Network::Client* client, Mobile::Character* chr ) { Network::PktHelper::PacketOut<Network::PktOut_88> msg; msg->Write<u32>( chr->serial_ext ); if ( ( !settingsManager.ssopt.privacy_paperdoll ) || ( client->chr == chr ) ) { std::string name = ( !chr->has_title_prefix() ? "" : chr->title_prefix() + " " ) + chr->name() + ( !chr->has_title_suffix() ? "" : " " + chr->title_suffix() ); if ( chr->has_title_race() ) name += " (" + chr->title_race() + ")"; msg->Write( name.c_str(), 60 ); } else msg->Write( chr->name().c_str(), 60 ); // MuadDib changed to reflect true status for 0x20 packet. 1/4/2007 // Paperdoll Appears different type Status byte than other walk/update // packets. Using poison/hidden here will break peace/war button. u8 flag1 = chr->warmode() ? 1 : 0; if ( client->UOExpansionFlag & Network::AOS && client->chr->serial_ext == chr->serial_ext ) flag1 |= CHAR_FLAG1_CANALTER; msg->Write<u8>( flag1 ); msg.Send( client ); }
void send_prompt( Network::Client* client, u32 serial ) { Network::PktHelper::PacketOut<Network::PktOut_9A> msg; msg->WriteFlipped<u16>( sizeof msg->buffer ); msg->Write<u32>( serial ); msg->WriteFlipped<u32>( 0x15u ); msg->offset += 5; // u32 type u8 text[0] msg.Send( client ); }
void MultiPlacementCursor::send_placemulti( Network::Client* client, unsigned int objtype, int flags, s16 xoffset, s16 yoffset, u32 hue ) { Network::PktHelper::PacketOut<Network::PktOut_99> msg; msg->Write<u8>( 0x1u ); msg->WriteFlipped<u32>( cursorid_ ); msg->offset += 12; // 12x u8 unk u16 multiid = Items::find_multidesc( objtype ).multiid; multiid += static_cast<u16>( ( flags & Multi::CRMULTI_FACING_MASK ) >> Multi::CRMULTI_FACING_SHIFT ); msg->WriteFlipped<u16>( multiid ); msg->WriteFlipped<s16>( xoffset ); msg->WriteFlipped<s16>( yoffset ); msg->offset += 2; // u16 maybe_zoffset if ( client->ClientType & Network::CLIENTTYPE_7090 ) msg->WriteFlipped<u32>( hue ); msg.Send( client ); client->chr->tcursor2 = this; }
void send_skillmsg( Network::Client* client, const Mobile::Character* chr ) { Network::PktHelper::PacketOut<Network::PktOut_3A> msg; msg->offset += 2; if ( settingsManager.ssopt.core_sends_caps ) msg->Write<u8>( PKTBI_3A_VALUES::FULL_LIST_CAP ); else msg->Write<u8>( PKTBI_3A_VALUES::FULL_LIST ); for ( unsigned short i = 0; i <= networkManager.uoclient_general.maxskills; ++i ) { const UOSkill& uoskill = GetUOSkill( i ); msg->WriteFlipped<u16>( static_cast<u16>( i + 1 ) ); // for some reason, we send this 1-based if ( uoskill.pAttr ) { const Mobile::AttributeValue& av = chr->attribute( uoskill.pAttr->attrid ); int value; value = av.effective_tenths(); if ( value > 0xFFFF ) value = 0xFFFF; msg->WriteFlipped<u16>( static_cast<u16>( value ) ); value = av.base(); if ( value > 0xFFFF ) value = 0xFFFF; msg->WriteFlipped<u16>( static_cast<u16>( value ) ); msg->Write<u8>( av.lock() ); if ( settingsManager.ssopt.core_sends_caps ) msg->WriteFlipped<u16>( av.cap() ); } else { msg->offset += 4; // u16 value/value_unmod msg->Write<u8>( PKTBI_3A_VALUES::LOCK_DOWN ); if ( settingsManager.ssopt.core_sends_caps ) msg->WriteFlipped<u16>( settingsManager.ssopt.default_attribute_cap ); } } if ( !settingsManager.ssopt.core_sends_caps ) msg->offset += 2; // u16 nullterm u16 len = msg->offset; msg->offset = 1; msg->WriteFlipped<u16>( len ); msg.Send( client, len ); }
bool LosCheckedCoordCursor::send_coord_cursor( Network::Client* client ) { if ( !client->chr->target_cursor_busy() ) { Network::PktHelper::PacketOut<Network::PktOut_6C> msg; msg->Write<u8>( PKTBI_6C::UNK1_01 ); msg->WriteFlipped<u32>( cursorid_ ); msg->Write<u8>( PKTBI_6C::CURSOR_TYPE_NEUTRAL ); // rest 0 msg.Send( client, sizeof msg->buffer ); client->chr->tcursor2 = this; return true; } else { return false; } }
void select_server( Network::Client* client, PKTIN_A0* msg ) // Relay player to a certain IP { unsigned servernum = cfBEu16( msg->servernum ) - 1; if ( servernum >= networkManager.servers.size() ) { client->forceDisconnect(); return; } ServerDescription* svr = networkManager.servers[servernum]; Network::PktHelper::PacketOut<Network::PktOut_8C> rsp; rsp->Write<u8>( svr->ip[3] ); rsp->Write<u8>( svr->ip[2] ); rsp->Write<u8>( svr->ip[1] ); rsp->Write<u8>( svr->ip[0] ); if ( client->listen_port != 0 ) rsp->WriteFlipped<u16>( client->listen_port ); else rsp->WriteFlipped<u16>( svr->port ); // MuadDib Added new seed system. This is for transferring KR/6017/Normal client detection from // loginserver // to the gameserver. Allows keeping client flags from remote loginserver to gameserver for 6017 // and kr // packets. unsigned int nseed = 0xFEFE0000 | client->ClientType; rsp->WriteFlipped<u32>( nseed ); // This was set to 0xffffffff in the past but this will conflict // with UO:KR detection rsp.Send( client ); client->cryptengine->Init( &nseed, Crypt::CCryptBase::typeGame ); }
void send_login_error( Network::Client* client, unsigned char reason ) { Network::PktHelper::PacketOut<Network::PktOut_82> msg; msg->Write<u8>( reason ); msg.Send( client ); }
void send_start( Network::Client* client ) { send_feature_enable( client ); // Shinigami: moved from start_client_char() to send before char selection unsigned i; u32 clientflag; // sets client flags unsigned char char_slots; // number of slots according to expansion, avoids crashing people unsigned char char_count; // number of chars to send: Max(char_slots, 5) char_slots = static_cast<u8>( Plib::systemstate.config .character_slots ); // sets it first to be the number defined in the config // TODO: Per account character slots? (With the actual character_slots defining maximum) // If more than 6 chars and no AOS, only send 5. Client is so boring sometimes... if ( char_slots >= 6 && !( client->UOExpansionFlag & Network::AOS ) ) char_slots = 5; char_count = 5; // UO always expects a minimum of 5? What a kludge... if ( char_slots > char_count ) // Max(char_slots, 5) char_count = char_slots; Network::PktHelper::PacketOut<Network::PktOut_A9> msg; msg->offset += 2; msg->Write<u8>( char_count ); for ( i = 0; i < char_count; i++ ) { if ( i < char_slots ) // Small kludge to have a minimum of 5 chars in the packet { // name only 30 long rest is password seems to fix the password promt problem Mobile::Character* chr = client->acct->get_character( i ); if ( chr ) { msg->Write( chr->name().c_str(), 30, false ); msg->offset += 30; // password } else msg->offset += 60; } else msg->offset += 60; } msg->Write<u8>( gamestate.startlocations.size() ); for ( i = 0; i < gamestate.startlocations.size(); i++ ) { msg->Write<u8>( i ); if ( client->ClientType & Network::CLIENTTYPE_70130 ) { msg->Write( gamestate.startlocations[i]->city.c_str(), 32, false ); msg->Write( gamestate.startlocations[i]->desc.c_str(), 32, false ); Coordinate coord = gamestate.startlocations[i]->coords[0]; msg->WriteFlipped<u32>( coord.x ); msg->WriteFlipped<u32>( coord.y ); msg->WriteFlipped<s32>( coord.z ); msg->WriteFlipped<u32>( gamestate.startlocations[i]->mapid ); // MapID msg->WriteFlipped<u32>( gamestate.startlocations[i]->cliloc_desc ); // Cliloc Description msg->offset += 4; } else { msg->Write( gamestate.startlocations[i]->city.c_str(), 31, false ); msg->Write( gamestate.startlocations[i]->desc.c_str(), 31, false ); } } clientflag = settingsManager.ssopt.uo_feature_enable; // 'default' flags. Maybe auto-enable them // according to the expansion? clientflag |= PKTOUT_A9::FLAG_SEND_UO3D_TYPE; // Let UO3D (KR,SA) send 0xE1 packet // Change this to a function for clarity? -- Nando if ( char_slots == 7 ) clientflag |= PKTOUT_A9::FLAG_UPTO_SEVEN_CHARACTERS; // 7th Character flag else if ( char_slots == 6 ) clientflag |= PKTOUT_A9::FLAG_UPTO_SIX_CHARACTERS; // 6th Character Flag else if ( char_slots == 1 ) clientflag |= 0x14; // Only one character (SIEGE (0x04) + LIMIT_CHAR (0x10)) msg->WriteFlipped<u32>( clientflag ); u16 len = msg->offset; msg->offset = 1; msg->WriteFlipped<u16>( len ); msg.Send( client, len ); }