• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

polserver / polserver / 25988041997

17 May 2026 10:13AM UTC coverage: 60.832% (-0.07%) from 60.903%
25988041997

Pull #884

github

turleypol
run hitscript, cleanup
Pull Request #884: Attackable item

268 of 559 new or added lines in 26 files covered. (47.94%)

18 existing lines in 7 files now uncovered.

44718 of 73511 relevant lines covered (60.83%)

502068.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

61.94
/pol-core/pol/item/weapon.cpp
1
/** @file
2
 *
3
 * @par History
4
 * - 2005/03/09 Shinigami: Added Prop Delay [ms]
5
 * - 2005/07/25 Shinigami: added MinDamage and MaxDamage in Weapon-Descriptor
6
 * - 2011/11/12 Tomi:    added extobj.wrestling
7
 */
8

9

10
#include "weapon.h"
11

12
#include <stddef.h>
13
#include <string>
14

15
#include "../../bscript/bstruct.h"
16
#include "../../bscript/executor.h"
17
#include "../../bscript/impstr.h"
18
#include "../../clib/cfgelem.h"
19
#include "../../clib/logfacility.h"
20
#include "../../clib/passert.h"
21
#include "../../clib/streamsaver.h"
22
#include "../../clib/strutil.h"
23
#include "../../plib/systemstate.h"
24
#include "../containr.h"
25
#include "../dice.h"
26
#include "../equipdsc.h"
27
#include "../extobj.h"
28
#include "../globals/settings.h"
29
#include "../globals/uvars.h"
30
#include "../layers.h"
31
#include "../mobile/charactr.h"
32
#include "../realms/realm.h"
33
#include "../syshookscript.h"
34
#include "../ufunc.h"
35
#include "../umanip.h"
36
#include "../uobject.h"
37
#include "itemdesc.h"
38
#include "mobile/attack.h"
39
#include "wepntmpl.h"
40

41

