Pol  Revision:cb584c9
dynproperties.h
Go to the documentation of this file.
1 
42 #ifndef __POL_DYNPROPS_H
43 #define __POL_DYNPROPS_H
44 
45 #include <bitset>
46 #include <boost/any.hpp>
47 #include <boost/variant.hpp>
48 #include <memory>
49 #include <string>
50 #include <type_traits>
51 #include <vector>
52 
53 #include "../clib/passert.h"
54 #include "../clib/rawtypes.h"
55 #include "gameclck.h"
56 
57 namespace Pol
58 {
59 namespace Core
60 {
61 // define to generate 3 methods for get/set/has
62 #define DYN_PROPERTY( name, type, id, defaultvalue ) \
63  type name() const \
64  { \
65  type val; \
66  if ( getmember<type>( id, &val ) ) \
67  return val; \
68  return defaultvalue; \
69  }; \
70  void name( const type& val ) { setmember( id, val, static_cast<type>( defaultvalue ) ); }; \
71  bool has_##name() const { return hasmember( id ); }
72 // define to generate 3 methods for get/set/has
73 #define DYN_PROPERTY_POINTER( name, type, id ) \
74  type name() const \
75  { \
76  type val; \
77  if ( getmember<type>( id, &val ) ) \
78  return val; \
79  return nullptr; \
80  }; \
81  void name( type val ) { setmemberPointer( id, val ); }; \
82  bool has_##name() const { return hasmember( id ); }
83 // enum for the propertys
85 {
86  PROP_AR_MOD = 0, // UArmor, Character
87  PROP_MAX_ITEMS_MOD = 1, // UContainer
88  PROP_MAX_SLOTS_MOD = 2, // UContainer
89  PROP_MAX_WEIGHT_MOD = 3, // UContainer
90  PROP_SELLPRICE = 4, // Item
91  PROP_BUYPRICE = 5, // Item
92  PROP_MAXHP_MOD = 6, // Item
93  PROP_NAME_SUFFIX = 7, // Item
94  PROP_RESIST_FIRE = 8, // UObject
95  PROP_RESIST_COLD = 9, // UObject
96  PROP_RESIST_ENERGY = 10, // UObject
97  PROP_RESIST_POISON = 11, // UObject
98  PROP_RESIST_PHYSICAL = 12, // UObject
99  PROP_DAMAGE_FIRE = 13, // UObject
100  PROP_DAMAGE_COLD = 14, // UObject
101  PROP_DAMAGE_ENERGY = 15, // UObject
102  PROP_DAMAGE_POISON = 16, // UObject
103  PROP_DAMAGE_PHYSICAL = 17, // UObject
104  PROP_DMG_MOD = 18, // UWeapon
105  PROP_SPEED_MOD = 19, // UWeapon
116  PROP_STATCAP_SKILLCAP = 30, // Character
117  PROP_EXT_STATBAR_LUCK = 31, // Character
118  PROP_EXT_STATBAR_FOLLOWERS = 32, // Character
119  PROP_EXT_STATBAR_TITHING = 33, // Character
120  PROP_MOVEMENTCOST_MOD = 34, // Character
121  PROP_QUALITY = 35, // Item (Equipment has fixed member)
122  PROP_DOUBLECLICK_WAIT = 36, // Character
123  PROP_DISABLE_SKILLS_UNTIL = 37, // Character
124  PROP_SQUELCHED_UNTIL = 38, // Character
125  PROP_DEAFENED_UNTIL = 39, // Character
126  PROP_LIGHTOVERRIDE_UNTIL = 40, // Character
127  PROP_LIGHTOVERRIDE = 41, // Character
128  PROP_TITLE_PREFIX = 42, // Character
129  PROP_TITLE_SUFFIX = 43, // Character
130  PROP_TITLE_GUILD = 44, // Character
131  PROP_TITLE_RACE = 45, // Character
132  PROP_SPEECH_COLOR = 46, // Npc
133  PROP_SPEECH_FONT = 47, // Npc
134  PROP_CARRY_CAPACITY_MOD = 48, // Character
135  PROP_DELAY_MOD = 49, // Character
136  PROP_HITCHANCE_MOD = 50, // Character
137  PROP_EVASIONCHANCE_MOD = 51, // Character
138  PROP_PARTY = 52, // Character
139  PROP_PARTY_CANDIDATE = 53, // Character
140  PROP_PARTY_OFFLINE = 54, // Character
141  PROP_GUILD = 55, // Character
142  PROP_GOTTEN_BY = 56, // Item
143  PROP_GOTTEN_ITEM = 57, // Character
144  PROP_PROCESS = 58, // Item
145  PROP_HOUSE = 59, // House
146 
147  PROP_FLAG_SIZE // used for bitset size
148 };
149 
150 // value & mod struct definition for e.g. the resist/damage properties
152 {
155  ValueModPack( s16 value_ );
156  ValueModPack();
157  bool operator==( const ValueModPack& other ) const;
158  ValueModPack& addToValue( const ValueModPack& other );
159  ValueModPack& addToValue( s16 other );
160  ValueModPack& addToMod( s16 other );
161  ValueModPack& setAsMod( s16 other );
163  s16 sum() const;
164 
165  static const ValueModPack DEFAULT;
166 };
167 static_assert( sizeof( ValueModPack ) == sizeof( u32 ), "size missmatch" );
168 
169 // combination of skill and stat cap
171 {
174  SkillStatCap();
175  SkillStatCap( s16 statcap_, u16 skillcap_ );
176  bool operator==( const SkillStatCap& other ) const;
177 
178  static const SkillStatCap DEFAULT;
179 };
180 static_assert( sizeof( SkillStatCap ) == sizeof( u32 ), "size missmatch" );
181 
182 // combination of followers/followers_max
184 {
188  ExtStatBarFollowers( s8 followers_, s8 followers_max_ );
189  bool operator==( const ExtStatBarFollowers& other ) const;
190 
192 };
193 static_assert( sizeof( ExtStatBarFollowers ) == sizeof( u16 ), "size missmatch" );
194 
195 // movement cost mod (not in variant storage)
197 {
198  double walk;
199  double run;
200  double walk_mounted;
201  double run_mounted;
202  MovementCostMod();
203  MovementCostMod( double walk_, double run_, double walk_mounted_, double run_mounted_ );
204  bool operator==( const MovementCostMod& other ) const;
205 
206  static const MovementCostMod DEFAULT;
207 };
208 
209 template <typename Storage>
211 
212 // small property type no types above size 4, for bigger types boost::any will be used
213 typedef boost::variant<u8, u16, u32, s8, s16, s32, ValueModPack, SkillStatCap, ExtStatBarFollowers,
214  gameclock_t>
216 template <typename T>
218 {
219  static const bool value =
220  std::is_same<T, u8>::value || std::is_same<T, u16>::value || std::is_same<T, u32>::value ||
221  std::is_same<T, s8>::value || std::is_same<T, s16>::value || std::is_same<T, s32>::value ||
222  std::is_same<T, ValueModPack>::value || std::is_same<T, SkillStatCap>::value ||
223  std::is_same<T, ExtStatBarFollowers>::value || std::is_same<T, gameclock_t>::value;
224 };
225 
226 // holder class
227 // stores the property kind and via boost::variant/boost::any the value
228 template <typename Storage>
230 {
231 public:
232  template <typename S>
233  friend class PropHolderContainer;
234  explicit PropHolder( DynPropTypes type );
235  PropHolder( DynPropTypes type, const Storage& value );
236  template <typename V>
237  V getValue() const;
238 
239 protected:
242 };
243 
244 // Container class
245 // simple vector of PropHolder instances, used to have common code between boost::any/variant
246 template <typename Storage>
248 {
249 public:
251  template <typename V>
252  bool getValue( DynPropTypes type, V* value ) const;
253  template <typename V>
254  bool updateValue( DynPropTypes type, const V& value );
255  template <typename V>
256  bool updateValuePointer( DynPropTypes type, V value );
257  template <typename V>
258  void addValue( DynPropTypes type, const V& value );
259  template <typename V>
260  void addValuePointer( DynPropTypes type, V value );
261  void removeValue( DynPropTypes type );
262  size_t estimateSize() const;
263 
264 private:
265  std::vector<PropHolder<Storage>> _props;
266 };
267 
268 // management class
269 // has a bitset for fast checking if a property exists
270 // simple vector for all the "small" PropHolders
271 // and a lazy filled unique_ptr for "big" PropHolders
272 class DynProps
273 {
274 public:
275  DynProps();
276  // fast bitflag check
277  bool hasProperty( DynPropTypes type ) const;
278  // get property returns false if non existent (checks via hasProperty before)
279  template <typename V>
280  bool getProperty( DynPropTypes type, V* value ) const;
281  // set property (sets also the flag)
282  template <typename V>
283  void setProperty( DynPropTypes type, const V& value );
284  template <typename V>
285  void setPropertyPointer( DynPropTypes type, V value );
286  // remove a prop
287  template <typename V>
288  void removeProperty( DynPropTypes type );
289  size_t estimateSize() const;
290 
291 private:
292  std::bitset<PROP_FLAG_SIZE> _prop_bits;
294  std::unique_ptr<PropHolderContainer<boost::any>> _any_props;
295 };
296 
297 // Base class for dynamic properties, should be derived from
298 // holds a pointer to the DynProps, which is lazy filled
299 // due to memory usage (empty DynProps is larger then an unique_ptr)
300 // TODO: should the ptr be release if the last member was removed?
302 {
303 public:
305  bool hasmember( DynPropTypes member ) const;
306  template <typename V>
307  bool getmember( DynPropTypes member, V* value ) const;
308  template <typename V>
309  void setmember( DynPropTypes member, const V& value, const V& defaultvalue );
310  template <typename V>
311  void setmemberPointer( DynPropTypes member, V value );
312  size_t estimateSizeDynProps() const;
313 
314 protected:
315  ~DynamicPropsHolder() = default;
316 
317 private:
318  void initProps();
319  std::unique_ptr<DynProps> _dynprops;
320 };
321 
322 
324 // Imp start
326 
328 // ValueModPack
329 
330 inline ValueModPack::ValueModPack( s16 value_ ) : value( value_ ), mod( 0 ) {}
331 inline ValueModPack::ValueModPack() : value( 0 ), mod( 0 ) {}
332 inline bool ValueModPack::operator==( const ValueModPack& other ) const
333 {
334  return value == other.value && mod == other.mod;
335 }
336 inline ValueModPack& ValueModPack::addToValue( const ValueModPack& other )
337 {
338  value += other.value + other.mod;
339  return *this;
340 }
341 inline ValueModPack& ValueModPack::addToValue( s16 other )
342 {
343  value += other;
344  return *this;
345 }
346 inline ValueModPack& ValueModPack::addToMod( s16 other )
347 {
348  mod += other;
349  return *this;
350 }
351 inline ValueModPack& ValueModPack::setAsMod( s16 other )
352 {
353  mod = other;
354  return *this;
355 }
356 inline ValueModPack& ValueModPack::resetModAsValue()
357 {
358  value = mod;
359  return *this;
360 }
361 inline s16 ValueModPack::sum() const
362 {
363  return value + mod;
364 }
365 
367 // SkillStatCap
368 inline SkillStatCap::SkillStatCap() : statcap( 0 ), skillcap( 0 ) {}
369 inline SkillStatCap::SkillStatCap( s16 statcap_, u16 skillcap_ )
370  : statcap( statcap_ ), skillcap( skillcap_ )
371 {
372 }
373 inline bool SkillStatCap::operator==( const SkillStatCap& other ) const
374 {
375  return statcap == other.statcap && skillcap == other.skillcap;
376 }
377 
379 // ExtStatBarFollowers
380 inline ExtStatBarFollowers::ExtStatBarFollowers() : followers( 0 ), followers_max( 0 ) {}
381 inline ExtStatBarFollowers::ExtStatBarFollowers( s8 followers_, s8 followers_max_ )
382  : followers( followers_ ), followers_max( followers_max_ )
383 {
384 }
385 inline bool ExtStatBarFollowers::operator==( const ExtStatBarFollowers& other ) const
386 {
387  return followers == other.followers && followers_max == other.followers_max;
388 }
389 
391 // MovementCostMod
393  : walk( 1.0 ), run( 1.0 ), walk_mounted( 1.0 ), run_mounted( 1.0 )
394 {
395 }
396 inline MovementCostMod::MovementCostMod( double walk_, double run_, double walk_mounted_,
397  double run_mounted_ )
398  : walk( walk_ ), run( run_ ), walk_mounted( walk_mounted_ ), run_mounted( run_mounted_ )
399 {
400 }
401 inline bool MovementCostMod::operator==( const MovementCostMod& other ) const
402 {
403  return walk == other.walk && run == other.run && walk_mounted == other.walk_mounted &&
404  run_mounted == other.run_mounted;
405 }
406 
408 // PropHolder
409 template <class Storage>
410 inline PropHolder<Storage>::PropHolder( DynPropTypes type ) : _type( type ), _value()
411 {
412 }
413 template <class Storage>
415  : _type( type ), _value( value )
416 {
417 }
418 
419 template <>
420 template <typename V>
422 {
423  return boost::any_cast<V>( _value );
424 }
425 template <>
426 template <typename V>
428 {
429  return boost::get<V>( _value );
430 }
431 
433 // PropHolderContainer
434 template <class Storage>
436 {
437 }
438 
439 template <class Storage>
440 template <typename V>
441 inline bool PropHolderContainer<Storage>::getValue( DynPropTypes type, V* value ) const
442 {
443  for ( const PropHolder<Storage>& prop : _props )
444  {
445  if ( prop._type == type )
446  {
447  *value = prop.template getValue<V>();
448  return true;
449  }
450  }
451  return false;
452 }
453 
454 template <class Storage>
455 template <typename V>
456 inline bool PropHolderContainer<Storage>::updateValue( DynPropTypes type, const V& value )
457 {
458  for ( PropHolder<Storage>& prop : _props )
459  {
460  if ( prop._type == type )
461  {
462  prop._value = value;
463  return true;
464  }
465  }
466  return false;
467 }
468 
469 template <class Storage>
470 template <typename V>
472 {
473  for ( PropHolder<Storage>& prop : _props )
474  {
475  if ( prop._type == type )
476  {
477  prop._value = value;
478  return true;
479  }
480  }
481  return false;
482 }
483 
484 template <class Storage>
485 template <typename V>
486 inline void PropHolderContainer<Storage>::addValue( DynPropTypes type, const V& value )
487 {
488  _props.emplace_back( type, value );
489 }
490 
491 template <class Storage>
492 template <typename V>
494 {
495  _props.emplace_back( type, value );
496 }
497 
498 template <class Storage>
500 {
501  _props.erase(
502  std::remove_if( _props.begin(), _props.end(),
503  [&type]( const PropHolder<Storage>& x ) { return type == x._type; } ),
504  _props.end() );
505 }
506 
507 template <class Storage>
509 {
510  return 3 * sizeof( void* ) + _props.capacity() * sizeof( PropHolder<Storage> );
511 }
512 
513 
515 // helper template functions to switch between both containers
516 namespace
517 {
518 template <typename V>
519 static typename std::enable_if<can_be_used_in_variant<V>::value, bool>::type getPropertyHelper(
520  const PropHolderContainer<variant_storage>& variant_props,
521  const std::unique_ptr<PropHolderContainer<boost::any>>& any_props, DynPropTypes type, V* value )
522 {
523  (void)any_props;
524  return variant_props.getValue( type, value );
525 }
526 template <typename V>
527 static typename std::enable_if<!can_be_used_in_variant<V>::value, bool>::type getPropertyHelper(
528  const PropHolderContainer<variant_storage>& variant_props,
529  const std::unique_ptr<PropHolderContainer<boost::any>>& any_props, DynPropTypes type, V* value )
530 {
531  (void)variant_props;
532  passert_always( any_props.get() );
533  return any_props->getValue( type, value );
534 }
535 
536 template <typename V>
537 static typename std::enable_if<can_be_used_in_variant<V>::value, bool>::type updatePropertyHelper(
539  std::unique_ptr<PropHolderContainer<boost::any>>& any_props, DynPropTypes type, const V& value )
540 {
541  (void)any_props;
542  return variant_props.updateValue( type, value );
543 }
544 template <typename V>
545 static typename std::enable_if<!can_be_used_in_variant<V>::value, bool>::type updatePropertyHelper(
547  std::unique_ptr<PropHolderContainer<boost::any>>& any_props, DynPropTypes type, const V& value )
548 {
549  (void)variant_props;
550  passert_always( any_props.get() );
551  return any_props->updateValue( type, value );
552 }
553 template <typename V>
554 static typename std::enable_if<can_be_used_in_variant<V>::value, void>::type addPropertyHelper(
556  std::unique_ptr<PropHolderContainer<boost::any>>& any_props, DynPropTypes type, const V& value )
557 {
558  (void)any_props;
559  variant_props.addValue( type, value );
560 }
561 template <typename V>
562 static typename std::enable_if<!can_be_used_in_variant<V>::value, void>::type addPropertyHelper(
564  std::unique_ptr<PropHolderContainer<boost::any>>& any_props, DynPropTypes type, const V& value )
565 {
566  (void)variant_props;
567  if ( !any_props )
568  any_props.reset( new PropHolderContainer<boost::any>() );
569  any_props->addValue( type, value );
570 }
571 
572 template <typename V>
573 static typename std::enable_if<can_be_used_in_variant<V>::value, void>::type removePropertyHelper(
575  std::unique_ptr<PropHolderContainer<boost::any>>& any_props, DynPropTypes type )
576 {
577  (void)any_props;
578  variant_props.removeValue( type );
579 }
580 template <typename V>
581 static typename std::enable_if<!can_be_used_in_variant<V>::value, void>::type removePropertyHelper(
583  std::unique_ptr<PropHolderContainer<boost::any>>& any_props, DynPropTypes type )
584 {
585  (void)variant_props;
586  passert_always( any_props.get() );
587  any_props->removeValue( type );
588 }
589 } // namespace
590 
592 // DynProps
593 inline DynProps::DynProps() : _prop_bits(), _props(), _any_props( nullptr ) {}
594 
595 inline bool DynProps::hasProperty( DynPropTypes type ) const
596 {
597  return _prop_bits.test( type );
598 }
599 template <typename V>
600 inline bool DynProps::getProperty( DynPropTypes type, V* value ) const
601 {
602  if ( !hasProperty( type ) )
603  return false;
604  return getPropertyHelper<V>( _props, _any_props, type, value );
605 }
606 
607 template <typename V>
608 inline void DynProps::setProperty( DynPropTypes type, const V& value )
609 {
610  if ( hasProperty( type ) )
611  {
612  bool res = updatePropertyHelper<V>( _props, _any_props, type, value );
613  passert_always( res );
614  return;
615  }
616  _prop_bits.set( type, true );
617  addPropertyHelper<V>( _props, _any_props, type, value );
618 }
619 
620 template <typename V>
621 inline void DynProps::setPropertyPointer( DynPropTypes type, V value )
622 {
623  if ( hasProperty( type ) )
624  {
625  passert_always( _any_props.get() );
626  bool res = _any_props->updateValue( type, value );
627  passert_always( res );
628  return;
629  }
630  _prop_bits.set( type, true );
631  if ( !_any_props )
633  _any_props->addValue( type, value );
634 }
635 
636 template <typename V>
638 {
639  if ( !hasProperty( type ) )
640  return;
641  removePropertyHelper<V>( _props, _any_props, type );
642  _prop_bits.set( type, false );
643 }
644 
645 inline size_t DynProps::estimateSize() const
646 {
647  size_t size = sizeof( std::bitset<PROP_FLAG_SIZE> ) + sizeof( std::unique_ptr<void> ) +
649  if ( _any_props )
650  size += _any_props->estimateSize();
651  return size;
652 }
653 
655 // DynamicPropsHolder
656 
657 inline DynamicPropsHolder::DynamicPropsHolder() : _dynprops( nullptr ) {}
658 
659 
661 {
662  if ( !_dynprops )
663  _dynprops.reset( new DynProps() );
664 }
665 
666 template <typename V>
667 inline bool DynamicPropsHolder::getmember( DynPropTypes member, V* value ) const
668 {
669  if ( !_dynprops )
670  return false;
671  return _dynprops->getProperty( member, value );
672 }
673 
674 inline bool DynamicPropsHolder::hasmember( DynPropTypes member ) const
675 {
676  if ( !_dynprops || !_dynprops->hasProperty( member ) )
677  return false;
678  return true;
679 }
680 
681 template <typename V>
682 inline void DynamicPropsHolder::setmember( DynPropTypes member, const V& value,
683  const V& defaultvalue )
684 {
685  if ( value == defaultvalue )
686  {
687  if ( _dynprops )
688  _dynprops->removeProperty<V>( member );
689  return;
690  }
691  initProps();
692  _dynprops->setProperty( member, value );
693 }
694 
695 template <typename V>
697 {
698  if ( value == nullptr )
699  {
700  if ( _dynprops )
701  _dynprops->removeProperty<V>( member );
702  return;
703  }
704  initProps();
705  _dynprops->setProperty( member, value );
706 }
707 
709 {
710  size_t size = sizeof( DynamicPropsHolder );
711  if ( _dynprops )
712  size += _dynprops->estimateSize();
713  return size;
714 }
715 
716 
717 } // namespace Core
718 } // namespace Pol
719 
720 #endif
unsigned char u8
Definition: rawtypes.h:25
unsigned int gameclock_t
Definition: gameclck.h:14
std::unique_ptr< PropHolderContainer< boost::any > > _any_props
void setPropertyPointer(DynPropTypes type, V value)
void setmember(DynPropTypes member, const V &value, const V &defaultvalue)
size_t estimateSize() const
bool operator==(const ExtStatBarFollowers &other) const
void addValuePointer(DynPropTypes type, V value)
size_t estimateSizeDynProps() const
ValueModPack & addToValue(const ValueModPack &other)
static const SkillStatCap DEFAULT
bool hasProperty(DynPropTypes type) const
static const ExtStatBarFollowers DEFAULT
bool operator==(const ValueModPack &other) const
void setmemberPointer(DynPropTypes member, V value)
unsigned short u16
Definition: rawtypes.h:26
unsigned int u32
Definition: rawtypes.h:27
bool getProperty(DynPropTypes type, V *value) const
PropHolderContainer< variant_storage > _props
signed short s16
Definition: rawtypes.h:30
signed int s32
Definition: rawtypes.h:31
bool getmember(DynPropTypes member, V *value) const
bool operator==(const MovementCostMod &other) const
signed char s8
Definition: rawtypes.h:29
void removeProperty(DynPropTypes type)
bool hasmember(DynPropTypes member) const
std::unique_ptr< DynProps > _dynprops
bool operator==(const SkillStatCap &other) const
std::bitset< PROP_FLAG_SIZE > _prop_bits
std::vector< PropHolder< Storage > > _props
ValueModPack & setAsMod(s16 other)
static const MovementCostMod DEFAULT
PropHolder(DynPropTypes type)
boost::variant< u8, u16, u32, s8, s16, s32, ValueModPack, SkillStatCap, ExtStatBarFollowers, gameclock_t > variant_storage
void removeValue(DynPropTypes type)
bool updateValue(DynPropTypes type, const V &value)
void addValue(DynPropTypes type, const V &value)
static const ValueModPack DEFAULT
bool getValue(DynPropTypes type, V *value) const
bool run(int argc, char **argv)
bool updateValuePointer(DynPropTypes type, V value)
ValueModPack & resetModAsValue()
#define passert_always(exp)
Definition: passert.h:80
void setProperty(DynPropTypes type, const V &value)
Definition: berror.cpp:12
ValueModPack & addToMod(s16 other)