Pol  Revision:f37d500
armor.cpp
Go to the documentation of this file.
1 
8 #include "armor.h"
9 
10 #include <stddef.h>
11 #include <stdexcept>
12 
13 #include <format/format.h>
14 #include "../../bscript/bstruct.h"
15 #include "../../bscript/impstr.h"
16 #include "../../clib/cfgelem.h"
17 #include "../../clib/logfacility.h"
18 #include "../../clib/passert.h"
19 #include "../../clib/streamsaver.h"
20 #include "../../clib/strutil.h"
21 #include "../../plib/pkg.h"
22 #include "../../plib/systemstate.h"
23 #include "../equipdsc.h"
24 #include "../extobj.h"
25 #include "../globals/settings.h"
26 #include "../layers.h"
27 #include "../tiles.h"
28 #include "../uobject.h"
29 #include "armrtmpl.h"
30 #include "itemdesc.h"
31 
32 
33 namespace Pol
34 {
35 namespace Mobile
36 {
37 const char* zone_to_zone_name( unsigned short zone );
38 unsigned short layer_to_zone( unsigned short layer );
39 unsigned short zone_name_to_zone( const char* zname );
40 }
41 namespace Items
42 {
46  bool forceShield )
47  : EquipDesc( objtype, elem, ARMORDESC, pkg ),
48  ar( elem.remove_ushort( "AR", 0 ) ),
49  zones(),
50  on_hit_script( elem.remove_string( "ONHITSCRIPT", "" ), pkg, "scripts/items/" )
51 {
52  std::string coverage;
53  while ( elem.remove_prop( "COVERAGE", &coverage ) )
54  {
55  try
56  {
57  zones.insert( Mobile::zone_name_to_zone( coverage.c_str() ) );
58  }
59  catch ( std::runtime_error& )
60  {
61  fmt::Writer tmp;
62  tmp.Format( "Error in Objtype 0x{:X}" ) << objtype;
63  if ( pkg == NULL )
64  tmp << "config/itemdesc.cfg\n";
65  else
66  tmp << pkg->dir() << "itemdesc.cfg\n";
67 
68  ERROR_PRINT << tmp.str();
69  throw;
70  }
71  }
72 
73  if ( zones.empty() )
74  {
75  // No 'COVERAGE' entries existed.
76  // default coverage based on object type/layer
77  unsigned short layer = Plib::systemstate.tile[graphic].layer;
78  // special case for shields - they effectively have no coverage.
79  if ( !forceShield && layer != Core::LAYER_HAND1 && layer != Core::LAYER_HAND2 )
80  {
81  try
82  {
83  zones.insert( Mobile::layer_to_zone( layer ) );
84  }
85  catch ( std::runtime_error& )
86  {
87  fmt::Writer tmp;
88  tmp.Format( "Error in Objtype 0x{:X}" ) << objtype;
89  if ( pkg == NULL )
90  tmp << "config/itemdesc.cfg\n";
91  else
92  tmp << pkg->dir() << "itemdesc.cfg\n";
93 
94  ERROR_PRINT << tmp.str();
95  throw;
96  }
97  }
98  }
99 }
100 
102 {
103  base::PopulateStruct( descriptor );
104  descriptor->addMember( "OnHitScript", new Bscript::String( on_hit_script.relativename( pkg ) ) );
105  descriptor->addMember( "AR", new Bscript::BLong( ar ) );
106 
107  std::unique_ptr<Bscript::ObjArray> arr_zones( new Bscript::ObjArray() );
108  std::set<unsigned short>::const_iterator itr;
109  for ( itr = zones.begin(); itr != zones.end(); ++itr )
110  arr_zones->addElement( new Bscript::String( Mobile::zone_to_zone_name( *itr ) ) );
111 
112 
113  if ( arr_zones->ref_arr.size() > 0 )
114  descriptor->addMember( "Coverage", arr_zones.release() );
115 }
116 
118 {
119  size_t size = base::estimatedSize() + sizeof( unsigned short ) /*ar*/
121  size += 3 * sizeof( void* ) + zones.size() * ( sizeof( unsigned short ) + 3 * sizeof( void* ) );
122  return size;
123 }
124 
125 UArmor::UArmor( const ArmorDesc& descriptor, const ArmorDesc* permanent_descriptor )
126  : Equipment( descriptor, Core::UOBJ_CLASS::CLASS_ARMOR, permanent_descriptor ),
127  onhitscript_( descriptor.on_hit_script )
128 {
129 }
130 
131 unsigned short UArmor::ar() const
132 {
133  short ar_mod = this->ar_mod();
134  int ar = ar_base() * hp_ / maxhp();
135  if ( ar_mod != 0 )
136  {
137  ar += ar_mod;
138  }
139 
140  if ( ar < 0 )
141  return 0;
142  else if ( ar <= USHRT_MAX )
143  return static_cast<unsigned short>( ar );
144  else
145  return USHRT_MAX;
146 }
147 
148 unsigned short UArmor::ar_base() const
149 {
150  return ARMOR_TMPL->ar;
151 }
152 
153 bool UArmor::covers( unsigned short zlayer ) const
154 {
155  passert( tmpl != NULL );
156  return ARMOR_TMPL->zones.find( zlayer ) != ARMOR_TMPL->zones.end();
157 }
158 
160 {
161  UArmor* armor = static_cast<UArmor*>( base::clone() );
162  armor->ar_mod( this->ar_mod() );
163  armor->onhitscript_ = onhitscript_;
164  armor->tmpl = tmpl;
165  return armor;
166 }
167 
169 {
170  base::printProperties( sw );
171  if ( has_ar_mod() )
172  sw() << "\tAR_mod\t" << ar_mod() << pf_endl;
173  if ( tmpl != NULL && onhitscript_ != ARMOR_TMPL->on_hit_script )
174  sw() << "\tOnHitScript\t" << onhitscript_.relativename( tmpl->pkg ) << pf_endl;
175 }
176 
178 {
179  base::readProperties( elem );
180  this->ar_mod( static_cast<s16>( elem.remove_int( "AR_MOD", 0 ) ) );
181  set_onhitscript( elem.remove_string( "ONHITSCRIPT", "" ) );
182 }
183 
184 void UArmor::set_onhitscript( const std::string& scriptname )
185 {
186  if ( scriptname.empty() )
187  {
189  }
190  else
191  {
192  onhitscript_.config( scriptname, itemdesc().pkg, "scripts/items/", true );
193  }
194 }
195 std::set<unsigned short> UArmor::tmplzones()
196 {
197  passert( tmpl != NULL );
198  return ARMOR_TMPL->zones;
199 }
200 
203 {
204  const ItemDesc& id = find_itemdesc( Core::settingsManager.extobj.shield );
205  if ( id.save_on_exit )
206  throw std::runtime_error( "Intrinsic Shield " +
207  Clib::hexint( Core::settingsManager.extobj.shield ) +
208  " must specify SaveOnExit 0" );
209 
210  if ( id.type != ItemDesc::ARMORDESC )
211  throw std::runtime_error(
212  "An Armor template for Intrinsic Shield is required in itemdesc.cfg" );
213 }
214 
220  const Plib::Package* pkg )
221 {
222  auto tmpl = new ArmorDesc( Core::settingsManager.extobj.shield, elem, pkg, true );
223  tmpl->is_intrinsic = true;
224  auto armr = new UArmor( *tmpl, tmpl );
225  armr->layer = Core::LAYER_HAND2;
226  armr->tmpl = tmpl;
227 
229 
230  return armr;
231 }
232 
238 {
239  std::string tmp;
240  if ( elem.remove_prop( "Shield", &tmp ) )
241  {
242  // Construct an ArmorTemplate for this NPC template.
243  Clib::ConfigElem shieldelem;
244  shieldelem.set_rest( elem.rest() );
245  shieldelem.set_source( elem );
246  shieldelem.add_prop( "Objtype", "0xFFFF" );
247  shieldelem.add_prop( "Graphic", "1" );
248  shieldelem.add_prop( "SaveOnExit", "0" );
249  shieldelem.add_prop( "AR", tmp.c_str() );
250 
251  if ( elem.remove_prop( "ShieldMaxHp", &tmp ) )
252  shieldelem.add_prop( "MaxHP", tmp.c_str() );
253  else
254  shieldelem.add_prop( "MaxHP", "1" );
255 
256  if ( elem.remove_prop( "ShieldOnHitScript", &tmp ) )
257  shieldelem.add_prop( "OnHitScript", tmp.c_str() );
258 
259  while ( elem.remove_prop( "ShieldCProp", &tmp ) )
260  shieldelem.add_prop( "CProp", tmp.c_str() );
261 
262  return create_intrinsic_shield( elem.rest(), shieldelem, pkg );
263  }
264  else
265  {
266  return NULL;
267  }
268 }
269 
270 size_t UArmor::estimatedSize() const
271 {
272  size_t size = base::estimatedSize() + onhitscript_.estimatedSize();
273  return size;
274 }
275 }
276 }
virtual unsigned short ar_base() const
Definition: armor.cpp:148
virtual Item * clone() const POL_OVERRIDE
Definition: equipmnt.cpp:63
std::string remove_string(const char *propname)
Definition: cfgfile.cpp:394
Core::ScriptDef on_hit_script
Definition: armrtmpl.h:35
void register_intrinsic_equipment(const std::string &name, Equipment *equip)
Must be called when a new intrinsic equipment is created.
Definition: equipmnt.cpp:137
SystemState systemstate
Definition: systemstate.cpp:12
void add_prop(const char *propname, const char *str)
Definition: cfgfile.cpp:503
virtual void printProperties(Clib::StreamWriter &sw) const POL_OVERRIDE
Definition: armor.cpp:168
virtual size_t estimatedSize() const POL_OVERRIDE
Definition: armor.cpp:270
virtual std::string name() const POL_OVERRIDE
Definition: item.cpp:110
#define ARMOR_TMPL
Definition: armor.h:38
virtual unsigned short ar() const
Definition: armor.cpp:131
size_t estimatedSize() const
Definition: scrdef.cpp:140
int remove_int(const char *propname)
Definition: cfgfile.cpp:353
const Core::EquipDesc * tmpl
Definition: equipmnt.h:84
std::string relativename(const Plib::Package *pkg=NULL) const
Definition: scrdef.cpp:102
std::set< unsigned short > zones
Definition: armrtmpl.h:34
virtual void printProperties(Clib::StreamWriter &sw) const POL_OVERRIDE
Definition: equipmnt.cpp:70
void addMember(const char *name, BObjectRef val)
Definition: bstruct.cpp:305
virtual size_t estimatedSize() const POL_OVERRIDE
Definition: equipmnt.cpp:109
virtual Item * clone() const POL_OVERRIDE
Definition: armor.cpp:159
const ItemDesc & find_itemdesc(unsigned int objtype)
Definition: itemdesc.cpp:933
unsigned short maxhp() const
Definition: item.cpp:325
std::string hexint(unsigned short v)
Definition: strutil.cpp:23
const char * rest() const
Definition: cfgfile.cpp:84
unsigned int u32
Definition: rawtypes.h:27
virtual void PopulateStruct(Bscript::BStruct *descriptor) const POL_OVERRIDE
Definition: armor.cpp:101
friend UArmor * create_intrinsic_shield(const char *name, Clib::ConfigElem &elem, const Plib::Package *pkg)
Creates a new intrinsic shield and returns it.
Definition: armor.cpp:219
const Plib::Package * pkg
Definition: itemdesc.h:84
void config(const std::string &name, const Plib::Package *pkg, const char *mainpfx, bool warn_if_not_found=true)
Definition: scrdef.cpp:55
UArmor * create_intrinsic_shield_from_npctemplate(Clib::ConfigElem &elem, const Plib::Package *pkg)
Creates a new intrinic shield for an NPC template and returns it.
Definition: armor.cpp:237
unsigned short ar
Definition: armrtmpl.h:33
const char * zone_to_zone_name(unsigned short zone)
Definition: charactr.cpp:196
#define passert(exp)
Definition: passert.h:62
virtual bool covers(unsigned short zlayer) const
Definition: armor.cpp:153
virtual void PopulateStruct(Bscript::BStruct *descriptor) const POL_OVERRIDE
Definition: equipdsc.cpp:18
SettingsManager settingsManager
Definition: settings.cpp:14
virtual void readProperties(Clib::ConfigElem &elem) POL_OVERRIDE
Definition: equipmnt.cpp:75
bool remove_prop(const char *propname, std::string *value)
Definition: cfgfile.cpp:141
UArmor(const ArmorDesc &descriptor, const ArmorDesc *permanent_descriptor)
Definition: armor.cpp:125
Core::ScriptDef onhitscript_
Definition: armor.h:90
unsigned short hp_
Definition: item.h:271
unsigned short layer_to_zone(unsigned short layer)
Definition: charactr.cpp:182
void set_source(const ConfigElem &elem)
Definition: cfgfile.cpp:99
virtual void readProperties(Clib::ConfigElem &elem) POL_OVERRIDE
Definition: armor.cpp:177
#define ERROR_PRINT
Definition: logfacility.h:230
std::set< unsigned short > tmplzones()
Definition: armor.cpp:195
unsigned short zone_name_to_zone(const char *zname)
Definition: charactr.cpp:201
const ItemDesc & itemdesc() const
Definition: item.cpp:127
ArmorDesc(u32 objtype, Clib::ConfigElem &elem, const Plib::Package *pkg, bool forceShield=false)
Since the constructor is doing some wrong guessing to tell when an armor is a shield, forceShield will force to consider it a shield.
Definition: armor.cpp:45
virtual size_t estimatedSize() const POL_OVERRIDE
Definition: equipdsc.cpp:22
void set_rest(const char *newrest)
Definition: cfgfile.cpp:89
#define pf_endl
Definition: proplist.cpp:25
Definition: berror.cpp:12
void validate_intrinsic_shield_template()
Must be called at startup, validates the intrinsic shield element.
Definition: armor.cpp:202
void set_onhitscript(const std::string &scriptname)
Definition: armor.cpp:184
virtual size_t estimatedSize() const POL_OVERRIDE
Definition: armor.cpp:117
const std::string & dir() const
Definition: pkg.h:79