Pol  Revision:cb584c9
containr.cpp
Go to the documentation of this file.
1 
23 #include "containr.h"
24 
25 #include <algorithm>
26 #include <assert.h>
27 #include <cstddef>
28 
29 #include "../clib/cfgelem.h"
30 #include "../clib/logfacility.h"
31 #include "../clib/passert.h"
32 #include "../clib/random.h"
33 #include "../clib/streamsaver.h"
34 #include "globals/state.h"
35 #include "item/itemdesc.h"
36 #include "mobile/charactr.h"
37 #include "network/client.h"
38 #include "profile.h"
39 #include "scrdef.h"
40 #include "scrsched.h"
41 #include "statmsg.h"
42 #include "uconst.h"
43 #include "ufunc.h"
44 #include "umanip.h"
45 #include "uobject.h"
46 #include "uoscrobj.h"
47 #include "uworld.h"
48 
49 
50 namespace Pol
51 {
52 namespace Core
53 {
55  : ULockable( descriptor, UOBJ_CLASS::CLASS_CONTAINER ),
56  desc( Items::find_container_desc( objtype_ ) ), // NOTE still grabs the permanent descriptor.
57  held_weight_( 0 ),
58  held_item_count_( 0 )
59 {
60 }
61 
63 {
64  passert_always( contents_.empty() );
65 }
66 
68 {
69  const size_t size = base::estimatedSize() + sizeof( u16 ) /*held_weight_*/
70  + sizeof( unsigned int ) /*held_item_count_*/
71  // no estimateSize here element is in objhash
72  + 3 * sizeof( Items::Item** ) + contents_.capacity() * sizeof( Items::Item* );
73  return size;
74 }
75 
77 {
78  while ( !contents_.empty() )
79  {
80  Contents::value_type item = contents_.back();
81  if ( ITEM_ELEM_PTR( item ) != nullptr ) // this is really only for wornitems.
82  {
83  item->container = nullptr;
84  item->destroy();
85  }
86  contents_.pop_back();
87  }
88 }
89 
90 
92 {
94  base::destroy();
95 }
96 // Consider: writing an "item count" property. On read,
97 // recursively read items (eliminate a lot of searching)
98 
100 {
101  base::printOn( sw );
102  printContents( sw );
103 }
104 
106 {
107  base::printOn( sw );
108 }
109 
111 {
112  for ( const auto& item : contents_ )
113  {
114  if ( item != nullptr )
115  {
116  if ( item->itemdesc().save_on_exit && item->saveonexit() )
117  {
118  sw << *item;
119  item->clear_dirty();
120  }
121  }
122  }
123 }
124 
125 bool UContainer::can_add_bulk( int tli_diff, int item_count_diff, int weight_diff ) const
126 {
128  {
130  {
131  if ( contents_.size() + tli_diff >= MAX_SLOTS )
132  return false;
133 
134  if ( contents_.size() + tli_diff >= max_slots() )
135  return false;
136  }
137 
138  if ( contents_.size() + tli_diff >= MAX_CONTAINER_ITEMS )
139  return false;
140 
141  if ( weight() + weight_diff > USHRT_MAX /* gcc...std::numeric_limits<unsigned short>::max()*/ )
142  return false;
143 
144  if ( held_weight_ + weight_diff > max_weight() )
145  return false;
146 
147  if ( held_item_count_ + item_count_diff > max_items() )
148  return false;
149 
150  if ( container != nullptr )
151  return container->can_add_bulk( 0, 0, weight_diff );
152  else
153  return true;
154  }
155  else
156  {
158  {
159  return ( ( contents_.size() < MAX_CONTAINER_ITEMS ) && ( contents_.size() < MAX_SLOTS ) );
160  }
161  else
162  {
163  return ( contents_.size() < MAX_CONTAINER_ITEMS );
164  }
165  }
166 }
167 
168 bool UContainer::can_add( const Items::Item& item ) const
169 {
170  return can_add_bulk( 1, 1, item.weight() );
171 }
172 
173 bool UContainer::can_add( unsigned short more_weight ) const
174 {
175  return can_add_bulk( 0, 0, more_weight );
176 }
177 
178 bool UContainer::can_add_to_slot( u8& slotIndex )
179 {
181  {
182  if ( slotIndex > max_slots() )
183  return false;
184 
185  if ( is_slot_empty( slotIndex ) )
186  return true;
187 
188  if ( find_empty_slot( slotIndex ) )
189  return true;
190  }
191  return true;
192 }
193 
195 {
196  // passert( can_add( *item ) );
197 
198  INC_PROFILEVAR( container_adds );
199  item->realm = realm;
200  item->container = this;
201  item->set_dirty();
202  contents_.push_back( Contents::value_type( item ) );
203 
204  add_bulk( item );
205 }
207 {
208  add_bulk( 1, item->weight() );
209 }
211 {
212  add_bulk( -static_cast<int>( 1 ), -static_cast<int>( item->weight() ) );
213 }
214 
215 void UContainer::add_bulk( int item_count_delta, int weight_delta )
216 {
217  held_item_count_ += item_count_delta;
218 
219  // passert( !stateManager.gflag_enforce_container_limits || (held_weight_ + weight_delta <=
220  // MAX_WEIGHT) );
221 
222  held_weight_ += static_cast<unsigned short>( weight_delta );
223  if ( container != nullptr )
224  {
225  container->add_bulk( 0, weight_delta );
226  }
227 }
228 
229 
230 unsigned int UContainer::weight() const
231 {
233 }
234 
235 unsigned int UContainer::item_count() const
236 {
238 }
239 
240 bool UContainer::is_slot_empty( u8& slotIndex )
241 {
242  if ( held_item_count_ == 0 )
243  return true;
244 
245  for ( const auto& item : contents_ )
246  {
247  if ( item == nullptr )
248  continue;
249  if ( item->slot_index() == slotIndex )
250  return false;
251  }
252  return true;
253 }
254 
255 bool UContainer::find_empty_slot( u8& slotIndex )
256 {
257  if ( held_item_count_ >= max_items() )
258  return false;
259 
260  if ( held_item_count_ >= max_slots() )
261  return false;
262 
263  bool slot_check = false;
264 
265  for ( u8 slot_location = 1; slot_location <= max_items(); ++slot_location )
266  {
267  for ( const auto& item : contents_ )
268  {
269  if ( item == nullptr )
270  continue;
271  if ( item->slot_index() == slot_location )
272  slot_check = true;
273  if ( !slot_check )
274  {
275  break;
276  }
277  }
278  if ( !slot_check )
279  {
280  slotIndex = slot_location;
281  return true;
282  }
283  else
284  {
285  slot_check = false;
286  }
287  }
288  return false;
289 }
290 
292 {
293  u16 rx, ry;
294  get_random_location( &rx, &ry );
295 
296  item->x = rx;
297  item->y = ry;
298  item->z = 0;
299 
300  add( item );
301 }
302 
304 {
305  for ( auto& item : contents_ )
306  {
307  if ( item ) // dave 1/1/03, wornitemscontainer can have null items!
308  {
309  arr->addElement( new Module::EItemRefObjImp( item ) );
310  // Austin 9-15-2006, added flag to not enumerate sub-containers.
311  if ( !( flags & ENUMERATE_ROOT_ONLY ) &&
312  ( item->isa( UOBJ_CLASS::CLASS_CONTAINER ) ) ) // FIXME check locks
313  {
314  UContainer* cont = static_cast<UContainer*>( item );
315  if ( !cont->locked() || ( flags & ENUMERATE_IGNORE_LOCKED ) )
316  cont->enumerate_contents( arr, flags );
317  }
318  }
319  }
320 }
321 
323 {
324  contents_.swap( cnt );
325  add_bulk( -static_cast<int>( held_item_count_ ), -static_cast<int>( held_weight_ ) );
326 }
327 
328 bool UContainer::can_swap( const UContainer& cont ) const
329 {
330  int weight_diff0 = cont.weight() - weight();
331  int item_count_diff0 = cont.item_count() - item_count();
332 
333  int weight_diff1 = -weight_diff0;
334  int item_count_diff1 = -item_count_diff0;
335 
336  return ( can_add_bulk( 0, item_count_diff0, weight_diff0 ) &&
337  cont.can_add_bulk( 0, item_count_diff1, weight_diff1 ) );
338 }
339 
341 {
342  assert( can_swap( cont ) );
343 
344  int weight_diff = cont.weight() - weight();
345  int item_count_diff = cont.item_count() - item_count();
346 
347  add_bulk( item_count_diff, weight_diff );
348  cont.add_bulk( -item_count_diff, -weight_diff );
349 
350  contents_.swap( cont.contents_ );
351 }
352 
353 Items::Item* UContainer::find_toplevel_polclass( unsigned int polclass ) const
354 {
355  for ( auto& item : contents_ )
356  {
357  if ( item && ( item->script_isa( polclass ) ) )
358  return item;
359  }
360  return nullptr;
361 }
362 
364 {
365  for ( auto& item : contents_ )
366  {
367  if ( item && ( item->objtype_ == objtype ) )
368  return item;
369  }
370  return nullptr;
371 }
373 {
374  for ( auto& item : contents_ )
375  {
376  if ( item && ( item->objtype_ == objtype ) && !item->inuse() )
377  return item;
378  }
379  return nullptr;
380 }
381 
382 Items::Item* UContainer::find_toplevel_objtype( u32 objtype, unsigned short maxamount ) const
383 {
384  for ( auto& item : contents_ )
385  {
386  if ( item && ( item->objtype_ == objtype ) && ( item->getamount() <= maxamount ) )
387  return item;
388  }
389  return nullptr;
390 }
392  unsigned short maxamount ) const
393 {
394  for ( auto& item : contents_ )
395  {
396  if ( item && ( item->objtype_ == objtype ) && ( item->getamount() <= maxamount ) &&
397  !item->inuse() )
398  return item;
399  }
400  return nullptr;
401 }
402 
404 {
405  if ( !adding_item->stackable() )
406  return nullptr;
407 
408  unsigned short maxamount = adding_item->itemdesc().stack_limit - adding_item->getamount();
409 
410  if ( maxamount > 0 )
411  {
412  for ( auto& item : contents_ )
413  {
414  if ( item && item->can_add_to_self( *adding_item, false ) )
415  {
416  return item;
417  }
418  }
419  }
420 
421  return nullptr;
422 }
423 
424 Items::Item* UContainer::find_objtype( u32 objtype, int flags ) const
425 {
426  Items::Item* _item = find_toplevel_objtype( objtype );
427  if ( _item != nullptr )
428  return _item;
429  if ( !( flags & FINDOBJTYPE_ROOT_ONLY ) )
430  {
431  for ( const auto& item : contents_ )
432  {
433  if ( item && item->isa( UOBJ_CLASS::CLASS_CONTAINER ) )
434  {
435  UContainer* cont = static_cast<UContainer*>( item );
436  if ( !cont->locked() || ( flags & FINDOBJTYPE_IGNORE_LOCKED ) )
437  {
438  auto child_item = cont->find_objtype( objtype, flags );
439  if ( child_item != nullptr )
440  return child_item;
441  }
442  }
443  }
444  }
445  return nullptr;
446 }
447 
448 
450 {
451  Items::Item* _item = find_toplevel_objtype_noninuse( objtype );
452  if ( _item != nullptr )
453  return _item;
454 
455  for ( const auto& item : contents_ )
456  {
457  if ( item && item->isa( UOBJ_CLASS::CLASS_CONTAINER ) && !item->inuse() )
458  {
459  UContainer* cont = static_cast<UContainer*>( item );
460  if ( !cont->locked() )
461  {
462  auto child_item = cont->find_objtype_noninuse( objtype );
463  if ( child_item != nullptr )
464  return child_item;
465  }
466  }
467  }
468  return nullptr;
469 }
470 
471 unsigned int UContainer::find_sumof_objtype_noninuse( u32 objtype ) const
472 {
473  unsigned int amt = 0;
474 
475  for ( auto& item : contents_ )
476  {
477  if ( item && !item->inuse() )
478  {
479  if ( item->objtype_ == objtype )
480  amt += item->getamount();
481 
482  if ( item->isa( UOBJ_CLASS::CLASS_CONTAINER ) )
483  {
484  UContainer* cont = static_cast<UContainer*>( item );
485  if ( !cont->locked() )
486  {
487  amt += cont->find_sumof_objtype_noninuse( objtype );
488  }
489  }
490  }
491  }
492  return amt;
493 }
494 
495 void UContainer::consume_sumof_objtype_noninuse( u32 objtype, unsigned int amount )
496 {
497  while ( amount != 0 )
498  {
499  Items::Item* item = find_objtype_noninuse( objtype );
500  passert_always( item != nullptr );
501 
502  unsigned short thisamt = item->getamount();
503  if ( thisamt > amount )
504  thisamt = static_cast<unsigned short>( amount );
505  subtract_amount_from_item( item, thisamt );
506  amount -= thisamt;
507  }
508 }
509 
510 Items::Item* UContainer::remove( u32 objserial, UContainer** found_in )
511 {
512  Items::Item* item;
513  iterator itr;
514 
515  item = find( objserial, itr );
516  if ( item != nullptr )
517  {
518  if ( found_in != nullptr )
519  *found_in = item->container;
520 
521  item->container->remove( itr );
522  }
523  return item;
524 }
525 
527 {
528  if ( item->container != this )
529  {
530  POLLOG.Format( "UContainer::remove(Item*), serial=0x{:X}, item=0x{:X}, item->cont=0x{:X}\n" )
531  << serial << item->serial << item->container->serial;
532  passert_always( item->container == this );
533  int* p = 0;
534  *p = 6;
535  }
536 
537  iterator itr = std::find( contents_.begin(), contents_.end(), item );
538  passert_always( itr != contents_.end() );
539 
540  // DAVE added this 11/17. refresh owner's weight on delete
541  Mobile::Character* chr_owner = item->GetCharacterOwner();
542 
543  if ( chr_owner != nullptr && chr_owner->client != nullptr )
544  {
546  }
547  remove( itr );
548 
549  if ( chr_owner != nullptr && chr_owner->client != nullptr )
550  {
551  send_full_statmsg( chr_owner->client, chr_owner );
552  // chr_owner->refresh_ar();
553  }
554 }
555 
556 // This is the only function that actually removes the item from the container. This could be
557 // inlined into UContainer::remove(Item *item) if we change UContainer::remove(u32 serial, ...)
558 // to call remove(*itr) instead of remove(itr). The code would be cleaner at the cost of an extra
559 // find.
560 // As I don't have time to test if that would make a big difference, I leave this note for the
561 // future.
562 // I wish you luck. (Nando, 2014/10/30)
564 {
565  INC_PROFILEVAR( container_removes );
566  Items::Item* item = GET_ITEM_PTR( itr );
567  contents_.erase( itr );
568  item->container = nullptr;
569  item->reset_slot();
570  item->set_dirty();
571  remove_bulk( item );
572 }
573 
574 // FIXME this is depth-first. Not sure I like that.
576 {
577  for ( auto& item : contents_ )
578  {
579  if ( item && item->isa( UOBJ_CLASS::CLASS_CONTAINER ) )
580  {
581  UContainer* cont = static_cast<UContainer*>( item );
582  if ( cont->serial == objserial )
583  return cont;
584  cont = cont->find_container( objserial );
585  if ( cont != nullptr )
586  return cont;
587  }
588  }
589  return nullptr;
590 }
591 
592 Items::Item* UContainer::find( u32 objserial, iterator& where_in_container )
593 {
594  for ( iterator itr = contents_.begin(); itr != contents_.end(); ++itr )
595  {
596  Items::Item* item = GET_ITEM_PTR( itr );
597  passert( item != nullptr );
598  if ( item != nullptr )
599  {
600  if ( item->serial == objserial )
601  {
602  where_in_container = itr;
603  return item;
604  }
605  if ( item->isa( UOBJ_CLASS::CLASS_CONTAINER ) )
606  {
607  UContainer* cont = static_cast<UContainer*>( item );
608  if ( !cont->locked() )
609  {
610  item = cont->find( objserial, where_in_container );
611  if ( item != nullptr )
612  return item;
613  }
614  }
615  }
616  }
617  return nullptr;
618 }
619 
620 Items::Item* UContainer::find( u32 objserial ) const
621 {
622  for ( const auto& item : contents_ )
623  {
624  passert( item != nullptr );
625  if ( item != nullptr )
626  {
627  if ( item->serial == objserial )
628  return item;
629 
630  if ( item->isa( UOBJ_CLASS::CLASS_CONTAINER ) )
631  {
632  UContainer* cont = static_cast<UContainer*>( item );
633  if ( !cont->locked() )
634  {
635  auto child_item = cont->find( objserial );
636  if ( child_item != nullptr )
637  return child_item;
638  }
639  }
640  }
641  }
642  return nullptr;
643 }
644 
646 {
647  for ( auto& item : contents_ )
648  {
649  passert( item != nullptr );
650  if ( item != nullptr )
651  {
652  if ( item->serial == objserial )
653  return item;
654  }
655  }
656  return nullptr;
657 }
658 
659 void UContainer::for_each_item( void ( *f )( Items::Item* item, void* a ), void* arg )
660 {
661  for ( auto& item : contents_ )
662  {
663  if ( item->isa( UOBJ_CLASS::CLASS_CONTAINER ) )
664  {
665  UContainer* cont = static_cast<UContainer*>( item );
666  cont->for_each_item( f, arg );
667  }
668  ( *f )( item, arg );
669  }
670 }
671 
673 {
674  return contents_.begin();
675 }
677 {
678  return contents_.end();
679 }
680 
682 {
683  return contents_.begin();
684 }
686 {
687  return contents_.end();
688 }
689 
691 {
692  client->pause();
693 
694  if ( !locked() )
695  {
696  send_open_gump( client, *this );
697  send_container_contents( client, *this );
698  }
699  else
700  {
701  send_sysmessage( client, "That is locked." );
702  }
703 
704  client->restart();
705 }
706 
708 {
709  return desc.gump;
710 }
711 
713 {
714  if ( desc.minx < desc.maxx )
715  {
716  *px = desc.minx + static_cast<u16>( Clib::random_int( desc.maxx - desc.minx - 1 ) );
717  }
718  else
719  {
720  *px = desc.minx;
721  }
722 
723  if ( desc.miny < desc.maxy )
724  {
725  *py = desc.miny + static_cast<u16>( Clib::random_int( desc.maxy - desc.miny - 1 ) );
726  }
727  else
728  {
729  *py = desc.miny;
730  }
731 }
732 
733 bool UContainer::is_legal_posn( const Items::Item* /*item*/, u16 px, u16 py ) const
734 {
735  return ( px >= desc.minx && px <= desc.maxx && py >= desc.miny && py <= desc.maxy );
736 }
737 
739 {
740  passert( container == nullptr );
741  if ( !locked() )
742  {
743  while ( !contents_.empty() )
744  {
745  Items::Item* item = ITEM_ELEM_PTR( contents_.back() );
746  if ( item->movable() )
747  {
748  contents_.pop_back();
749  item->set_dirty();
750  item->x = x;
751  item->y = y;
752  item->z = z;
753  item->container = nullptr;
754  add_item_to_world( item );
755  move_item( item, x, y, z, nullptr );
756  if ( multi )
757  multi->register_object( item );
758  item->layer = 0;
759  }
760  else
761  {
762  destroy_item( item );
763  }
764  }
765  }
766 }
767 
768 
770 {
771  if ( !desc.on_remove_script.empty() )
772  {
773  // static code analysis indicates (C6211) that this might leak, but I can't use an auto_ptr<>
774  // because of UninitObject::create() ... ideas? Nando - 2010-07-10
775  Bscript::BObjectImp* chrParam = nullptr;
776  if ( chr ) // consider: move this into make_mobileref
777  chrParam = new Module::ECharacterRefObjImp( chr );
778  else
779  chrParam = Bscript::UninitObject::create();
780  // Luth: 10/22/2008 - on_remove_script now called with all appropriate parameters
782  new Module::EItemRefObjImp( item ), new Bscript::BLong( item->getamount() ),
783  new Bscript::BLong( move ) );
784  }
785 }
786 
788  Items::Item* existing_item, unsigned short amt_to_add,
789  Items::Item* adding_item )
790 {
791  if ( !desc.can_insert_script.empty() )
792  {
794  mob ? mob->make_ref() : Bscript::UninitObject::create(), make_ref(),
795  new Bscript::BLong( movetype ), new Bscript::BLong( INSERT_INCREASE_STACK ),
796  adding_item ? adding_item->make_ref() : Bscript::UninitObject::create(),
797  existing_item->make_ref(), new Bscript::BLong( amt_to_add ) );
798  }
799  else
800  {
801  return true;
802  }
803 }
804 
806  Items::Item* existing_item, unsigned short amt_to_add )
807 {
808  if ( !desc.on_insert_script.empty() )
809  {
811  make_ref(), new Bscript::BLong( movetype ),
813  existing_item->make_ref(), new Bscript::BLong( amt_to_add ) );
814  }
815 }
816 
818  Items::Item* new_item )
819 {
820  if ( !desc.can_insert_script.empty() )
821  {
823  mob ? mob->make_ref() : Bscript::UninitObject::create(), make_ref(),
824  new Bscript::BLong( movetype ), new Bscript::BLong( INSERT_ADD_ITEM ),
825  new_item->make_ref() );
826  }
827  else
828  {
829  return true;
830  }
831 }
832 
834  Items::Item* new_item )
835 {
836  if ( !desc.on_insert_script.empty() )
837  {
838  Items::Item* existing_stack = find_addable_stack( new_item );
839 
841  make_ref(), new Bscript::BLong( movetype ), new Bscript::BLong( INSERT_ADD_ITEM ),
842  new_item->make_ref(),
843  existing_stack ? existing_stack->make_ref() : Bscript::UninitObject::create(),
844  new Bscript::BLong( new_item->getamount() ) );
845  }
846 }
847 
849 {
850  if ( !desc.can_remove_script.empty() )
851  {
852  Bscript::BObjectImp* chrParam = nullptr;
853  if ( chr != nullptr ) // TODO: consider moving this into make_mobileref
854  chrParam = chr->make_ref();
855  else
856  chrParam = Bscript::UninitObject::create();
857  return call_script( desc.can_remove_script, chrParam, make_ref(), item->make_ref(),
858  new Bscript::BLong( move ) );
859  }
860  else
861  {
862  return true;
863  }
864 }
865 
866 
868 {
869  base::printProperties( sw );
870  if ( has_max_items_mod() )
871  sw() << "\tMax_Items_mod\t" << max_items_mod() << pf_endl;
872  if ( has_max_weight_mod() )
873  sw() << "\tMax_Weight_mod\t" << max_weight_mod() << pf_endl;
874  if ( has_max_slots_mod() )
875  sw() << "\tMax_Slots_mod\t" << max_slots_mod() << pf_endl;
877  sw() << "\tNoDropException\t" << no_drop_exception() << pf_endl;
878 }
879 
881 {
882  base::readProperties( elem );
883  max_items_mod( static_cast<s16>( elem.remove_int( "MAX_ITEMS_MOD", 0 ) ) );
884  max_weight_mod( static_cast<s16>( elem.remove_int( "MAX_WEIGHT_MOD", 0 ) ) );
885  max_slots_mod( static_cast<s8>( elem.remove_int( "MAX_SLOTS_MOD", 0 ) ) );
886  no_drop_exception( elem.remove_bool( "NoDropException", default_no_drop_exception() ) );
887 }
888 
889 unsigned int UContainer::find_sumof_objtype_noninuse( u32 objtype, u32 amtToGet,
890  Contents& saveItemsTo, int flags ) const
891 {
892  unsigned int amt = 0;
893 
894  for ( auto& item : contents_ )
895  {
896  if ( item && !item->inuse() )
897  {
898  if ( item->objtype_ == objtype )
899  {
900  saveItemsTo.push_back( item );
901  amt += item->getamount();
902  }
903  if ( !( flags & FINDSUBSTANCE_ROOT_ONLY ) && ( item->isa( UOBJ_CLASS::CLASS_CONTAINER ) ) )
904  {
905  UContainer* cont = static_cast<UContainer*>( item );
906  if ( !cont->locked() || ( flags & FINDSUBSTANCE_IGNORE_LOCKED ) )
907  {
908  amt += cont->find_sumof_objtype_noninuse( objtype, amtToGet - amt, saveItemsTo, flags );
909  }
910  }
911  }
912  if ( !( flags & FINDSUBSTANCE_FIND_ALL ) )
913  {
914  if ( amt >= amtToGet )
915  return amt;
916  }
917  }
918  return amt;
919 }
920 
922 {
923  auto item = static_cast<UContainer*>( base::clone() );
924 
925  item->max_items_mod( this->max_items_mod() );
926  item->max_weight_mod( this->max_weight_mod() );
927  item->max_slots_mod( this->max_slots_mod() );
929 
930  return item;
931 }
932 
933 unsigned short UContainer::max_items() const
934 {
935  const auto max_items = desc.max_items + max_items_mod();
936 
937  return std::max( 1, std::min<decltype( max_items )>( max_items, MAX_CONTAINER_ITEMS ) );
938 }
939 
940 unsigned short UContainer::max_weight() const
941 {
942  const s32 max_weight = desc.max_weight + max_weight_mod();
943 
944  if ( max_weight < 1 )
945  return USHRT_MAX;
946  else if ( max_weight <= USHRT_MAX )
947  return static_cast<u16>( max_weight );
948  else
949  return USHRT_MAX;
950 }
951 
953 {
954  const auto max_slots = desc.max_slots + max_slots_mod();
955 
956  return std::max( 0, std::min<decltype( max_slots )>( max_slots, MAX_SLOTS ) );
957 }
958 
960 {
962 }
963 
964 void UContainer::no_drop_exception( bool newvalue )
965 {
967 }
968 
970 {
971  return desc.no_drop_exception;
972 }
973 } // namespace Core
974 } // namespace Pol
bool empty() const
Definition: scrdef.h:41
virtual void printProperties(Clib::StreamWriter &sw) const POL_OVERRIDE
Definition: lockable.cpp:28
virtual void on_insert_add_item(Mobile::Character *mob, MoveType move, Items::Item *new_item)
Definition: containr.cpp:833
Contents::const_iterator const_iterator
Definition: containr.h:115
void on_remove(Mobile::Character *chr, Items::Item *item, MoveType move=MT_PLAYER)
Definition: containr.cpp:769
unsigned char u8
Definition: rawtypes.h:25
std::vector< Items::Item * > Contents
Definition: containr.h:113
void enumerate_contents(Bscript::ObjArray *arr, int flags)
Definition: containr.cpp:303
const Items::ContainerDesc & desc
Definition: containr.h:235
unsigned short stack_limit
Definition: itemdesc.h:126
virtual Items::Item * clone() const POL_OVERRIDE
Definition: lockable.cpp:37
UContainer * find_container(u32 serial) const
Definition: containr.cpp:575
bool can_add_to_slot(u8 &slotIndex)
Definition: containr.cpp:178
bool is_legal_posn(const Items::Item *item, u16 x, u16 y) const
Definition: containr.cpp:733
unsigned int find_sumof_objtype_noninuse(u32 objtype) const
Definition: containr.cpp:471
const int FINDSUBSTANCE_IGNORE_LOCKED
Definition: core.h:85
virtual Bscript::BObjectImp * make_ref() POL_OVERRIDE
Definition: uoscrobj.cpp:1628
virtual bool can_add(const Items::Item &item) const
Definition: containr.cpp:168
virtual void printProperties(Clib::StreamWriter &sw) const POL_OVERRIDE
Definition: containr.cpp:867
void add_item_to_world(Items::Item *item)
Definition: uworld.cpp:31
bool stackable() const
Definition: item.cpp:570
virtual void add_bulk(int item_count_delta, int weight_delta)
Definition: containr.cpp:215
const int INSERT_ADD_ITEM
Definition: core.h:55
void extract(Contents &cnt)
Definition: containr.cpp:322
const int INSERT_INCREASE_STACK
Definition: core.h:56
Core::ScriptDef on_remove_script
Definition: itemdesc.h:174
bool is_slot_empty(u8 &slotIndex)
Definition: containr.cpp:240
virtual void readProperties(Clib::ConfigElem &elem) POL_OVERRIDE
Definition: lockable.cpp:22
bool can_add_bulk(int tli_diff, int item_count_diff, int weight_diff) const
Definition: containr.cpp:125
Items::Item * find(u32 serial) const
Definition: containr.cpp:620
bool get(ENUM flag) const
Definition: uobject.h:108
int remove_int(const char *propname)
Definition: cfgfile.cpp:340
virtual void builtin_on_use(Network::Client *client) POL_OVERRIDE
Definition: containr.cpp:690
#define MAX_SLOTS
Definition: uconst.h:91
void send_open_gump(Network::Client *client, const UContainer &cont)
Definition: ufunc2.cpp:67
virtual void register_object(UObject *obj)
Definition: multis.cpp:60
Contents::iterator iterator
Definition: containr.h:114
virtual void readProperties(Clib::ConfigElem &elem) POL_OVERRIDE
Definition: containr.cpp:880
virtual ~UContainer()
Definition: containr.cpp:62
u8 max_slots() const
Definition: containr.cpp:952
Core::ScriptDef on_insert_script
Definition: itemdesc.h:172
virtual void add(Items::Item *item)
Definition: containr.cpp:194
bool can_swap(const UContainer &cont) const
Definition: containr.cpp:328
void swap(UContainer &cont)
Definition: containr.cpp:340
void remove_bulk(const Items::Item *item)
Definition: containr.cpp:210
virtual Items::Item * remove(u32 serial, UContainer **found_in=nullptr)
Definition: containr.cpp:510
#define ITEM_ELEM_PTR(elem)
Definition: containr.h:39
void set_dirty()
Definition: uobject.h:291
Items::Item * find_addable_stack(const Items::Item *adding_item) const
Definition: containr.cpp:403
unsigned short u16
Definition: rawtypes.h:26
unsigned int u32
Definition: rawtypes.h:27
void get_random_location(u16 *px, u16 *py) const
Definition: containr.cpp:712
bool call_script(const ScriptDef &script, Bscript::BObjectImp *param0)
Definition: scrsched.cpp:546
virtual void destroy()
Definition: uobject.cpp:122
void destroy_item(Item *item)
Definition: ufunc.cpp:1538
AttributeFlags< OBJ_FLAGS > flags_
Definition: uobject.h:274
virtual unsigned int weight() const POL_OVERRIDE
Definition: containr.cpp:230
Items::Item * find_toplevel(u32 serial) const
Definition: containr.cpp:645
bool locked() const
Definition: lockable.h:65
#define MAX_CONTAINER_ITEMS
Definition: uconst.h:90
int random_int(int i)
Definition: random.cpp:34
Core::ScriptDef can_insert_script
Definition: itemdesc.h:171
const int FINDOBJTYPE_ROOT_ONLY
Definition: core.h:83
static UninitObject * create()
Definition: bobject.h:482
unsigned short max_weight() const
Definition: containr.cpp:940
signed int s32
Definition: rawtypes.h:31
#define passert(exp)
Definition: passert.h:62
virtual void destroy() POL_OVERRIDE
Definition: containr.cpp:91
void on_insert_increase_stack(Mobile::Character *mob, MoveType move, Items::Item *existing_item, unsigned short amt_added)
Definition: containr.cpp:805
Items::Item * find_toplevel_objtype(u32 objtype) const
Definition: containr.cpp:363
virtual Bscript::BObjectImp * make_ref() POL_OVERRIDE
Definition: uoscrobj.cpp:1650
#define POLLOG
Definition: logfacility.h:219
const int FINDSUBSTANCE_FIND_ALL
Definition: core.h:87
void add_at_random_location(Items::Item *item)
Definition: containr.cpp:291
virtual unsigned int item_count() const
Definition: item.cpp:944
Core::UContainer * container
Definition: item.h:256
#define GET_ITEM_PTR(itr)
Definition: containr.h:38
virtual void printOn(Clib::StreamWriter &sw) const POL_OVERRIDE
Definition: containr.cpp:99
void send_remove_object_to_inrange(const UObject *centerObject)
Definition: ufunc.cpp:428
void send_full_statmsg(Network::Client *client, Mobile::Character *chr)
Definition: statmsg.cpp:32
void move_item(Item *item, UFACING facing)
Definition: ufunc.cpp:1601
void consume_sumof_objtype_noninuse(u32 objtype, unsigned int amount)
Definition: containr.cpp:495
SettingsManager settingsManager
Definition: settings.cpp:14
virtual void spill_contents(Multi::UMulti *supporting_multi) POL_OVERRIDE
Definition: containr.cpp:738
virtual void printSelfOn(Clib::StreamWriter &sw) const POL_OVERRIDE
Definition: containr.cpp:105
bool movable() const
Definition: item.h:300
StateManager stateManager
Definition: state.cpp:8
virtual unsigned int item_count() const POL_OVERRIDE
Definition: containr.cpp:235
unsigned int held_item_count_
Definition: containr.h:238
Items::Item * find_objtype_noninuse(u32 objtype) const
Definition: containr.cpp:449
Items::Item * find_toplevel_objtype_noninuse(u32 objtype) const
Definition: containr.cpp:372
u16 getamount() const
Definition: item.h:295
void addElement(BObjectImp *imp)
Definition: object.cpp:1399
void subtract_amount_from_item(Item *item, unsigned short amount)
Definition: ufunc.cpp:1584
bool no_drop_exception() const
Definition: containr.cpp:959
UContainer(const Items::ContainerDesc &descriptor)
Definition: containr.cpp:54
void send_container_contents(Network::Client *client, const UContainer &cont)
Definition: ufunc2.cpp:78
Core::ScriptDef can_remove_script
Definition: itemdesc.h:173
Realms::Realm * realm
Definition: baseobject.h:56
bool check_can_remove_script(Mobile::Character *chr, Items::Item *item, MoveType move=MT_PLAYER)
Definition: containr.cpp:848
virtual void printOn(Clib::StreamWriter &) const
Definition: uobject.cpp:332
bool can_insert_increase_stack(Mobile::Character *mob, MoveType move, Items::Item *existing_item, unsigned short amt_to_add, Items::Item *adding_item)
Definition: containr.cpp:787
bool gflag_enforce_container_limits
Definition: state.h:38
bool default_no_drop_exception() const
Definition: containr.cpp:969
bool isa(UOBJ_CLASS uobj_class) const
Definition: baseobject.h:99
void change(ENUM flag, bool value)
Definition: uobject.h:115
const int FINDOBJTYPE_IGNORE_LOCKED
Definition: core.h:82
Items::Item * find_toplevel_polclass(unsigned int polclass) const
Definition: containr.cpp:353
Items::Item * find_objtype(u32 objtype, int flags) const
Definition: containr.cpp:424
unsigned short max_items() const
Definition: containr.cpp:933
const ItemDesc & itemdesc() const
Definition: item.cpp:127
virtual size_t estimatedSize() const POL_OVERRIDE
Definition: containr.cpp:67
const ContainerDesc & find_container_desc(u32 objtype)
Definition: itemdesc.cpp:942
void reset_slot()
Definition: item.h:363
virtual unsigned int weight() const POL_OVERRIDE
Definition: item.cpp:940
#define passert_always(exp)
Definition: passert.h:80
const int ENUMERATE_IGNORE_LOCKED
Definition: core.h:61
virtual Items::Item * clone() const POL_OVERRIDE
Definition: containr.cpp:921
#define pf_endl
Definition: proplist.cpp:25
Mobile::Character * GetCharacterOwner()
Definition: item.cpp:1168
const int ENUMERATE_ROOT_ONLY
Definition: core.h:62
const int FINDSUBSTANCE_ROOT_ONLY
Definition: core.h:86
u16 gump() const
Definition: containr.cpp:707
bool find_empty_slot(u8 &slotIndex)
Definition: containr.cpp:255
virtual size_t estimatedSize() const POL_OVERRIDE
Definition: lockable.cpp:45
Definition: berror.cpp:12
bool remove_bool(const char *propname)
Definition: cfgfile.cpp:426
void send_sysmessage(Network::Client *client, const char *text, unsigned short font, unsigned short color)
Definition: ufunc.cpp:1147
virtual void for_each_item(void(*f)(Item *item, void *a), void *arg)
Definition: containr.cpp:659
bool can_insert_add_item(Mobile::Character *mob, MoveType move, Items::Item *new_item)
Definition: containr.cpp:817
void printContents(Clib::StreamWriter &sw) const
Definition: containr.cpp:110
#define INC_PROFILEVAR(counter)
Definition: profile.h:85