42
namespace Pol::Items
43
{
44
/*
45
WeaponDesc::WeaponDesc() :
46
skillid( SKILLID_WRESTLING ),
47
speed( 100 ),
48
delay( 0 ),
49
damage_dice(),
50
projectile(false),
51
projectile_type(0),
52
maxhp(1)
53
{
54
}
55
*/
56

57
Core::UACTION remove_action( Clib::ConfigElem& elem, const char* name, Core::UACTION deflt )
72✔
58
{
59
  unsigned short tmp = elem.remove_ushort( name, static_cast<unsigned short>( deflt ) );
72✔
60
  if ( Core::UACTION_IS_VALID( tmp ) )
72✔
61
  {
62
    return static_cast<Core::UACTION>( tmp );
72✔
63
  }
64

65
  elem.throw_error( std::string( name ) + " is out of range" );
×
66
}
67
Core::UACTION remove_action( Clib::ConfigElem& elem, const char* name )
×
68
{
69
  unsigned short tmp = elem.remove_ushort( name );
×
70
  if ( Core::UACTION_IS_VALID( tmp ) )
×
71
  {
72
    return static_cast<Core::UACTION>( tmp );
×
73
  }
74

75
  elem.throw_error( std::string( name ) + " is out of range" );
×
76
}
77

78
Core::UACTION default_anim( bool two_handed )
×
79
{
80
  if ( two_handed )
×
81
    return Core::ACTION_RIDINGHORSE7;
×
82
  return Core::ACTION_RIDINGHORSE4;
×
83
}
84

85
WeaponDesc::WeaponDesc( u32 objtype, Clib::ConfigElem& elem, const Plib::Package* pkg )
36✔
86
    : EquipDesc( objtype, elem, WEAPONDESC, pkg ),
87
      pAttr( nullptr ),
36✔
88
      delay( elem.remove_ushort( "DELAY", 0 ) ),
72✔
89
      hit_script( elem.remove_string( "HITSCRIPT", "" ), pkg, "scripts/items/" ),
36✔
90
      damage_dice(),
36✔
91
      projectile( elem.remove_bool( "PROJECTILE", false ) ),
36✔
92
      projectile_type( 0 ),
36✔
93
      projectile_anim( 0 ),
36✔
94
      projectile_sound( 0 ),
36✔
95
      anim( remove_action( elem, "Anim", Core::ACTION_HUMAN_ATTACK ) ),
36✔
96
      mounted_anim( remove_action( elem, "MountedAnim", anim ) ),
36✔
97
      hit_sound( elem.remove_ushort( "HITSOUND", 0 ) ),
36✔
98
      miss_sound( elem.remove_ushort( "MISSSOUND", 0 ) ),
36✔
99
      two_handed( elem.remove_bool( "TWOHANDED", false ) ),
36✔
100
      minrange( elem.remove_ushort( "MINRANGE", projectile ? 2 : 0 ) ),
36✔
101
      maxrange( elem.remove_ushort( "MAXRANGE", projectile ? 20 : 1 ) )
72✔
102
{
103
  if ( delay == 0 )
36✔
104
    speed = elem.remove_ushort( "SPEED" );
30✔
105
  else
106
    speed = 35;
6✔
107

108
  std::string attrname = elem.remove_string( "Attribute", "" );
36✔
109
  if ( attrname.empty() )
36✔
110
  {
111
    attrname = elem.remove_string( "SkillID", "" );
×
112

113
    // throw the error this time
114
    if ( attrname.empty() )
×
115
      attrname = elem.remove_string( "Attribute" );
×
116

117
    elem.warn( "Element specifies a SkillID instead of an Attribute" );
×
118
  }
119

120
  pAttr = Mobile::Attribute::FindAttribute( attrname );
36✔
121
  if ( !pAttr )
36✔
122
  {
123
    elem.throw_error( "Attribute " + attrname + " not found" );
×
124
  }
125

126
  if ( elem.has_prop( "INTRINSIC" ) )
36✔
127
  {
128
    elem.throw_error( "Weapon has INTRINSIC property, which is no longer needed" );
×
129
  }
130

131
  if ( speed <= 0 )
36✔
132
  {
133
    elem.throw_error( "Weapon has illegal Speed value (Speed must be positive)" );
×
134
  }
135
  if ( maxhp <= 0 )
36✔
136
  {
137
    elem.throw_error( "Weapon has illegal MaxHP value (MaxHP must be positive)" );
×
138
  }
139

140
  std::string errmsg;
36✔
141
  if ( !damage_dice.load( elem.remove_string( "DAMAGE" ).c_str(), &errmsg ) )
36✔
142
  {
143
    elem.throw_error( "Error parsing DAMAGE string for WeaponTemplate\n" + errmsg );
×
144

145
    /*cerr << "Error parsing DAMAGE string for WeaponTemplate " << objtype << endl;
146
    cerr << "  " << errmsg << endl;
147
    throw runtime_error( "Configuration error" );*/
148
  }
149

150

151
  if ( projectile )
36✔
152
  {
153
    projectile_type = elem.remove_ushort( "ProjectileType" );
×
154
    projectile_anim = elem.remove_ushort( "ProjectileAnim" );
×
155
    projectile_sound = elem.remove_ushort( "ProjectileSound" );
×
156
  }
157
}
36✔
158

159
unsigned short WeaponDesc::get_random_damage() const
8✔
160
{
161
  return damage_dice.roll();
8✔
162
}
163

164
void WeaponDesc::PopulateStruct( Bscript::BStruct* descriptor ) const
×
165
{
166
  using namespace Bscript;
167
  base::PopulateStruct( descriptor );
×
168
  descriptor->addMember( "Speed", new BLong( speed ) );
×
169
  descriptor->addMember( "Delay", new BLong( delay ) );
×
170

171
  descriptor->addMember( "Projectile", new BLong( projectile ) );
×
172
  descriptor->addMember( "ProjectileType", new BLong( projectile_type ) );
×
173
  descriptor->addMember( "ProjectileAnim", new BLong( projectile_anim ) );
×
174
  descriptor->addMember( "ProjectileSound", new BLong( projectile_sound ) );
×
175

176
  descriptor->addMember( "HitSound", new BLong( hit_sound ) );
×
177
  descriptor->addMember( "MissSound", new BLong( miss_sound ) );
×
178

179
  descriptor->addMember( "MinRange", new BLong( minrange ) );
×
180
  descriptor->addMember( "MaxRange", new BLong( maxrange ) );
×
181

182
  // descriptor->addMember( "Intrinsic", new BLong(is_intrinsic) );
183
  descriptor->addMember( "TwoHanded", new BLong( two_handed ) );
×
184

185
  descriptor->addMember( "Anim", new BLong( anim ) );
×
186
  descriptor->addMember( "MountedAnim", new BLong( mounted_anim ) );
×
187

188
  std::string tempstr;
×
189
  damage_dice.die_string( tempstr );
×
190
  descriptor->addMember( "Damage", new String( tempstr ) );
×
191
  descriptor->addMember( "MinDamage", new BLong( damage_dice.min_value() ) );
×
192
  descriptor->addMember( "MaxDamage", new BLong( damage_dice.max_value() ) );
×
193

194
  descriptor->addMember( "HitScript", new String( hit_script.relativename( pkg ) ) );
×
195
  descriptor->addMember( "Attribute", new String( pAttr->name ) );
×
196
}
×
197

198
size_t WeaponDesc::estimatedSize() const
12✔
199
{
200
  return base::estimatedSize() + sizeof( const Mobile::Attribute* ) /*pAttr*/
12✔
201
         + sizeof( unsigned short )                                 /*speed*/
202
         + sizeof( unsigned short )                                 /*delay*/
203
         + sizeof( Core::ScriptDef )                                /*hit_script*/
204
         + sizeof( Core::Dice )                                     /*damage_dice*/
205
         + sizeof( bool )                                           /*projectile*/
206
         + sizeof( unsigned short )                                 /*projectile_type*/
207
         + sizeof( unsigned short )                                 /*projectile_anim*/
208
         + sizeof( unsigned short )                                 /*projectile_sound*/
209
         + sizeof( Core::UACTION )                                  /*anim*/
210
         + sizeof( Core::UACTION )                                  /*mounted_anim*/
211
         + sizeof( unsigned short )                                 /*hit_sound*/
212
         + sizeof( unsigned short )                                 /*miss_sound*/
213
         + sizeof( bool )                                           /*two_handed*/
214
         + sizeof( unsigned short )                                 /*minrange*/
215
         + sizeof( unsigned short )                                 /*maxrange*/
216
         + hit_script.estimatedSize();
12✔
217
}
218

219
/// Creates a new intrinsic weapon and returns it
220
/// @param name: the unique weapon's name
221
/// @param elem: the config element to create from
222
/// @param pkg: the package
223
UWeapon* create_intrinsic_weapon( const char* name, Clib::ConfigElem& elem,
30✔
224
                                  const Plib::Package* pkg )
225
{
226
  auto tmpl = new WeaponDesc( Core::settingsManager.extobj.wrestling, elem, pkg );
30✔
227
  tmpl->is_intrinsic = true;
30✔
228
  auto wpn = new UWeapon( *tmpl, tmpl );
30✔
229
  wpn->layer = Core::LAYER_HAND1;
30✔
230
  wpn->tmpl = tmpl;
30✔
231
  wpn->copyprops( tmpl->props );
30✔
232

233
  Items::register_intrinsic_equipment( name, wpn );
30✔
234

235
  return wpn;
30✔
236
}
237

238
/// Creates the intrinsic wrestling weapon for PCs
239
/// must be called at startup
240
void load_intrinsic_weapons()
3✔
241
{
242
  const ItemDesc& id = find_itemdesc( Core::settingsManager.extobj.wrestling );
3✔
243
  if ( id.save_on_exit )
3✔
244
    throw std::runtime_error( "Wrestling weapon " +
×
245
                              Clib::hexint( Core::settingsManager.extobj.wrestling ) +
×
246
                              " must specify SaveOnExit 0" );
×
247

248
  if ( id.type == ItemDesc::WEAPONDESC )
3✔
249
  {
250
    const WeaponDesc* weapon_descriptor = static_cast<const WeaponDesc*>( &id );
3✔
251
    Core::gamestate.wrestling_weapon = new UWeapon( *weapon_descriptor, weapon_descriptor );
3✔
252

253
    {
254
      // sets wrestling weapondesc as intrinsic
255
      WeaponDesc* wdesc = const_cast<WeaponDesc*>( weapon_descriptor );
3✔
256
      wdesc->is_intrinsic = true;
3✔
257
      wdesc->is_pc_intrinsic = true;
3✔
258
    }
259
    Core::gamestate.wrestling_weapon->inuse( true );
3✔
260
    Core::gamestate.wrestling_weapon->layer = Core::LAYER_HAND1;
3✔
261

262
    Items::insert_intrinsic_equipment( "PC_weapon", Core::gamestate.wrestling_weapon );
3✔
263
  }
264

265
  // wrestling_weapon = find_intrinsic_weapon( "Wrestling" );
266
  if ( Core::gamestate.wrestling_weapon == nullptr )
3✔
267
    throw std::runtime_error( "A WeaponTemplate for Wrestling is required in itemdesc.cfg" );
×
268
}
3✔
269

270
/// Creates a new intrinic weapon for an NPC template and returns it
271
/// @param elem: The conig element defining the NPC
272
/// @param pkg: The package
273
/// @returns The created weapon or nullptr if none is defined in the template
274
UWeapon* create_intrinsic_weapon_from_npctemplate( Clib::ConfigElem& elem,
30✔
275
                                                   const Plib::Package* pkg )
276
{
277
  if ( !elem.has_prop( "AttackSpeed" ) && !elem.has_prop( "AttackDelay" ) )
30✔
278
    return nullptr;
×
279

280
  std::string tmp;
30✔
281
  // Construct a WeaponTemplate for this NPC template.
282
  Clib::ConfigElem wpnelem;
30✔
283
  wpnelem.set_rest( elem.rest() );
30✔
284
  wpnelem.set_source( elem );
30✔
285
  wpnelem.add_prop( "Objtype", "0xFFFF" );
30✔
286
  wpnelem.add_prop( "Graphic", "1" );
30✔
287
  if ( elem.remove_prop( "AttackSpeed", &tmp ) )
30✔
288
    wpnelem.add_prop( "Speed", tmp );
24✔
289

290
  if ( elem.remove_prop( "AttackDelay", &tmp ) )
30✔
291
    wpnelem.add_prop( "Delay", tmp );
6✔
292

293
  wpnelem.add_prop( "Damage", elem.remove_string( "AttackDamage" ) );
30✔
294

295
  if ( elem.has_prop( "AttackSkillId" ) )
30✔
296
    wpnelem.add_prop( "SkillId", elem.remove_string( "AttackSkillId" ) );
×
297
  else
298
    wpnelem.add_prop( "Attribute", elem.remove_string( "AttackAttribute" ) );
30✔
299

300
  wpnelem.add_prop( "HitSound", elem.remove_string( "AttackHitSound", "0" ) );
30✔
301
  wpnelem.add_prop( "MissSound", elem.remove_string( "AttackMissSound", "0" ) );
30✔
302
  wpnelem.add_prop( "Anim", elem.remove_string( "AttackAnimation", "0" ) );
30✔
303
  wpnelem.add_prop( "MaxHp", "1" );
30✔
304
  if ( elem.remove_prop( "AttackHitScript", &tmp ) )
30✔
305
    wpnelem.add_prop( "HitScript", tmp );
3✔
306
  if ( elem.remove_prop( "AttackMinRange", &tmp ) )
30✔
307
    wpnelem.add_prop( "MinRange", tmp );
×
308
  if ( elem.remove_prop( "AttackMaxRange", &tmp ) )
30✔
309
    wpnelem.add_prop( "MaxRange", tmp );
×
310

311
  if ( elem.has_prop( "AttackProjectile" ) )
30✔
312
  {
313
    wpnelem.add_prop( "Projectile", "1" );
×
314
    wpnelem.add_prop( "ProjectileType", elem.remove_string( "AttackProjectileType" ) );
×
315
    wpnelem.add_prop( "ProjectileAnim", elem.remove_string( "AttackProjectileAnim" ) );
×
316
    wpnelem.add_prop( "ProjectileSound", elem.remove_string( "AttackProjectileSound" ) );
×
317
  }
318

319
  while ( elem.remove_prop( "AttackCProp", &tmp ) )
33✔
320
    wpnelem.add_prop( "CProp", tmp );
3✔
321

322
  return create_intrinsic_weapon( elem.rest(), wpnelem, pkg );
30✔
323
}
30✔
324

325
UWeapon::UWeapon( const WeaponDesc& descriptor, const WeaponDesc* permanent_descriptor )
35✔
326
    : Equipment( descriptor, Core::UOBJ_CLASS::CLASS_WEAPON, permanent_descriptor ),
327
      hit_script_( descriptor.hit_script )
35✔
328
{
329
}
35✔
330

331
size_t UWeapon::estimatedSize() const
11✔
332
{
333
  return base::estimatedSize() + hit_script_.estimatedSize();
11✔
334
}
335

336
unsigned short UWeapon::speed() const
17✔
337
{
338
  int speed_ = WEAPON_TMPL->speed + speed_mod();
17✔
339

340
  if ( speed_ < 0 )
17✔
341
    return 0;
×
342
  if ( speed_ <= USHRT_MAX )
17✔
343
    return static_cast<u16>( speed_ );
17✔
344
  return USHRT_MAX;
×
345
}
346

347
unsigned short UWeapon::delay() const
17✔
348
{
349
  return WEAPON_TMPL->delay;
17✔
350
}
351

352
const Mobile::Attribute& UWeapon::attribute() const
16✔
353
{
354
  return *( WEAPON_TMPL->pAttr );
16✔
355
}
356

357
unsigned short UWeapon::get_random_damage() const
8✔
358
{
359
  int dmg = int( WEAPON_TMPL->get_random_damage() ) * hp_ / maxhp();
8✔
360
  dmg += damage_mod();
8✔
361
  if ( dmg < 0 )
8✔
362
    return 0;
×
363
  if ( dmg <= USHRT_MAX )
8✔
364
    return static_cast<unsigned short>( dmg );
8✔
365
  return USHRT_MAX;
×
366
}
367

368
unsigned short UWeapon::min_weapon_damage() const
81✔
369
{
370
  int dmg = static_cast<int>( WEAPON_TMPL->damage_dice.min_value() ) + damage_mod();
81✔
371
  if ( dmg < 0 )
81✔
372
    return 0;
×
373
  if ( dmg <= USHRT_MAX )
81✔
374
    return static_cast<unsigned short>( dmg );
81✔
375
  return USHRT_MAX;
×
376
}
377

378
unsigned short UWeapon::max_weapon_damage() const
81✔
379
{
380
  int dmg = static_cast<int>( WEAPON_TMPL->damage_dice.max_value() ) + damage_mod();
81✔
381
  if ( dmg < 0 )
81✔
382
    return 0;
×
383
  if ( dmg <= USHRT_MAX )
81✔
384
    return static_cast<unsigned short>( dmg );
81✔
385
  return USHRT_MAX;
×
386
}
387

388
bool UWeapon::is_projectile() const
29✔
389
{
390
  passert( tmpl != nullptr );
29✔
391
  return WEAPON_TMPL->projectile;
29✔
392
}
393

394
unsigned short UWeapon::projectile_sound() const
×
395
{
396
  passert( tmpl != nullptr );
×
397
  return WEAPON_TMPL->projectile_sound;
×
398
}
399

400
unsigned short UWeapon::projectile_anim() const
×
401
{
402
  passert( tmpl != nullptr );
×
403
  return WEAPON_TMPL->projectile_anim;
×
404
}
405

406
Core::UACTION UWeapon::anim() const
8✔
407
{
408
  passert( tmpl != nullptr );
8✔
409
  return WEAPON_TMPL->anim;
8✔
410
}
411

412
Core::UACTION UWeapon::mounted_anim() const
×
413
{
414
  passert( tmpl != nullptr );
×
415
  return WEAPON_TMPL->mounted_anim;
×
416
}
417

418
unsigned short UWeapon::hit_sound() const
8✔
419
{
420
  passert( tmpl != nullptr );
8✔
421
  return WEAPON_TMPL->hit_sound;
8✔
422
}
423

424
unsigned short UWeapon::miss_sound() const
×
425
{
426
  passert( tmpl != nullptr );
×
427
  return WEAPON_TMPL->miss_sound;
×
428
}
429

430
const WeaponDesc& UWeapon::descriptor() const
×
431
{
432
  passert( tmpl != nullptr );
×
433
  return *WEAPON_TMPL;
×
434
}
435

436
bool UWeapon::consume_projectile( Core::UContainer* cont ) const
×
437
{
438
  passert( tmpl != nullptr );
×
439

440
  Item* item = cont->find_objtype_noninuse( WEAPON_TMPL->projectile_type );
×
441
  if ( item != nullptr )
×
442
  {
443
    subtract_amount_from_item( item, 1 );
×
444
    return true;
×
445
  }
446

447
  return false;
×
448
}
449

450
bool UWeapon::in_range( const Mobile::Character* wielder, const Mobile::Attackable& target ) const
23✔
451
{
452
  const auto* tar_obj = target.object();
23✔
453
  unsigned short dist = wielder->distance_to( tar_obj->toplevel_pos() );
23✔
454
  signed short min_dist_mod = wielder->min_attack_range_increase().sum();
23✔
455
  signed short max_dist_mod = wielder->max_attack_range_increase().sum();
23✔
456
  signed short min_dist = WEAPON_TMPL->minrange + min_dist_mod;
23✔
457
  signed short max_dist = WEAPON_TMPL->maxrange + max_dist_mod;
23✔
458
  min_dist = std::max( min_dist, 0_s16 );
23✔
459
  max_dist = std::max( max_dist, 0_s16 );
23✔
460
  min_dist = std::min( max_dist, min_dist );
23✔
461
  max_dist = std::max( max_dist, min_dist );
23✔
462
  INFO_PRINTLN_TRACE( 22 )
23✔
463
  ( "in_range({:#x},{:#x}):\n"
×
464
    "dist:   {}\n"
465
    "weap_minrange: {}\n"
466
    "mod_minrange: {}\n"
467
    "weap_maxrange: {}\n"
468
    "mod_maxrange: {}\n"
469
    "calc_min: {}\n"
470
    "calc_max: {}\n"
471
    "has_los:  {}\n",
NEW
472
    wielder->serial, tar_obj->serial, dist, WEAPON_TMPL->minrange, min_dist_mod,
×
473
    WEAPON_TMPL->maxrange, max_dist_mod, min_dist, max_dist,
×
NEW
474
    wielder->realm()->has_los( *wielder, *tar_obj ) );
×
475
  return ( dist >= min_dist && dist <= max_dist &&
43✔
476
           wielder->realm()->has_los( *wielder, *tar_obj ) );
43✔
477
}
478

479
// FIXME weak, weak..
480
Item* UWeapon::clone() const
×
481
{
482
  UWeapon* wpn = static_cast<UWeapon*>( base::clone() );
×
483
  wpn->hit_script_ = hit_script_;
×
484
  wpn->damage_mod( this->damage_mod() );
×
485
  wpn->speed_mod( this->speed_mod() );
×
486

487
  return wpn;
×
488
}
489

490
void UWeapon::printProperties( Clib::StreamWriter& sw ) const
2✔
491
{
492
  base::printProperties( sw );
2✔
493

494
  short speed_mod_ = speed_mod();
2✔
495
  short dmg_mod = damage_mod();
2✔
496

497
  if ( dmg_mod )
2✔
498
    sw.add( "dmg_mod", dmg_mod );
2✔
499
  if ( speed_mod_ )
2✔
500
    sw.add( "speed_mod", speed_mod_ );
2✔
501
  if ( !( hit_script_ == WEAPON_TMPL->hit_script ) )
2✔
502
    sw.add( "HitScript", hit_script_.relativename( tmpl->pkg ) );
2✔
503
}
2✔
504

505
void UWeapon::readProperties( Clib::ConfigElem& elem )
1✔
506
{
507
  base::readProperties( elem );
1✔
508

509
  damage_mod( static_cast<s16>( elem.remove_int( "DMG_MOD", 0 ) ) );
1✔
510
  speed_mod( static_cast<s16>( elem.remove_int( "SPEED_MOD", 0 ) ) );
1✔
511

512
  // if the HITSCRIPT is not specified in the data file, keep the value from the template.
513
  if ( elem.has_prop( "HITSCRIPT" ) )
1✔
514
    set_hit_script( elem.remove_string( "HITSCRIPT" ) );
1✔
515
}
1✔
516

517
void UWeapon::set_hit_script( const std::string& scriptname )
2✔
518
{
519
  if ( scriptname.empty() )
2✔
520
  {
521
    hit_script_.clear();
×
522
  }
523
  else
524
  {
525
    passert( tmpl != nullptr );
2✔
526
    hit_script_.config( scriptname, tmpl->pkg, "scripts/items/", true );
2✔
527
  }
528
}
2✔
529

530
bool UWeapon::get_method_hook( const char* methodname, Bscript::Executor* ex,
×
531
                               Core::ExportScript** hook, unsigned int* PC ) const
532
{
533
  if ( Core::gamestate.system_hooks.get_method_hook(
×
534
           Core::gamestate.system_hooks.weapon_method_script.get(), methodname, ex, hook, PC ) )
535
    return true;
×
536
  return base::get_method_hook( methodname, ex, hook, PC );
×
537
}
538
}  // namespace Pol::Items
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc