Pol  Revision:cb584c9
party.cpp
Go to the documentation of this file.
1 
14 #include "pol_global_config.h"
15 
16 #include "party.h"
17 
18 #include <ctype.h>
19 #include <iostream>
20 #include <stdlib.h>
21 #include <string>
22 #include <time.h>
23 
24 #include "../clib/cfgelem.h"
25 #include "../clib/cfgfile.h"
26 #include "../clib/cfgsect.h"
27 #include "../clib/clib_endian.h"
28 #include "../clib/fileutil.h"
29 #include "../clib/logfacility.h"
30 #include "../clib/streamsaver.h"
31 #include "../plib/systemstate.h"
32 #include "clfunc.h"
33 #include "fnsearch.h"
34 #include "globals/network.h"
35 #include "globals/settings.h"
36 #include "globals/uvars.h"
37 #include "mobile/charactr.h"
38 #include "module/partymod.h"
39 #include "network/client.h"
40 #include "network/packethelper.h"
41 #include "network/packets.h"
42 #include "party_cfg.h"
43 #include "pktboth.h"
44 #include "pktdef.h"
45 #include "polclock.h"
46 #include "schedule.h"
47 #include "statmsg.h"
48 #include "syshook.h"
49 #include "ufunc.h"
50 #include "unicode.h"
51 #include "uobject.h"
52 #include "uoclient.h"
53 
54 #ifdef MEMORYLEAK
55 #include "../bscript/bobject.h"
56 #endif
57 
58 
59 namespace Pol
60 {
61 namespace Core
62 {
63 void handle_unknown_packet( Network::Client* client );
64 
65 Party::Party( u32 serial )
66  : _member_serials(),
67  _candidates_serials(),
68  _offlinemember_serials(),
69  _leaderserial( serial ),
70  _proplist( Core::CPropProfiler::Type::PARTY )
71 {
72  _member_serials.push_back( serial );
73 }
74 
76  : _member_serials(),
79  _leaderserial( 0 ),
80  _proplist( Core::CPropProfiler::Type::PARTY )
81 {
82  _leaderserial = elem.remove_ulong( "LEADER" );
83  unsigned int tmp;
84  while ( elem.remove_prop( "MEMBER", &tmp ) )
85  {
86  _member_serials.push_back( tmp );
87  }
88  _proplist.readProperties( elem );
89 }
90 
92 {
93  settingsManager.party_cfg.General.MaxPartyMembers = elem.remove_ushort( "MaxPartyMembers", 10 );
95  elem.remove_bool( "TreatNoAsPrivate", false );
96  settingsManager.party_cfg.General.DeclineTimeout = elem.remove_ushort( "DeclineTimeout", 10 );
98  elem.remove_bool( "RemoveMemberOnLogoff", false );
101  elem.remove_bool( "RejoinPartyOnLogon", false );
102  else
104  std::string tmp = elem.remove_string( "PrivateMsgPrefix", "" );
105  if ( tmp.size() == 0 )
107  else
108  {
109  std::unique_ptr<Bscript::ObjArray> arr( new Bscript::ObjArray );
110  tmp += " ";
111  for ( unsigned i = 0; i < tmp.size(); ++i )
112  {
113  arr->addElement( new Bscript::BLong( static_cast<unsigned char>( tmp[i] ) ) );
114  }
115  settingsManager.party_cfg.General.PrivateMsgPrefixLen = (unsigned char)arr->ref_arr.size();
118 
119  Bscript::ObjArray* arrPtr = arr.get();
123  }
124 }
125 
127 {
128  std::string temp;
129  if ( elem.remove_prop( "CanAddToParty", &temp ) )
131  if ( elem.remove_prop( "CanRemoveMember", &temp ) )
133  FindExportedFunction( elem, nullptr, temp, 2 );
134  if ( elem.remove_prop( "CanLeaveParty", &temp ) )
136  if ( elem.remove_prop( "OnPublicChat", &temp ) )
138  if ( elem.remove_prop( "OnPrivateChat", &temp ) )
140  if ( elem.remove_prop( "OnDisband", &temp ) )
141  settingsManager.party_cfg.Hooks.OnDisband = FindExportedFunction( elem, nullptr, temp, 1 );
142  if ( elem.remove_prop( "ChangePublicChat", &temp ) )
144  FindExportedFunction( elem, nullptr, temp, 2 );
145  if ( elem.remove_prop( "ChangePrivateChat", &temp ) )
147  FindExportedFunction( elem, nullptr, temp, 3 );
148  if ( elem.remove_prop( "OnLeaveParty", &temp ) )
150  if ( elem.remove_prop( "OnAddToParty", &temp ) )
152  if ( elem.remove_prop( "OnPartyCreate", &temp ) )
154  if ( elem.remove_prop( "OnDecline", &temp ) )
155  settingsManager.party_cfg.Hooks.OnDecline = FindExportedFunction( elem, nullptr, temp, 1 );
156  if ( elem.remove_prop( "OnLootPermChange", &temp ) )
158  FindExportedFunction( elem, nullptr, temp, 1 );
159 }
160 void load_party_cfg( bool reload )
161 {
162  if ( !Clib::FileExists( "config/party.cfg" ) )
163  {
170  }
171  else
172  {
173  Clib::ConfigFile cf( "config/party.cfg" );
174 
175  Clib::ConfigSection general( cf, "General" );
176  Clib::ConfigSection hooks( cf, "HookList", Clib::CST_NORMAL );
177 
178  Clib::ConfigElem elem;
179 
180  while ( cf.read( elem ) )
181  {
182  if ( general.matches( elem ) )
183  load_party_cfg_general( elem );
184  else if ( hooks.matches( elem ) && !reload )
185  load_party_cfg_hooks( elem );
186  }
187  }
188 }
189 
191 {
192  if ( settingsManager.party_cfg.Hooks.CanAddToParty != nullptr )
193  {
196  }
198  {
201  }
202  if ( settingsManager.party_cfg.Hooks.CanLeaveParty != nullptr )
203  {
206  }
207  if ( settingsManager.party_cfg.Hooks.OnPublicChat != nullptr )
208  {
211  }
212  if ( settingsManager.party_cfg.Hooks.OnPrivateChat != nullptr )
213  {
216  }
217  if ( settingsManager.party_cfg.Hooks.OnDisband != nullptr )
218  {
221  }
223  {
226  }
228  {
231  }
232  if ( settingsManager.party_cfg.Hooks.OnLeaveParty != nullptr )
233  {
236  }
237  if ( settingsManager.party_cfg.Hooks.OnAddToParty != nullptr )
238  {
241  }
242  if ( settingsManager.party_cfg.Hooks.OnPartyCreate != nullptr )
243  {
246  }
247  if ( settingsManager.party_cfg.Hooks.OnDecline != nullptr )
248  {
251  }
253  {
256  }
257 }
259 {
261 
262  for ( auto& party : gamestate.parties )
263  {
264  party->cleanup();
265  }
266  gamestate.parties.clear();
267 }
268 
270 {
271  _member_serials.clear();
272  _candidates_serials.clear();
273  _offlinemember_serials.clear();
274 }
275 
277 {
278  return _leaderserial;
279 }
280 
281 bool Party::is_member( u32 serial ) const
282 {
283  return std::find( _member_serials.begin(), _member_serials.end(), serial ) !=
284  _member_serials.end();
285 }
286 
287 bool Party::is_candidate( u32 serial ) const
288 {
289  return std::find( _candidates_serials.begin(), _candidates_serials.end(), serial ) !=
290  _candidates_serials.end();
291 }
292 
294 {
295  std::vector<u32>::iterator itr = _member_serials.begin();
296  while ( itr != _member_serials.end() )
297  {
298  Mobile::Character* chr = system_find_mobile( *itr );
299  if ( chr != nullptr )
300  {
301  chr->party( this );
302  ++itr;
303  }
304  else
305  itr = _member_serials.erase( itr );
306  }
307  if ( _member_serials.empty() )
308  return ( false );
309  if ( !test_size() )
310  return ( false );
311  if ( system_find_mobile( _leaderserial ) == nullptr )
312  _leaderserial = *_member_serials.begin();
313 
314  return true;
315 }
316 
317 bool Party::is_leader( u32 serial ) const
318 {
319  return _leaderserial == serial;
320 }
321 
322 u32 Party::get_member_at( unsigned short pos ) const
323 {
324  if ( _member_serials.size() < pos )
325  return 0;
326  return _member_serials[pos];
327 }
328 
329 bool Party::add_candidate( u32 serial )
330 {
331  if ( ( _member_serials.size() + _candidates_serials.size() ) >=
333  return false;
334  _candidates_serials.push_back( serial );
335  return true;
336 }
337 
338 bool Party::add_member( u32 serial )
339 {
340  if ( ( _member_serials.size() + _candidates_serials.size() ) >=
342  return false;
343  _member_serials.push_back( serial );
344  return true;
345 }
346 
348 {
349  _offlinemember_serials.push_back( serial );
350 }
351 
353 {
354  auto itr = std::find_if( _candidates_serials.begin(), _candidates_serials.end(),
355  [&]( u32& i ) { return i == serial; } );
356  if ( itr != _candidates_serials.end() )
357  {
358  _candidates_serials.erase( itr );
359  return true;
360  }
361  return false;
362 }
363 
364 bool Party::remove_member( u32 serial )
365 {
366  auto itr = std::find_if( _member_serials.begin(), _member_serials.end(),
367  [&]( u32& i ) { return i == serial; } );
368  if ( itr != _member_serials.end() )
369  {
370  _member_serials.erase( itr );
371  return true;
372  }
373  return false;
374 }
375 
377 {
378  auto itr = std::find_if( _offlinemember_serials.begin(), _offlinemember_serials.end(),
379  [&]( u32& i ) { return i == serial; } );
380  if ( itr != _offlinemember_serials.end() )
381  {
382  _offlinemember_serials.erase( itr );
383  return true;
384  }
385  return false;
386 }
387 
388 void Party::set_leader( u32 serial )
389 {
390  auto itr = std::find_if( _member_serials.begin(), _member_serials.end(),
391  [&]( u32& i ) { return i == serial; } );
392  if ( itr != _member_serials.end() )
393  {
394  _member_serials.erase( itr );
395  }
396  _member_serials.insert( _member_serials.begin(), serial );
397  _leaderserial = serial;
398 }
399 
400 bool Party::test_size() const
401 {
402  if ( ( _candidates_serials.empty() ) && ( _member_serials.size() <= 1 ) )
403  return false;
404  return true;
405 }
406 
407 bool Party::can_add() const
408 {
409  if ( ( _member_serials.size() + _candidates_serials.size() ) >=
411  return false;
412  return true;
413 }
414 
416 {
418  msg->offset += 4; // len+sub
419  msg->Write<u8>( PKTBI_BF_06::PARTYCMD_ADD );
420  msg->offset++; // nummembers
421 
422  // TODO: refactor the loop below to use std::remove_if() + extract a method
423  auto itr = _member_serials.begin();
424  while ( itr != _member_serials.end() )
425  {
426  Mobile::Character* chr = system_find_mobile( *itr );
427  if ( chr != nullptr )
428  {
429  msg->Write<u32>( chr->serial_ext );
430  ++itr;
431  }
432  else
433  itr = _member_serials.erase( itr );
434  }
435 
436  u16 len = msg->offset;
437  msg->offset = 6;
438  msg->Write<u8>( _member_serials.size() );
439  msg->offset = 1;
440  msg->WriteFlipped<u16>( len );
441 
442  if ( to_chr == nullptr )
443  {
444  for ( const auto& serial : _member_serials )
445  {
446  Mobile::Character* chr = system_find_mobile( serial );
447  if ( chr != nullptr )
448  {
449  if ( chr->has_active_client() )
450  msg.Send( chr->client, len );
451  }
452  }
453  }
454  else
455  msg.Send( to_chr->client, len );
456 }
457 
459 {
462 
463  for ( const auto& serial : _member_serials )
464  {
465  Mobile::Character* chr = system_find_mobile( serial );
466  if ( chr != nullptr )
467  {
468  chr->party( nullptr );
469  if ( chr->has_active_client() )
470  {
471  send_empty_party( chr );
472  send_sysmessage_cl( chr->client, CLP_Disbanded ); // Your party has disbanded.
473  }
474  }
475  }
476  for ( const auto& serial : _candidates_serials )
477  {
478  Mobile::Character* chr = system_find_mobile( serial );
479  if ( chr != nullptr )
480  chr->candidate_of( nullptr );
481  }
482  for ( const auto& serial : _offlinemember_serials )
483  {
484  Mobile::Character* chr = system_find_mobile( serial );
485  if ( chr != nullptr )
486  chr->offline_mem_of( nullptr );
487  }
488 
489  _member_serials.clear();
490  _candidates_serials.clear();
491  _offlinemember_serials.clear();
492 }
493 
495 {
496  *disband = false;
497  if ( remchr->serial == _leaderserial )
498  {
499  *disband = true;
500  return;
501  }
502  else
503  {
505  msg->offset += 4; // len+sub
506  msg->Write<u8>( PKTBI_BF_06::PARTYCMD_REMOVE );
507  msg->offset++; // nummembers
508  msg->Write<u32>( remchr->serial_ext );
509 
510  // TODO: refactor the loop below to use std::remove_if() + extract a method
511  auto itr = _member_serials.begin();
512  while ( itr != _member_serials.end() )
513  {
514  Mobile::Character* chr = system_find_mobile( *itr );
515  if ( chr != nullptr )
516  {
517  msg->Write<u32>( chr->serial_ext );
518  ++itr;
519  }
520  else
521  itr = _member_serials.erase( itr );
522  }
523  u16 len = msg->offset;
524  msg->offset = 6;
525  msg->Write<u8>( _member_serials.size() );
526  msg->offset = 1;
527  msg->WriteFlipped<u16>( len );
528 
529  for ( const auto& serial : _member_serials )
530  {
531  Mobile::Character* chr = system_find_mobile( serial );
532  if ( chr != nullptr )
533  {
534  if ( chr->has_active_client() )
535  msg.Send( chr->client, len );
536  }
537  }
538  send_msg_to_all( CLP_Player_Removed ); // A player has been removed from your party.
539  if ( !test_size() )
540  {
541  send_msg_to_all( CLP_Last_Person ); // The last person has left the party...
542  *disband = true;
543  }
544  }
545 }
546 
547 void Party::send_msg_to_all( unsigned int clilocnr, const char* affix,
548  Mobile::Character* exeptchr ) const
549 {
552  if ( affix != nullptr )
553  build_sysmessage_cl_affix( msgcc.Get(), clilocnr, affix, true );
554  else
555  build_sysmessage_cl( msgc1.Get(), clilocnr );
556 
557  for ( const auto& serial : _member_serials )
558  {
559  Mobile::Character* chr = system_find_mobile( serial );
560  if ( chr != nullptr )
561  {
562  if ( chr != exeptchr )
563  {
564  if ( chr->has_active_client() )
565  {
566  if ( affix != nullptr )
567  msgcc.Send( chr->client );
568  else
569  msgc1.Send( chr->client );
570  }
571  }
572  }
573  }
574 }
575 
577 {
578  if ( ( chr != bob ) && ( is_member( bob->serial ) ) && ( chr->realm == bob->realm ) &&
579  ( pol_distance( chr->x, chr->y, bob->x, bob->y ) < 20 ) )
580  {
581  if ( !chr->is_visible_to_me( bob ) )
582  send_short_statmsg( chr->client, bob );
583 
584  send_attributes_normalized( chr, bob );
585  }
586 }
587 
589 {
590  if ( newmember == nullptr )
591  return;
592  for ( const auto& serial : _member_serials )
593  {
594  Mobile::Character* chr = system_find_mobile( serial );
595  if ( chr != nullptr )
596  {
597  if ( newmember != chr )
598  {
599  if ( chr->has_active_client() )
600  {
601  send_short_statmsg( chr->client, newmember );
602  send_attributes_normalized( chr, newmember );
603  }
604  if ( newmember->has_active_client() )
605  {
606  send_short_statmsg( newmember->client, chr );
607  send_attributes_normalized( newmember, chr );
608  }
609  }
610  }
611  }
612 }
613 
615 {
617  msg->Write<u32>( chr->serial_ext );
618 
619  const auto& vital = chr->vital( networkManager.uoclient_general.mana.id );
620  int h = vital.current_ones();
621  if ( h > 0xFFFF )
622  h = 0xFFFF;
623  int mh = vital.maximum_ones();
624  if ( mh > 0xFFFF )
625  mh = 0xFFFF;
626  msg->WriteFlipped<u16>( 1000u );
627  msg->WriteFlipped<u16>( static_cast<u16>( h * 1000 / mh ) );
628 
629  for ( const auto& serial : _member_serials )
630  {
631  Mobile::Character* mem = system_find_mobile( serial );
632  if ( mem != nullptr )
633  {
634  if ( mem != chr )
635  {
636  if ( mem->has_active_client() )
637  msg.Send( mem->client );
638  }
639  }
640  }
641 }
643 {
645  msg->Write<u32>( chr->serial_ext );
646 
647  const auto& vital = chr->vital( networkManager.uoclient_general.stamina.id );
648  int h = vital.current_ones();
649  if ( h > 0xFFFF )
650  h = 0xFFFF;
651  int mh = vital.maximum_ones();
652  if ( mh > 0xFFFF )
653  mh = 0xFFFF;
654  msg->WriteFlipped<u16>( 1000u );
655  msg->WriteFlipped<u16>( static_cast<u16>( h * 1000 / mh ) );
656 
657  for ( const auto& serial : _member_serials )
658  {
659  Mobile::Character* mem = system_find_mobile( serial );
660  if ( mem != nullptr )
661  {
662  if ( mem != chr )
663  {
664  if ( mem->has_active_client() )
665  msg.Send( mem->client );
666  }
667  }
668  }
669 }
670 
671 void Party::send_member_msg_public( Mobile::Character* chr, u16* wtext, size_t wtextlen ) const
672 {
674  msg->offset += 4; // len+sub
675  msg->Write<u8>( PKTBI_BF_06::PARTYCMD_PARTY_MSG );
676  msg->Write<u32>( chr->serial_ext );
677 
679  {
680  Bscript::ObjArray* arr;
681  if ( !Core::convertUCtoArray( wtext, arr, static_cast<unsigned int>( wtextlen ),
682  true ) ) // convert back with ctBEu16()
683  return;
684  Bscript::BObject obj =
686  if ( obj->isa( Bscript::BObjectImp::OTArray ) )
687  {
688  arr = static_cast<Bscript::ObjArray*>( obj.impptr() );
689  unsigned len = static_cast<unsigned int>( arr->ref_arr.size() );
690  if ( len > SPEECH_MAX_LEN )
691  len = SPEECH_MAX_LEN;
692  if ( !Core::convertArrayToUC( arr, wtext, len, true ) )
693  return;
694  wtextlen = len + 1;
695  }
696  else if ( obj->isa( Bscript::BObjectImp::OTLong ) ) // break on return(0)
697  {
698  if ( !obj->isTrue() )
699  return;
700  }
701  }
702  msg->Write( &wtext[0], static_cast<u16>( wtextlen ), false );
703  u16 len = msg->offset;
704  msg->offset = 1;
705  msg->WriteFlipped<u16>( len );
706 
707  for ( const auto& serial : _member_serials )
708  {
709  Mobile::Character* mem = system_find_mobile( serial );
710  if ( mem != nullptr )
711  {
712  if ( mem->has_active_client() )
713  msg.Send( mem->client, len );
714  }
715  }
716 }
717 
719  size_t wtextlen ) const
720 {
721  if ( !tochr->has_active_client() )
722  return;
724  msg->offset += 4; // len+sub
725  msg->Write<u8>( PKTBI_BF_06::PARTYCMD_MEMBER_MSG );
726  msg->Write<u32>( chr->serial_ext );
727 
729  {
730  Bscript::ObjArray* arr;
731  if ( !Core::convertUCtoArray( wtext, arr, static_cast<unsigned int>( wtextlen ),
732  true ) ) // convert back with ctBEu16()
733  return;
735  chr->make_ref(), tochr->make_ref(), arr );
736  if ( obj->isa( Bscript::BObjectImp::OTArray ) )
737  {
738  arr = static_cast<Bscript::ObjArray*>( obj.impptr() );
739  unsigned len = static_cast<unsigned int>( arr->ref_arr.size() );
740  if ( len > SPEECH_MAX_LEN )
741  len = SPEECH_MAX_LEN;
742  if ( !Core::convertArrayToUC( arr, wtext, len, true ) )
743  return;
744  wtextlen = len + 1;
745  }
746  else if ( obj->isa( Bscript::BObjectImp::OTLong ) ) // break on return(0)
747  {
748  if ( !obj->isTrue() )
749  return;
750  }
751  }
757 
758  msg->Write( &wtext[0], static_cast<u16>( wtextlen ), false );
759  u16 len = msg->offset;
760  msg->offset = 1;
761  msg->WriteFlipped<u16>( len );
762 
763  msg.Send( tochr->client, len );
764 }
765 
767 {
768  if ( _member_serials.size() <= 1 )
769  return;
770  if ( system_find_mobile( _leaderserial ) == nullptr )
771  return;
772 
773  sw() << "Party" << pf_endl << "{" << pf_endl << "\tLeader\t0x" << fmt::hex( _leaderserial )
774  << pf_endl;
775 
776  for ( const auto& mserial : _member_serials )
777  {
778  Mobile::Character* mem = system_find_mobile( mserial );
779  if ( mem != nullptr )
780  sw() << "\tMember\t0x" << fmt::hex( mserial ) << pf_endl;
781  }
783  sw() << "}" << pf_endl << pf_endl;
784  // sw.flush();
785 }
786 
787 size_t Party::estimateSize() const
788 {
789  return 3 * sizeof( u32* ) + _member_serials.capacity() * sizeof( u32 ) + 3 * sizeof( u32* ) +
790  _candidates_serials.capacity() * sizeof( u32 ) + 3 * sizeof( u32* ) +
791  _offlinemember_serials.capacity() * sizeof( u32 ) + sizeof( u32 ) /*_leaderserial*/
793 }
794 
796 {
797  if ( chr != nullptr && chr->has_active_client() )
798  {
800  msg->WriteFlipped<u16>( 11u );
801  msg->offset += 2; // sub
802  msg->Write<u8>( PKTBI_BF_06::PARTYCMD_REMOVE );
803  msg->offset++; // nummembers
804  msg->Write<u32>( chr->serial_ext );
805  msg.Send( chr->client );
806  }
807 }
808 
810 {
811  Parties::iterator itr = gamestate.parties.begin();
812  while ( itr != gamestate.parties.end() )
813  {
814  if ( !( *itr )->register_with_members() )
815  {
816  ( *itr )->disband();
817  itr = gamestate.parties.erase( itr );
818  }
819  else
820  ++itr;
821  }
822 }
823 
825 {
826  auto itr = std::find_if( gamestate.parties.begin(), gamestate.parties.end(),
827  [&]( PartyRef& party ) { return party->is_leader( leader ); } );
828  if ( itr != gamestate.parties.end() )
829  {
830  ( *itr )->disband();
831  gamestate.parties.erase( itr );
832  }
833 }
834 
836 {
837  std::string partyfile = Plib::systemstate.config.world_data_path + "parties.txt";
838 
839  if ( !Clib::FileExists( partyfile ) )
840  return;
842  return;
843 
844  INFO_PRINT << " " << partyfile << ":";
845  Clib::ConfigFile cf( partyfile );
846  Clib::ConfigSection sect_party( cf, "PARTY", Clib::CST_NORMAL );
847  Clib::ConfigElem elem;
848  static int num_until_dot = 1000;
849  clock_t start = clock();
850  while ( cf.read( elem ) )
851  {
852  if ( --num_until_dot == 0 )
853  {
854  INFO_PRINT << ".";
855  num_until_dot = 1000;
856  }
857  if ( sect_party.matches( elem ) )
858  gamestate.parties.push_back( ref_ptr<Party>( new Party( elem ) ) );
859  }
860  clock_t end = clock();
861  int ms = static_cast<int>( ( end - start ) * 1000.0 / CLOCKS_PER_SEC );
862 
863  INFO_PRINT << " " << gamestate.parties.size() << " elements in " << ms << " ms.\n";
864 
866 }
867 
869 {
871  return;
872  for ( const auto& party : gamestate.parties )
873  {
874  party->printOn( sw );
875  }
876 }
877 
879 {
880  if ( chr->has_party() )
881  {
883  {
884  Party* party = chr->party();
885  if ( party->remove_member( chr->serial ) )
886  {
887  bool disband = false;
888  if ( party->is_leader( chr->serial ) )
889  {
890  if ( !party->test_size() )
891  {
892  disband_party( party->leader() );
893  chr->party( nullptr );
894  return;
895  }
896  party->set_leader( party->get_member_at( 0 ) );
897  party->send_msg_to_all(
898  CLP_Player_Removed ); // A player has been removed from your party.
899  party->send_member_list( nullptr );
900  }
901  else
902  party->send_remove_member( chr, &disband );
903  chr->party( nullptr );
906 
907  if ( disband )
908  disband_party( party->leader() );
909  else
910  {
912  {
913  party->add_offline_mem( chr->serial );
914  chr->offline_mem_of( party );
915  }
916  }
917  }
918  }
919  }
920 }
921 
922 
924 {
925  if ( chr->has_offline_mem_of() )
926  {
927  Party* party = chr->offline_mem_of();
928  if ( party->remove_offline_mem( chr->serial ) )
929  {
930  if ( party->add_member( chr->serial ) )
931  {
932  chr->party( party );
933  send_sysmessage_cl( chr->client, CLP_Rejoined ); // You have rejoined the party.
934  party->send_member_list( nullptr );
935  party->send_stats_on_add( chr );
936  party->send_msg_to_all( CLP_Player_Rejoined, chr->name().c_str(),
937  chr ); //: rejoined the party.
938  }
939  }
940  chr->offline_mem_of( nullptr );
941  }
942  else if ( !chr->has_party() )
943  send_empty_party( chr );
944  else
945  {
946  Party* party = chr->party();
947  send_sysmessage_cl( chr->client, CLP_Rejoined ); // You have rejoined the party.
948  party->send_member_list( chr );
949  party->send_stats_on_add( chr );
950  party->send_msg_to_all( CLP_Player_Rejoined, chr->name().c_str(),
951  chr ); //: rejoined the party.
952  }
953 }
954 
955 
957 {
958  switch ( msg->partydata.partycmd )
959  {
961  handle_add( client, msg );
962  break;
964  handle_remove( client, msg );
965  break;
967  handle_member_msg( client, msg );
968  break;
970  handle_party_msg( client, msg );
971  break;
973  handle_loot_perm( client, msg );
974  break;
976  handle_accept_invite( client, msg );
977  break;
979  handle_decline_invite( client, msg );
980  break;
981  default:
982  handle_unknown_packet( client );
983  }
984 }
985 
987 {
988  if ( chr->client != nullptr )
989  {
991  add_candidate( add, chr );
992  }
993 }
994 
995 void handle_add( Network::Client* client, PKTBI_BF* msg )
996 {
997  if ( msg->partydata.partyadd.memberid == 0x0 )
998  {
999  send_sysmessage_cl( client, CLP_Who_To_Add ); // Who would you like to add to your party?
1001  }
1002  else
1003  {
1005  add_candidate( member, client->chr );
1006  }
1007 }
1008 
1010 {
1011  if ( chr->client != nullptr )
1012  {
1014  if ( rem != nullptr )
1015  {
1016  Party* party = chr->party();
1017  if ( ( party == nullptr ) || ( !party->is_leader( chr->serial ) ) ||
1018  ( !party->is_member( rem->serial ) ) )
1019  return;
1020  if ( chr == rem )
1021  send_sysmessage_cl( chr->client, CLP_Cannot_Remove_Self ); // You may only remove yourself
1022  // from a party if you are not
1023  // the leader.
1024  else
1025  {
1027  {
1029  rem->make_ref() ) )
1030  {
1031  party->send_member_list( chr ); // resend list
1032  return;
1033  }
1034  }
1035  if ( party->remove_member( rem->serial ) )
1036  {
1037  bool disband;
1038  party->send_remove_member( rem, &disband );
1039  rem->party( nullptr );
1042 
1043  send_sysmessage_cl( rem->client, CLP_Removed ); // You have been removed from the party.
1044  send_empty_party( rem );
1045  if ( disband )
1046  disband_party( party->leader() );
1047  }
1048  }
1049  }
1050  }
1051 }
1052 
1054 {
1055  Party* party = client->chr->party();
1056  if ( party == nullptr )
1057  {
1058  send_sysmessage_cl( client, CLP_No_Party ); // You are not in a party.
1059  return;
1060  }
1062  // leader wants target
1063  if ( ( party->is_leader( client->chr->serial ) ) && ( member == nullptr ) )
1064  {
1065  send_sysmessage_cl( client,
1066  CLP_Who_to_Remove ); // Who would you like to remove from your party?
1068  }
1069  // leader kicks member, or member kicks himself
1070  else if ( ( ( party->is_leader( client->chr->serial ) ) || ( client->chr == member ) ) &&
1071  ( party->is_member( member->serial ) ) )
1072  {
1073  if ( client->chr == member )
1074  {
1076  {
1078  {
1079  party->send_member_list( client->chr ); // resend list
1080  return;
1081  }
1082  }
1083  }
1084  else
1085  {
1087  {
1089  member->make_ref() ) )
1090  {
1091  party->send_member_list( client->chr ); // resend list
1092  return;
1093  }
1094  }
1095  }
1096  if ( party->remove_member( member->serial ) )
1097  {
1098  bool disband;
1099  member->party( nullptr );
1100  party->send_remove_member( member, &disband );
1103  client->chr->make_ref() );
1104  if ( member->has_active_client() )
1105  {
1106  send_sysmessage_cl( member->client, CLP_Removed ); // You have been removed from the party.
1107  send_empty_party( member );
1108  }
1109  if ( disband )
1110  disband_party( party->leader() );
1111  }
1112  }
1113 }
1114 
1116 {
1117  using std::wcout;
1118  Mobile::Character* member =
1120  if ( member != nullptr )
1121  {
1122  Party* party = client->chr->party();
1123 
1124  if ( ( party != nullptr ) && ( member->has_party() ) && ( party->is_member( member->serial ) ) )
1125  {
1126  int intextlen;
1127  u16* themsg = msg->partydata.partymembermsg.wtext;
1128  // u8 * bytemsg = ((u8 *) themsg);
1129  // int wtextoffset = 0;
1130  int i;
1131 
1132  u16 wtextbuf[SPEECH_MAX_LEN + 1];
1133  size_t wtextbuflen;
1134 
1135  intextlen =
1136  ( cfBEu16( msg->msglen ) - 10 ) / sizeof( msg->partydata.partymembermsg.wtext[0] ) - 1;
1137 
1138  // intextlen does not include the null terminator.
1139 
1140  // Preprocess the text into a sanity-checked, printable, null-terminated form in textbuf
1141  if ( intextlen < 0 )
1142  intextlen = 0;
1143  if ( intextlen > SPEECH_MAX_LEN )
1144  intextlen = SPEECH_MAX_LEN;
1145 
1146  wtextbuflen = 0;
1147  for ( i = 0; i < intextlen; i++ )
1148  {
1149  u16 wc = cfBEu16( themsg[i] );
1150  if ( wc == 0 )
1151  break; // quit early on embedded nulls
1152  if ( wc == L'~' )
1153  continue; // skip unprintable tildes.
1154  wtextbuf[wtextbuflen++] = ctBEu16( wc );
1155  }
1156  wtextbuf[wtextbuflen++] = (u16)0;
1157 
1159  {
1160  Bscript::ObjArray* arr;
1161  if ( Core::convertUCtoArray( wtextbuf, arr, wtextbuflen,
1162  true ) ) // convert back with ctBEu16()
1164  member->make_ref(), arr );
1165  }
1166 
1167  party->send_member_msg_private( client->chr, member, wtextbuf, wtextbuflen );
1168  }
1169  else
1170  send_sysmessage_cl( client, CLP_No_Party ); // You are not in a party.
1171  }
1172 }
1173 
1175 {
1176  using std::wcout; // wcout.narrow() function r0x! :-)
1177  Party* party = client->chr->party();
1178  if ( party != nullptr )
1179  {
1180  int intextlen;
1181  u16* themsg = msg->partydata.partymsg.wtext;
1182  // u8 * bytemsg = ((u8 *) themsg);
1183  // int wtextoffset = 0;
1184  int i, starti;
1185  Mobile::Character* member = nullptr;
1186 
1187  u16 wtextbuf[SPEECH_MAX_LEN + 1];
1188  size_t wtextbuflen;
1189 
1190  intextlen = ( cfBEu16( msg->msglen ) - 6 ) / sizeof( msg->partydata.partymsg.wtext[0] ) - 1;
1191 
1192  // intextlen does not include the null terminator.
1193 
1194  // Preprocess the text into a sanity-checked, printable, null-terminated form in textbuf
1195  if ( intextlen < 0 )
1196  intextlen = 0;
1197  if ( intextlen > SPEECH_MAX_LEN )
1198  intextlen = SPEECH_MAX_LEN;
1199 
1200  wtextbuflen = 0;
1201  starti = 0;
1203  {
1204  char no_c = wcout.narrow( (wchar_t)cfBEu16( themsg[0] ), '?' );
1205  if ( ( isdigit( no_c ) ) && ( cfBEu16( themsg[1] ) == L' ' ) )
1206  {
1207  int no = atoi( &no_c );
1208  if ( no == 0 )
1209  no = 9;
1210  else
1211  no--;
1212  u32 mem = party->get_member_at( (unsigned short)no );
1213  if ( mem != 0 )
1214  {
1215  member = system_find_mobile( mem );
1216  if ( ( member != nullptr ) && ( member->has_active_client() ) )
1217  starti = 2;
1218  }
1219  }
1220  }
1221 
1222  for ( i = starti; i < intextlen; i++ )
1223  {
1224  u16 wc = cfBEu16( themsg[i] );
1225  if ( wc == 0 )
1226  break; // quit early on embedded nulls
1227  if ( wc == L'~' )
1228  continue; // skip unprintable tildes.
1229  wtextbuf[wtextbuflen++] = ctBEu16( wc );
1230  }
1231  wtextbuf[wtextbuflen++] = (u16)0;
1232 
1233  if ( starti == 2 ) // private chat
1234  {
1236  {
1237  Bscript::ObjArray* arr;
1238  if ( Core::convertUCtoArray( wtextbuf, arr, wtextbuflen,
1239  true ) ) // convert back with ctBEu16()
1241  member->make_ref(), arr );
1242  }
1243  party->send_member_msg_private( client->chr, member, wtextbuf, wtextbuflen );
1244  }
1245  else
1246  {
1248  {
1249  Bscript::ObjArray* arr;
1250  if ( Core::convertUCtoArray( wtextbuf, arr, wtextbuflen,
1251  true ) ) // convert back with ctBEu16()
1253  }
1254 
1255  party->send_member_msg_public( client->chr, wtextbuf, wtextbuflen );
1256  }
1257  }
1258  else
1259  send_sysmessage_cl( client, CLP_No_Party ); // You are not in a party.
1260 }
1261 
1263 {
1264  if ( !client->chr->has_party() )
1265  send_sysmessage_cl( client, CLP_No_Party ); // You are not in a party.
1266  else
1267  {
1268  bool loot = msg->partydata.partylootperm.canloot ? true : false;
1269  client->chr->set_party_can_loot( loot );
1272  // You have chosen to allow your party to loot your corpse.
1273  // You have chosen to prevent your party from looting your corpse.
1275  }
1276 }
1277 
1279 {
1282  if ( leader != nullptr )
1283  {
1284  Party* party = leader->party();
1285  if ( party != nullptr )
1286  {
1287  if ( party->remove_candidate( client->chr->serial ) )
1288  {
1289  client->chr->cancel_party_invite_timeout();
1290  client->chr->candidate_of( nullptr );
1291  if ( party->add_member( client->chr->serial ) )
1292  {
1293  client->chr->party( party );
1296  send_sysmessage_cl( client, CLP_Added ); // You have been added to the party.
1297 
1298  party->send_msg_to_all( CLP_Joined, client->chr->name().c_str(),
1299  client->chr ); // : joined the party.
1300  party->send_member_list( nullptr );
1301  party->send_stats_on_add( client->chr );
1302  }
1303  }
1304  }
1305  else
1306  send_sysmessage_cl( client, CLP_No_Invite ); // No one has invited you to be in a party.
1307  }
1308 }
1309 
1311 {
1314  if ( leader != nullptr )
1315  {
1316  Party* party = leader->party();
1317  if ( party != nullptr )
1318  {
1319  if ( party->remove_candidate( client->chr->serial ) )
1320  {
1321  client->chr->cancel_party_invite_timeout();
1322  client->chr->candidate_of( nullptr );
1324  client, CLP_Decline ); // You notify them that you do not wish to join the party.
1325  if ( leader->has_active_client() )
1326  send_sysmessage_cl_affix( leader->client, CLP_Notify_Decline, client->chr->name().c_str(),
1327  true ); //: Does not wish to join the party.
1330  if ( !party->test_size() )
1331  disband_party( leader->serial );
1332  }
1333  else if ( party->is_member( client->chr->serial ) )
1334  send_sysmessage_cl( client, CLP_Too_Late_Decline ); // Too late to decline, you are already
1335  // in the party. Try /quit.
1336  }
1337  else
1338  send_sysmessage_cl( client, CLP_No_Invite ); // No one has invited you to be in a party.
1339  }
1340 }
1341 
1343 {
1344  if ( leader == nullptr )
1345  return;
1346  if ( member == nullptr )
1347  {
1348  send_sysmessage_cl( leader->client,
1349  CLP_Add_Living ); // You may only add living things to your party!
1350  return;
1351  }
1352  Party* party = leader->party();
1353  if ( member == leader )
1354  send_sysmessage_cl( leader->client, CLP_Add_Yourself ); // You cannot add yourself to a party.
1355  else if ( ( party != nullptr ) && ( !party->is_leader( leader->serial ) ) )
1357  leader->client,
1358  CLP_Add_No_Leader ); // You may only add members to the party if you are the leader.
1359  else if ( ( party != nullptr ) && ( !party->can_add() ) )
1361  leader->client,
1362  CLP_Max_Size ); // You may only have 10 in your party (this includes candidates).
1363  else if ( member->isa( UOBJ_CLASS::CLASS_NPC ) )
1364  send_sysmessage_cl( leader->client, CLP_Ignore_Offer ); // The creature ignores your offer.
1365  else if ( ( party != nullptr ) && ( party->is_member( member->serial ) ) )
1366  send_sysmessage_cl( leader->client,
1367  CLP_Already_Your_Party ); // This person is already in your party!
1368  else if ( ( party != nullptr ) && ( party->is_candidate( member->serial ) ) )
1369  send_sysmessage_cl( leader->client,
1370  CLP_Already_Your_Party ); // This person is already in your party!
1371  else if ( member->has_party() )
1372  send_sysmessage_cl( leader->client,
1373  CLP_Already_in_a_Party ); // This person is already in a party!
1374  else
1375  {
1376  if ( member->has_candidate_of() )
1377  send_sysmessage_cl( leader->client,
1378  CLP_Already_in_a_Party ); // This person is already in a party!
1379  else
1380  {
1382  {
1384  member->make_ref() ) )
1385  return;
1386  }
1388  member->set_party_invite_timeout();
1389 
1390  if ( party == nullptr )
1391  {
1392  party = new Party( leader->serial );
1393  gamestate.parties.push_back( ref_ptr<Party>( party ) );
1394  leader->party( party );
1397  Module::CreatePartyRefObjImp( party ) );
1398  }
1399  if ( party->add_candidate( member->serial ) )
1400  {
1401  member->candidate_of( party );
1402  send_invite( member, leader );
1403  }
1404  else
1406  leader->client,
1407  CLP_Max_Size ); // You may only have 10 in your party (this includes candidates).
1408  }
1409  }
1410 }
1411 
1413 {
1414  Party* party = mem->candidate_of();
1415  if ( party != nullptr )
1416  {
1417  if ( party->remove_candidate( mem->serial ) )
1418  {
1419  if ( mem->has_active_client() )
1421  mem->client, CLP_Decline ); // You notify them that you do not wish to join the party.
1425  if ( leader != nullptr )
1426  {
1427  if ( leader->has_active_client() )
1428  send_sysmessage_cl_affix( leader->client, CLP_Notify_Decline, mem->name().c_str(),
1429  true ); //: Does not wish to join the party.
1430  if ( !party->test_size() )
1431  disband_party( leader->serial );
1432  }
1433  }
1434  mem->candidate_of( nullptr );
1435  }
1436 }
1437 
1439 {
1441  msg->WriteFlipped<u16>( 10u );
1442  msg->offset += 2; // sub
1443  msg->Write<u8>( PKTBI_BF_06::PARTYCMD_INVITE_MEMBER );
1444  msg->Write<u32>( leader->serial_ext );
1445  msg.Send( member->client );
1446 
1447  // : You are invited to join the party. Type /accept to join or /decline to decline the offer.
1448  send_sysmessage_cl_affix( member->client, CLP_Invite, leader->name().c_str(), true );
1449  send_sysmessage_cl( leader->client, CLP_Invited ); // You have invited them to join the party.
1450 }
1451 
1453 {
1455  msg->Write<u32>( bob->serial_ext );
1456 
1457  const auto& hits = bob->vital( networkManager.uoclient_general.hits.id );
1458  int h = hits.current_ones();
1459  if ( h > 0xFFFF )
1460  h = 0xFFFF;
1461  int mh = hits.maximum_ones();
1462  if ( mh > 0xFFFF )
1463  mh = 0xFFFF;
1464  msg->WriteFlipped<u16>( 1000u );
1465  msg->WriteFlipped<u16>( static_cast<u16>( h * 1000 / mh ) );
1466 
1467  const auto& mana = bob->vital( networkManager.uoclient_general.mana.id );
1468  h = mana.current_ones();
1469  if ( h > 0xFFFF )
1470  h = 0xFFFF;
1471  mh = mana.maximum_ones();
1472  if ( mh > 0xFFFF )
1473  mh = 0xFFFF;
1474  msg->WriteFlipped<u16>( 1000u );
1475  msg->WriteFlipped<u16>( static_cast<u16>( h * 1000 / mh ) );
1476 
1477  const auto& stam = bob->vital( networkManager.uoclient_general.stamina.id );
1478  h = stam.current_ones();
1479  if ( h > 0xFFFF )
1480  h = 0xFFFF;
1481  mh = stam.maximum_ones();
1482  if ( mh > 0xFFFF )
1483  mh = 0xFFFF;
1484  msg->WriteFlipped<u16>( 1000u );
1485  msg->WriteFlipped<u16>( static_cast<u16>( h * 1000 / mh ) );
1486 
1487  msg.Send( chr->client );
1488 }
1489 } // namespace Core
1490 namespace Mobile
1491 {
1493 {
1494  return mob_flags_.get( MOB_FLAGS::PARTY_CAN_LOOT );
1495 }
1496 
1498 {
1499  mob_flags_.change( MOB_FLAGS::PARTY_CAN_LOOT, b );
1500 }
1501 
1503 {
1504  if ( this->party_decline_timeout_ != nullptr )
1505  this->party_decline_timeout_->cancel();
1506  Core::polclock_t timeout =
1507  Core::polclock() +
1509  new Core::OneShotTaskInst<Character*>( &this->party_decline_timeout_, timeout,
1510  Core::invite_timeout, this );
1511 }
1512 
1514 {
1515  if ( this->party_decline_timeout_ != nullptr )
1516  return false;
1517  return true;
1518 }
1519 
1521 {
1522  if ( this->party_decline_timeout_ != nullptr )
1523  this->party_decline_timeout_->cancel();
1524 }
1525 } // namespace Mobile
1526 } // namespace Pol
const int CLP_Already_in_a_Party
Definition: party_cfg.h:52
void printProperties(Clib::StreamWriter &sw) const
Definition: proplist.cpp:429
unsigned char u8
Definition: rawtypes.h:25
void set_party_can_loot(bool)
Definition: party.cpp:1497
void cancel_party_invite_timeout()
Definition: party.cpp:1520
PKTBI_BF_06_01_IN partyadd
Definition: pktboth.h:616
const int CLP_Who_To_Add
Definition: party_cfg.h:67
void build_sysmessage_cl_affix(PktOut_CC *msg, unsigned int cliloc_num, const char *affix, bool prepend, const u16 *arguments, unsigned short font, unsigned short color)
Definition: clfunc.cpp:279
void set_party_invite_timeout()
Definition: party.cpp:1502
struct Pol::Core::Party_Cfg::@14 Hooks
void send_sysmessage_cl(Client *client, unsigned int cliloc_num, const u16 *arguments, unsigned short font, unsigned short color)
Definition: clfunc.cpp:26
FullMsgTargetCursor remove_member_cursor
Definition: target.h:229
const int CLP_Last_Person
Definition: party_cfg.h:62
std::string remove_string(const char *propname)
Definition: cfgfile.cpp:381
void printOn(Clib::StreamWriter &sw) const
Definition: party.cpp:766
void unload_party()
Definition: party.cpp:258
ExportedFunction * OnPartyCreate
Definition: party_cfg.h:43
ExportedFunction * ChangePublicChat
Definition: party_cfg.h:37
void party_cmd_handler(Client *client, PKTBI_BF *msg)
Definition: party.cpp:956
const int CLP_Rejoined
Definition: party_cfg.h:49
ExportedFunction * OnDecline
Definition: party_cfg.h:39
bool remove_offline_mem(u32 serial)
Definition: party.cpp:376
bool is_leader(u32 serial) const
Definition: party.cpp:317
const int CLP_No_Invite
Definition: party_cfg.h:78
SystemState systemstate
Definition: systemstate.cpp:12
PKTBI_BF_06_02_IN partyremove
Definition: pktboth.h:618
bool call(Bscript::BObjectImp *p0)
Definition: syshook.cpp:44
bool isa(BObjectType type) const
Definition: bobject.h:353
void send_short_statmsg(Network::Client *client, Mobile::Character *chr)
Definition: statmsg.cpp:235
Network::Client * client
Definition: charactr.h:871
polclock_t polclock()
Definition: polclock.cpp:72
Core::PolConfig config
Definition: systemstate.h:43
bool party_can_loot() const
Definition: party.cpp:1492
std::string world_data_path
Definition: polcfg.h:28
size_t estimateSize() const
Definition: party.cpp:787
Cursors target_cursors
Definition: uvars.h:234
PKTBI_BF_06_03 partymembermsg
Definition: pktboth.h:621
u32 _leaderserial
Definition: party.h:98
const int CLP_Added
Definition: party_cfg.h:55
ExportedFunction * OnLootPermChange
Definition: party_cfg.h:42
const int CLP_Invite
Definition: party_cfg.h:70
bool remove_candidate(u32 serial)
Definition: party.cpp:352
struct Pol::Core::Party_Cfg::@13 General
#define cfBEu32(x)
Definition: clib_endian.h:43
#define SPEECH_MAX_LEN
Definition: pktdef.h:27
ExportedFunction * CanRemoveMember
Definition: party_cfg.h:35
void handle_unknown_packet(Client *client)
PKTBI_BF_06_08 partyaccinvite
Definition: pktboth.h:626
BObjectImp * CreatePartyRefObjImp(Core::Party *party)
Definition: partymod.cpp:119
unsigned int remove_ulong(const char *propname)
Definition: cfgfile.cpp:461
bool is_visible_to_me(const Character *chr) const
Definition: charactr.cpp:2658
#define ctBEu16(x)
Definition: clib_endian.h:46
u32 get_member_at(unsigned short pos) const
Definition: party.cpp:322
bool has_active_client() const
Definition: charactr.cpp:448
ExportedFunction * OnAddToParty
Definition: party_cfg.h:38
bool is_member(u32 serial) const
Definition: party.cpp:281
u32 leader() const
Definition: party.cpp:276
size_t estimatedSize() const
Definition: proplist.cpp:362
const int CLP_No_Party
Definition: party_cfg.h:77
bool remove_member(u32 serial)
Definition: party.cpp:364
std::vector< u32 > _offlinemember_serials
Definition: party.h:97
void send_msg_to_all(unsigned int clilocnr, const char *affix=0, Mobile::Character *exeptchr=nullptr) const
Definition: party.cpp:547
FullMsgTargetCursor add_member_cursor
Definition: target.h:228
bool matches(const ConfigElem &elem)
Definition: cfgsect.cpp:32
void load_party_cfg_general(Clib::ConfigElem &elem)
Definition: party.cpp:91
const int CLP_Notify_Decline
Definition: party_cfg.h:73
ExportedFunction * CanLeaveParty
Definition: party_cfg.h:34
const int CLP_Cannot_Remove_Self
Definition: party_cfg.h:56
int current_ones() const
Definition: charactr.h:193
const int CLP_Too_Late_Decline
Definition: party_cfg.h:79
void invite_timeout(Mobile::Character *mem)
Definition: party.cpp:1412
Mobile::Character * chr
Definition: client.h:182
void send_stat_to(Mobile::Character *chr, Mobile::Character *bob) const
Definition: party.cpp:576
void handle_party_msg(Network::Client *client, PKTBI_BF *msg)
Definition: party.cpp:1174
void register_party_members()
Definition: party.cpp:809
void add_offline_mem(u32 serial)
Definition: party.cpp:347
unsigned short u16
Definition: rawtypes.h:26
unsigned int u32
Definition: rawtypes.h:27
const int CLP_Ignore_Offer
Definition: party_cfg.h:54
void disband()
Definition: party.cpp:458
void handle_add(Network::Client *client, PKTBI_BF *msg)
Definition: party.cpp:995
void build_sysmessage_cl(PktOut_C1 *msg, unsigned int cliloc_num, const u16 *arguments, unsigned short font, unsigned short color)
Definition: clfunc.cpp:247
void on_loggon_party(Mobile::Character *chr)
Definition: party.cpp:923
const int CLP_Max_Size
Definition: party_cfg.h:76
PKTBI_BF_06 partydata
Definition: pktboth.h:853
void send_empty_party(Mobile::Character *chr)
Definition: party.cpp:795
const int CLP_Prevent_Loot
Definition: party_cfg.h:59
const int CLP_Allow_Loot
Definition: party_cfg.h:58
void on_loggoff_party(Mobile::Character *chr)
Definition: party.cpp:878
PKTBI_BF_06_04_IN partymsg
Definition: pktboth.h:622
const int CLP_Removed
Definition: party_cfg.h:63
void handle_loot_perm(Network::Client *client, PKTBI_BF *msg)
Definition: party.cpp:1262
virtual bool isTrue() const
Definition: object.cpp:911
void disband_party(u32 leader)
Definition: party.cpp:824
ExportedFunction * OnDisband
Definition: party_cfg.h:40
void handle_member_msg(Network::Client *client, PKTBI_BF *msg)
Definition: party.cpp:1115
PKTBI_BF_06_06 partylootperm
Definition: pktboth.h:624
const unsigned CST_NORMAL
Definition: cfgsect.h:19
const int CLP_Player_Rejoined
Definition: party_cfg.h:69
Definition: refptr.h:65
ExportedFunction * OnPublicChat
Definition: party_cfg.h:45
NetworkManager networkManager
Definition: network.cpp:28
const int CLP_Add_Yourself
Definition: party_cfg.h:50
bool convertArrayToUC(Bscript::ObjArray *&in_text, u16 *out_wtext, size_t textlen, bool ConvToBE, bool nullterm)
Definition: unicode.cpp:21
void Send(Client *client, int len=-1) const
Definition: packethelper.h:69
Parties parties
Definition: uvars.h:158
void on_stam_changed(Mobile::Character *chr) const
Definition: party.cpp:642
void handle_accept_invite(Network::Client *client, PKTBI_BF *msg)
Definition: party.cpp:1278
ExportedFunction * OnLeaveParty
Definition: party_cfg.h:41
void unload_party_hooks()
Definition: party.cpp:190
void write_party(Clib::StreamWriter &sw)
Definition: party.cpp:868
const int CLP_Decline
Definition: party_cfg.h:74
const int CLP_Already_Your_Party
Definition: party_cfg.h:51
#define cfBEu16(x)
Definition: clib_endian.h:44
virtual Bscript::BObjectImp * make_ref() POL_OVERRIDE
Definition: uoscrobj.cpp:1650
void cleanup()
Definition: party.cpp:269
void readProperties(Clib::ConfigElem &elem)
Definition: proplist.cpp:464
int polclock_t
Definition: polclock.h:26
bool convertUCtoArray(const u16 *in_wtext, Bscript::ObjArray *&out_text, size_t textlen, bool ConvFromBE)
Definition: unicode.cpp:46
const int CLP_Player_Removed
Definition: party_cfg.h:64
bool has_party_invite_timeout() const
Definition: party.cpp:1513
PKTBI_BF_06_09 partydecinvite
Definition: pktboth.h:627
GameState gamestate
Definition: uvars.cpp:74
Party(Clib::ConfigElem &elem)
Definition: party.cpp:75
BObjectImp * impptr()
Definition: bobject.h:428
void on_mana_changed(Mobile::Character *chr) const
Definition: party.cpp:614
const int CLP_Add_No_Leader
Definition: party_cfg.h:65
std::vector< u32 > _member_serials
Definition: party.h:95
void handle_add_member_cursor(Mobile::Character *chr, PKTBI_6C *msgin)
Definition: party.cpp:986
SettingsManager settingsManager
Definition: settings.cpp:14
void send_member_msg_public(Mobile::Character *chr, u16 *wtext, size_t wtextlen) const
Definition: party.cpp:671
Bscript::BObject call_object(Bscript::BObjectImp *p0, Bscript::BObjectImp *p1)
Definition: syshook.cpp:80
Mobile::Character * system_find_mobile(u32 serial)
Definition: fnsearch.cpp:32
void handle_remove_member_cursor(Mobile::Character *chr, PKTBI_6C *msgin)
Definition: party.cpp:1009
const int CLP_Add_Living
Definition: party_cfg.h:53
bool remove_prop(const char *propname, std::string *value)
Definition: cfgfile.cpp:128
const int CLP_Who_to_Remove
Definition: party_cfg.h:68
bool test_size() const
Definition: party.cpp:400
void load_party_cfg_hooks(Clib::ConfigElem &elem)
Definition: party.cpp:126
u16 PrivateMsgPrefix[SPEECH_MAX_LEN+1]
Definition: party_cfg.h:25
void send_attributes_normalized(Mobile::Character *chr, Mobile::Character *bob)
Definition: party.cpp:1452
void load_party_cfg(bool reload)
Definition: party.cpp:160
void handle_decline_invite(Network::Client *client, PKTBI_BF *msg)
Definition: party.cpp:1310
unsigned char PrivateMsgPrefixLen
Definition: party_cfg.h:26
void send_sysmessage_cl_affix(Client *client, unsigned int cliloc_num, const char *affix, bool prepend, const u16 *arguments, unsigned short font, unsigned short color)
Definition: clfunc.cpp:128
unsigned short pol_distance(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2)
Definition: ufunc.cpp:481
PropertyList _proplist
Definition: party.h:99
const int CLP_Joined
Definition: party_cfg.h:75
Realms::Realm * realm
Definition: baseobject.h:56
bool send_object_cursor(Network::Client *client, PKTBI_6C::CURSOR_TYPE crstype=PKTBI_6C::CURSOR_TYPE_NEUTRAL)
Definition: target.cpp:133
void send_member_list(Mobile::Character *to_chr)
Definition: party.cpp:415
unsigned short remove_ushort(const char *propname)
Definition: cfgfile.cpp:318
ExportedFunction * FindExportedFunction(Clib::ConfigElem &elem, const Plib::Package *pkg, const std::string &descriptor, unsigned nargs, bool complain_if_missing)
Definition: syshook.cpp:344
bool can_add() const
Definition: party.cpp:407
bool isa(UOBJ_CLASS uobj_class) const
Definition: baseobject.h:99
const VitalValue & vital(unsigned vitalid) const
Definition: charactr.h:1061
ExportedFunction * CanAddToParty
Definition: party_cfg.h:33
bool add_candidate(u32 serial)
Definition: party.cpp:329
void handle_remove(Network::Client *client, PKTBI_BF *msg)
Definition: party.cpp:1053
bool is_candidate(u32 serial) const
Definition: party.cpp:287
void read_party_dat()
Definition: party.cpp:835
void send_remove_member(Mobile::Character *chr, bool *disband)
Definition: party.cpp:494
void set_leader(u32 serial)
Definition: party.cpp:388
bool FileExists(const char *filename)
Definition: fileutil.cpp:118
ExportedFunction * OnPrivateChat
Definition: party_cfg.h:44
const int CLP_Disbanded
Definition: party_cfg.h:61
bool register_with_members()
Definition: party.cpp:293
bool read(ConfigElem &elem)
Definition: cfgfile.cpp:1015
unsigned short DeclineTimeout
Definition: party_cfg.h:24
void send_stats_on_add(Mobile::Character *newmember) const
Definition: party.cpp:588
#define INFO_PRINT
Definition: logfacility.h:223
ExportedFunction * ChangePrivateChat
Definition: party_cfg.h:36
virtual std::string name() const
Definition: uobject.cpp:196
bool add_member(u32 serial)
Definition: party.cpp:338
#define pf_endl
Definition: proplist.cpp:25
std::vector< u32 > _candidates_serials
Definition: party.h:96
const int CLP_Invited
Definition: party_cfg.h:72
Definition: berror.cpp:12
const polclock_t POLCLOCKS_PER_SEC
Definition: polclock.h:29
bool remove_bool(const char *propname)
Definition: cfgfile.cpp:426
void send_member_msg_private(Mobile::Character *chr, Mobile::Character *tochr, u16 *wtext, size_t wtextlen) const
Definition: party.cpp:718
unsigned short MaxPartyMembers
Definition: party_cfg.h:22
UoClientGeneral uoclient_general
Definition: network.h:67
void send_invite(Mobile::Character *member, Mobile::Character *leader)
Definition: party.cpp:1438